Merge branch '3.3-stable' into new-cursors-on-3.3-stable
diff --git a/docs/CODEOWNERS b/.github/CODEOWNERS
similarity index 100%
rename from docs/CODEOWNERS
rename to .github/CODEOWNERS
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0b09e0f..55262d8 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -3,6 +3,7 @@
     pull_request:
     push:
         branches: [ ci, master, latest, 3.3-stable ]
+    workflow_dispatch:
 permissions:
     statuses: write
     contents: read
@@ -15,7 +16,7 @@
             CC: clang
             CFLAGS: -Werror
         steps:
-            - uses: actions/checkout@v2
+            - uses: actions/checkout@v3
             - name: Install dependencies
               run: |
                   sudo apt update
@@ -38,7 +39,7 @@
             CC: clang
             CFLAGS: -Werror
         steps:
-            - uses: actions/checkout@v2
+            - uses: actions/checkout@v3
             - name: Install dependencies
               run: |
                   sudo apt update
@@ -61,7 +62,7 @@
             CC: clang
             CFLAGS: -Werror
         steps:
-            - uses: actions/checkout@v2
+            - uses: actions/checkout@v3
             - name: Install dependencies
               run: |
                   sudo apt update
@@ -84,7 +85,7 @@
             CFLAGS: -Werror
             MACOSX_DEPLOYMENT_TARGET: 10.8
         steps:
-            - uses: actions/checkout@v2
+            - uses: actions/checkout@v3
 
             - name: Configure static library
               run: cmake -S . -B build-static
@@ -102,7 +103,7 @@
         env:
             CFLAGS: /WX
         steps:
-            - uses: actions/checkout@v2
+            - uses: actions/checkout@v3
 
             - name: Configure static library
               run: cmake -S . -B build-static -G "Visual Studio 17 2022"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 78b38e4..b035b98 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,8 +1,6 @@
 cmake_minimum_required(VERSION 3.0...3.20 FATAL_ERROR)
 
-project(GLFW VERSION 3.3.7 LANGUAGES C)
-
-set(CMAKE_LEGACY_CYGWIN_WIN32 OFF)
+project(GLFW VERSION 3.3.9 LANGUAGES C)
 
 if (POLICY CMP0054)
     cmake_policy(SET CMP0054 NEW)
@@ -47,6 +45,7 @@
 else()
     set(GLFW_LIB_NAME glfw3)
 endif()
+set(GLFW_LIB_NAME_SUFFIX "")
 
 if (GLFW_VULKAN_STATIC)
     if (BUILD_SHARED_LIBS)
@@ -198,6 +197,10 @@
     if (GLFW_USE_HYBRID_HPG)
         set(_GLFW_USE_HYBRID_HPG 1)
     endif()
+
+    if (BUILD_SHARED_LIBS)
+        set (GLFW_LIB_NAME_SUFFIX "dll")
+    endif()
 endif()
 
 #--------------------------------------------------------------------
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 0bc0cd2..0178337 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -8,6 +8,7 @@
  - Bobyshev Alexander
  - Laurent Aphecetche
  - Matt Arsenault
+ - Takuro Ashie
  - ashishgamedev
  - David Avedissian
  - Keith Bauer
@@ -18,11 +19,13 @@
  - Nevyn Bengtsson
  - Niklas Bergström
  - Denis Bernard
+ - BiBi
  - Doug Binks
  - blanco
  - Waris Boonyasiriwat
  - Kyle Brenneman
  - Rok Breulj
+ - TheBrokenRail
  - Kai Burjack
  - Martin Capitanio
  - Nicolas Caramelli
@@ -43,6 +46,7 @@
  - Noel Cower
  - CuriouserThing
  - Jason Daly
+ - danhambleton
  - Jarrod Davis
  - Olivier Delannoy
  - Paul R. Deppe
@@ -57,36 +61,49 @@
  - Jan Ekström
  - Siavash Eliasi
  - TheExileFox
+ - Nikita Fediuchin
  - Felipe Ferreira
  - Michael Fogleman
+ - forworldm
  - Jason Francis
  - Gerald Franz
  - Mário Freitas
  - GeO4d
  - Marcus Geelnard
+ - Gegy
  - ghuser404
  - Charles Giessen
  - Ryan C. Gordon
  - Stephen Gowen
  - Kovid Goyal
+ - Kevin Grandemange
  - Eloi Marín Gratacós
+ - Grzesiek11
  - Stefan Gustavson
  - Andrew Gutekanst
  - Stephen Gutekanst
  - Jonathan Hale
+ - Daniel Hauser
  - hdf89shfdfs
+ - Moritz Heinemann
  - Sylvain Hellegouarch
+ - Björn Hempel
  - Matthew Henry
  - heromyth
  - Lucas Hinderberger
  - Paul Holden
+ - Hajime Hoshi
  - Warren Hu
  - Charles Huber
+ - Brent Huisman
  - illustris
  - InKryption
  - IntellectualKitty
  - Aaron Jacobs
+ - JannikGM
  - Erik S. V. Jansson
+ - jjYBdx4IL
+ - Peter Johnson
  - Toni Jovanoski
  - Arseny Kapoulkine
  - Cem Karan
@@ -109,12 +126,15 @@
  - Anders Lindqvist
  - Leon Linhart
  - Marco Lizza
+ - lo-v-ol
  - Eyal Lotem
  - Aaron Loucks
  - Luflosi
  - lukect
  - Tristam MacDonald
+ - Jean-Luc Mackail
  - Hans Mackowiak
+ - Ramiro Magno
  - Дмитри Малышев
  - Zbigniew Mandziejewicz
  - Adam Marcus
@@ -127,19 +147,24 @@
  - Marcel Metz
  - Liam Middlebrook
  - Ave Milia
+ - Icyllis Milica
  - Jonathan Miller
  - Kenneth Miller
  - Bruce Mitchener
  - Jack Moffitt
+ - Ravi Mohan
  - Jeff Molofee
  - Alexander Monakov
  - Pierre Morel
  - Jon Morton
  - Pierre Moulon
  - Martins Mozeiko
+ - James Murphy
  - Julian Møller
  - ndogxj
+ - F. Nedelec
  - Kristian Nielsen
+ - Joel Niemelä
  - Kamil Nowakowski
  - onox
  - Denis Ovod
@@ -150,10 +175,12 @@
  - Christopher Pelloux
  - Arturo J. Pérez
  - Vladimir Perminov
+ - Olivier Perret
  - Anthony Pesch
  - Orson Peters
  - Emmanuel Gil Peyrot
  - Cyril Pichard
+ - Pilzschaf
  - Keith Pitt
  - Stanislav Podgorskiy
  - Konstantin Podsvirov
@@ -162,10 +189,13 @@
  - Pablo Prietz
  - przemekmirek
  - pthom
+ - Martin Pulec
  - Guillaume Racicot
+ - Christian Rauch
  - Philip Rideout
  - Eddie Ringle
  - Max Risuhin
+ - Joe Roback
  - Jorge Rodriguez
  - Luca Rood
  - Ed Ropple
@@ -178,11 +208,13 @@
  - Matt Sealey
  - Steve Sexton
  - Arkady Shapkin
+ - Mingjie Shen
  - Ali Sherief
  - Yoshiki Shibukawa
  - Dmitri Shuralyov
  - Joao da Silva
  - Daniel Sieger
+ - Michael Skec
  - Daniel Skorupski
  - Slemmie
  - Bradley Smith
@@ -201,6 +233,7 @@
  - TTK-Bandit
  - Sergey Tikhomirov
  - Arthur Tombs
+ - TronicLabs
  - Ioannis Tsakpinis
  - Samuli Tuomola
  - Matthew Turner
@@ -210,10 +243,12 @@
  - Jari Vetoniemi
  - Ricardo Vieira
  - Nicholas Vitovitch
+ - Vladimír Vondruš
  - Simon Voordouw
  - Corentin Wallez
  - Torsten Walluhn
  - Patrick Walton
+ - Jim Wang
  - Xo Wang
  - Jay Weisskopf
  - Frank Wille
diff --git a/README.md b/README.md
index cc2667e..486679b 100644
--- a/README.md
+++ b/README.md
@@ -123,33 +123,33 @@
 
 ## Changelog
 
- - [Win32] Bugfix: A window created maximized and undecorated would cover the whole
-   monitor (#1806)
- - [Win32] Bugfix: The default restored window position was lost when creating a maximized
-   window
- - [Win32] Bugfix: `glfwMaximizeWindow` would make a hidden window visible
- - [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003)
- - [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences
- - [X11] Bugfix: Waiting for events would fail if file descriptor was too large
-   (#2024)
- - [X11] Bugfix: Joystick events could lead to busy-waiting (#1872)
- - [X11] Bugfix: `glfwWaitEvents*` did not continue for joystick events
- - [X11] Bugfix: `glfwPostEmptyEvent` could be ignored due to race condition
-   (#379,#1281,#1285,#2033)
- - [X11] Bugfix: Dynamic loading on NetBSD failed due to soname differences
- - [X11] Bugfix: Left shift of int constant relied on undefined behavior (#1951)
- - [Wayland] Added support for key names via xkbcommon
- - [Wayland] Bugfix: Key repeat could lead to a race condition (#1710)
- - [Wayland] Bugfix: Activating a window would emit two input focus events
- - [Wayland] Bugfix: Disable key repeat mechanism when window loses input focus
- - [Wayland] Bugfix: Window hiding and showing did not work (#1492,#1731)
- - [Wayland] Bugfix: A key being repeated was not released when window lost focus
- - [Wayland] Bugfix: Showing a hidden window did not emit a window refresh event
- - [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE`
- - [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN`
- - [Wayland] Bugfix: Text input did not repeat along with key repeat
- - [Wayland] Bugfix: `glfwPostEmptyEvent` sometimes had no effect (#1520,#1521)
- - [GLX] Bugfix: Context creation failed if GLX 1.4 was not exported by GLX library
+ - Bugfix: `glfwGetKeyScancode` returned `0` on error when initialized instead of `-1`
+ - Bugfix: Failure to make a newly created context current could cause segfault (#2327)
+ - [Win32] Fix pkg-config for dynamic library on Windows (#2386, #2420)
+ - [Win32] Bugfix: `glfwWaitEventsTimeout` did not return for some sent messages (#2408)
+ - [Win32] Bugfix: XInput could reportedly provide invalid DPad bit masks (#2291)
+ - [Cocoa] Bugfix: Compilation failed on OS X 10.8 due to unconditional use of 10.9+
+   symbols (#2161)
+ - [Cocoa] Bugfix: Full screen windows were resizable by the user (#2377,#2405)
+ - [Cocoa] Bugfix: Full screen windows were miniaturized when clicked on macOS
+   10.15 (#2377,#2405)
+ - [Cocoa] Bugfix: Querying joystick elements could reportedly segfault on macOS
+   13 Ventura (#2320)
+ - [Cocoa] Bugfix: Print Screen key was not correctly reported (#1786,#2169)
+ - [Wayland] Added improved fallback window decorations via libdecor (#1639,#1693)
+ - [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450)
+ - [Wayland] Disabled alpha channel for opaque windows on systems lacking
+   `EGL_EXT_present_opaque` (#1895)
+ - [Wayland] Bugfix: Buffer would overrun when storing received drag offer (#2225)
+ - [Wayland] Bugfix: Joysticks connected after `glfwInit` were not detected (#2198)
+ - [Wayland] Bugfix: Fallback decorations emitted `GLFW_CURSOR_UNAVAILABLE` errors
+ - [Wayland] Bugfix: Some events could fail to end wait for new events (#2397)
+ - [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043)
+ - [Linux] Bugfix: A small amount of memory could leak if initialization failed (#2229)
+ - [EGL] Added loading of glvnd `libOpenGL.so.0` where available for OpenGL
+ - [EGL] Bugfix: `EGL_EXT_present_opaque` caused issues on X11 with Nvidia blob (#2365)
+ - [EGL] Bugfix: Setting `GLFW_CONTEXT_DEBUG` caused creation to fail (#2348)
+ - [GLX] Added loading of glvnd `libGLX.so.0` where available
 
 
 ## Contact
diff --git a/deps/glad/vk_platform.h b/deps/glad/vk_platform.h
index d7d22e1..277e96a 100644
--- a/deps/glad/vk_platform.h
+++ b/deps/glad/vk_platform.h
@@ -2,19 +2,9 @@
 /* File: vk_platform.h */
 /* */
 /*
-** Copyright (c) 2014-2017 The Khronos Group Inc.
+** Copyright 2014-2022 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.
+** SPDX-License-Identifier: Apache-2.0
 */
 
 
@@ -52,7 +42,7 @@
     #define VKAPI_CALL __stdcall
     #define VKAPI_PTR  VKAPI_CALL
 #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
-    #error "Vulkan isn't supported for the 'armeabi' NDK ABI"
+    #error "Vulkan is not supported for the 'armeabi' NDK ABI"
 #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
     /* On Android 32-bit ARM targets, Vulkan functions use the "hardfloat" */
     /* calling convention, i.e. float parameters are passed in registers. This */
@@ -68,7 +58,9 @@
     #define VKAPI_PTR
 #endif
 
-#include <stddef.h>
+#if !defined(VK_NO_STDDEF_H)
+    #include <stddef.h>
+#endif /* !defined(VK_NO_STDDEF_H) */
 
 #if !defined(VK_NO_STDINT_H)
     #if defined(_MSC_VER) && (_MSC_VER < 1600)
diff --git a/deps/glad/vulkan.h b/deps/glad/vulkan.h
index 6bace71..39288ee 100644
--- a/deps/glad/vulkan.h
+++ b/deps/glad/vulkan.h
@@ -1,26 +1,27 @@
 /**
- * Loader generated by glad 2.0.0-beta on Sun Apr 14 17:03:38 2019
+ * Loader generated by glad 2.0.0-beta on Wed Jul 13 21:24:58 2022
  *
  * Generator: C/C++
  * Specification: vk
- * Extensions: 3
+ * Extensions: 4
  *
  * APIs:
- *  - vulkan=1.1
+ *  - vulkan=1.3
  *
  * Options:
- *  - MX_GLOBAL = False
- *  - LOADER = False
  *  - ALIAS = False
- *  - HEADER_ONLY = False
  *  - DEBUG = False
+ *  - HEADER_ONLY = False
+ *  - LOADER = False
  *  - MX = False
+ *  - MX_GLOBAL = False
+ *  - ON_DEMAND = False
  *
  * Commandline:
- *    --api='vulkan=1.1' --extensions='VK_EXT_debug_report,VK_KHR_surface,VK_KHR_swapchain' c
+ *    --api='vulkan=1.3' --extensions='VK_EXT_debug_report,VK_KHR_portability_enumeration,VK_KHR_surface,VK_KHR_swapchain' c
  *
  * Online:
- *    http://glad.sh/#api=vulkan%3D1.1&extensions=VK_EXT_debug_report%2CVK_KHR_surface%2CVK_KHR_swapchain&generator=c&options=
+ *    http://glad.sh/#api=vulkan%3D1.3&extensions=VK_EXT_debug_report%2CVK_KHR_portability_enumeration%2CVK_KHR_surface%2CVK_KHR_swapchain&generator=c&options=
  *
  */
 
@@ -28,12 +29,12 @@
 #define GLAD_VULKAN_H_
 
 #ifdef VULKAN_H_
-    #error  header already included (API: vulkan), remove previous include!
+  #error  header already included (API: vulkan), remove previous include!
 #endif
 #define VULKAN_H_ 1
 
 #ifdef VULKAN_CORE_H_
-    #error  header already included (API: vulkan), remove previous include!
+  #error  header already included (API: vulkan), remove previous include!
 #endif
 #define VULKAN_CORE_H_ 1
 
@@ -142,15 +143,16 @@
 #define GLAPIENTRY GLAD_API_PTR
 #endif
 
-
 #define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
 #define GLAD_VERSION_MAJOR(version) (version / 10000)
 #define GLAD_VERSION_MINOR(version) (version % 10000)
 
+#define GLAD_GENERATOR_VERSION "2.0.0-beta"
+
 typedef void (*GLADapiproc)(void);
 
 typedef GLADapiproc (*GLADloadfunc)(const char *name);
-typedef GLADapiproc (*GLADuserptrloadfunc)(const char *name, void *userptr);
+typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name);
 
 typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
 typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
@@ -159,21 +161,25 @@
 
 #define VK_ATTACHMENT_UNUSED (~0U)
 #define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
-#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 9
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION 10
 #define VK_FALSE 0
+#define VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME "VK_KHR_portability_enumeration"
+#define VK_KHR_PORTABILITY_ENUMERATION_SPEC_VERSION 1
 #define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface"
 #define VK_KHR_SURFACE_SPEC_VERSION 25
 #define VK_KHR_SWAPCHAIN_EXTENSION_NAME "VK_KHR_swapchain"
 #define VK_KHR_SWAPCHAIN_SPEC_VERSION 70
-#define VK_LOD_CLAMP_NONE 1000.0f
+#define VK_LOD_CLAMP_NONE 1000.0F
 #define VK_LUID_SIZE 8
 #define VK_MAX_DESCRIPTION_SIZE 256
 #define VK_MAX_DEVICE_GROUP_SIZE 32
+#define VK_MAX_DRIVER_INFO_SIZE 256
+#define VK_MAX_DRIVER_NAME_SIZE 256
 #define VK_MAX_EXTENSION_NAME_SIZE 256
 #define VK_MAX_MEMORY_HEAPS 16
 #define VK_MAX_MEMORY_TYPES 32
 #define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
-#define VK_QUEUE_FAMILY_EXTERNAL (~0U-1)
+#define VK_QUEUE_FAMILY_EXTERNAL (~1U)
 #define VK_QUEUE_FAMILY_IGNORED (~0U)
 #define VK_REMAINING_ARRAY_LAYERS (~0U)
 #define VK_REMAINING_MIP_LEVELS (~0U)
@@ -183,29 +189,65 @@
 #define VK_WHOLE_SIZE (~0ULL)
 
 
-#include <glad/vk_platform.h>
+#include "vk_platform.h"
+/* DEPRECATED: This define is deprecated. VK_MAKE_API_VERSION should be used instead. */
 #define VK_MAKE_VERSION(major, minor, patch) \
-    (((major) << 22) | ((minor) << 12) | (patch))
+    ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))
+/* DEPRECATED: This define is deprecated. VK_API_VERSION_MAJOR should be used instead. */
 #define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
-#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
-#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
+/* DEPRECATED: This define is deprecated. VK_API_VERSION_MINOR should be used instead. */
+#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU)
+/* DEPRECATED: This define is deprecated. VK_API_VERSION_PATCH should be used instead. */
+#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU)
+#define VK_MAKE_API_VERSION(variant, major, minor, patch) \
+    ((((uint32_t)(variant)) << 29) | (((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))
+#define VK_API_VERSION_VARIANT(version) ((uint32_t)(version) >> 29)
+#define VK_API_VERSION_MAJOR(version) (((uint32_t)(version) >> 22) & 0x7FU)
+#define VK_API_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3FFU)
+#define VK_API_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU)
 /* DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead. */
 /*#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 0) // Patch version should always be set to 0 */
 /* Vulkan 1.0 version number */
-#define VK_API_VERSION_1_0 VK_MAKE_VERSION(1, 0, 0)/* Patch version should always be set to 0 */
+#define VK_API_VERSION_1_0 VK_MAKE_API_VERSION(0, 1, 0, 0)/* Patch version should always be set to 0 */
 /* Vulkan 1.1 version number */
-#define VK_API_VERSION_1_1 VK_MAKE_VERSION(1, 1, 0)/* Patch version should always be set to 0 */
+#define VK_API_VERSION_1_1 VK_MAKE_API_VERSION(0, 1, 1, 0)/* Patch version should always be set to 0 */
+/* Vulkan 1.2 version number */
+#define VK_API_VERSION_1_2 VK_MAKE_API_VERSION(0, 1, 2, 0)/* Patch version should always be set to 0 */
+/* Vulkan 1.3 version number */
+#define VK_API_VERSION_1_3 VK_MAKE_API_VERSION(0, 1, 3, 0)/* Patch version should always be set to 0 */
 /* Version of this file */
-#define VK_HEADER_VERSION 106
+#define VK_HEADER_VERSION 220
+/* Complete version of this file */
+#define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, 1, 3, VK_HEADER_VERSION)
 #define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
-#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE)
-#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+#ifndef VK_USE_64_BIT_PTR_DEFINES
+    #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+        #define VK_USE_64_BIT_PTR_DEFINES 1
+    #else
+        #define VK_USE_64_BIT_PTR_DEFINES 0
+    #endif
+#endif
+#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE
+    #if (VK_USE_64_BIT_PTR_DEFINES==1)
+        #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201103L))
+            #define VK_NULL_HANDLE nullptr
+        #else
+            #define VK_NULL_HANDLE ((void*)0)
+        #endif
+    #else
+        #define VK_NULL_HANDLE 0ULL
+    #endif
+#endif
+#ifndef VK_NULL_HANDLE
+    #define VK_NULL_HANDLE 0
+#endif
+#ifndef VK_DEFINE_NON_DISPATCHABLE_HANDLE
+    #if (VK_USE_64_BIT_PTR_DEFINES==1)
         #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
-#else
+    #else
         #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+    #endif
 #endif
-#endif
-#define VK_NULL_HANDLE 0
 
 
 
@@ -241,17 +283,21 @@
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache)
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorUpdateTemplate)
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSamplerYcbcrConversion)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPrivateDataSlot)
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR)
 VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
 typedef enum VkAttachmentLoadOp {
     VK_ATTACHMENT_LOAD_OP_LOAD = 0,
     VK_ATTACHMENT_LOAD_OP_CLEAR = 1,
-    VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2
+    VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2,
+    VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF
 } VkAttachmentLoadOp;
 typedef enum VkAttachmentStoreOp {
     VK_ATTACHMENT_STORE_OP_STORE = 0,
-    VK_ATTACHMENT_STORE_OP_DONT_CARE = 1
+    VK_ATTACHMENT_STORE_OP_DONT_CARE = 1,
+    VK_ATTACHMENT_STORE_OP_NONE = 1000301000,
+    VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF
 } VkAttachmentStoreOp;
 typedef enum VkBlendFactor {
     VK_BLEND_FACTOR_ZERO = 0,
@@ -272,14 +318,16 @@
     VK_BLEND_FACTOR_SRC1_COLOR = 15,
     VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16,
     VK_BLEND_FACTOR_SRC1_ALPHA = 17,
-    VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18
+    VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18,
+    VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF
 } VkBlendFactor;
 typedef enum VkBlendOp {
     VK_BLEND_OP_ADD = 0,
     VK_BLEND_OP_SUBTRACT = 1,
     VK_BLEND_OP_REVERSE_SUBTRACT = 2,
     VK_BLEND_OP_MIN = 3,
-    VK_BLEND_OP_MAX = 4
+    VK_BLEND_OP_MAX = 4,
+    VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF
 } VkBlendOp;
 typedef enum VkBorderColor {
     VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0,
@@ -287,21 +335,45 @@
     VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2,
     VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3,
     VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4,
-    VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5
+    VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5,
+    VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF
 } VkBorderColor;
-
+typedef enum VkFramebufferCreateFlagBits {
+    VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT = 1,
+    VK_FRAMEBUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkFramebufferCreateFlagBits;
 typedef enum VkPipelineCacheHeaderVersion {
-    VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1
+    VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1,
+    VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF
 } VkPipelineCacheHeaderVersion;
-
+typedef enum VkPipelineCacheCreateFlagBits {
+    VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT = 1,
+    VK_PIPELINE_CACHE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineCacheCreateFlagBits;
+typedef enum VkPipelineShaderStageCreateFlagBits {
+    VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT = 1,
+    VK_PIPELINE_SHADER_STAGE_CREATE_REQUIRE_FULL_SUBGROUPS_BIT = 2,
+    VK_PIPELINE_SHADER_STAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineShaderStageCreateFlagBits;
+typedef enum VkDescriptorSetLayoutCreateFlagBits {
+    VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT = 2,
+    VK_DESCRIPTOR_SET_LAYOUT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorSetLayoutCreateFlagBits;
+typedef enum VkInstanceCreateFlagBits {
+    VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR = 1,
+    VK_INSTANCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkInstanceCreateFlagBits;
 typedef enum VkDeviceQueueCreateFlagBits {
-    VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 1
+    VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT = 1,
+    VK_DEVICE_QUEUE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkDeviceQueueCreateFlagBits;
 typedef enum VkBufferCreateFlagBits {
     VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 1,
     VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 2,
     VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 4,
-    VK_BUFFER_CREATE_PROTECTED_BIT = 8
+    VK_BUFFER_CREATE_PROTECTED_BIT = 8,
+    VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 16,
+    VK_BUFFER_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkBufferCreateFlagBits;
 typedef enum VkBufferUsageFlagBits {
     VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 1,
@@ -312,13 +384,16 @@
     VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 32,
     VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 64,
     VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 128,
-    VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 256
+    VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 256,
+    VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT = 131072,
+    VK_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkBufferUsageFlagBits;
 typedef enum VkColorComponentFlagBits {
     VK_COLOR_COMPONENT_R_BIT = 1,
     VK_COLOR_COMPONENT_G_BIT = 2,
     VK_COLOR_COMPONENT_B_BIT = 4,
-    VK_COLOR_COMPONENT_A_BIT = 8
+    VK_COLOR_COMPONENT_A_BIT = 8,
+    VK_COLOR_COMPONENT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkColorComponentFlagBits;
 typedef enum VkComponentSwizzle {
     VK_COMPONENT_SWIZZLE_IDENTITY = 0,
@@ -327,27 +402,33 @@
     VK_COMPONENT_SWIZZLE_R = 3,
     VK_COMPONENT_SWIZZLE_G = 4,
     VK_COMPONENT_SWIZZLE_B = 5,
-    VK_COMPONENT_SWIZZLE_A = 6
+    VK_COMPONENT_SWIZZLE_A = 6,
+    VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF
 } VkComponentSwizzle;
 typedef enum VkCommandPoolCreateFlagBits {
     VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 1,
     VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 2,
-    VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 4
+    VK_COMMAND_POOL_CREATE_PROTECTED_BIT = 4,
+    VK_COMMAND_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkCommandPoolCreateFlagBits;
 typedef enum VkCommandPoolResetFlagBits {
-    VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 1
+    VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 1,
+    VK_COMMAND_POOL_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkCommandPoolResetFlagBits;
 typedef enum VkCommandBufferResetFlagBits {
-    VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 1
+    VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 1,
+    VK_COMMAND_BUFFER_RESET_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkCommandBufferResetFlagBits;
 typedef enum VkCommandBufferLevel {
     VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0,
-    VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1
+    VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1,
+    VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF
 } VkCommandBufferLevel;
 typedef enum VkCommandBufferUsageFlagBits {
     VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 1,
     VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 2,
-    VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 4
+    VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 4,
+    VK_COMMAND_BUFFER_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkCommandBufferUsageFlagBits;
 typedef enum VkCompareOp {
     VK_COMPARE_OP_NEVER = 0,
@@ -357,13 +438,15 @@
     VK_COMPARE_OP_GREATER = 4,
     VK_COMPARE_OP_NOT_EQUAL = 5,
     VK_COMPARE_OP_GREATER_OR_EQUAL = 6,
-    VK_COMPARE_OP_ALWAYS = 7
+    VK_COMPARE_OP_ALWAYS = 7,
+    VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF
 } VkCompareOp;
 typedef enum VkCullModeFlagBits {
     VK_CULL_MODE_NONE = 0,
     VK_CULL_MODE_FRONT_BIT = 1,
     VK_CULL_MODE_BACK_BIT = 2,
-    VK_CULL_MODE_FRONT_AND_BACK = 0x00000003
+    VK_CULL_MODE_FRONT_AND_BACK = 0x00000003,
+    VK_CULL_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkCullModeFlagBits;
 typedef enum VkDescriptorType {
     VK_DESCRIPTOR_TYPE_SAMPLER = 0,
@@ -376,7 +459,9 @@
     VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7,
     VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
     VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
-    VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10
+    VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
+    VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK = 1000138000,
+    VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF
 } VkDescriptorType;
 typedef enum VkDynamicState {
     VK_DYNAMIC_STATE_VIEWPORT = 0,
@@ -388,15 +473,32 @@
     VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6,
     VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7,
     VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8,
-    VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1)
+    VK_DYNAMIC_STATE_CULL_MODE = 1000267000,
+    VK_DYNAMIC_STATE_FRONT_FACE = 1000267001,
+    VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY = 1000267002,
+    VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT = 1000267003,
+    VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT = 1000267004,
+    VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE = 1000267005,
+    VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE = 1000267006,
+    VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE = 1000267007,
+    VK_DYNAMIC_STATE_DEPTH_COMPARE_OP = 1000267008,
+    VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE = 1000267009,
+    VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE = 1000267010,
+    VK_DYNAMIC_STATE_STENCIL_OP = 1000267011,
+    VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE = 1000377001,
+    VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE = 1000377002,
+    VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE = 1000377004,
+    VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF
 } VkDynamicState;
 typedef enum VkFenceCreateFlagBits {
-    VK_FENCE_CREATE_SIGNALED_BIT = 1
+    VK_FENCE_CREATE_SIGNALED_BIT = 1,
+    VK_FENCE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkFenceCreateFlagBits;
 typedef enum VkPolygonMode {
     VK_POLYGON_MODE_FILL = 0,
     VK_POLYGON_MODE_LINE = 1,
-    VK_POLYGON_MODE_POINT = 2
+    VK_POLYGON_MODE_POINT = 2,
+    VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF
 } VkPolygonMode;
 typedef enum VkFormat {
     VK_FORMAT_UNDEFINED = 0,
@@ -617,7 +719,28 @@
     VK_FORMAT_G16_B16R16_2PLANE_420_UNORM = 1000156030,
     VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM = 1000156031,
     VK_FORMAT_G16_B16R16_2PLANE_422_UNORM = 1000156032,
-    VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033
+    VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM = 1000156033,
+    VK_FORMAT_G8_B8R8_2PLANE_444_UNORM = 1000330000,
+    VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16 = 1000330001,
+    VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16 = 1000330002,
+    VK_FORMAT_G16_B16R16_2PLANE_444_UNORM = 1000330003,
+    VK_FORMAT_A4R4G4B4_UNORM_PACK16 = 1000340000,
+    VK_FORMAT_A4B4G4R4_UNORM_PACK16 = 1000340001,
+    VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK = 1000066000,
+    VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK = 1000066001,
+    VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK = 1000066002,
+    VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK = 1000066003,
+    VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK = 1000066004,
+    VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK = 1000066005,
+    VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK = 1000066006,
+    VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK = 1000066007,
+    VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK = 1000066008,
+    VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK = 1000066009,
+    VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK = 1000066010,
+    VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK = 1000066011,
+    VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK = 1000066012,
+    VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK = 1000066013,
+    VK_FORMAT_MAX_ENUM = 0x7FFFFFFF
 } VkFormat;
 typedef enum VkFormatFeatureFlagBits {
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 1,
@@ -641,11 +764,14 @@
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 1048576,
     VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 2097152,
     VK_FORMAT_FEATURE_DISJOINT_BIT = 4194304,
-    VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 8388608
+    VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT = 8388608,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 65536,
+    VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkFormatFeatureFlagBits;
 typedef enum VkFrontFace {
     VK_FRONT_FACE_COUNTER_CLOCKWISE = 0,
-    VK_FRONT_FACE_CLOCKWISE = 1
+    VK_FRONT_FACE_CLOCKWISE = 1,
+    VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF
 } VkFrontFace;
 typedef enum VkImageAspectFlagBits {
     VK_IMAGE_ASPECT_COLOR_BIT = 1,
@@ -654,7 +780,9 @@
     VK_IMAGE_ASPECT_METADATA_BIT = 8,
     VK_IMAGE_ASPECT_PLANE_0_BIT = 16,
     VK_IMAGE_ASPECT_PLANE_1_BIT = 32,
-    VK_IMAGE_ASPECT_PLANE_2_BIT = 64
+    VK_IMAGE_ASPECT_PLANE_2_BIT = 64,
+    VK_IMAGE_ASPECT_NONE = 0,
+    VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkImageAspectFlagBits;
 typedef enum VkImageCreateFlagBits {
     VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 1,
@@ -668,7 +796,8 @@
     VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT = 128,
     VK_IMAGE_CREATE_EXTENDED_USAGE_BIT = 256,
     VK_IMAGE_CREATE_PROTECTED_BIT = 2048,
-    VK_IMAGE_CREATE_DISJOINT_BIT = 512
+    VK_IMAGE_CREATE_DISJOINT_BIT = 512,
+    VK_IMAGE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkImageCreateFlagBits;
 typedef enum VkImageLayout {
     VK_IMAGE_LAYOUT_UNDEFINED = 0,
@@ -682,16 +811,25 @@
     VK_IMAGE_LAYOUT_PREINITIALIZED = 8,
     VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL = 1000117000,
     VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL = 1000117001,
-    VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002
+    VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL = 1000241000,
+    VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_OPTIMAL = 1000241001,
+    VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL = 1000241002,
+    VK_IMAGE_LAYOUT_STENCIL_READ_ONLY_OPTIMAL = 1000241003,
+    VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL = 1000314000,
+    VK_IMAGE_LAYOUT_ATTACHMENT_OPTIMAL = 1000314001,
+    VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
+    VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF
 } VkImageLayout;
 typedef enum VkImageTiling {
     VK_IMAGE_TILING_OPTIMAL = 0,
-    VK_IMAGE_TILING_LINEAR = 1
+    VK_IMAGE_TILING_LINEAR = 1,
+    VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF
 } VkImageTiling;
 typedef enum VkImageType {
     VK_IMAGE_TYPE_1D = 0,
     VK_IMAGE_TYPE_2D = 1,
-    VK_IMAGE_TYPE_3D = 2
+    VK_IMAGE_TYPE_3D = 2,
+    VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF
 } VkImageType;
 typedef enum VkImageUsageFlagBits {
     VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 1,
@@ -701,9 +839,9 @@
     VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 16,
     VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 32,
     VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 64,
-    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 128
+    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 128,
+    VK_IMAGE_USAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkImageUsageFlagBits;
-
 typedef enum VkImageViewType {
     VK_IMAGE_VIEW_TYPE_1D = 0,
     VK_IMAGE_VIEW_TYPE_2D = 1,
@@ -711,15 +849,18 @@
     VK_IMAGE_VIEW_TYPE_CUBE = 3,
     VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4,
     VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5,
-    VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6
+    VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6,
+    VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF
 } VkImageViewType;
 typedef enum VkSharingMode {
     VK_SHARING_MODE_EXCLUSIVE = 0,
-    VK_SHARING_MODE_CONCURRENT = 1
+    VK_SHARING_MODE_CONCURRENT = 1,
+    VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF
 } VkSharingMode;
 typedef enum VkIndexType {
     VK_INDEX_TYPE_UINT16 = 0,
-    VK_INDEX_TYPE_UINT32 = 1
+    VK_INDEX_TYPE_UINT32 = 1,
+    VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF
 } VkIndexType;
 typedef enum VkLogicOp {
     VK_LOGIC_OP_CLEAR = 0,
@@ -737,11 +878,13 @@
     VK_LOGIC_OP_COPY_INVERTED = 12,
     VK_LOGIC_OP_OR_INVERTED = 13,
     VK_LOGIC_OP_NAND = 14,
-    VK_LOGIC_OP_SET = 15
+    VK_LOGIC_OP_SET = 15,
+    VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF
 } VkLogicOp;
 typedef enum VkMemoryHeapFlagBits {
     VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 1,
-    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 2
+    VK_MEMORY_HEAP_MULTI_INSTANCE_BIT = 2,
+    VK_MEMORY_HEAP_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkMemoryHeapFlagBits;
 typedef enum VkAccessFlagBits {
     VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 1,
@@ -760,7 +903,9 @@
     VK_ACCESS_HOST_READ_BIT = 8192,
     VK_ACCESS_HOST_WRITE_BIT = 16384,
     VK_ACCESS_MEMORY_READ_BIT = 32768,
-    VK_ACCESS_MEMORY_WRITE_BIT = 65536
+    VK_ACCESS_MEMORY_WRITE_BIT = 65536,
+    VK_ACCESS_NONE = 0,
+    VK_ACCESS_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkAccessFlagBits;
 typedef enum VkMemoryPropertyFlagBits {
     VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 1,
@@ -768,25 +913,32 @@
     VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 4,
     VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 8,
     VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 16,
-    VK_MEMORY_PROPERTY_PROTECTED_BIT = 32
+    VK_MEMORY_PROPERTY_PROTECTED_BIT = 32,
+    VK_MEMORY_PROPERTY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkMemoryPropertyFlagBits;
 typedef enum VkPhysicalDeviceType {
     VK_PHYSICAL_DEVICE_TYPE_OTHER = 0,
     VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1,
     VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2,
     VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3,
-    VK_PHYSICAL_DEVICE_TYPE_CPU = 4
+    VK_PHYSICAL_DEVICE_TYPE_CPU = 4,
+    VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF
 } VkPhysicalDeviceType;
 typedef enum VkPipelineBindPoint {
     VK_PIPELINE_BIND_POINT_GRAPHICS = 0,
-    VK_PIPELINE_BIND_POINT_COMPUTE = 1
+    VK_PIPELINE_BIND_POINT_COMPUTE = 1,
+    VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF
 } VkPipelineBindPoint;
 typedef enum VkPipelineCreateFlagBits {
     VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 1,
     VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 2,
     VK_PIPELINE_CREATE_DERIVATIVE_BIT = 4,
     VK_PIPELINE_CREATE_VIEW_INDEX_FROM_DEVICE_INDEX_BIT = 8,
-    VK_PIPELINE_CREATE_DISPATCH_BASE = 16
+    VK_PIPELINE_CREATE_DISPATCH_BASE_BIT = 16,
+    VK_PIPELINE_CREATE_DISPATCH_BASE = VK_PIPELINE_CREATE_DISPATCH_BASE_BIT,
+    VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT = 256,
+    VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT = 512,
+    VK_PIPELINE_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkPipelineCreateFlagBits;
 typedef enum VkPrimitiveTopology {
     VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0,
@@ -799,10 +951,12 @@
     VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7,
     VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8,
     VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9,
-    VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10
+    VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10,
+    VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF
 } VkPrimitiveTopology;
 typedef enum VkQueryControlFlagBits {
-    VK_QUERY_CONTROL_PRECISE_BIT = 1
+    VK_QUERY_CONTROL_PRECISE_BIT = 1,
+    VK_QUERY_CONTROL_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkQueryControlFlagBits;
 typedef enum VkQueryPipelineStatisticFlagBits {
     VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 1,
@@ -815,29 +969,34 @@
     VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 128,
     VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 256,
     VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 512,
-    VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 1024
+    VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 1024,
+    VK_QUERY_PIPELINE_STATISTIC_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkQueryPipelineStatisticFlagBits;
 typedef enum VkQueryResultFlagBits {
     VK_QUERY_RESULT_64_BIT = 1,
     VK_QUERY_RESULT_WAIT_BIT = 2,
     VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 4,
-    VK_QUERY_RESULT_PARTIAL_BIT = 8
+    VK_QUERY_RESULT_PARTIAL_BIT = 8,
+    VK_QUERY_RESULT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkQueryResultFlagBits;
 typedef enum VkQueryType {
     VK_QUERY_TYPE_OCCLUSION = 0,
     VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
-    VK_QUERY_TYPE_TIMESTAMP = 2
+    VK_QUERY_TYPE_TIMESTAMP = 2,
+    VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF
 } VkQueryType;
 typedef enum VkQueueFlagBits {
     VK_QUEUE_GRAPHICS_BIT = 1,
     VK_QUEUE_COMPUTE_BIT = 2,
     VK_QUEUE_TRANSFER_BIT = 4,
     VK_QUEUE_SPARSE_BINDING_BIT = 8,
-    VK_QUEUE_PROTECTED_BIT = 16
+    VK_QUEUE_PROTECTED_BIT = 16,
+    VK_QUEUE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkQueueFlagBits;
 typedef enum VkSubpassContents {
     VK_SUBPASS_CONTENTS_INLINE = 0,
-    VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1
+    VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1,
+    VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF
 } VkSubpassContents;
 typedef enum VkResult {
     VK_SUCCESS = 0,
@@ -858,13 +1017,18 @@
     VK_ERROR_TOO_MANY_OBJECTS = -10,
     VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
     VK_ERROR_FRAGMENTED_POOL = -12,
+    VK_ERROR_UNKNOWN = -13,
     VK_ERROR_OUT_OF_POOL_MEMORY = -1000069000,
     VK_ERROR_INVALID_EXTERNAL_HANDLE = -1000072003,
+    VK_ERROR_FRAGMENTATION = -1000161000,
+    VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS = -1000257000,
+    VK_PIPELINE_COMPILE_REQUIRED = 1000297000,
     VK_ERROR_SURFACE_LOST_KHR = -1000000000,
     VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
     VK_SUBOPTIMAL_KHR = 1000001003,
     VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
-    VK_ERROR_VALIDATION_FAILED_EXT = -1000011001
+    VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
+    VK_RESULT_MAX_ENUM = 0x7FFFFFFF
 } VkResult;
 typedef enum VkShaderStageFlagBits {
     VK_SHADER_STAGE_VERTEX_BIT = 1,
@@ -874,15 +1038,19 @@
     VK_SHADER_STAGE_FRAGMENT_BIT = 16,
     VK_SHADER_STAGE_COMPUTE_BIT = 32,
     VK_SHADER_STAGE_ALL_GRAPHICS = 0x0000001F,
-    VK_SHADER_STAGE_ALL = 0x7FFFFFFF
+    VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
+    VK_SHADER_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkShaderStageFlagBits;
 typedef enum VkSparseMemoryBindFlagBits {
-    VK_SPARSE_MEMORY_BIND_METADATA_BIT = 1
+    VK_SPARSE_MEMORY_BIND_METADATA_BIT = 1,
+    VK_SPARSE_MEMORY_BIND_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkSparseMemoryBindFlagBits;
 typedef enum VkStencilFaceFlagBits {
     VK_STENCIL_FACE_FRONT_BIT = 1,
     VK_STENCIL_FACE_BACK_BIT = 2,
-    VK_STENCIL_FRONT_AND_BACK = 0x00000003
+    VK_STENCIL_FACE_FRONT_AND_BACK = 0x00000003,
+    VK_STENCIL_FRONT_AND_BACK = VK_STENCIL_FACE_FRONT_AND_BACK,
+    VK_STENCIL_FACE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkStencilFaceFlagBits;
 typedef enum VkStencilOp {
     VK_STENCIL_OP_KEEP = 0,
@@ -892,7 +1060,8 @@
     VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4,
     VK_STENCIL_OP_INVERT = 5,
     VK_STENCIL_OP_INCREMENT_AND_WRAP = 6,
-    VK_STENCIL_OP_DECREMENT_AND_WRAP = 7
+    VK_STENCIL_OP_DECREMENT_AND_WRAP = 7,
+    VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF
 } VkStencilOp;
 typedef enum VkStructureType {
     VK_STRUCTURE_TYPE_APPLICATION_INFO = 0,
@@ -1011,6 +1180,108 @@
     VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT = 1000168001,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES = 1000063000,
     VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES = 49,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES = 50,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES = 51,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES = 52,
+    VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO = 1000147000,
+    VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2 = 1000109000,
+    VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2 = 1000109001,
+    VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2 = 1000109002,
+    VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2 = 1000109003,
+    VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2 = 1000109004,
+    VK_STRUCTURE_TYPE_SUBPASS_BEGIN_INFO = 1000109005,
+    VK_STRUCTURE_TYPE_SUBPASS_END_INFO = 1000109006,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES = 1000177000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES = 1000196000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES = 1000180000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES = 1000082000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES = 1000197000,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO = 1000161000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES = 1000161001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES = 1000161002,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO = 1000161003,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_LAYOUT_SUPPORT = 1000161004,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES = 1000199000,
+    VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE = 1000199001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES = 1000221000,
+    VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO = 1000246000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES = 1000130000,
+    VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO = 1000130001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES = 1000211000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGELESS_FRAMEBUFFER_FEATURES = 1000108000,
+    VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENTS_CREATE_INFO = 1000108001,
+    VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO = 1000108002,
+    VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO = 1000108003,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES = 1000253000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES = 1000175000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SEPARATE_DEPTH_STENCIL_LAYOUTS_FEATURES = 1000241000,
+    VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_STENCIL_LAYOUT = 1000241001,
+    VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_STENCIL_LAYOUT = 1000241002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES = 1000261000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES = 1000207000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES = 1000207001,
+    VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO = 1000207002,
+    VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO = 1000207003,
+    VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO = 1000207004,
+    VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO = 1000207005,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES = 1000257000,
+    VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO = 1000244001,
+    VK_STRUCTURE_TYPE_BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO = 1000257002,
+    VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO = 1000257003,
+    VK_STRUCTURE_TYPE_DEVICE_MEMORY_OPAQUE_CAPTURE_ADDRESS_INFO = 1000257004,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES = 53,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES = 54,
+    VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO = 1000192000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES = 1000215000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TOOL_PROPERTIES = 1000245000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES = 1000276000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES = 1000295000,
+    VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO = 1000295001,
+    VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO = 1000295002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES = 1000297000,
+    VK_STRUCTURE_TYPE_MEMORY_BARRIER_2 = 1000314000,
+    VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER_2 = 1000314001,
+    VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 = 1000314002,
+    VK_STRUCTURE_TYPE_DEPENDENCY_INFO = 1000314003,
+    VK_STRUCTURE_TYPE_SUBMIT_INFO_2 = 1000314004,
+    VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO = 1000314005,
+    VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO = 1000314006,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES = 1000314007,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ZERO_INITIALIZE_WORKGROUP_MEMORY_FEATURES = 1000325000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES = 1000335000,
+    VK_STRUCTURE_TYPE_COPY_BUFFER_INFO_2 = 1000337000,
+    VK_STRUCTURE_TYPE_COPY_IMAGE_INFO_2 = 1000337001,
+    VK_STRUCTURE_TYPE_COPY_BUFFER_TO_IMAGE_INFO_2 = 1000337002,
+    VK_STRUCTURE_TYPE_COPY_IMAGE_TO_BUFFER_INFO_2 = 1000337003,
+    VK_STRUCTURE_TYPE_BLIT_IMAGE_INFO_2 = 1000337004,
+    VK_STRUCTURE_TYPE_RESOLVE_IMAGE_INFO_2 = 1000337005,
+    VK_STRUCTURE_TYPE_BUFFER_COPY_2 = 1000337006,
+    VK_STRUCTURE_TYPE_IMAGE_COPY_2 = 1000337007,
+    VK_STRUCTURE_TYPE_IMAGE_BLIT_2 = 1000337008,
+    VK_STRUCTURE_TYPE_BUFFER_IMAGE_COPY_2 = 1000337009,
+    VK_STRUCTURE_TYPE_IMAGE_RESOLVE_2 = 1000337010,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES = 1000225000,
+    VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO = 1000225001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES = 1000225002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES = 1000138000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES = 1000138001,
+    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK = 1000138002,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO = 1000138003,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXTURE_COMPRESSION_ASTC_HDR_FEATURES = 1000066000,
+    VK_STRUCTURE_TYPE_RENDERING_INFO = 1000044000,
+    VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO = 1000044001,
+    VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO = 1000044002,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES = 1000044003,
+    VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO = 1000044004,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_FEATURES = 1000280000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES = 1000280001,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES = 1000281001,
+    VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_3 = 1000360000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES = 1000413000,
+    VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES = 1000413001,
+    VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS = 1000413002,
+    VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS = 1000413003,
     VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000,
     VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001,
     VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR = 1000060007,
@@ -1020,35 +1291,43 @@
     VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_INFO_KHR = 1000060011,
     VK_STRUCTURE_TYPE_DEVICE_GROUP_SWAPCHAIN_CREATE_INFO_KHR = 1000060012,
     VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT = 1000011000,
-    VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT
+    VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
+    VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
 } VkStructureType;
 typedef enum VkSystemAllocationScope {
     VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0,
     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1,
     VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2,
     VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3,
-    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4
+    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4,
+    VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF
 } VkSystemAllocationScope;
 typedef enum VkInternalAllocationType {
-    VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0
+    VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0,
+    VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF
 } VkInternalAllocationType;
 typedef enum VkSamplerAddressMode {
     VK_SAMPLER_ADDRESS_MODE_REPEAT = 0,
     VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1,
     VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2,
-    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3
+    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3,
+    VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4,
+    VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF
 } VkSamplerAddressMode;
 typedef enum VkFilter {
     VK_FILTER_NEAREST = 0,
-    VK_FILTER_LINEAR = 1
+    VK_FILTER_LINEAR = 1,
+    VK_FILTER_MAX_ENUM = 0x7FFFFFFF
 } VkFilter;
 typedef enum VkSamplerMipmapMode {
     VK_SAMPLER_MIPMAP_MODE_NEAREST = 0,
-    VK_SAMPLER_MIPMAP_MODE_LINEAR = 1
+    VK_SAMPLER_MIPMAP_MODE_LINEAR = 1,
+    VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF
 } VkSamplerMipmapMode;
 typedef enum VkVertexInputRate {
     VK_VERTEX_INPUT_RATE_VERTEX = 0,
-    VK_VERTEX_INPUT_RATE_INSTANCE = 1
+    VK_VERTEX_INPUT_RATE_INSTANCE = 1,
+    VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF
 } VkVertexInputRate;
 typedef enum VkPipelineStageFlagBits {
     VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 1,
@@ -1067,12 +1346,15 @@
     VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 8192,
     VK_PIPELINE_STAGE_HOST_BIT = 16384,
     VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 32768,
-    VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 65536
+    VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 65536,
+    VK_PIPELINE_STAGE_NONE = 0,
+    VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkPipelineStageFlagBits;
 typedef enum VkSparseImageFormatFlagBits {
     VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 1,
     VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 2,
-    VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 4
+    VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 4,
+    VK_SPARSE_IMAGE_FORMAT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkSparseImageFormatFlagBits;
 typedef enum VkSampleCountFlagBits {
     VK_SAMPLE_COUNT_1_BIT = 1,
@@ -1081,18 +1363,23 @@
     VK_SAMPLE_COUNT_8_BIT = 8,
     VK_SAMPLE_COUNT_16_BIT = 16,
     VK_SAMPLE_COUNT_32_BIT = 32,
-    VK_SAMPLE_COUNT_64_BIT = 64
+    VK_SAMPLE_COUNT_64_BIT = 64,
+    VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkSampleCountFlagBits;
 typedef enum VkAttachmentDescriptionFlagBits {
-    VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 1
+    VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 1,
+    VK_ATTACHMENT_DESCRIPTION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkAttachmentDescriptionFlagBits;
 typedef enum VkDescriptorPoolCreateFlagBits {
-    VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 1
+    VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 1,
+    VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT = 2,
+    VK_DESCRIPTOR_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkDescriptorPoolCreateFlagBits;
 typedef enum VkDependencyFlagBits {
     VK_DEPENDENCY_BY_REGION_BIT = 1,
     VK_DEPENDENCY_DEVICE_GROUP_BIT = 4,
-    VK_DEPENDENCY_VIEW_LOCAL_BIT = 2
+    VK_DEPENDENCY_VIEW_LOCAL_BIT = 2,
+    VK_DEPENDENCY_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkDependencyFlagBits;
 typedef enum VkObjectType {
     VK_OBJECT_TYPE_UNKNOWN = 0,
@@ -1123,33 +1410,252 @@
     VK_OBJECT_TYPE_COMMAND_POOL = 25,
     VK_OBJECT_TYPE_SAMPLER_YCBCR_CONVERSION = 1000156000,
     VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE = 1000085000,
+    VK_OBJECT_TYPE_PRIVATE_DATA_SLOT = 1000295000,
     VK_OBJECT_TYPE_SURFACE_KHR = 1000000000,
     VK_OBJECT_TYPE_SWAPCHAIN_KHR = 1000001000,
-    VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000
+    VK_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT = 1000011000,
+    VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
 } VkObjectType;
+typedef enum VkEventCreateFlagBits {
+    VK_EVENT_CREATE_DEVICE_ONLY_BIT = 1,
+    VK_EVENT_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkEventCreateFlagBits;
 typedef enum VkDescriptorUpdateTemplateType {
-    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0
+    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET = 0,
+    VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_MAX_ENUM = 0x7FFFFFFF
 } VkDescriptorUpdateTemplateType;
-
 typedef enum VkPointClippingBehavior {
     VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES = 0,
-    VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1
+    VK_POINT_CLIPPING_BEHAVIOR_USER_CLIP_PLANES_ONLY = 1,
+    VK_POINT_CLIPPING_BEHAVIOR_MAX_ENUM = 0x7FFFFFFF
 } VkPointClippingBehavior;
+typedef enum VkResolveModeFlagBits {
+    VK_RESOLVE_MODE_NONE = 0,
+    VK_RESOLVE_MODE_SAMPLE_ZERO_BIT = 1,
+    VK_RESOLVE_MODE_AVERAGE_BIT = 2,
+    VK_RESOLVE_MODE_MIN_BIT = 4,
+    VK_RESOLVE_MODE_MAX_BIT = 8,
+    VK_RESOLVE_MODE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkResolveModeFlagBits;
+typedef enum VkDescriptorBindingFlagBits {
+    VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT = 1,
+    VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT = 2,
+    VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT = 4,
+    VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT = 8,
+    VK_DESCRIPTOR_BINDING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorBindingFlagBits;
+typedef enum VkSemaphoreType {
+    VK_SEMAPHORE_TYPE_BINARY = 0,
+    VK_SEMAPHORE_TYPE_TIMELINE = 1,
+    VK_SEMAPHORE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkSemaphoreType;
+typedef enum VkPipelineCreationFeedbackFlagBits {
+    VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT = 1,
+    VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT,
+    VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT = 2,
+    VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT,
+    VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT = 4,
+    VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT = VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT,
+    VK_PIPELINE_CREATION_FEEDBACK_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineCreationFeedbackFlagBits;
+typedef enum VkSemaphoreWaitFlagBits {
+    VK_SEMAPHORE_WAIT_ANY_BIT = 1,
+    VK_SEMAPHORE_WAIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSemaphoreWaitFlagBits;
+typedef enum VkToolPurposeFlagBits {
+    VK_TOOL_PURPOSE_VALIDATION_BIT = 1,
+    VK_TOOL_PURPOSE_VALIDATION_BIT_EXT = VK_TOOL_PURPOSE_VALIDATION_BIT,
+    VK_TOOL_PURPOSE_PROFILING_BIT = 2,
+    VK_TOOL_PURPOSE_PROFILING_BIT_EXT = VK_TOOL_PURPOSE_PROFILING_BIT,
+    VK_TOOL_PURPOSE_TRACING_BIT = 4,
+    VK_TOOL_PURPOSE_TRACING_BIT_EXT = VK_TOOL_PURPOSE_TRACING_BIT,
+    VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT = 8,
+    VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT_EXT = VK_TOOL_PURPOSE_ADDITIONAL_FEATURES_BIT,
+    VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT = 16,
+    VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT_EXT = VK_TOOL_PURPOSE_MODIFYING_FEATURES_BIT,
+    VK_TOOL_PURPOSE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkToolPurposeFlagBits;
+typedef uint64_t VkAccessFlagBits2;
+static const VkAccessFlagBits2 VK_ACCESS_2_NONE = 0;
+static const VkAccessFlagBits2 VK_ACCESS_2_NONE_KHR = 0;
+static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT = 1;
+static const VkAccessFlagBits2 VK_ACCESS_2_INDIRECT_COMMAND_READ_BIT_KHR = 1;
+static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT = 2;
+static const VkAccessFlagBits2 VK_ACCESS_2_INDEX_READ_BIT_KHR = 2;
+static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT = 4;
+static const VkAccessFlagBits2 VK_ACCESS_2_VERTEX_ATTRIBUTE_READ_BIT_KHR = 4;
+static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT = 8;
+static const VkAccessFlagBits2 VK_ACCESS_2_UNIFORM_READ_BIT_KHR = 8;
+static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT = 16;
+static const VkAccessFlagBits2 VK_ACCESS_2_INPUT_ATTACHMENT_READ_BIT_KHR = 16;
+static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT = 32;
+static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_READ_BIT_KHR = 32;
+static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT = 64;
+static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_WRITE_BIT_KHR = 64;
+static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT = 128;
+static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_READ_BIT_KHR = 128;
+static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT = 256;
+static const VkAccessFlagBits2 VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT_KHR = 256;
+static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 512;
+static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_READ_BIT_KHR = 512;
+static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 1024;
+static const VkAccessFlagBits2 VK_ACCESS_2_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT_KHR = 1024;
+static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT = 2048;
+static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_READ_BIT_KHR = 2048;
+static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT = 4096;
+static const VkAccessFlagBits2 VK_ACCESS_2_TRANSFER_WRITE_BIT_KHR = 4096;
+static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT = 8192;
+static const VkAccessFlagBits2 VK_ACCESS_2_HOST_READ_BIT_KHR = 8192;
+static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT = 16384;
+static const VkAccessFlagBits2 VK_ACCESS_2_HOST_WRITE_BIT_KHR = 16384;
+static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT = 32768;
+static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_READ_BIT_KHR = 32768;
+static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT = 65536;
+static const VkAccessFlagBits2 VK_ACCESS_2_MEMORY_WRITE_BIT_KHR = 65536;
+static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT = 4294967296;
+static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_SAMPLED_READ_BIT_KHR = 4294967296;
+static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT = 8589934592;
+static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_READ_BIT_KHR = 8589934592;
+static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT = 17179869184;
+static const VkAccessFlagBits2 VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT_KHR = 17179869184;
+
+typedef uint64_t VkPipelineStageFlagBits2;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE = 0;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_NONE_KHR = 0;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT = 1;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT_KHR = 1;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT = 2;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT_KHR = 2;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT = 4;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT_KHR = 4;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT = 8;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT_KHR = 8;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT = 16;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT_KHR = 16;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT = 32;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT_KHR = 32;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT = 64;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT_KHR = 64;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT = 128;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT_KHR = 128;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT = 256;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_EARLY_FRAGMENT_TESTS_BIT_KHR = 256;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT = 512;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_LATE_FRAGMENT_TESTS_BIT_KHR = 512;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT = 1024;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR = 1024;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT = 2048;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COMPUTE_SHADER_BIT_KHR = 2048;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT = 4096;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_TRANSFER_BIT_KHR = 4096;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT = 4096;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_TRANSFER_BIT_KHR = 4096;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT = 8192;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT_KHR = 8192;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT = 16384;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_HOST_BIT_KHR = 16384;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT = 32768;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT_KHR = 32768;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT = 65536;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR = 65536;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT = 4294967296;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_COPY_BIT_KHR = 4294967296;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT = 8589934592;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_RESOLVE_BIT_KHR = 8589934592;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT = 17179869184;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_BLIT_BIT_KHR = 17179869184;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT = 34359738368;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_CLEAR_BIT_KHR = 34359738368;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT = 68719476736;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT_KHR = 68719476736;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT = 137438953472;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT_KHR = 137438953472;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT = 274877906944;
+static const VkPipelineStageFlagBits2 VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT_KHR = 274877906944;
+
+typedef uint64_t VkFormatFeatureFlagBits2;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT = 1;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT_KHR = 1;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT = 2;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT_KHR = 2;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT = 4;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT_KHR = 4;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT = 8;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT_KHR = 8;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT = 16;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT_KHR = 16;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 32;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT_KHR = 32;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT = 64;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT_KHR = 64;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT = 128;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT_KHR = 128;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT = 256;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT_KHR = 256;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT = 512;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT_KHR = 512;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT = 1024;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_SRC_BIT_KHR = 1024;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_DST_BIT = 2048;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_BLIT_DST_BIT_KHR = 2048;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 4096;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT_KHR = 4096;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT = 8192;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT = 8192;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT = 16384;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT_KHR = 16384;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT = 32768;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT_KHR = 32768;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT = 65536;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT_KHR = 65536;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT = 131072;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT_KHR = 131072;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT = 262144;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT_KHR = 262144;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT = 524288;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT_KHR = 524288;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT = 1048576;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT_KHR = 1048576;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT = 2097152;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT_KHR = 2097152;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DISJOINT_BIT = 4194304;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_DISJOINT_BIT_KHR = 4194304;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT = 8388608;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT_KHR = 8388608;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT = 2147483648;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR = 2147483648;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT = 4294967296;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR = 4294967296;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT = 8589934592;
+static const VkFormatFeatureFlagBits2 VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT_KHR = 8589934592;
+
+typedef enum VkRenderingFlagBits {
+    VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT = 1,
+    VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT,
+    VK_RENDERING_SUSPENDING_BIT = 2,
+    VK_RENDERING_SUSPENDING_BIT_KHR = VK_RENDERING_SUSPENDING_BIT,
+    VK_RENDERING_RESUMING_BIT = 4,
+    VK_RENDERING_RESUMING_BIT_KHR = VK_RENDERING_RESUMING_BIT,
+    VK_RENDERING_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkRenderingFlagBits;
 typedef enum VkColorSpaceKHR {
     VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,
-    VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
+    VK_COLORSPACE_SRGB_NONLINEAR_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+    VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF
 } VkColorSpaceKHR;
 typedef enum VkCompositeAlphaFlagBitsKHR {
     VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 1,
     VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 2,
     VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 4,
-    VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 8
+    VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 8,
+    VK_COMPOSITE_ALPHA_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
 } VkCompositeAlphaFlagBitsKHR;
 typedef enum VkPresentModeKHR {
     VK_PRESENT_MODE_IMMEDIATE_KHR = 0,
     VK_PRESENT_MODE_MAILBOX_KHR = 1,
     VK_PRESENT_MODE_FIFO_KHR = 2,
-    VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3
+    VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3,
+    VK_PRESENT_MODE_MAX_ENUM_KHR = 0x7FFFFFFF
 } VkPresentModeKHR;
 typedef enum VkSurfaceTransformFlagBitsKHR {
     VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 1,
@@ -1160,14 +1666,16 @@
     VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 32,
     VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 64,
     VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 128,
-    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 256
+    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 256,
+    VK_SURFACE_TRANSFORM_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
 } VkSurfaceTransformFlagBitsKHR;
 typedef enum VkDebugReportFlagBitsEXT {
     VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 1,
     VK_DEBUG_REPORT_WARNING_BIT_EXT = 2,
     VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 4,
     VK_DEBUG_REPORT_ERROR_BIT_EXT = 8,
-    VK_DEBUG_REPORT_DEBUG_BIT_EXT = 16
+    VK_DEBUG_REPORT_DEBUG_BIT_EXT = 16,
+    VK_DEBUG_REPORT_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
 } VkDebugReportFlagBitsEXT;
 typedef enum VkDebugReportObjectTypeEXT {
     VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0,
@@ -1202,12 +1710,11 @@
     VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_CALLBACK_EXT_EXT,
     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_VALIDATION_CACHE_EXT = VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT,
     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_DESCRIPTOR_UPDATE_TEMPLATE_EXT = 1000085000,
+    VK_DEBUG_REPORT_OBJECT_TYPE_MAX_ENUM_EXT = 0x7FFFFFFF
 } VkDebugReportObjectTypeEXT;
 typedef enum VkExternalMemoryHandleTypeFlagBits {
     VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT = 1,
@@ -1216,58 +1723,73 @@
     VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT = 8,
     VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT = 16,
     VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT = 32,
-    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 64
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT = 64,
+    VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkExternalMemoryHandleTypeFlagBits;
 typedef enum VkExternalMemoryFeatureFlagBits {
     VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT = 1,
     VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT = 2,
-    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 4
+    VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT = 4,
+    VK_EXTERNAL_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkExternalMemoryFeatureFlagBits;
 typedef enum VkExternalSemaphoreHandleTypeFlagBits {
     VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT = 1,
     VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 2,
     VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 4,
     VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT = 8,
-    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 16
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE_BIT = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D12_FENCE_BIT,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT = 16,
+    VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkExternalSemaphoreHandleTypeFlagBits;
 typedef enum VkExternalSemaphoreFeatureFlagBits {
     VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT = 1,
-    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 2
+    VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT = 2,
+    VK_EXTERNAL_SEMAPHORE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkExternalSemaphoreFeatureFlagBits;
 typedef enum VkSemaphoreImportFlagBits {
-    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 1
+    VK_SEMAPHORE_IMPORT_TEMPORARY_BIT = 1,
+    VK_SEMAPHORE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkSemaphoreImportFlagBits;
 typedef enum VkExternalFenceHandleTypeFlagBits {
     VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT = 1,
     VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_BIT = 2,
     VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT = 4,
-    VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 8
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT = 8,
+    VK_EXTERNAL_FENCE_HANDLE_TYPE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkExternalFenceHandleTypeFlagBits;
 typedef enum VkExternalFenceFeatureFlagBits {
     VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT = 1,
-    VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 2
+    VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT = 2,
+    VK_EXTERNAL_FENCE_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkExternalFenceFeatureFlagBits;
 typedef enum VkFenceImportFlagBits {
-    VK_FENCE_IMPORT_TEMPORARY_BIT = 1
+    VK_FENCE_IMPORT_TEMPORARY_BIT = 1,
+    VK_FENCE_IMPORT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkFenceImportFlagBits;
 typedef enum VkPeerMemoryFeatureFlagBits {
     VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT = 1,
     VK_PEER_MEMORY_FEATURE_COPY_DST_BIT = 2,
     VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT = 4,
-    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 8
+    VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT = 8,
+    VK_PEER_MEMORY_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkPeerMemoryFeatureFlagBits;
 typedef enum VkMemoryAllocateFlagBits {
-    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 1
+    VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT = 1,
+    VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT = 2,
+    VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT = 4,
+    VK_MEMORY_ALLOCATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkMemoryAllocateFlagBits;
 typedef enum VkDeviceGroupPresentModeFlagBitsKHR {
     VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR = 1,
     VK_DEVICE_GROUP_PRESENT_MODE_REMOTE_BIT_KHR = 2,
     VK_DEVICE_GROUP_PRESENT_MODE_SUM_BIT_KHR = 4,
-    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 8
+    VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_MULTI_DEVICE_BIT_KHR = 8,
+    VK_DEVICE_GROUP_PRESENT_MODE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
 } VkDeviceGroupPresentModeFlagBitsKHR;
 typedef enum VkSwapchainCreateFlagBitsKHR {
     VK_SWAPCHAIN_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_KHR = 1,
-    VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 2
+    VK_SWAPCHAIN_CREATE_PROTECTED_BIT_KHR = 2,
+    VK_SWAPCHAIN_CREATE_FLAG_BITS_MAX_ENUM_KHR = 0x7FFFFFFF
 } VkSwapchainCreateFlagBitsKHR;
 typedef enum VkSubgroupFeatureFlagBits {
     VK_SUBGROUP_FEATURE_BASIC_BIT = 1,
@@ -1277,32 +1799,84 @@
     VK_SUBGROUP_FEATURE_SHUFFLE_BIT = 16,
     VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT = 32,
     VK_SUBGROUP_FEATURE_CLUSTERED_BIT = 64,
-    VK_SUBGROUP_FEATURE_QUAD_BIT = 128
+    VK_SUBGROUP_FEATURE_QUAD_BIT = 128,
+    VK_SUBGROUP_FEATURE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
 } VkSubgroupFeatureFlagBits;
 typedef enum VkTessellationDomainOrigin {
     VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT = 0,
-    VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1
+    VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT = 1,
+    VK_TESSELLATION_DOMAIN_ORIGIN_MAX_ENUM = 0x7FFFFFFF
 } VkTessellationDomainOrigin;
 typedef enum VkSamplerYcbcrModelConversion {
     VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY = 0,
     VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY = 1,
     VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709 = 2,
     VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601 = 3,
-    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020 = 4,
+    VK_SAMPLER_YCBCR_MODEL_CONVERSION_MAX_ENUM = 0x7FFFFFFF
 } VkSamplerYcbcrModelConversion;
 typedef enum VkSamplerYcbcrRange {
     VK_SAMPLER_YCBCR_RANGE_ITU_FULL = 0,
-    VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1
+    VK_SAMPLER_YCBCR_RANGE_ITU_NARROW = 1,
+    VK_SAMPLER_YCBCR_RANGE_MAX_ENUM = 0x7FFFFFFF
 } VkSamplerYcbcrRange;
 typedef enum VkChromaLocation {
     VK_CHROMA_LOCATION_COSITED_EVEN = 0,
-    VK_CHROMA_LOCATION_MIDPOINT = 1
+    VK_CHROMA_LOCATION_MIDPOINT = 1,
+    VK_CHROMA_LOCATION_MAX_ENUM = 0x7FFFFFFF
 } VkChromaLocation;
+typedef enum VkSamplerReductionMode {
+    VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE = 0,
+    VK_SAMPLER_REDUCTION_MODE_MIN = 1,
+    VK_SAMPLER_REDUCTION_MODE_MAX = 2,
+    VK_SAMPLER_REDUCTION_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerReductionMode;
+typedef enum VkShaderFloatControlsIndependence {
+    VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_32_BIT_ONLY = 0,
+    VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL = 1,
+    VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE = 2,
+    VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_MAX_ENUM = 0x7FFFFFFF
+} VkShaderFloatControlsIndependence;
+typedef enum VkSubmitFlagBits {
+    VK_SUBMIT_PROTECTED_BIT = 1,
+    VK_SUBMIT_PROTECTED_BIT_KHR = VK_SUBMIT_PROTECTED_BIT,
+    VK_SUBMIT_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VkSubmitFlagBits;
 typedef enum VkVendorId {
     VK_VENDOR_ID_VIV = 0x10001,
     VK_VENDOR_ID_VSI = 0x10002,
-    VK_VENDOR_ID_KAZAN = 0x10003
+    VK_VENDOR_ID_KAZAN = 0x10003,
+    VK_VENDOR_ID_CODEPLAY = 0x10004,
+    VK_VENDOR_ID_MESA = 0x10005,
+    VK_VENDOR_ID_POCL = 0x10006,
+    VK_VENDOR_ID_MAX_ENUM = 0x7FFFFFFF
 } VkVendorId;
+typedef enum VkDriverId {
+    VK_DRIVER_ID_AMD_PROPRIETARY = 1,
+    VK_DRIVER_ID_AMD_OPEN_SOURCE = 2,
+    VK_DRIVER_ID_MESA_RADV = 3,
+    VK_DRIVER_ID_NVIDIA_PROPRIETARY = 4,
+    VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS = 5,
+    VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA = 6,
+    VK_DRIVER_ID_IMAGINATION_PROPRIETARY = 7,
+    VK_DRIVER_ID_QUALCOMM_PROPRIETARY = 8,
+    VK_DRIVER_ID_ARM_PROPRIETARY = 9,
+    VK_DRIVER_ID_GOOGLE_SWIFTSHADER = 10,
+    VK_DRIVER_ID_GGP_PROPRIETARY = 11,
+    VK_DRIVER_ID_BROADCOM_PROPRIETARY = 12,
+    VK_DRIVER_ID_MESA_LLVMPIPE = 13,
+    VK_DRIVER_ID_MOLTENVK = 14,
+    VK_DRIVER_ID_COREAVI_PROPRIETARY = 15,
+    VK_DRIVER_ID_JUICE_PROPRIETARY = 16,
+    VK_DRIVER_ID_VERISILICON_PROPRIETARY = 17,
+    VK_DRIVER_ID_MESA_TURNIP = 18,
+    VK_DRIVER_ID_MESA_V3DV = 19,
+    VK_DRIVER_ID_MESA_PANVK = 20,
+    VK_DRIVER_ID_SAMSUNG_PROPRIETARY = 21,
+    VK_DRIVER_ID_MESA_VENUS = 22,
+    VK_DRIVER_ID_MESA_DOZEN = 23,
+    VK_DRIVER_ID_MAX_ENUM = 0x7FFFFFFF
+} VkDriverId;
 typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)(
     void*                                       pUserData,
     size_t                                      size,
@@ -1332,28 +1906,34 @@
     VkStructureType   sType;
     struct  VkBaseOutStructure *  pNext;
 } VkBaseOutStructure;
+
 typedef struct VkBaseInStructure {
     VkStructureType   sType;
     const struct  VkBaseInStructure *  pNext;
 } VkBaseInStructure;
+
 typedef struct VkOffset2D {
     int32_t          x;
     int32_t          y;
 } VkOffset2D;
+
 typedef struct VkOffset3D {
     int32_t          x;
     int32_t          y;
     int32_t          z;
 } VkOffset3D;
+
 typedef struct VkExtent2D {
     uint32_t          width;
     uint32_t          height;
 } VkExtent2D;
+
 typedef struct VkExtent3D {
     uint32_t          width;
     uint32_t          height;
     uint32_t          depth;
 } VkExtent3D;
+
 typedef struct VkViewport {
     float   x;
     float   y;
@@ -1362,31 +1942,37 @@
     float                         minDepth;
     float                         maxDepth;
 } VkViewport;
+
 typedef struct VkRect2D {
     VkOffset2D       offset;
     VkExtent2D       extent;
 } VkRect2D;
+
 typedef struct VkClearRect {
     VkRect2D         rect;
     uint32_t         baseArrayLayer;
     uint32_t         layerCount;
 } VkClearRect;
+
 typedef struct VkComponentMapping {
     VkComponentSwizzle   r;
     VkComponentSwizzle   g;
     VkComponentSwizzle   b;
     VkComponentSwizzle   a;
 } VkComponentMapping;
+
 typedef struct VkExtensionProperties {
     char              extensionName [ VK_MAX_EXTENSION_NAME_SIZE ];
     uint32_t          specVersion;
 } VkExtensionProperties;
+
 typedef struct VkLayerProperties {
     char              layerName [ VK_MAX_EXTENSION_NAME_SIZE ];
     uint32_t          specVersion;
     uint32_t          implementationVersion;
     char              description [ VK_MAX_DESCRIPTION_SIZE ];
 } VkLayerProperties;
+
 typedef struct VkApplicationInfo {
     VkStructureType   sType;
     const  void *      pNext;
@@ -1396,6 +1982,7 @@
     uint32_t          engineVersion;
     uint32_t          apiVersion;
 } VkApplicationInfo;
+
 typedef struct VkAllocationCallbacks {
     void *            pUserData;
     PFN_vkAllocationFunction     pfnAllocation;
@@ -1404,11 +1991,13 @@
     PFN_vkInternalAllocationNotification   pfnInternalAllocation;
     PFN_vkInternalFreeNotification   pfnInternalFree;
 } VkAllocationCallbacks;
+
 typedef struct VkDescriptorImageInfo {
     VkSampler         sampler;
     VkImageView       imageView;
     VkImageLayout     imageLayout;
 } VkDescriptorImageInfo;
+
 typedef struct VkCopyDescriptorSet {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1420,10 +2009,12 @@
     uint32_t                 dstArrayElement;
     uint32_t                 descriptorCount;
 } VkCopyDescriptorSet;
+
 typedef struct VkDescriptorPoolSize {
     VkDescriptorType         type;
     uint32_t                 descriptorCount;
 } VkDescriptorPoolSize;
+
 typedef struct VkDescriptorSetAllocateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1431,28 +2022,33 @@
     uint32_t                 descriptorSetCount;
     const  VkDescriptorSetLayout *  pSetLayouts;
 } VkDescriptorSetAllocateInfo;
+
 typedef struct VkSpecializationMapEntry {
     uint32_t                       constantID;
     uint32_t                       offset;
     size_t   size;
 } VkSpecializationMapEntry;
+
 typedef struct VkSpecializationInfo {
     uint32_t                 mapEntryCount;
     const  VkSpecializationMapEntry *  pMapEntries;
     size_t                   dataSize;
     const  void *             pData;
 } VkSpecializationInfo;
+
 typedef struct VkVertexInputBindingDescription {
     uint32_t                 binding;
     uint32_t                 stride;
     VkVertexInputRate        inputRate;
 } VkVertexInputBindingDescription;
+
 typedef struct VkVertexInputAttributeDescription {
     uint32_t                 location;
     uint32_t                 binding;
     VkFormat                 format;
     uint32_t                 offset;
 } VkVertexInputAttributeDescription;
+
 typedef struct VkStencilOpState {
     VkStencilOp              failOp;
     VkStencilOp              passOp;
@@ -1462,6 +2058,15 @@
     uint32_t                 writeMask;
     uint32_t                 reference;
 } VkStencilOpState;
+
+typedef struct VkPipelineCacheHeaderVersionOne {
+    uint32_t                 headerSize;
+    VkPipelineCacheHeaderVersion   headerVersion;
+    uint32_t                 vendorID;
+    uint32_t                 deviceID;
+    uint8_t                  pipelineCacheUUID [ VK_UUID_SIZE ];
+} VkPipelineCacheHeaderVersionOne;
+
 typedef struct VkCommandBufferAllocateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1469,29 +2074,35 @@
     VkCommandBufferLevel     level;
     uint32_t                 commandBufferCount;
 } VkCommandBufferAllocateInfo;
+
 typedef union VkClearColorValue {
     float                    float32 [4];
     int32_t                  int32 [4];
     uint32_t                 uint32 [4];
 } VkClearColorValue;
+
 typedef struct VkClearDepthStencilValue {
     float                    depth;
     uint32_t                 stencil;
 } VkClearDepthStencilValue;
+
 typedef union VkClearValue {
     VkClearColorValue        color;
     VkClearDepthStencilValue   depthStencil;
 } VkClearValue;
+
 typedef struct VkAttachmentReference {
     uint32_t                 attachment;
     VkImageLayout            layout;
 } VkAttachmentReference;
+
 typedef struct VkDrawIndirectCommand {
     uint32_t                         vertexCount;
     uint32_t                         instanceCount;
     uint32_t                         firstVertex;
     uint32_t   firstInstance;
 } VkDrawIndirectCommand;
+
 typedef struct VkDrawIndexedIndirectCommand {
     uint32_t                         indexCount;
     uint32_t                         instanceCount;
@@ -1499,15 +2110,18 @@
     int32_t                          vertexOffset;
     uint32_t   firstInstance;
 } VkDrawIndexedIndirectCommand;
+
 typedef struct VkDispatchIndirectCommand {
     uint32_t   x;
     uint32_t   y;
     uint32_t   z;
 } VkDispatchIndirectCommand;
+
 typedef struct VkSurfaceFormatKHR {
     VkFormat                           format;
     VkColorSpaceKHR                    colorSpace;
 } VkSurfaceFormatKHR;
+
 typedef struct VkPresentInfoKHR {
     VkStructureType   sType;
     const  void *   pNext;
@@ -1518,27 +2132,54 @@
     const  uint32_t *  pImageIndices;
     VkResult *  pResults;
 } VkPresentInfoKHR;
+
+typedef struct VkDevicePrivateDataCreateInfo {
+    VkStructureType   sType;
+    const  void *                             pNext;
+    uint32_t                                 privateDataSlotRequestCount;
+} VkDevicePrivateDataCreateInfo;
+
+typedef struct VkConformanceVersion {
+    uint8_t                            major;
+    uint8_t                            minor;
+    uint8_t                            subminor;
+    uint8_t                            patch;
+} VkConformanceVersion;
+
+typedef struct VkPhysicalDeviceDriverProperties {
+    VkStructureType   sType;
+    void *                             pNext;
+    VkDriverId                    driverID;
+    char                          driverName [ VK_MAX_DRIVER_NAME_SIZE ];
+    char                          driverInfo [ VK_MAX_DRIVER_INFO_SIZE ];
+    VkConformanceVersion          conformanceVersion;
+} VkPhysicalDeviceDriverProperties;
+
 typedef struct VkPhysicalDeviceExternalImageFormatInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkExternalMemoryHandleTypeFlagBits   handleType;
 } VkPhysicalDeviceExternalImageFormatInfo;
+
 typedef struct VkPhysicalDeviceExternalSemaphoreInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkExternalSemaphoreHandleTypeFlagBits   handleType;
 } VkPhysicalDeviceExternalSemaphoreInfo;
+
 typedef struct VkPhysicalDeviceExternalFenceInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkExternalFenceHandleTypeFlagBits   handleType;
 } VkPhysicalDeviceExternalFenceInfo;
+
 typedef struct VkPhysicalDeviceMultiviewProperties {
     VkStructureType   sType;
     void *                             pNext;
     uint32_t                           maxMultiviewViewCount;
     uint32_t                           maxMultiviewInstanceIndex;
 } VkPhysicalDeviceMultiviewProperties;
+
 typedef struct VkRenderPassMultiviewCreateInfo {
     VkStructureType          sType;
     const  void *             pNext;
@@ -1549,12 +2190,14 @@
     uint32_t                 correlationMaskCount;
     const  uint32_t *  pCorrelationMasks;
 } VkRenderPassMultiviewCreateInfo;
+
 typedef struct VkBindBufferMemoryDeviceGroupInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     uint32_t           deviceIndexCount;
     const  uint32_t *   pDeviceIndices;
 } VkBindBufferMemoryDeviceGroupInfo;
+
 typedef struct VkBindImageMemoryDeviceGroupInfo {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -1563,6 +2206,7 @@
     uint32_t           splitInstanceBindRegionCount;
     const  VkRect2D *   pSplitInstanceBindRegions;
 } VkBindImageMemoryDeviceGroupInfo;
+
 typedef struct VkDeviceGroupRenderPassBeginInfo {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -1570,11 +2214,13 @@
     uint32_t           deviceRenderAreaCount;
     const  VkRect2D *   pDeviceRenderAreas;
 } VkDeviceGroupRenderPassBeginInfo;
+
 typedef struct VkDeviceGroupCommandBufferBeginInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     uint32_t                           deviceMask;
 } VkDeviceGroupCommandBufferBeginInfo;
+
 typedef struct VkDeviceGroupSubmitInfo {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -1585,23 +2231,27 @@
     uint32_t           signalSemaphoreCount;
     const  uint32_t *   pSignalSemaphoreDeviceIndices;
 } VkDeviceGroupSubmitInfo;
+
 typedef struct VkDeviceGroupBindSparseInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     uint32_t                           resourceDeviceIndex;
     uint32_t                           memoryDeviceIndex;
 } VkDeviceGroupBindSparseInfo;
+
 typedef struct VkImageSwapchainCreateInfoKHR {
     VkStructureType   sType;
     const  void *                       pNext;
     VkSwapchainKHR     swapchain;
 } VkImageSwapchainCreateInfoKHR;
+
 typedef struct VkBindImageMemorySwapchainInfoKHR {
     VkStructureType   sType;
     const  void *                       pNext;
     VkSwapchainKHR   swapchain;
     uint32_t                           imageIndex;
 } VkBindImageMemorySwapchainInfoKHR;
+
 typedef struct VkAcquireNextImageInfoKHR {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -1611,6 +2261,7 @@
     VkFence   fence;
     uint32_t                           deviceMask;
 } VkAcquireNextImageInfoKHR;
+
 typedef struct VkDeviceGroupPresentInfoKHR {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -1618,12 +2269,14 @@
     const  uint32_t *  pDeviceMasks;
     VkDeviceGroupPresentModeFlagBitsKHR   mode;
 } VkDeviceGroupPresentInfoKHR;
+
 typedef struct VkDeviceGroupDeviceCreateInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     uint32_t                           physicalDeviceCount;
     const  VkPhysicalDevice *   pPhysicalDevices;
 } VkDeviceGroupDeviceCreateInfo;
+
 typedef struct VkDescriptorUpdateTemplateEntry {
     uint32_t                           dstBinding;
     uint32_t                           dstArrayElement;
@@ -1632,61 +2285,243 @@
     size_t                             offset;
     size_t                             stride;
 } VkDescriptorUpdateTemplateEntry;
+
 typedef struct VkBufferMemoryRequirementsInfo2 {
     VkStructureType   sType;
     const  void *                                                           pNext;
     VkBuffer                                                               buffer;
 } VkBufferMemoryRequirementsInfo2;
+
 typedef struct VkImageMemoryRequirementsInfo2 {
     VkStructureType   sType;
     const  void *                                                           pNext;
     VkImage                                                                image;
 } VkImageMemoryRequirementsInfo2;
+
 typedef struct VkImageSparseMemoryRequirementsInfo2 {
     VkStructureType   sType;
     const  void *                                                           pNext;
     VkImage                                                                image;
 } VkImageSparseMemoryRequirementsInfo2;
+
 typedef struct VkPhysicalDevicePointClippingProperties {
     VkStructureType   sType;
     void *                             pNext;
-    VkPointClippingBehavior        pointClippingBehavior;
+    VkPointClippingBehavior       pointClippingBehavior;
 } VkPhysicalDevicePointClippingProperties;
+
 typedef struct VkMemoryDedicatedAllocateInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkImage            image;
     VkBuffer           buffer;
 } VkMemoryDedicatedAllocateInfo;
+
 typedef struct VkPipelineTessellationDomainOriginStateCreateInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkTessellationDomainOrigin      domainOrigin;
 } VkPipelineTessellationDomainOriginStateCreateInfo;
+
 typedef struct VkSamplerYcbcrConversionInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkSamplerYcbcrConversion        conversion;
 } VkSamplerYcbcrConversionInfo;
+
 typedef struct VkBindImagePlaneMemoryInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkImageAspectFlagBits              planeAspect;
 } VkBindImagePlaneMemoryInfo;
+
 typedef struct VkImagePlaneMemoryRequirementsInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkImageAspectFlagBits              planeAspect;
 } VkImagePlaneMemoryRequirementsInfo;
+
 typedef struct VkSamplerYcbcrConversionImageFormatProperties {
     VkStructureType   sType;
     void *       pNext;
     uint32_t                           combinedImageSamplerDescriptorCount;
 } VkSamplerYcbcrConversionImageFormatProperties;
+
+typedef struct VkSamplerReductionModeCreateInfo {
+    VkStructureType   sType;
+    const  void *                       pNext;
+    VkSamplerReductionMode             reductionMode;
+} VkSamplerReductionModeCreateInfo;
+
+typedef struct VkPhysicalDeviceInlineUniformBlockProperties {
+    VkStructureType   sType;
+    void *                   pNext;
+    uint32_t                 maxInlineUniformBlockSize;
+    uint32_t                 maxPerStageDescriptorInlineUniformBlocks;
+    uint32_t                 maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks;
+    uint32_t                 maxDescriptorSetInlineUniformBlocks;
+    uint32_t                 maxDescriptorSetUpdateAfterBindInlineUniformBlocks;
+} VkPhysicalDeviceInlineUniformBlockProperties;
+
+typedef struct VkWriteDescriptorSetInlineUniformBlock {
+    VkStructureType   sType;
+    const  void *  pNext;
+    uint32_t                      dataSize;
+    const  void *   pData;
+} VkWriteDescriptorSetInlineUniformBlock;
+
+typedef struct VkDescriptorPoolInlineUniformBlockCreateInfo {
+    VkStructureType   sType;
+    const  void *  pNext;
+    uint32_t                      maxInlineUniformBlockBindings;
+} VkDescriptorPoolInlineUniformBlockCreateInfo;
+
+typedef struct VkImageFormatListCreateInfo {
+    VkStructureType   sType;
+    const  void *                             pNext;
+    uint32_t                 viewFormatCount;
+    const  VkFormat *   pViewFormats;
+} VkImageFormatListCreateInfo;
+
+typedef struct VkDescriptorSetVariableDescriptorCountAllocateInfo {
+    VkStructureType   sType;
+    const  void *                             pNext;
+    uint32_t                 descriptorSetCount;
+    const  uint32_t *  pDescriptorCounts;
+} VkDescriptorSetVariableDescriptorCountAllocateInfo;
+
+typedef struct VkDescriptorSetVariableDescriptorCountLayoutSupport {
+    VkStructureType   sType;
+    void *             pNext;
+    uint32_t           maxVariableDescriptorCount;
+} VkDescriptorSetVariableDescriptorCountLayoutSupport;
+
+typedef struct VkSubpassBeginInfo {
+    VkStructureType   sType;
+    const  void *             pNext;
+    VkSubpassContents        contents;
+} VkSubpassBeginInfo;
+
+typedef struct VkSubpassEndInfo {
+    VkStructureType   sType;
+    const  void *             pNext;
+} VkSubpassEndInfo;
+
+typedef struct VkPhysicalDeviceTimelineSemaphoreProperties {
+    VkStructureType   sType;
+    void *                   pNext;
+    uint64_t                 maxTimelineSemaphoreValueDifference;
+} VkPhysicalDeviceTimelineSemaphoreProperties;
+
+typedef struct VkSemaphoreTypeCreateInfo {
+    VkStructureType   sType;
+    const  void *             pNext;
+    VkSemaphoreType          semaphoreType;
+    uint64_t                 initialValue;
+} VkSemaphoreTypeCreateInfo;
+
+typedef struct VkTimelineSemaphoreSubmitInfo {
+    VkStructureType   sType;
+    const  void *                       pNext;
+    uint32_t           waitSemaphoreValueCount;
+    const  uint64_t *  pWaitSemaphoreValues;
+    uint32_t           signalSemaphoreValueCount;
+    const  uint64_t *  pSignalSemaphoreValues;
+} VkTimelineSemaphoreSubmitInfo;
+
+typedef struct VkSemaphoreSignalInfo {
+    VkStructureType   sType;
+    const  void *             pNext;
+    VkSemaphore              semaphore;
+    uint64_t                 value;
+} VkSemaphoreSignalInfo;
+
+typedef struct VkBufferDeviceAddressInfo {
+    VkStructureType   sType;
+    const  void *                                             pNext;
+    VkBuffer                                                 buffer;
+} VkBufferDeviceAddressInfo;
+
+typedef struct VkBufferOpaqueCaptureAddressCreateInfo {
+    VkStructureType   sType;
+    const  void *                       pNext;
+    uint64_t                           opaqueCaptureAddress;
+} VkBufferOpaqueCaptureAddressCreateInfo;
+
+typedef struct VkRenderPassAttachmentBeginInfo {
+    VkStructureType   sType;
+    const  void *                               pNext;
+    uint32_t                   attachmentCount;
+    const  VkImageView *  pAttachments;
+} VkRenderPassAttachmentBeginInfo;
+
+typedef struct VkAttachmentReferenceStencilLayout {
+    VkStructureType sType;
+    void *     pNext;
+    VkImageLayout                    stencilLayout;
+} VkAttachmentReferenceStencilLayout;
+
+typedef struct VkAttachmentDescriptionStencilLayout {
+    VkStructureType sType;
+    void *     pNext;
+    VkImageLayout                    stencilInitialLayout;
+    VkImageLayout                    stencilFinalLayout;
+} VkAttachmentDescriptionStencilLayout;
+
+typedef struct VkPipelineShaderStageRequiredSubgroupSizeCreateInfo {
+    VkStructureType   sType;
+    void *   pNext;
+    uint32_t                 requiredSubgroupSize;
+} VkPipelineShaderStageRequiredSubgroupSizeCreateInfo;
+
+typedef struct VkMemoryOpaqueCaptureAddressAllocateInfo {
+    VkStructureType   sType;
+    const  void *                    pNext;
+    uint64_t                        opaqueCaptureAddress;
+} VkMemoryOpaqueCaptureAddressAllocateInfo;
+
+typedef struct VkDeviceMemoryOpaqueCaptureAddressInfo {
+    VkStructureType   sType;
+    const  void *                       pNext;
+    VkDeviceMemory                     memory;
+} VkDeviceMemoryOpaqueCaptureAddressInfo;
+
+typedef struct VkCommandBufferSubmitInfo {
+    VkStructureType        sType;
+    const  void *                                                                 pNext;
+    VkCommandBuffer                                                              commandBuffer;
+    uint32_t                                                                     deviceMask;
+} VkCommandBufferSubmitInfo;
+
+typedef struct VkPipelineRenderingCreateInfo {
+    VkStructureType   sType;
+    const  void *                                                 pNext;
+    uint32_t                                                                     viewMask;
+    uint32_t                                                     colorAttachmentCount;
+    const  VkFormat *            pColorAttachmentFormats;
+    VkFormat                                               depthAttachmentFormat;
+    VkFormat                                               stencilAttachmentFormat;
+} VkPipelineRenderingCreateInfo;
+
+typedef struct VkRenderingAttachmentInfo {
+    VkStructureType         sType;
+    const  void *                                                 pNext;
+    VkImageView                                                  imageView;
+    VkImageLayout                                                                imageLayout;
+    VkResolveModeFlagBits                                        resolveMode;
+    VkImageView                                                  resolveImageView;
+    VkImageLayout                                                                resolveImageLayout;
+    VkAttachmentLoadOp                                                           loadOp;
+    VkAttachmentStoreOp                                                          storeOp;
+    VkClearValue                                                                 clearValue;
+} VkRenderingAttachmentInfo;
+
 typedef uint32_t VkSampleMask;
 typedef uint32_t VkBool32;
 typedef uint32_t VkFlags;
+typedef uint64_t VkFlags64;
 typedef uint64_t VkDeviceSize;
+typedef uint64_t VkDeviceAddress;
 typedef VkFlags VkFramebufferCreateFlags;
 typedef VkFlags VkQueryPoolCreateFlags;
 typedef VkFlags VkRenderPassCreateFlags;
@@ -1746,7 +2581,14 @@
 typedef VkFlags VkDescriptorPoolResetFlags;
 typedef VkFlags VkDependencyFlags;
 typedef VkFlags VkSubgroupFeatureFlags;
+typedef VkFlags VkPrivateDataSlotCreateFlags;
 typedef VkFlags VkDescriptorUpdateTemplateCreateFlags;
+typedef VkFlags VkPipelineCreationFeedbackFlags;
+typedef VkFlags VkSemaphoreWaitFlags;
+typedef VkFlags64 VkAccessFlags2;
+typedef VkFlags64 VkPipelineStageFlags2;
+typedef VkFlags64 VkFormatFeatureFlags2;
+typedef VkFlags VkRenderingFlags;
 typedef VkFlags VkCompositeAlphaFlagsKHR;
 typedef VkFlags VkSurfaceTransformFlagsKHR;
 typedef VkFlags VkSwapchainCreateFlagsKHR;
@@ -1763,6 +2605,10 @@
 typedef VkFlags VkExternalFenceHandleTypeFlags;
 typedef VkFlags VkExternalFenceFeatureFlags;
 typedef VkFlags VkFenceImportFlags;
+typedef VkFlags VkDescriptorBindingFlags;
+typedef VkFlags VkResolveModeFlags;
+typedef VkFlags VkToolPurposeFlags;
+typedef VkFlags VkSubmitFlags;
 typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)(
     VkDebugReportFlagsEXT                       flags,
     VkDebugReportObjectTypeEXT                  objectType,
@@ -1780,6 +2626,7 @@
     uint32_t          queueCount;
     const  float *     pQueuePriorities;
 } VkDeviceQueueCreateInfo;
+
 typedef struct VkInstanceCreateInfo {
     VkStructureType   sType;
     const  void *      pNext;
@@ -1790,28 +2637,33 @@
     uint32_t                 enabledExtensionCount;
     const  char * const*       ppEnabledExtensionNames;
 } VkInstanceCreateInfo;
+
 typedef struct VkQueueFamilyProperties {
     VkQueueFlags             queueFlags;
     uint32_t                 queueCount;
     uint32_t                 timestampValidBits;
     VkExtent3D               minImageTransferGranularity;
 } VkQueueFamilyProperties;
+
 typedef struct VkMemoryAllocateInfo {
     VkStructureType   sType;
     const  void *             pNext;
     VkDeviceSize             allocationSize;
     uint32_t                 memoryTypeIndex;
 } VkMemoryAllocateInfo;
+
 typedef struct VkMemoryRequirements {
     VkDeviceSize             size;
     VkDeviceSize             alignment;
     uint32_t                 memoryTypeBits;
 } VkMemoryRequirements;
+
 typedef struct VkSparseImageFormatProperties {
-    VkImageAspectFlags       aspectMask;
-    VkExtent3D               imageGranularity;
+    VkImageAspectFlags         aspectMask;
+    VkExtent3D                                  imageGranularity;
     VkSparseImageFormatFlags   flags;
 } VkSparseImageFormatProperties;
+
 typedef struct VkSparseImageMemoryRequirements {
     VkSparseImageFormatProperties   formatProperties;
     uint32_t                 imageMipTailFirstLod;
@@ -1819,14 +2671,17 @@
     VkDeviceSize             imageMipTailOffset;
     VkDeviceSize             imageMipTailStride;
 } VkSparseImageMemoryRequirements;
+
 typedef struct VkMemoryType {
     VkMemoryPropertyFlags    propertyFlags;
     uint32_t                 heapIndex;
 } VkMemoryType;
+
 typedef struct VkMemoryHeap {
     VkDeviceSize             size;
     VkMemoryHeapFlags        flags;
 } VkMemoryHeap;
+
 typedef struct VkMappedMemoryRange {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1834,11 +2689,13 @@
     VkDeviceSize             offset;
     VkDeviceSize             size;
 } VkMappedMemoryRange;
+
 typedef struct VkFormatProperties {
     VkFormatFeatureFlags     linearTilingFeatures;
     VkFormatFeatureFlags     optimalTilingFeatures;
     VkFormatFeatureFlags     bufferFeatures;
 } VkFormatProperties;
+
 typedef struct VkImageFormatProperties {
     VkExtent3D               maxExtent;
     uint32_t                 maxMipLevels;
@@ -1846,11 +2703,13 @@
     VkSampleCountFlags       sampleCounts;
     VkDeviceSize             maxResourceSize;
 } VkImageFormatProperties;
+
 typedef struct VkDescriptorBufferInfo {
     VkBuffer                 buffer;
     VkDeviceSize             offset;
     VkDeviceSize             range;
 } VkDescriptorBufferInfo;
+
 typedef struct VkWriteDescriptorSet {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1863,6 +2722,7 @@
     const  VkDescriptorBufferInfo *  pBufferInfo;
     const  VkBufferView *     pTexelBufferView;
 } VkWriteDescriptorSet;
+
 typedef struct VkBufferCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1873,6 +2733,7 @@
     uint32_t                 queueFamilyIndexCount;
     const  uint32_t *         pQueueFamilyIndices;
 } VkBufferCreateInfo;
+
 typedef struct VkBufferViewCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1882,17 +2743,20 @@
     VkDeviceSize             offset;
     VkDeviceSize             range;
 } VkBufferViewCreateInfo;
+
 typedef struct VkImageSubresource {
     VkImageAspectFlags       aspectMask;
     uint32_t                 mipLevel;
     uint32_t                 arrayLayer;
 } VkImageSubresource;
+
 typedef struct VkImageSubresourceLayers {
     VkImageAspectFlags       aspectMask;
     uint32_t                 mipLevel;
     uint32_t                 baseArrayLayer;
     uint32_t                 layerCount;
 } VkImageSubresourceLayers;
+
 typedef struct VkImageSubresourceRange {
     VkImageAspectFlags       aspectMask;
     uint32_t                 baseMipLevel;
@@ -1900,12 +2764,14 @@
     uint32_t                 baseArrayLayer;
     uint32_t                 layerCount;
 } VkImageSubresourceRange;
+
 typedef struct VkMemoryBarrier {
     VkStructureType   sType;
     const  void *             pNext;
     VkAccessFlags            srcAccessMask;
     VkAccessFlags            dstAccessMask;
 } VkMemoryBarrier;
+
 typedef struct VkBufferMemoryBarrier {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1917,6 +2783,7 @@
     VkDeviceSize             offset;
     VkDeviceSize             size;
 } VkBufferMemoryBarrier;
+
 typedef struct VkImageMemoryBarrier {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1929,6 +2796,7 @@
     VkImage                  image;
     VkImageSubresourceRange   subresourceRange;
 } VkImageMemoryBarrier;
+
 typedef struct VkImageCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1946,6 +2814,7 @@
     const  uint32_t *         pQueueFamilyIndices;
     VkImageLayout            initialLayout;
 } VkImageCreateInfo;
+
 typedef struct VkSubresourceLayout {
     VkDeviceSize             offset;
     VkDeviceSize             size;
@@ -1953,6 +2822,7 @@
     VkDeviceSize             arrayPitch;
     VkDeviceSize             depthPitch;
 } VkSubresourceLayout;
+
 typedef struct VkImageViewCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -1963,11 +2833,13 @@
     VkComponentMapping       components;
     VkImageSubresourceRange   subresourceRange;
 } VkImageViewCreateInfo;
+
 typedef struct VkBufferCopy {
     VkDeviceSize                         srcOffset;
     VkDeviceSize                         dstOffset;
     VkDeviceSize   size;
 } VkBufferCopy;
+
 typedef struct VkSparseMemoryBind {
     VkDeviceSize             resourceOffset;
     VkDeviceSize             size;
@@ -1975,6 +2847,7 @@
     VkDeviceSize             memoryOffset;
     VkSparseMemoryBindFlags flags;
 } VkSparseMemoryBind;
+
 typedef struct VkSparseImageMemoryBind {
     VkImageSubresource       subresource;
     VkOffset3D               offset;
@@ -1983,21 +2856,25 @@
     VkDeviceSize             memoryOffset;
     VkSparseMemoryBindFlags flags;
 } VkSparseImageMemoryBind;
+
 typedef struct VkSparseBufferMemoryBindInfo {
     VkBuffer   buffer;
     uint32_t                 bindCount;
     const  VkSparseMemoryBind *  pBinds;
 } VkSparseBufferMemoryBindInfo;
+
 typedef struct VkSparseImageOpaqueMemoryBindInfo {
     VkImage   image;
     uint32_t                 bindCount;
     const  VkSparseMemoryBind *  pBinds;
 } VkSparseImageOpaqueMemoryBindInfo;
+
 typedef struct VkSparseImageMemoryBindInfo {
     VkImage   image;
     uint32_t                 bindCount;
     const  VkSparseImageMemoryBind *  pBinds;
 } VkSparseImageMemoryBindInfo;
+
 typedef struct VkBindSparseInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2012,6 +2889,7 @@
     uint32_t                 signalSemaphoreCount;
     const  VkSemaphore *      pSignalSemaphores;
 } VkBindSparseInfo;
+
 typedef struct VkImageCopy {
     VkImageSubresourceLayers   srcSubresource;
     VkOffset3D               srcOffset;
@@ -2019,12 +2897,14 @@
     VkOffset3D               dstOffset;
     VkExtent3D               extent;
 } VkImageCopy;
+
 typedef struct VkImageBlit {
     VkImageSubresourceLayers   srcSubresource;
     VkOffset3D               srcOffsets [2];
     VkImageSubresourceLayers   dstSubresource;
     VkOffset3D               dstOffsets [2];
 } VkImageBlit;
+
 typedef struct VkBufferImageCopy {
     VkDeviceSize             bufferOffset;
     uint32_t                 bufferRowLength;
@@ -2033,6 +2913,7 @@
     VkOffset3D               imageOffset;
     VkExtent3D               imageExtent;
 } VkBufferImageCopy;
+
 typedef struct VkImageResolve {
     VkImageSubresourceLayers   srcSubresource;
     VkOffset3D               srcOffset;
@@ -2040,6 +2921,7 @@
     VkOffset3D               dstOffset;
     VkExtent3D               extent;
 } VkImageResolve;
+
 typedef struct VkShaderModuleCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2047,6 +2929,7 @@
     size_t                   codeSize;
     const  uint32_t *             pCode;
 } VkShaderModuleCreateInfo;
+
 typedef struct VkDescriptorSetLayoutBinding {
     uint32_t                 binding;
     VkDescriptorType         descriptorType;
@@ -2054,6 +2937,7 @@
     VkShaderStageFlags       stageFlags;
     const  VkSampler *        pImmutableSamplers;
 } VkDescriptorSetLayoutBinding;
+
 typedef struct VkDescriptorSetLayoutCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2061,6 +2945,7 @@
     uint32_t                 bindingCount;
     const  VkDescriptorSetLayoutBinding *  pBindings;
 } VkDescriptorSetLayoutCreateInfo;
+
 typedef struct VkDescriptorPoolCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2069,6 +2954,7 @@
     uint32_t                 poolSizeCount;
     const  VkDescriptorPoolSize *  pPoolSizes;
 } VkDescriptorPoolCreateInfo;
+
 typedef struct VkPipelineShaderStageCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2078,6 +2964,7 @@
     const  char *             pName;
     const  VkSpecializationInfo *  pSpecializationInfo;
 } VkPipelineShaderStageCreateInfo;
+
 typedef struct VkComputePipelineCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2087,6 +2974,7 @@
     VkPipeline        basePipelineHandle;
     int32_t                  basePipelineIndex;
 } VkComputePipelineCreateInfo;
+
 typedef struct VkPipelineVertexInputStateCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2096,6 +2984,7 @@
     uint32_t                 vertexAttributeDescriptionCount;
     const  VkVertexInputAttributeDescription *  pVertexAttributeDescriptions;
 } VkPipelineVertexInputStateCreateInfo;
+
 typedef struct VkPipelineInputAssemblyStateCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2103,12 +2992,14 @@
     VkPrimitiveTopology      topology;
     VkBool32                 primitiveRestartEnable;
 } VkPipelineInputAssemblyStateCreateInfo;
+
 typedef struct VkPipelineTessellationStateCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
     VkPipelineTessellationStateCreateFlags      flags;
     uint32_t                 patchControlPoints;
 } VkPipelineTessellationStateCreateInfo;
+
 typedef struct VkPipelineViewportStateCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2118,6 +3009,7 @@
     uint32_t                 scissorCount;
     const  VkRect2D *         pScissors;
 } VkPipelineViewportStateCreateInfo;
+
 typedef struct VkPipelineRasterizationStateCreateInfo {
     VkStructureType   sType;
     const  void *  pNext;
@@ -2133,6 +3025,7 @@
     float                    depthBiasSlopeFactor;
     float                    lineWidth;
 } VkPipelineRasterizationStateCreateInfo;
+
 typedef struct VkPipelineMultisampleStateCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2144,6 +3037,7 @@
     VkBool32                 alphaToCoverageEnable;
     VkBool32                 alphaToOneEnable;
 } VkPipelineMultisampleStateCreateInfo;
+
 typedef struct VkPipelineColorBlendAttachmentState {
     VkBool32                 blendEnable;
     VkBlendFactor            srcColorBlendFactor;
@@ -2154,6 +3048,7 @@
     VkBlendOp                alphaBlendOp;
     VkColorComponentFlags    colorWriteMask;
 } VkPipelineColorBlendAttachmentState;
+
 typedef struct VkPipelineColorBlendStateCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2164,6 +3059,7 @@
     const  VkPipelineColorBlendAttachmentState *  pAttachments;
     float                    blendConstants [4];
 } VkPipelineColorBlendStateCreateInfo;
+
 typedef struct VkPipelineDynamicStateCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2171,6 +3067,7 @@
     uint32_t                 dynamicStateCount;
     const  VkDynamicState *   pDynamicStates;
 } VkPipelineDynamicStateCreateInfo;
+
 typedef struct VkPipelineDepthStencilStateCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2185,6 +3082,7 @@
     float                    minDepthBounds;
     float                    maxDepthBounds;
 } VkPipelineDepthStencilStateCreateInfo;
+
 typedef struct VkGraphicsPipelineCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2206,6 +3104,7 @@
     VkPipeline        basePipelineHandle;
     int32_t                  basePipelineIndex;
 } VkGraphicsPipelineCreateInfo;
+
 typedef struct VkPipelineCacheCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2213,11 +3112,13 @@
     size_t                   initialDataSize;
     const  void *             pInitialData;
 } VkPipelineCacheCreateInfo;
+
 typedef struct VkPushConstantRange {
     VkShaderStageFlags       stageFlags;
     uint32_t                 offset;
     uint32_t                 size;
 } VkPushConstantRange;
+
 typedef struct VkPipelineLayoutCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2227,6 +3128,7 @@
     uint32_t                 pushConstantRangeCount;
     const  VkPushConstantRange *  pPushConstantRanges;
 } VkPipelineLayoutCreateInfo;
+
 typedef struct VkSamplerCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2247,12 +3149,14 @@
     VkBorderColor            borderColor;
     VkBool32                 unnormalizedCoordinates;
 } VkSamplerCreateInfo;
+
 typedef struct VkCommandPoolCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
     VkCommandPoolCreateFlags     flags;
     uint32_t                 queueFamilyIndex;
 } VkCommandPoolCreateInfo;
+
 typedef struct VkCommandBufferInheritanceInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2263,12 +3167,14 @@
     VkQueryControlFlags      queryFlags;
     VkQueryPipelineStatisticFlags   pipelineStatistics;
 } VkCommandBufferInheritanceInfo;
+
 typedef struct VkCommandBufferBeginInfo {
     VkStructureType   sType;
     const  void *             pNext;
     VkCommandBufferUsageFlags    flags;
     const  VkCommandBufferInheritanceInfo *        pInheritanceInfo;
 } VkCommandBufferBeginInfo;
+
 typedef struct VkRenderPassBeginInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2278,11 +3184,13 @@
     uint32_t                 clearValueCount;
     const  VkClearValue *     pClearValues;
 } VkRenderPassBeginInfo;
+
 typedef struct VkClearAttachment {
     VkImageAspectFlags       aspectMask;
     uint32_t                 colorAttachment;
     VkClearValue             clearValue;
 } VkClearAttachment;
+
 typedef struct VkAttachmentDescription {
     VkAttachmentDescriptionFlags   flags;
     VkFormat                 format;
@@ -2294,6 +3202,7 @@
     VkImageLayout            initialLayout;
     VkImageLayout            finalLayout;
 } VkAttachmentDescription;
+
 typedef struct VkSubpassDescription {
     VkSubpassDescriptionFlags   flags;
     VkPipelineBindPoint      pipelineBindPoint;
@@ -2306,6 +3215,7 @@
     uint32_t                 preserveAttachmentCount;
     const  uint32_t *  pPreserveAttachments;
 } VkSubpassDescription;
+
 typedef struct VkSubpassDependency {
     uint32_t                 srcSubpass;
     uint32_t                 dstSubpass;
@@ -2315,10 +3225,11 @@
     VkAccessFlags            dstAccessMask;
     VkDependencyFlags        dependencyFlags;
 } VkSubpassDependency;
+
 typedef struct VkRenderPassCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
-    VkRenderPassCreateFlags      flags;
+    VkRenderPassCreateFlags   flags;
     uint32_t     attachmentCount;
     const  VkAttachmentDescription *  pAttachments;
     uint32_t                 subpassCount;
@@ -2326,16 +3237,19 @@
     uint32_t         dependencyCount;
     const  VkSubpassDependency *  pDependencies;
 } VkRenderPassCreateInfo;
+
 typedef struct VkEventCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
     VkEventCreateFlags       flags;
 } VkEventCreateInfo;
+
 typedef struct VkFenceCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
     VkFenceCreateFlags       flags;
 } VkFenceCreateInfo;
+
 typedef struct VkPhysicalDeviceFeatures {
     VkBool32                 robustBufferAccess;
     VkBool32                 fullDrawIndexUint32;
@@ -2393,13 +3307,15 @@
     VkBool32                 variableMultisampleRate;
     VkBool32                 inheritedQueries;
 } VkPhysicalDeviceFeatures;
+
 typedef struct VkPhysicalDeviceSparseProperties {
-    VkBool32                 residencyStandard2DBlockShape;
-    VkBool32                 residencyStandard2DMultisampleBlockShape;
-    VkBool32                 residencyStandard3DBlockShape;
-    VkBool32                 residencyAlignedMipSize;
-    VkBool32                 residencyNonResidentStrict;
+    VkBool32             residencyStandard2DBlockShape;
+    VkBool32             residencyStandard2DMultisampleBlockShape;
+    VkBool32             residencyStandard3DBlockShape;
+    VkBool32             residencyAlignedMipSize;
+    VkBool32             residencyNonResidentStrict;
 } VkPhysicalDeviceSparseProperties;
+
 typedef struct VkPhysicalDeviceLimits {
     uint32_t                 maxImageDimension1D;
     uint32_t                 maxImageDimension2D;
@@ -2456,28 +3372,28 @@
     uint32_t                 maxComputeWorkGroupCount [3];
     uint32_t                 maxComputeWorkGroupInvocations;
     uint32_t                 maxComputeWorkGroupSize [3];
-    uint32_t                 subPixelPrecisionBits;
-    uint32_t                 subTexelPrecisionBits;
-    uint32_t                 mipmapPrecisionBits;
+    uint32_t                subPixelPrecisionBits;
+    uint32_t                subTexelPrecisionBits;
+    uint32_t                mipmapPrecisionBits;
     uint32_t                 maxDrawIndexedIndexValue;
     uint32_t                 maxDrawIndirectCount;
     float                    maxSamplerLodBias;
     float                    maxSamplerAnisotropy;
     uint32_t                 maxViewports;
     uint32_t                 maxViewportDimensions [2];
-    float                    viewportBoundsRange [2];
-    uint32_t                 viewportSubPixelBits;
-    size_t                   minMemoryMapAlignment;
-    VkDeviceSize             minTexelBufferOffsetAlignment;
-    VkDeviceSize             minUniformBufferOffsetAlignment;
-    VkDeviceSize             minStorageBufferOffsetAlignment;
+    float                  viewportBoundsRange [2];
+    uint32_t                viewportSubPixelBits;
+    size_t               minMemoryMapAlignment;
+    VkDeviceSize         minTexelBufferOffsetAlignment;
+    VkDeviceSize         minUniformBufferOffsetAlignment;
+    VkDeviceSize         minStorageBufferOffsetAlignment;
     int32_t                  minTexelOffset;
     uint32_t                 maxTexelOffset;
     int32_t                  minTexelGatherOffset;
     uint32_t                 maxTexelGatherOffset;
     float                    minInterpolationOffset;
     float                    maxInterpolationOffset;
-    uint32_t                 subPixelInterpolationOffsetBits;
+    uint32_t                subPixelInterpolationOffsetBits;
     uint32_t                 maxFramebufferWidth;
     uint32_t                 maxFramebufferHeight;
     uint32_t                 maxFramebufferLayers;
@@ -2492,27 +3408,29 @@
     VkSampleCountFlags       sampledImageStencilSampleCounts;
     VkSampleCountFlags       storageImageSampleCounts;
     uint32_t                 maxSampleMaskWords;
-    VkBool32                 timestampComputeAndGraphics;
-    float                    timestampPeriod;
+    VkBool32             timestampComputeAndGraphics;
+    float                timestampPeriod;
     uint32_t                 maxClipDistances;
     uint32_t                 maxCullDistances;
     uint32_t                 maxCombinedClipAndCullDistances;
     uint32_t                 discreteQueuePriorities;
-    float                    pointSizeRange [2];
-    float                    lineWidthRange [2];
-    float                    pointSizeGranularity;
-    float                    lineWidthGranularity;
-    VkBool32                 strictLines;
-    VkBool32                 standardSampleLocations;
-    VkDeviceSize             optimalBufferCopyOffsetAlignment;
-    VkDeviceSize             optimalBufferCopyRowPitchAlignment;
-    VkDeviceSize             nonCoherentAtomSize;
+    float                  pointSizeRange [2];
+    float                  lineWidthRange [2];
+    float                pointSizeGranularity;
+    float                lineWidthGranularity;
+    VkBool32             strictLines;
+    VkBool32             standardSampleLocations;
+    VkDeviceSize         optimalBufferCopyOffsetAlignment;
+    VkDeviceSize         optimalBufferCopyRowPitchAlignment;
+    VkDeviceSize         nonCoherentAtomSize;
 } VkPhysicalDeviceLimits;
+
 typedef struct VkSemaphoreCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
     VkSemaphoreCreateFlags   flags;
 } VkSemaphoreCreateInfo;
+
 typedef struct VkQueryPoolCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
@@ -2521,17 +3439,19 @@
     uint32_t                 queryCount;
     VkQueryPipelineStatisticFlags   pipelineStatistics;
 } VkQueryPoolCreateInfo;
+
 typedef struct VkFramebufferCreateInfo {
     VkStructureType   sType;
     const  void *             pNext;
     VkFramebufferCreateFlags      flags;
-    VkRenderPass             renderPass;
+    VkRenderPass                             renderPass;
     uint32_t                 attachmentCount;
     const  VkImageView *      pAttachments;
     uint32_t                 width;
     uint32_t                 height;
     uint32_t                 layers;
 } VkFramebufferCreateInfo;
+
 typedef struct VkSubmitInfo {
     VkStructureType   sType;
     const  void *  pNext;
@@ -2543,6 +3463,7 @@
     uint32_t         signalSemaphoreCount;
     const  VkSemaphore *      pSignalSemaphores;
 } VkSubmitInfo;
+
 typedef struct VkSurfaceCapabilitiesKHR {
     uint32_t                           minImageCount;
     uint32_t                           maxImageCount;
@@ -2555,6 +3476,7 @@
     VkCompositeAlphaFlagsKHR           supportedCompositeAlpha;
     VkImageUsageFlags                  supportedUsageFlags;
 } VkSurfaceCapabilitiesKHR;
+
 typedef struct VkSwapchainCreateInfoKHR {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -2575,6 +3497,7 @@
     VkBool32                           clipped;
     VkSwapchainKHR     oldSwapchain;
 } VkSwapchainCreateInfoKHR;
+
 typedef struct VkDebugReportCallbackCreateInfoEXT {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -2582,21 +3505,37 @@
     PFN_vkDebugReportCallbackEXT       pfnCallback;
     void *             pUserData;
 } VkDebugReportCallbackCreateInfoEXT;
+
+typedef struct VkPrivateDataSlotCreateInfo {
+    VkStructureType   sType;
+    const  void *                             pNext;
+    VkPrivateDataSlotCreateFlags          flags;
+} VkPrivateDataSlotCreateInfo;
+
+typedef struct VkPhysicalDevicePrivateDataFeatures {
+    VkStructureType   sType;
+    void *                                   pNext;
+    VkBool32                                 privateData;
+} VkPhysicalDevicePrivateDataFeatures;
+
 typedef struct VkPhysicalDeviceFeatures2 {
     VkStructureType   sType;
     void *                             pNext;
     VkPhysicalDeviceFeatures           features;
 } VkPhysicalDeviceFeatures2;
+
 typedef struct VkFormatProperties2 {
     VkStructureType   sType;
     void *                             pNext;
     VkFormatProperties                 formatProperties;
 } VkFormatProperties2;
+
 typedef struct VkImageFormatProperties2 {
     VkStructureType   sType;
     void *  pNext;
     VkImageFormatProperties            imageFormatProperties;
 } VkImageFormatProperties2;
+
 typedef struct VkPhysicalDeviceImageFormatInfo2 {
     VkStructureType   sType;
     const  void *  pNext;
@@ -2606,16 +3545,19 @@
     VkImageUsageFlags                  usage;
     VkImageCreateFlags   flags;
 } VkPhysicalDeviceImageFormatInfo2;
+
 typedef struct VkQueueFamilyProperties2 {
     VkStructureType   sType;
     void *                             pNext;
-    VkQueueFamilyProperties            queueFamilyProperties;
+    VkQueueFamilyProperties         queueFamilyProperties;
 } VkQueueFamilyProperties2;
+
 typedef struct VkSparseImageFormatProperties2 {
     VkStructureType   sType;
     void *                             pNext;
-    VkSparseImageFormatProperties      properties;
+    VkSparseImageFormatProperties   properties;
 } VkSparseImageFormatProperties2;
+
 typedef struct VkPhysicalDeviceSparseImageFormatInfo2 {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -2625,23 +3567,28 @@
     VkImageUsageFlags                  usage;
     VkImageTiling                      tiling;
 } VkPhysicalDeviceSparseImageFormatInfo2;
+
 typedef struct VkPhysicalDeviceVariablePointersFeatures {
     VkStructureType   sType;
     void *                             pNext;
     VkBool32                           variablePointersStorageBuffer;
     VkBool32                           variablePointers;
 } VkPhysicalDeviceVariablePointersFeatures;
-typedef struct VkPhysicalDeviceVariablePointerFeatures  VkPhysicalDeviceVariablePointerFeatures;
+
+typedef struct VkPhysicalDeviceVariablePointersFeatures  VkPhysicalDeviceVariablePointerFeatures;
+
 typedef struct VkExternalMemoryProperties {
     VkExternalMemoryFeatureFlags    externalMemoryFeatures;
     VkExternalMemoryHandleTypeFlags   exportFromImportedHandleTypes;
     VkExternalMemoryHandleTypeFlags   compatibleHandleTypes;
 } VkExternalMemoryProperties;
+
 typedef struct VkExternalImageFormatProperties {
     VkStructureType   sType;
     void *                             pNext;
     VkExternalMemoryProperties   externalMemoryProperties;
 } VkExternalImageFormatProperties;
+
 typedef struct VkPhysicalDeviceExternalBufferInfo {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -2649,35 +3596,41 @@
     VkBufferUsageFlags                 usage;
     VkExternalMemoryHandleTypeFlagBits   handleType;
 } VkPhysicalDeviceExternalBufferInfo;
+
 typedef struct VkExternalBufferProperties {
     VkStructureType   sType;
     void *                             pNext;
     VkExternalMemoryProperties      externalMemoryProperties;
 } VkExternalBufferProperties;
+
 typedef struct VkPhysicalDeviceIDProperties {
     VkStructureType   sType;
     void *                             pNext;
-    uint8_t                            deviceUUID [ VK_UUID_SIZE ];
-    uint8_t                            driverUUID [ VK_UUID_SIZE ];
-    uint8_t                            deviceLUID [ VK_LUID_SIZE ];
-    uint32_t                           deviceNodeMask;
-    VkBool32                           deviceLUIDValid;
+    uint8_t                       deviceUUID [ VK_UUID_SIZE ];
+    uint8_t                       driverUUID [ VK_UUID_SIZE ];
+    uint8_t                       deviceLUID [ VK_LUID_SIZE ];
+    uint32_t                      deviceNodeMask;
+    VkBool32                      deviceLUIDValid;
 } VkPhysicalDeviceIDProperties;
+
 typedef struct VkExternalMemoryImageCreateInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkExternalMemoryHandleTypeFlags   handleTypes;
 } VkExternalMemoryImageCreateInfo;
+
 typedef struct VkExternalMemoryBufferCreateInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkExternalMemoryHandleTypeFlags   handleTypes;
 } VkExternalMemoryBufferCreateInfo;
+
 typedef struct VkExportMemoryAllocateInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkExternalMemoryHandleTypeFlags   handleTypes;
 } VkExportMemoryAllocateInfo;
+
 typedef struct VkExternalSemaphoreProperties {
     VkStructureType   sType;
     void *                             pNext;
@@ -2685,11 +3638,13 @@
     VkExternalSemaphoreHandleTypeFlags   compatibleHandleTypes;
     VkExternalSemaphoreFeatureFlags   externalSemaphoreFeatures;
 } VkExternalSemaphoreProperties;
+
 typedef struct VkExportSemaphoreCreateInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkExternalSemaphoreHandleTypeFlags   handleTypes;
 } VkExportSemaphoreCreateInfo;
+
 typedef struct VkExternalFenceProperties {
     VkStructureType   sType;
     void *                             pNext;
@@ -2697,11 +3652,13 @@
     VkExternalFenceHandleTypeFlags   compatibleHandleTypes;
     VkExternalFenceFeatureFlags   externalFenceFeatures;
 } VkExternalFenceProperties;
+
 typedef struct VkExportFenceCreateInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkExternalFenceHandleTypeFlags   handleTypes;
 } VkExportFenceCreateInfo;
+
 typedef struct VkPhysicalDeviceMultiviewFeatures {
     VkStructureType   sType;
     void *                             pNext;
@@ -2709,6 +3666,7 @@
     VkBool32                           multiviewGeometryShader;
     VkBool32                           multiviewTessellationShader;
 } VkPhysicalDeviceMultiviewFeatures;
+
 typedef struct VkPhysicalDeviceGroupProperties {
     VkStructureType   sType;
     void *                             pNext;
@@ -2716,12 +3674,14 @@
     VkPhysicalDevice                   physicalDevices [ VK_MAX_DEVICE_GROUP_SIZE ];
     VkBool32                           subsetAllocation;
 } VkPhysicalDeviceGroupProperties;
+
 typedef struct VkMemoryAllocateFlagsInfo {
     VkStructureType   sType;
     const  void *                       pNext;
     VkMemoryAllocateFlags   flags;
     uint32_t                           deviceMask;
 } VkMemoryAllocateFlagsInfo;
+
 typedef struct VkBindBufferMemoryInfo {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -2729,6 +3689,7 @@
     VkDeviceMemory                     memory;
     VkDeviceSize                       memoryOffset;
 } VkBindBufferMemoryInfo;
+
 typedef struct VkBindImageMemoryInfo {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -2736,17 +3697,20 @@
     VkDeviceMemory                     memory;
     VkDeviceSize                       memoryOffset;
 } VkBindImageMemoryInfo;
+
 typedef struct VkDeviceGroupPresentCapabilitiesKHR {
     VkStructureType   sType;
-    const  void *                       pNext;
+    void *             pNext;
     uint32_t                           presentMask [ VK_MAX_DEVICE_GROUP_SIZE ];
     VkDeviceGroupPresentModeFlagsKHR   modes;
 } VkDeviceGroupPresentCapabilitiesKHR;
+
 typedef struct VkDeviceGroupSwapchainCreateInfoKHR {
     VkStructureType   sType;
     const  void *                       pNext;
     VkDeviceGroupPresentModeFlagsKHR                           modes;
 } VkDeviceGroupSwapchainCreateInfoKHR;
+
 typedef struct VkDescriptorUpdateTemplateCreateInfo {
     VkStructureType   sType;
     const  void *                                pNext;
@@ -2759,17 +3723,20 @@
     VkPipelineLayout pipelineLayout;
     uint32_t   set;
 } VkDescriptorUpdateTemplateCreateInfo;
+
 typedef struct VkInputAttachmentAspectReference {
     uint32_t                          subpass;
     uint32_t                          inputAttachmentIndex;
     VkImageAspectFlags                aspectMask;
 } VkInputAttachmentAspectReference;
+
 typedef struct VkRenderPassInputAttachmentAspectCreateInfo {
     VkStructureType   sType;
     const  void *                      pNext;
     uint32_t                          aspectReferenceCount;
     const  VkInputAttachmentAspectReference *  pAspectReferences;
 } VkRenderPassInputAttachmentAspectCreateInfo;
+
 typedef struct VkPhysicalDevice16BitStorageFeatures {
     VkStructureType   sType;
     void *       pNext;
@@ -2778,36 +3745,60 @@
     VkBool32                           storagePushConstant16;
     VkBool32                           storageInputOutput16;
 } VkPhysicalDevice16BitStorageFeatures;
+
 typedef struct VkPhysicalDeviceSubgroupProperties {
     VkStructureType   sType;
     void *                    pNext;
-    uint32_t                        subgroupSize;
+    uint32_t                       subgroupSize;
     VkShaderStageFlags              supportedStages;
     VkSubgroupFeatureFlags          supportedOperations;
     VkBool32   quadOperationsInAllStages;
 } VkPhysicalDeviceSubgroupProperties;
+
+typedef struct VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures {
+    VkStructureType   sType;
+    void *                           pNext;
+    VkBool32   shaderSubgroupExtendedTypes;
+} VkPhysicalDeviceShaderSubgroupExtendedTypesFeatures;
+
+typedef struct VkDeviceBufferMemoryRequirements {
+    VkStructureType   sType;
+    const  void *                                                            pNext;
+    const  VkBufferCreateInfo *                                                              pCreateInfo;
+} VkDeviceBufferMemoryRequirements;
+
+typedef struct VkDeviceImageMemoryRequirements {
+    VkStructureType   sType;
+    const  void *                                                           pNext;
+    const  VkImageCreateInfo *                                                              pCreateInfo;
+    VkImageAspectFlagBits                                                  planeAspect;
+} VkDeviceImageMemoryRequirements;
+
 typedef struct VkMemoryRequirements2 {
     VkStructureType   sType;
     void *  pNext;
     VkMemoryRequirements                                                   memoryRequirements;
 } VkMemoryRequirements2;
-typedef struct VkMemoryRequirements2KHR  VkMemoryRequirements2KHR;
+
 typedef struct VkSparseImageMemoryRequirements2 {
     VkStructureType   sType;
     void *                                        pNext;
     VkSparseImageMemoryRequirements                                        memoryRequirements;
 } VkSparseImageMemoryRequirements2;
+
 typedef struct VkMemoryDedicatedRequirements {
     VkStructureType   sType;
     void *                             pNext;
     VkBool32                           prefersDedicatedAllocation;
     VkBool32                           requiresDedicatedAllocation;
 } VkMemoryDedicatedRequirements;
+
 typedef struct VkImageViewUsageCreateInfo {
     VkStructureType   sType;
     const  void *  pNext;
     VkImageUsageFlags   usage;
 } VkImageViewUsageCreateInfo;
+
 typedef struct VkSamplerYcbcrConversionCreateInfo {
     VkStructureType   sType;
     const  void *                       pNext;
@@ -2820,26 +3811,31 @@
     VkFilter                           chromaFilter;
     VkBool32                           forceExplicitReconstruction;
 } VkSamplerYcbcrConversionCreateInfo;
+
 typedef struct VkPhysicalDeviceSamplerYcbcrConversionFeatures {
     VkStructureType   sType;
     void *       pNext;
     VkBool32                           samplerYcbcrConversion;
 } VkPhysicalDeviceSamplerYcbcrConversionFeatures;
+
 typedef struct VkProtectedSubmitInfo {
     VkStructureType   sType;
     const  void *                      pNext;
     VkBool32                          protectedSubmit;
 } VkProtectedSubmitInfo;
+
 typedef struct VkPhysicalDeviceProtectedMemoryFeatures {
     VkStructureType   sType;
     void *                                pNext;
     VkBool32                              protectedMemory;
 } VkPhysicalDeviceProtectedMemoryFeatures;
+
 typedef struct VkPhysicalDeviceProtectedMemoryProperties {
     VkStructureType   sType;
     void *                                pNext;
     VkBool32                              protectedNoFault;
 } VkPhysicalDeviceProtectedMemoryProperties;
+
 typedef struct VkDeviceQueueInfo2 {
     VkStructureType   sType;
     const  void *                          pNext;
@@ -2847,23 +3843,887 @@
     uint32_t                              queueFamilyIndex;
     uint32_t                              queueIndex;
 } VkDeviceQueueInfo2;
+
+typedef struct VkPhysicalDeviceSamplerFilterMinmaxProperties {
+    VkStructureType   sType;
+    void *                   pNext;
+    VkBool32                 filterMinmaxSingleComponentFormats;
+    VkBool32                 filterMinmaxImageComponentMapping;
+} VkPhysicalDeviceSamplerFilterMinmaxProperties;
+
+typedef struct VkPhysicalDeviceInlineUniformBlockFeatures {
+    VkStructureType   sType;
+    void *   pNext;
+    VkBool32                 inlineUniformBlock;
+    VkBool32                 descriptorBindingInlineUniformBlockUpdateAfterBind;
+} VkPhysicalDeviceInlineUniformBlockFeatures;
+
 typedef struct VkPhysicalDeviceMaintenance3Properties {
     VkStructureType   sType;
     void *                             pNext;
     uint32_t                           maxPerSetDescriptors;
     VkDeviceSize                       maxMemoryAllocationSize;
 } VkPhysicalDeviceMaintenance3Properties;
+
+typedef struct VkPhysicalDeviceMaintenance4Features {
+    VkStructureType   sType;
+    void *                             pNext;
+    VkBool32                                           maintenance4;
+} VkPhysicalDeviceMaintenance4Features;
+
+typedef struct VkPhysicalDeviceMaintenance4Properties {
+    VkStructureType   sType;
+    void *                             pNext;
+    VkDeviceSize                       maxBufferSize;
+} VkPhysicalDeviceMaintenance4Properties;
+
 typedef struct VkDescriptorSetLayoutSupport {
     VkStructureType   sType;
     void *             pNext;
     VkBool32           supported;
 } VkDescriptorSetLayoutSupport;
+
 typedef struct VkPhysicalDeviceShaderDrawParametersFeatures {
     VkStructureType   sType;
     void *                             pNext;
     VkBool32                           shaderDrawParameters;
 } VkPhysicalDeviceShaderDrawParametersFeatures;
-typedef struct VkPhysicalDeviceShaderDrawParameterFeatures  VkPhysicalDeviceShaderDrawParameterFeatures;
+
+typedef struct VkPhysicalDeviceShaderDrawParametersFeatures  VkPhysicalDeviceShaderDrawParameterFeatures;
+
+typedef struct VkPhysicalDeviceShaderFloat16Int8Features {
+    VkStructureType   sType;
+    void *       pNext;
+    VkBool32                           shaderFloat16;
+    VkBool32                           shaderInt8;
+} VkPhysicalDeviceShaderFloat16Int8Features;
+
+typedef struct VkPhysicalDeviceFloatControlsProperties {
+    VkStructureType   sType;
+    void *                             pNext;
+    VkShaderFloatControlsIndependence   denormBehaviorIndependence;
+    VkShaderFloatControlsIndependence   roundingModeIndependence;
+    VkBool32                           shaderSignedZeroInfNanPreserveFloat16;
+    VkBool32                           shaderSignedZeroInfNanPreserveFloat32;
+    VkBool32                           shaderSignedZeroInfNanPreserveFloat64;
+    VkBool32                           shaderDenormPreserveFloat16;
+    VkBool32                           shaderDenormPreserveFloat32;
+    VkBool32                           shaderDenormPreserveFloat64;
+    VkBool32                           shaderDenormFlushToZeroFloat16;
+    VkBool32                           shaderDenormFlushToZeroFloat32;
+    VkBool32                           shaderDenormFlushToZeroFloat64;
+    VkBool32                           shaderRoundingModeRTEFloat16;
+    VkBool32                           shaderRoundingModeRTEFloat32;
+    VkBool32                           shaderRoundingModeRTEFloat64;
+    VkBool32                           shaderRoundingModeRTZFloat16;
+    VkBool32                           shaderRoundingModeRTZFloat32;
+    VkBool32                           shaderRoundingModeRTZFloat64;
+} VkPhysicalDeviceFloatControlsProperties;
+
+typedef struct VkPhysicalDeviceHostQueryResetFeatures {
+    VkStructureType   sType;
+    void *         pNext;
+    VkBool32                             hostQueryReset;
+} VkPhysicalDeviceHostQueryResetFeatures;
+
+typedef struct VkPhysicalDeviceDescriptorIndexingFeatures {
+    VkStructureType   sType;
+    void *                             pNext;
+    VkBool32                 shaderInputAttachmentArrayDynamicIndexing;
+    VkBool32                 shaderUniformTexelBufferArrayDynamicIndexing;
+    VkBool32                 shaderStorageTexelBufferArrayDynamicIndexing;
+    VkBool32                 shaderUniformBufferArrayNonUniformIndexing;
+    VkBool32                 shaderSampledImageArrayNonUniformIndexing;
+    VkBool32                 shaderStorageBufferArrayNonUniformIndexing;
+    VkBool32                 shaderStorageImageArrayNonUniformIndexing;
+    VkBool32                 shaderInputAttachmentArrayNonUniformIndexing;
+    VkBool32                 shaderUniformTexelBufferArrayNonUniformIndexing;
+    VkBool32                 shaderStorageTexelBufferArrayNonUniformIndexing;
+    VkBool32                 descriptorBindingUniformBufferUpdateAfterBind;
+    VkBool32                 descriptorBindingSampledImageUpdateAfterBind;
+    VkBool32                 descriptorBindingStorageImageUpdateAfterBind;
+    VkBool32                 descriptorBindingStorageBufferUpdateAfterBind;
+    VkBool32                 descriptorBindingUniformTexelBufferUpdateAfterBind;
+    VkBool32                 descriptorBindingStorageTexelBufferUpdateAfterBind;
+    VkBool32                 descriptorBindingUpdateUnusedWhilePending;
+    VkBool32                 descriptorBindingPartiallyBound;
+    VkBool32                 descriptorBindingVariableDescriptorCount;
+    VkBool32                 runtimeDescriptorArray;
+} VkPhysicalDeviceDescriptorIndexingFeatures;
+
+typedef struct VkPhysicalDeviceDescriptorIndexingProperties {
+    VkStructureType   sType;
+    void *                             pNext;
+    uint32_t                 maxUpdateAfterBindDescriptorsInAllPools;
+    VkBool32                 shaderUniformBufferArrayNonUniformIndexingNative;
+    VkBool32                 shaderSampledImageArrayNonUniformIndexingNative;
+    VkBool32                 shaderStorageBufferArrayNonUniformIndexingNative;
+    VkBool32                 shaderStorageImageArrayNonUniformIndexingNative;
+    VkBool32                 shaderInputAttachmentArrayNonUniformIndexingNative;
+    VkBool32                 robustBufferAccessUpdateAfterBind;
+    VkBool32                 quadDivergentImplicitLod;
+    uint32_t                 maxPerStageDescriptorUpdateAfterBindSamplers;
+    uint32_t                 maxPerStageDescriptorUpdateAfterBindUniformBuffers;
+    uint32_t                 maxPerStageDescriptorUpdateAfterBindStorageBuffers;
+    uint32_t                 maxPerStageDescriptorUpdateAfterBindSampledImages;
+    uint32_t                 maxPerStageDescriptorUpdateAfterBindStorageImages;
+    uint32_t                 maxPerStageDescriptorUpdateAfterBindInputAttachments;
+    uint32_t                 maxPerStageUpdateAfterBindResources;
+    uint32_t                 maxDescriptorSetUpdateAfterBindSamplers;
+    uint32_t                 maxDescriptorSetUpdateAfterBindUniformBuffers;
+    uint32_t                 maxDescriptorSetUpdateAfterBindUniformBuffersDynamic;
+    uint32_t                 maxDescriptorSetUpdateAfterBindStorageBuffers;
+    uint32_t                 maxDescriptorSetUpdateAfterBindStorageBuffersDynamic;
+    uint32_t                 maxDescriptorSetUpdateAfterBindSampledImages;
+    uint32_t                 maxDescriptorSetUpdateAfterBindStorageImages;
+    uint32_t                 maxDescriptorSetUpdateAfterBindInputAttachments;
+} VkPhysicalDeviceDescriptorIndexingProperties;
+
+typedef struct VkDescriptorSetLayoutBindingFlagsCreateInfo {
+    VkStructureType   sType;
+    const  void *                                                         pNext;
+    uint32_t                                             bindingCount;
+    const  VkDescriptorBindingFlags *  pBindingFlags;
+} VkDescriptorSetLayoutBindingFlagsCreateInfo;
+
+typedef struct VkAttachmentDescription2 {
+    VkStructureType   sType;
+    const  void *             pNext;
+    VkAttachmentDescriptionFlags   flags;
+    VkFormat                                       format;
+    VkSampleCountFlagBits                          samples;
+    VkAttachmentLoadOp                             loadOp;
+    VkAttachmentStoreOp                            storeOp;
+    VkAttachmentLoadOp                             stencilLoadOp;
+    VkAttachmentStoreOp                            stencilStoreOp;
+    VkImageLayout                                  initialLayout;
+    VkImageLayout                                  finalLayout;
+} VkAttachmentDescription2;
+
+typedef struct VkAttachmentReference2 {
+    VkStructureType   sType;
+    const  void *  pNext;
+    uint32_t                            attachment;
+    VkImageLayout                       layout;
+    VkImageAspectFlags   aspectMask;
+} VkAttachmentReference2;
+
+typedef struct VkSubpassDescription2 {
+    VkStructureType   sType;
+    const  void *                            pNext;
+    VkSubpassDescriptionFlags                     flags;
+    VkPipelineBindPoint                                           pipelineBindPoint;
+    uint32_t                                                      viewMask;
+    uint32_t                                      inputAttachmentCount;
+    const  VkAttachmentReference2 *     pInputAttachments;
+    uint32_t                                      colorAttachmentCount;
+    const  VkAttachmentReference2 *     pColorAttachments;
+    const  VkAttachmentReference2 *  pResolveAttachments;
+    const  VkAttachmentReference2 *                pDepthStencilAttachment;
+    uint32_t                                      preserveAttachmentCount;
+    const  uint32_t *                pPreserveAttachments;
+} VkSubpassDescription2;
+
+typedef struct VkSubpassDependency2 {
+    VkStructureType   sType;
+    const  void *  pNext;
+    uint32_t                            srcSubpass;
+    uint32_t                            dstSubpass;
+    VkPipelineStageFlags   srcStageMask;
+    VkPipelineStageFlags   dstStageMask;
+    VkAccessFlags       srcAccessMask;
+    VkAccessFlags       dstAccessMask;
+    VkDependencyFlags   dependencyFlags;
+    int32_t                             viewOffset;
+} VkSubpassDependency2;
+
+typedef struct VkRenderPassCreateInfo2 {
+    VkStructureType   sType;
+    const  void *                                               pNext;
+    VkRenderPassCreateFlags                    flags;
+    uint32_t                                   attachmentCount;
+    const  VkAttachmentDescription2 *     pAttachments;
+    uint32_t                                                   subpassCount;
+    const  VkSubpassDescription2 *           pSubpasses;
+    uint32_t                                   dependencyCount;
+    const  VkSubpassDependency2 *         pDependencies;
+    uint32_t                                   correlatedViewMaskCount;
+    const  uint32_t *             pCorrelatedViewMasks;
+} VkRenderPassCreateInfo2;
+
+typedef struct VkPhysicalDeviceTimelineSemaphoreFeatures {
+    VkStructureType   sType;
+    void *                   pNext;
+    VkBool32                 timelineSemaphore;
+} VkPhysicalDeviceTimelineSemaphoreFeatures;
+
+typedef struct VkSemaphoreWaitInfo {
+    VkStructureType   sType;
+    const  void *             pNext;
+    VkSemaphoreWaitFlags   flags;
+    uint32_t                 semaphoreCount;
+    const  VkSemaphore *  pSemaphores;
+    const  uint64_t *     pValues;
+} VkSemaphoreWaitInfo;
+
+typedef struct VkPhysicalDevice8BitStorageFeatures {
+    VkStructureType   sType;
+    void *       pNext;
+    VkBool32                           storageBuffer8BitAccess;
+    VkBool32                           uniformAndStorageBuffer8BitAccess;
+    VkBool32                           storagePushConstant8;
+} VkPhysicalDevice8BitStorageFeatures;
+
+typedef struct VkPhysicalDeviceVulkanMemoryModelFeatures {
+    VkStructureType   sType;
+    void *       pNext;
+    VkBool32                           vulkanMemoryModel;
+    VkBool32                           vulkanMemoryModelDeviceScope;
+    VkBool32                           vulkanMemoryModelAvailabilityVisibilityChains;
+} VkPhysicalDeviceVulkanMemoryModelFeatures;
+
+typedef struct VkPhysicalDeviceShaderAtomicInt64Features {
+    VkStructureType   sType;
+    void *                                pNext;
+    VkBool32                              shaderBufferInt64Atomics;
+    VkBool32                              shaderSharedInt64Atomics;
+} VkPhysicalDeviceShaderAtomicInt64Features;
+
+typedef struct VkPhysicalDeviceDepthStencilResolveProperties {
+    VkStructureType   sType;
+    void *                                 pNext;
+    VkResolveModeFlags                     supportedDepthResolveModes;
+    VkResolveModeFlags                     supportedStencilResolveModes;
+    VkBool32                               independentResolveNone;
+    VkBool32                               independentResolve;
+} VkPhysicalDeviceDepthStencilResolveProperties;
+
+typedef struct VkSubpassDescriptionDepthStencilResolve {
+    VkStructureType   sType;
+    const  void *                               pNext;
+    VkResolveModeFlagBits                depthResolveMode;
+    VkResolveModeFlagBits                stencilResolveMode;
+    const  VkAttachmentReference2 *             pDepthStencilResolveAttachment;
+} VkSubpassDescriptionDepthStencilResolve;
+
+typedef struct VkImageStencilUsageCreateInfo {
+    VkStructureType   sType;
+    const  void *  pNext;
+    VkImageUsageFlags   stencilUsage;
+} VkImageStencilUsageCreateInfo;
+
+typedef struct VkPhysicalDeviceScalarBlockLayoutFeatures {
+    VkStructureType   sType;
+    void *                                pNext;
+    VkBool32                              scalarBlockLayout;
+} VkPhysicalDeviceScalarBlockLayoutFeatures;
+
+typedef struct VkPhysicalDeviceUniformBufferStandardLayoutFeatures {
+    VkStructureType   sType;
+    void *                                pNext;
+    VkBool32                              uniformBufferStandardLayout;
+} VkPhysicalDeviceUniformBufferStandardLayoutFeatures;
+
+typedef struct VkPhysicalDeviceBufferDeviceAddressFeatures {
+    VkStructureType   sType;
+    void *         pNext;
+    VkBool32                             bufferDeviceAddress;
+    VkBool32                             bufferDeviceAddressCaptureReplay;
+    VkBool32                             bufferDeviceAddressMultiDevice;
+} VkPhysicalDeviceBufferDeviceAddressFeatures;
+
+typedef struct VkPhysicalDeviceImagelessFramebufferFeatures {
+    VkStructureType   sType;
+    void *                                     pNext;
+    VkBool32                                   imagelessFramebuffer;
+} VkPhysicalDeviceImagelessFramebufferFeatures;
+
+typedef struct VkFramebufferAttachmentImageInfo {
+    VkStructureType   sType;
+    const  void *                               pNext;
+    VkImageCreateFlags         flags;
+    VkImageUsageFlags                          usage;
+    uint32_t                                   width;
+    uint32_t                                   height;
+    uint32_t                                   layerCount;
+    uint32_t                   viewFormatCount;
+    const  VkFormat *     pViewFormats;
+} VkFramebufferAttachmentImageInfo;
+
+typedef struct VkPhysicalDeviceTextureCompressionASTCHDRFeatures {
+    VkStructureType   sType;
+    void *   pNext;
+    VkBool32                 textureCompressionASTC_HDR;
+} VkPhysicalDeviceTextureCompressionASTCHDRFeatures;
+
+typedef struct VkPipelineCreationFeedback {
+    VkPipelineCreationFeedbackFlags       flags;
+    uint64_t                              duration;
+} VkPipelineCreationFeedback;
+
+typedef struct VkPipelineCreationFeedbackCreateInfo {
+    VkStructureType   sType;
+    const  void *          pNext;
+    VkPipelineCreationFeedback *          pPipelineCreationFeedback;
+    uint32_t              pipelineStageCreationFeedbackCount;
+    VkPipelineCreationFeedback *  pPipelineStageCreationFeedbacks;
+} VkPipelineCreationFeedbackCreateInfo;
+
+typedef struct VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures {
+    VkStructureType sType;
+    void *     pNext;
+    VkBool32                         separateDepthStencilLayouts;
+} VkPhysicalDeviceSeparateDepthStencilLayoutsFeatures;
+
+typedef struct VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures {
+    VkStructureType   sType;
+    void *       pNext;
+    VkBool32                     shaderDemoteToHelperInvocation;
+} VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures;
+
+typedef struct VkPhysicalDeviceTexelBufferAlignmentProperties {
+    VkStructureType   sType;
+    void *               pNext;
+    VkDeviceSize                         storageTexelBufferOffsetAlignmentBytes;
+    VkBool32                           storageTexelBufferOffsetSingleTexelAlignment;
+    VkDeviceSize                         uniformTexelBufferOffsetAlignmentBytes;
+    VkBool32                           uniformTexelBufferOffsetSingleTexelAlignment;
+} VkPhysicalDeviceTexelBufferAlignmentProperties;
+
+typedef struct VkPhysicalDeviceSubgroupSizeControlFeatures {
+    VkStructureType   sType;
+    void *   pNext;
+    VkBool32                 subgroupSizeControl;
+    VkBool32                 computeFullSubgroups;
+} VkPhysicalDeviceSubgroupSizeControlFeatures;
+
+typedef struct VkPhysicalDeviceSubgroupSizeControlProperties {
+    VkStructureType   sType;
+    void *                           pNext;
+    uint32_t   minSubgroupSize;
+    uint32_t   maxSubgroupSize;
+    uint32_t   maxComputeWorkgroupSubgroups;
+    VkShaderStageFlags           requiredSubgroupSizeStages;
+} VkPhysicalDeviceSubgroupSizeControlProperties;
+
+typedef struct VkPhysicalDevicePipelineCreationCacheControlFeatures {
+    VkStructureType   sType;
+    void *  pNext;
+    VkBool32                pipelineCreationCacheControl;
+} VkPhysicalDevicePipelineCreationCacheControlFeatures;
+
+typedef struct VkPhysicalDeviceVulkan11Features {
+    VkStructureType sType;
+    void *     pNext;
+    VkBool32                           storageBuffer16BitAccess;
+    VkBool32                           uniformAndStorageBuffer16BitAccess;
+    VkBool32                           storagePushConstant16;
+    VkBool32                           storageInputOutput16;
+    VkBool32                           multiview;
+    VkBool32                           multiviewGeometryShader;
+    VkBool32                           multiviewTessellationShader;
+    VkBool32                           variablePointersStorageBuffer;
+    VkBool32                           variablePointers;
+    VkBool32                           protectedMemory;
+    VkBool32                           samplerYcbcrConversion;
+    VkBool32                           shaderDrawParameters;
+} VkPhysicalDeviceVulkan11Features;
+
+typedef struct VkPhysicalDeviceVulkan11Properties {
+    VkStructureType sType;
+    void *       pNext;
+    uint8_t                            deviceUUID [ VK_UUID_SIZE ];
+    uint8_t                            driverUUID [ VK_UUID_SIZE ];
+    uint8_t                            deviceLUID [ VK_LUID_SIZE ];
+    uint32_t                           deviceNodeMask;
+    VkBool32                           deviceLUIDValid;
+    uint32_t                        subgroupSize;
+    VkShaderStageFlags              subgroupSupportedStages;
+    VkSubgroupFeatureFlags          subgroupSupportedOperations;
+    VkBool32                        subgroupQuadOperationsInAllStages;
+    VkPointClippingBehavior       pointClippingBehavior;
+    uint32_t                           maxMultiviewViewCount;
+    uint32_t                           maxMultiviewInstanceIndex;
+    VkBool32                      protectedNoFault;
+    uint32_t                           maxPerSetDescriptors;
+    VkDeviceSize                       maxMemoryAllocationSize;
+} VkPhysicalDeviceVulkan11Properties;
+
+typedef struct VkPhysicalDeviceVulkan12Features {
+    VkStructureType sType;
+    void *     pNext;
+    VkBool32                           samplerMirrorClampToEdge;
+    VkBool32                           drawIndirectCount;
+    VkBool32                           storageBuffer8BitAccess;
+    VkBool32                           uniformAndStorageBuffer8BitAccess;
+    VkBool32                           storagePushConstant8;
+    VkBool32                           shaderBufferInt64Atomics;
+    VkBool32                           shaderSharedInt64Atomics;
+    VkBool32                           shaderFloat16;
+    VkBool32                           shaderInt8;
+    VkBool32                           descriptorIndexing;
+    VkBool32                           shaderInputAttachmentArrayDynamicIndexing;
+    VkBool32                           shaderUniformTexelBufferArrayDynamicIndexing;
+    VkBool32                           shaderStorageTexelBufferArrayDynamicIndexing;
+    VkBool32                           shaderUniformBufferArrayNonUniformIndexing;
+    VkBool32                           shaderSampledImageArrayNonUniformIndexing;
+    VkBool32                           shaderStorageBufferArrayNonUniformIndexing;
+    VkBool32                           shaderStorageImageArrayNonUniformIndexing;
+    VkBool32                           shaderInputAttachmentArrayNonUniformIndexing;
+    VkBool32                           shaderUniformTexelBufferArrayNonUniformIndexing;
+    VkBool32                           shaderStorageTexelBufferArrayNonUniformIndexing;
+    VkBool32                           descriptorBindingUniformBufferUpdateAfterBind;
+    VkBool32                           descriptorBindingSampledImageUpdateAfterBind;
+    VkBool32                           descriptorBindingStorageImageUpdateAfterBind;
+    VkBool32                           descriptorBindingStorageBufferUpdateAfterBind;
+    VkBool32                           descriptorBindingUniformTexelBufferUpdateAfterBind;
+    VkBool32                           descriptorBindingStorageTexelBufferUpdateAfterBind;
+    VkBool32                           descriptorBindingUpdateUnusedWhilePending;
+    VkBool32                           descriptorBindingPartiallyBound;
+    VkBool32                           descriptorBindingVariableDescriptorCount;
+    VkBool32                           runtimeDescriptorArray;
+    VkBool32                           samplerFilterMinmax;
+    VkBool32                           scalarBlockLayout;
+    VkBool32                           imagelessFramebuffer;
+    VkBool32                           uniformBufferStandardLayout;
+    VkBool32                           shaderSubgroupExtendedTypes;
+    VkBool32                           separateDepthStencilLayouts;
+    VkBool32                           hostQueryReset;
+    VkBool32                           timelineSemaphore;
+    VkBool32                           bufferDeviceAddress;
+    VkBool32                           bufferDeviceAddressCaptureReplay;
+    VkBool32                           bufferDeviceAddressMultiDevice;
+    VkBool32                           vulkanMemoryModel;
+    VkBool32                           vulkanMemoryModelDeviceScope;
+    VkBool32                           vulkanMemoryModelAvailabilityVisibilityChains;
+    VkBool32                           shaderOutputViewportIndex;
+    VkBool32                           shaderOutputLayer;
+    VkBool32                           subgroupBroadcastDynamicId;
+} VkPhysicalDeviceVulkan12Features;
+
+typedef struct VkPhysicalDeviceVulkan12Properties {
+    VkStructureType sType;
+    void *     pNext;
+    VkDriverId                         driverID;
+    char                               driverName [ VK_MAX_DRIVER_NAME_SIZE ];
+    char                               driverInfo [ VK_MAX_DRIVER_INFO_SIZE ];
+    VkConformanceVersion               conformanceVersion;
+    VkShaderFloatControlsIndependence denormBehaviorIndependence;
+    VkShaderFloatControlsIndependence roundingModeIndependence;
+    VkBool32                           shaderSignedZeroInfNanPreserveFloat16;
+    VkBool32                           shaderSignedZeroInfNanPreserveFloat32;
+    VkBool32                           shaderSignedZeroInfNanPreserveFloat64;
+    VkBool32                           shaderDenormPreserveFloat16;
+    VkBool32                           shaderDenormPreserveFloat32;
+    VkBool32                           shaderDenormPreserveFloat64;
+    VkBool32                           shaderDenormFlushToZeroFloat16;
+    VkBool32                           shaderDenormFlushToZeroFloat32;
+    VkBool32                           shaderDenormFlushToZeroFloat64;
+    VkBool32                           shaderRoundingModeRTEFloat16;
+    VkBool32                           shaderRoundingModeRTEFloat32;
+    VkBool32                           shaderRoundingModeRTEFloat64;
+    VkBool32                           shaderRoundingModeRTZFloat16;
+    VkBool32                           shaderRoundingModeRTZFloat32;
+    VkBool32                           shaderRoundingModeRTZFloat64;
+    uint32_t                           maxUpdateAfterBindDescriptorsInAllPools;
+    VkBool32                           shaderUniformBufferArrayNonUniformIndexingNative;
+    VkBool32                           shaderSampledImageArrayNonUniformIndexingNative;
+    VkBool32                           shaderStorageBufferArrayNonUniformIndexingNative;
+    VkBool32                           shaderStorageImageArrayNonUniformIndexingNative;
+    VkBool32                           shaderInputAttachmentArrayNonUniformIndexingNative;
+    VkBool32                           robustBufferAccessUpdateAfterBind;
+    VkBool32                           quadDivergentImplicitLod;
+    uint32_t                           maxPerStageDescriptorUpdateAfterBindSamplers;
+    uint32_t                           maxPerStageDescriptorUpdateAfterBindUniformBuffers;
+    uint32_t                           maxPerStageDescriptorUpdateAfterBindStorageBuffers;
+    uint32_t                           maxPerStageDescriptorUpdateAfterBindSampledImages;
+    uint32_t                           maxPerStageDescriptorUpdateAfterBindStorageImages;
+    uint32_t                           maxPerStageDescriptorUpdateAfterBindInputAttachments;
+    uint32_t                           maxPerStageUpdateAfterBindResources;
+    uint32_t                           maxDescriptorSetUpdateAfterBindSamplers;
+    uint32_t                           maxDescriptorSetUpdateAfterBindUniformBuffers;
+    uint32_t                           maxDescriptorSetUpdateAfterBindUniformBuffersDynamic;
+    uint32_t                           maxDescriptorSetUpdateAfterBindStorageBuffers;
+    uint32_t                           maxDescriptorSetUpdateAfterBindStorageBuffersDynamic;
+    uint32_t                           maxDescriptorSetUpdateAfterBindSampledImages;
+    uint32_t                           maxDescriptorSetUpdateAfterBindStorageImages;
+    uint32_t                           maxDescriptorSetUpdateAfterBindInputAttachments;
+    VkResolveModeFlags                 supportedDepthResolveModes;
+    VkResolveModeFlags                 supportedStencilResolveModes;
+    VkBool32                           independentResolveNone;
+    VkBool32                           independentResolve;
+    VkBool32                           filterMinmaxSingleComponentFormats;
+    VkBool32                           filterMinmaxImageComponentMapping;
+    uint64_t                           maxTimelineSemaphoreValueDifference;
+    VkSampleCountFlags   framebufferIntegerColorSampleCounts;
+} VkPhysicalDeviceVulkan12Properties;
+
+typedef struct VkPhysicalDeviceVulkan13Features {
+    VkStructureType sType;
+    void *             pNext;
+    VkBool32                           robustImageAccess;
+    VkBool32                           inlineUniformBlock;
+    VkBool32                           descriptorBindingInlineUniformBlockUpdateAfterBind;
+    VkBool32                           pipelineCreationCacheControl;
+    VkBool32                           privateData;
+    VkBool32                           shaderDemoteToHelperInvocation;
+    VkBool32                           shaderTerminateInvocation;
+    VkBool32                           subgroupSizeControl;
+    VkBool32                           computeFullSubgroups;
+    VkBool32                           synchronization2;
+    VkBool32                           textureCompressionASTC_HDR;
+    VkBool32                           shaderZeroInitializeWorkgroupMemory;
+    VkBool32                           dynamicRendering;
+    VkBool32                           shaderIntegerDotProduct;
+    VkBool32                           maintenance4;
+} VkPhysicalDeviceVulkan13Features;
+
+typedef struct VkPhysicalDeviceVulkan13Properties {
+    VkStructureType sType;
+    void *                           pNext;
+    uint32_t   minSubgroupSize;
+    uint32_t   maxSubgroupSize;
+    uint32_t   maxComputeWorkgroupSubgroups;
+    VkShaderStageFlags           requiredSubgroupSizeStages;
+    uint32_t                         maxInlineUniformBlockSize;
+    uint32_t                         maxPerStageDescriptorInlineUniformBlocks;
+    uint32_t                         maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks;
+    uint32_t                         maxDescriptorSetInlineUniformBlocks;
+    uint32_t                         maxDescriptorSetUpdateAfterBindInlineUniformBlocks;
+    uint32_t                         maxInlineUniformTotalSize;
+    VkBool32                     integerDotProduct8BitUnsignedAccelerated;
+    VkBool32                     integerDotProduct8BitSignedAccelerated;
+    VkBool32                     integerDotProduct8BitMixedSignednessAccelerated;
+    VkBool32                     integerDotProduct4x8BitPackedUnsignedAccelerated;
+    VkBool32                     integerDotProduct4x8BitPackedSignedAccelerated;
+    VkBool32                     integerDotProduct4x8BitPackedMixedSignednessAccelerated;
+    VkBool32                     integerDotProduct16BitUnsignedAccelerated;
+    VkBool32                     integerDotProduct16BitSignedAccelerated;
+    VkBool32                     integerDotProduct16BitMixedSignednessAccelerated;
+    VkBool32                     integerDotProduct32BitUnsignedAccelerated;
+    VkBool32                     integerDotProduct32BitSignedAccelerated;
+    VkBool32                     integerDotProduct32BitMixedSignednessAccelerated;
+    VkBool32                     integerDotProduct64BitUnsignedAccelerated;
+    VkBool32                     integerDotProduct64BitSignedAccelerated;
+    VkBool32                     integerDotProduct64BitMixedSignednessAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating8BitUnsignedAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating8BitSignedAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating16BitUnsignedAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating16BitSignedAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating32BitUnsignedAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating32BitSignedAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating64BitUnsignedAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating64BitSignedAccelerated;
+    VkBool32                     integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated;
+    VkDeviceSize                  storageTexelBufferOffsetAlignmentBytes;
+    VkBool32                    storageTexelBufferOffsetSingleTexelAlignment;
+    VkDeviceSize                  uniformTexelBufferOffsetAlignmentBytes;
+    VkBool32                    uniformTexelBufferOffsetSingleTexelAlignment;
+    VkDeviceSize                     maxBufferSize;
+} VkPhysicalDeviceVulkan13Properties;
+
+typedef struct VkPhysicalDeviceToolProperties {
+    VkStructureType   sType;
+    void *  pNext;
+    char                    name [ VK_MAX_EXTENSION_NAME_SIZE ];
+    char                    version [ VK_MAX_EXTENSION_NAME_SIZE ];
+    VkToolPurposeFlags      purposes;
+    char                    description [ VK_MAX_DESCRIPTION_SIZE ];
+    char                    layer [ VK_MAX_EXTENSION_NAME_SIZE ];
+} VkPhysicalDeviceToolProperties;
+
+typedef struct VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures {
+    VkStructureType   sType;
+    void *           pNext;
+    VkBool32         shaderZeroInitializeWorkgroupMemory;
+} VkPhysicalDeviceZeroInitializeWorkgroupMemoryFeatures;
+
+typedef struct VkPhysicalDeviceImageRobustnessFeatures {
+    VkStructureType   sType;
+    void *               pNext;
+    VkBool32                             robustImageAccess;
+} VkPhysicalDeviceImageRobustnessFeatures;
+
+typedef struct VkBufferCopy2 {
+    VkStructureType   sType;
+    const  void *         pNext;
+    VkDeviceSize                         srcOffset;
+    VkDeviceSize                         dstOffset;
+    VkDeviceSize   size;
+} VkBufferCopy2;
+
+typedef struct VkImageCopy2 {
+    VkStructureType   sType;
+    const  void *         pNext;
+    VkImageSubresourceLayers             srcSubresource;
+    VkOffset3D                           srcOffset;
+    VkImageSubresourceLayers             dstSubresource;
+    VkOffset3D                           dstOffset;
+    VkExtent3D                           extent;
+} VkImageCopy2;
+
+typedef struct VkImageBlit2 {
+    VkStructureType   sType;
+    const  void *         pNext;
+    VkImageSubresourceLayers             srcSubresource;
+    VkOffset3D                           srcOffsets [2];
+    VkImageSubresourceLayers             dstSubresource;
+    VkOffset3D                           dstOffsets [2];
+} VkImageBlit2;
+
+typedef struct VkBufferImageCopy2 {
+    VkStructureType   sType;
+    const  void *         pNext;
+    VkDeviceSize                         bufferOffset;
+    uint32_t                             bufferRowLength;
+    uint32_t                             bufferImageHeight;
+    VkImageSubresourceLayers             imageSubresource;
+    VkOffset3D                           imageOffset;
+    VkExtent3D                           imageExtent;
+} VkBufferImageCopy2;
+
+typedef struct VkImageResolve2 {
+    VkStructureType   sType;
+    const  void *         pNext;
+    VkImageSubresourceLayers             srcSubresource;
+    VkOffset3D                           srcOffset;
+    VkImageSubresourceLayers             dstSubresource;
+    VkOffset3D                           dstOffset;
+    VkExtent3D                           extent;
+} VkImageResolve2;
+
+typedef struct VkCopyBufferInfo2 {
+    VkStructureType   sType;
+    const  void *         pNext;
+    VkBuffer                             srcBuffer;
+    VkBuffer                             dstBuffer;
+    uint32_t                             regionCount;
+    const  VkBufferCopy2 *  pRegions;
+} VkCopyBufferInfo2;
+
+typedef struct VkCopyImageInfo2 {
+    VkStructureType   sType;
+    const  void *         pNext;
+    VkImage                              srcImage;
+    VkImageLayout                        srcImageLayout;
+    VkImage                              dstImage;
+    VkImageLayout                        dstImageLayout;
+    uint32_t                             regionCount;
+    const  VkImageCopy2 *  pRegions;
+} VkCopyImageInfo2;
+
+typedef struct VkBlitImageInfo2 {
+    VkStructureType   sType;
+    const  void *             pNext;
+    VkImage                                  srcImage;
+    VkImageLayout                            srcImageLayout;
+    VkImage                                  dstImage;
+    VkImageLayout                            dstImageLayout;
+    uint32_t                                 regionCount;
+    const  VkImageBlit2 *   pRegions;
+    VkFilter                                 filter;
+} VkBlitImageInfo2;
+
+typedef struct VkCopyBufferToImageInfo2 {
+    VkStructureType   sType;
+    const  void *                  pNext;
+    VkBuffer                                      srcBuffer;
+    VkImage                                       dstImage;
+    VkImageLayout                                 dstImageLayout;
+    uint32_t                                      regionCount;
+    const  VkBufferImageCopy2 *  pRegions;
+} VkCopyBufferToImageInfo2;
+
+typedef struct VkCopyImageToBufferInfo2 {
+    VkStructureType   sType;
+    const  void *                    pNext;
+    VkImage                                         srcImage;
+    VkImageLayout                                   srcImageLayout;
+    VkBuffer                                        dstBuffer;
+    uint32_t                                        regionCount;
+    const  VkBufferImageCopy2 *    pRegions;
+} VkCopyImageToBufferInfo2;
+
+typedef struct VkResolveImageInfo2 {
+    VkStructureType   sType;
+    const  void *                 pNext;
+    VkImage                                      srcImage;
+    VkImageLayout                                srcImageLayout;
+    VkImage                                      dstImage;
+    VkImageLayout                                dstImageLayout;
+    uint32_t                                     regionCount;
+    const  VkImageResolve2 *    pRegions;
+} VkResolveImageInfo2;
+
+typedef struct VkPhysicalDeviceShaderTerminateInvocationFeatures {
+    VkStructureType sType;
+    void *     pNext;
+    VkBool32                                         shaderTerminateInvocation;
+} VkPhysicalDeviceShaderTerminateInvocationFeatures;
+
+typedef struct VkMemoryBarrier2 {
+    VkStructureType   sType;
+    const  void *                             pNext;
+    VkPipelineStageFlags2    srcStageMask;
+    VkAccessFlags2           srcAccessMask;
+    VkPipelineStageFlags2    dstStageMask;
+    VkAccessFlags2           dstAccessMask;
+} VkMemoryBarrier2;
+
+typedef struct VkImageMemoryBarrier2 {
+    VkStructureType   sType;
+    const  void *                             pNext;
+    VkPipelineStageFlags2    srcStageMask;
+    VkAccessFlags2           srcAccessMask;
+    VkPipelineStageFlags2    dstStageMask;
+    VkAccessFlags2           dstAccessMask;
+    VkImageLayout                            oldLayout;
+    VkImageLayout                            newLayout;
+    uint32_t                                 srcQueueFamilyIndex;
+    uint32_t                                 dstQueueFamilyIndex;
+    VkImage                                  image;
+    VkImageSubresourceRange                  subresourceRange;
+} VkImageMemoryBarrier2;
+
+typedef struct VkBufferMemoryBarrier2 {
+    VkStructureType   sType;
+    const  void *                             pNext;
+    VkPipelineStageFlags2    srcStageMask;
+    VkAccessFlags2           srcAccessMask;
+    VkPipelineStageFlags2    dstStageMask;
+    VkAccessFlags2           dstAccessMask;
+    uint32_t                                 srcQueueFamilyIndex;
+    uint32_t                                 dstQueueFamilyIndex;
+    VkBuffer                                 buffer;
+    VkDeviceSize                             offset;
+    VkDeviceSize                             size;
+} VkBufferMemoryBarrier2;
+
+typedef struct VkDependencyInfo {
+    VkStructureType   sType;
+    const  void *                                                   pNext;
+    VkDependencyFlags                              dependencyFlags;
+    uint32_t                                       memoryBarrierCount;
+    const  VkMemoryBarrier2 *              pMemoryBarriers;
+    uint32_t                                       bufferMemoryBarrierCount;
+    const  VkBufferMemoryBarrier2 *  pBufferMemoryBarriers;
+    uint32_t                                       imageMemoryBarrierCount;
+    const  VkImageMemoryBarrier2 *    pImageMemoryBarriers;
+} VkDependencyInfo;
+
+typedef struct VkSemaphoreSubmitInfo {
+    VkStructureType             sType;
+    const  void *                                                                 pNext;
+    VkSemaphore                                                                  semaphore;
+    uint64_t                                                                     value;
+    VkPipelineStageFlags2                                        stageMask;
+    uint32_t                                                                     deviceIndex;
+} VkSemaphoreSubmitInfo;
+
+typedef struct VkSubmitInfo2 {
+    VkStructureType                     sType;
+    const  void *                                                                 pNext;
+    VkSubmitFlags                                                flags;
+    uint32_t                                                     waitSemaphoreInfoCount;
+    const  VkSemaphoreSubmitInfo *                   pWaitSemaphoreInfos;
+    uint32_t                                                     commandBufferInfoCount;
+    const  VkCommandBufferSubmitInfo *               pCommandBufferInfos;
+    uint32_t                                                     signalSemaphoreInfoCount;
+    const  VkSemaphoreSubmitInfo *                 pSignalSemaphoreInfos;
+} VkSubmitInfo2;
+
+typedef struct VkPhysicalDeviceSynchronization2Features {
+    VkStructureType   sType;
+    void *         pNext;
+    VkBool32                             synchronization2;
+} VkPhysicalDeviceSynchronization2Features;
+
+typedef struct VkPhysicalDeviceShaderIntegerDotProductFeatures {
+    VkStructureType   sType;
+    void *                pNext;
+    VkBool32                              shaderIntegerDotProduct;
+} VkPhysicalDeviceShaderIntegerDotProductFeatures;
+
+typedef struct VkPhysicalDeviceShaderIntegerDotProductProperties {
+    VkStructureType   sType;
+    void *                pNext;
+    VkBool32          integerDotProduct8BitUnsignedAccelerated;
+    VkBool32          integerDotProduct8BitSignedAccelerated;
+    VkBool32          integerDotProduct8BitMixedSignednessAccelerated;
+    VkBool32          integerDotProduct4x8BitPackedUnsignedAccelerated;
+    VkBool32          integerDotProduct4x8BitPackedSignedAccelerated;
+    VkBool32          integerDotProduct4x8BitPackedMixedSignednessAccelerated;
+    VkBool32          integerDotProduct16BitUnsignedAccelerated;
+    VkBool32          integerDotProduct16BitSignedAccelerated;
+    VkBool32          integerDotProduct16BitMixedSignednessAccelerated;
+    VkBool32          integerDotProduct32BitUnsignedAccelerated;
+    VkBool32          integerDotProduct32BitSignedAccelerated;
+    VkBool32          integerDotProduct32BitMixedSignednessAccelerated;
+    VkBool32          integerDotProduct64BitUnsignedAccelerated;
+    VkBool32          integerDotProduct64BitSignedAccelerated;
+    VkBool32          integerDotProduct64BitMixedSignednessAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating8BitUnsignedAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating8BitSignedAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating16BitUnsignedAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating16BitSignedAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating32BitUnsignedAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating32BitSignedAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating64BitUnsignedAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating64BitSignedAccelerated;
+    VkBool32          integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated;
+} VkPhysicalDeviceShaderIntegerDotProductProperties;
+
+typedef struct VkFormatProperties3 {
+    VkStructureType   sType;
+    void *                             pNext;
+    VkFormatFeatureFlags2              linearTilingFeatures;
+    VkFormatFeatureFlags2              optimalTilingFeatures;
+    VkFormatFeatureFlags2              bufferFeatures;
+} VkFormatProperties3;
+
+typedef struct VkRenderingInfo {
+    VkStructureType                    sType;
+    const  void *                                                 pNext;
+    VkRenderingFlags                                             flags;
+    VkRect2D                                                                     renderArea;
+    uint32_t                                                                     layerCount;
+    uint32_t                                                                     viewMask;
+    uint32_t                                                     colorAttachmentCount;
+    const  VkRenderingAttachmentInfo *                 pColorAttachments;
+    const  VkRenderingAttachmentInfo *                            pDepthAttachment;
+    const  VkRenderingAttachmentInfo *                            pStencilAttachment;
+} VkRenderingInfo;
+
+typedef struct VkPhysicalDeviceDynamicRenderingFeatures {
+    VkStructureType   sType;
+    void *                                 pNext;
+    VkBool32                                                                     dynamicRendering;
+} VkPhysicalDeviceDynamicRenderingFeatures;
+
+typedef struct VkCommandBufferInheritanceRenderingInfo {
+    VkStructureType   sType;
+    const  void *                                                 pNext;
+    VkRenderingFlags                                             flags;
+    uint32_t                                                                     viewMask;
+    uint32_t                                                     colorAttachmentCount;
+    const  VkFormat *                                  pColorAttachmentFormats;
+    VkFormat                                                                     depthAttachmentFormat;
+    VkFormat                                                                     stencilAttachmentFormat;
+    VkSampleCountFlagBits                                        rasterizationSamples;
+} VkCommandBufferInheritanceRenderingInfo;
+
 typedef struct VkPhysicalDeviceProperties {
     uint32_t         apiVersion;
     uint32_t         driverVersion;
@@ -2875,6 +4735,7 @@
     VkPhysicalDeviceLimits   limits;
     VkPhysicalDeviceSparseProperties   sparseProperties;
 } VkPhysicalDeviceProperties;
+
 typedef struct VkDeviceCreateInfo {
     VkStructureType   sType;
     const  void *      pNext;
@@ -2887,218 +4748,285 @@
     const  char * const*       ppEnabledExtensionNames;
     const  VkPhysicalDeviceFeatures *  pEnabledFeatures;
 } VkDeviceCreateInfo;
+
 typedef struct VkPhysicalDeviceMemoryProperties {
     uint32_t                 memoryTypeCount;
     VkMemoryType             memoryTypes [ VK_MAX_MEMORY_TYPES ];
     uint32_t                 memoryHeapCount;
     VkMemoryHeap             memoryHeaps [ VK_MAX_MEMORY_HEAPS ];
 } VkPhysicalDeviceMemoryProperties;
+
 typedef struct VkPhysicalDeviceProperties2 {
     VkStructureType   sType;
     void *                             pNext;
     VkPhysicalDeviceProperties         properties;
 } VkPhysicalDeviceProperties2;
+
 typedef struct VkPhysicalDeviceMemoryProperties2 {
     VkStructureType   sType;
     void *                             pNext;
     VkPhysicalDeviceMemoryProperties   memoryProperties;
 } VkPhysicalDeviceMemoryProperties2;
 
+typedef struct VkFramebufferAttachmentsCreateInfo {
+    VkStructureType   sType;
+    const  void *                               pNext;
+    uint32_t                   attachmentImageInfoCount;
+    const  VkFramebufferAttachmentImageInfo *  pAttachmentImageInfos;
+} VkFramebufferAttachmentsCreateInfo;
+
+
 
 #define VK_VERSION_1_0 1
 GLAD_API_CALL int GLAD_VK_VERSION_1_0;
 #define VK_VERSION_1_1 1
 GLAD_API_CALL int GLAD_VK_VERSION_1_1;
+#define VK_VERSION_1_2 1
+GLAD_API_CALL int GLAD_VK_VERSION_1_2;
+#define VK_VERSION_1_3 1
+GLAD_API_CALL int GLAD_VK_VERSION_1_3;
 #define VK_EXT_debug_report 1
 GLAD_API_CALL int GLAD_VK_EXT_debug_report;
+#define VK_KHR_portability_enumeration 1
+GLAD_API_CALL int GLAD_VK_KHR_portability_enumeration;
 #define VK_KHR_surface 1
 GLAD_API_CALL int GLAD_VK_KHR_surface;
 #define VK_KHR_swapchain 1
 GLAD_API_CALL int GLAD_VK_KHR_swapchain;
 
 
-typedef VkResult (GLAD_API_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice   device, const  VkAcquireNextImageInfoKHR *  pAcquireInfo, uint32_t *  pImageIndex);
-typedef VkResult (GLAD_API_PTR *PFN_vkAcquireNextImageKHR)(VkDevice   device, VkSwapchainKHR   swapchain, uint64_t   timeout, VkSemaphore   semaphore, VkFence   fence, uint32_t *  pImageIndex);
-typedef VkResult (GLAD_API_PTR *PFN_vkAllocateCommandBuffers)(VkDevice   device, const  VkCommandBufferAllocateInfo *  pAllocateInfo, VkCommandBuffer *  pCommandBuffers);
-typedef VkResult (GLAD_API_PTR *PFN_vkAllocateDescriptorSets)(VkDevice   device, const  VkDescriptorSetAllocateInfo *  pAllocateInfo, VkDescriptorSet *  pDescriptorSets);
-typedef VkResult (GLAD_API_PTR *PFN_vkAllocateMemory)(VkDevice   device, const  VkMemoryAllocateInfo *  pAllocateInfo, const  VkAllocationCallbacks *  pAllocator, VkDeviceMemory *  pMemory);
-typedef VkResult (GLAD_API_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer   commandBuffer, const  VkCommandBufferBeginInfo *  pBeginInfo);
-typedef VkResult (GLAD_API_PTR *PFN_vkBindBufferMemory)(VkDevice   device, VkBuffer   buffer, VkDeviceMemory   memory, VkDeviceSize   memoryOffset);
-typedef VkResult (GLAD_API_PTR *PFN_vkBindBufferMemory2)(VkDevice   device, uint32_t   bindInfoCount, const  VkBindBufferMemoryInfo *  pBindInfos);
-typedef VkResult (GLAD_API_PTR *PFN_vkBindImageMemory)(VkDevice   device, VkImage   image, VkDeviceMemory   memory, VkDeviceSize   memoryOffset);
-typedef VkResult (GLAD_API_PTR *PFN_vkBindImageMemory2)(VkDevice   device, uint32_t   bindInfoCount, const  VkBindImageMemoryInfo *  pBindInfos);
-typedef void (GLAD_API_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer   commandBuffer, VkQueryPool   queryPool, uint32_t   query, VkQueryControlFlags   flags);
-typedef void (GLAD_API_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer   commandBuffer, const  VkRenderPassBeginInfo *  pRenderPassBegin, VkSubpassContents   contents);
-typedef void (GLAD_API_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer   commandBuffer, VkPipelineBindPoint   pipelineBindPoint, VkPipelineLayout   layout, uint32_t   firstSet, uint32_t   descriptorSetCount, const  VkDescriptorSet *  pDescriptorSets, uint32_t   dynamicOffsetCount, const  uint32_t *  pDynamicOffsets);
-typedef void (GLAD_API_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer   commandBuffer, VkBuffer   buffer, VkDeviceSize   offset, VkIndexType   indexType);
-typedef void (GLAD_API_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer   commandBuffer, VkPipelineBindPoint   pipelineBindPoint, VkPipeline   pipeline);
-typedef void (GLAD_API_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer   commandBuffer, uint32_t   firstBinding, uint32_t   bindingCount, const  VkBuffer *  pBuffers, const  VkDeviceSize *  pOffsets);
-typedef void (GLAD_API_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer   commandBuffer, VkImage   srcImage, VkImageLayout   srcImageLayout, VkImage   dstImage, VkImageLayout   dstImageLayout, uint32_t   regionCount, const  VkImageBlit *  pRegions, VkFilter   filter);
-typedef void (GLAD_API_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer   commandBuffer, uint32_t   attachmentCount, const  VkClearAttachment *  pAttachments, uint32_t   rectCount, const  VkClearRect *  pRects);
-typedef void (GLAD_API_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer   commandBuffer, VkImage   image, VkImageLayout   imageLayout, const  VkClearColorValue *  pColor, uint32_t   rangeCount, const  VkImageSubresourceRange *  pRanges);
-typedef void (GLAD_API_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer   commandBuffer, VkImage   image, VkImageLayout   imageLayout, const  VkClearDepthStencilValue *  pDepthStencil, uint32_t   rangeCount, const  VkImageSubresourceRange *  pRanges);
-typedef void (GLAD_API_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer   commandBuffer, VkBuffer   srcBuffer, VkBuffer   dstBuffer, uint32_t   regionCount, const  VkBufferCopy *  pRegions);
-typedef void (GLAD_API_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer   commandBuffer, VkBuffer   srcBuffer, VkImage   dstImage, VkImageLayout   dstImageLayout, uint32_t   regionCount, const  VkBufferImageCopy *  pRegions);
-typedef void (GLAD_API_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer   commandBuffer, VkImage   srcImage, VkImageLayout   srcImageLayout, VkImage   dstImage, VkImageLayout   dstImageLayout, uint32_t   regionCount, const  VkImageCopy *  pRegions);
-typedef void (GLAD_API_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer   commandBuffer, VkImage   srcImage, VkImageLayout   srcImageLayout, VkBuffer   dstBuffer, uint32_t   regionCount, const  VkBufferImageCopy *  pRegions);
-typedef void (GLAD_API_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer   commandBuffer, VkQueryPool   queryPool, uint32_t   firstQuery, uint32_t   queryCount, VkBuffer   dstBuffer, VkDeviceSize   dstOffset, VkDeviceSize   stride, VkQueryResultFlags   flags);
-typedef void (GLAD_API_PTR *PFN_vkCmdDispatch)(VkCommandBuffer   commandBuffer, uint32_t   groupCountX, uint32_t   groupCountY, uint32_t   groupCountZ);
-typedef void (GLAD_API_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer   commandBuffer, uint32_t   baseGroupX, uint32_t   baseGroupY, uint32_t   baseGroupZ, uint32_t   groupCountX, uint32_t   groupCountY, uint32_t   groupCountZ);
-typedef void (GLAD_API_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer   commandBuffer, VkBuffer   buffer, VkDeviceSize   offset);
-typedef void (GLAD_API_PTR *PFN_vkCmdDraw)(VkCommandBuffer   commandBuffer, uint32_t   vertexCount, uint32_t   instanceCount, uint32_t   firstVertex, uint32_t   firstInstance);
-typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer   commandBuffer, uint32_t   indexCount, uint32_t   instanceCount, uint32_t   firstIndex, int32_t   vertexOffset, uint32_t   firstInstance);
-typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer   commandBuffer, VkBuffer   buffer, VkDeviceSize   offset, uint32_t   drawCount, uint32_t   stride);
-typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer   commandBuffer, VkBuffer   buffer, VkDeviceSize   offset, uint32_t   drawCount, uint32_t   stride);
-typedef void (GLAD_API_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer   commandBuffer, VkQueryPool   queryPool, uint32_t   query);
-typedef void (GLAD_API_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer   commandBuffer);
-typedef void (GLAD_API_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer   commandBuffer, uint32_t   commandBufferCount, const  VkCommandBuffer *  pCommandBuffers);
-typedef void (GLAD_API_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer   commandBuffer, VkBuffer   dstBuffer, VkDeviceSize   dstOffset, VkDeviceSize   size, uint32_t   data);
-typedef void (GLAD_API_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer   commandBuffer, VkSubpassContents   contents);
-typedef void (GLAD_API_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer   commandBuffer, VkPipelineStageFlags   srcStageMask, VkPipelineStageFlags   dstStageMask, VkDependencyFlags   dependencyFlags, uint32_t   memoryBarrierCount, const  VkMemoryBarrier *  pMemoryBarriers, uint32_t   bufferMemoryBarrierCount, const  VkBufferMemoryBarrier *  pBufferMemoryBarriers, uint32_t   imageMemoryBarrierCount, const  VkImageMemoryBarrier *  pImageMemoryBarriers);
-typedef void (GLAD_API_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer   commandBuffer, VkPipelineLayout   layout, VkShaderStageFlags   stageFlags, uint32_t   offset, uint32_t   size, const  void *  pValues);
-typedef void (GLAD_API_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer   commandBuffer, VkEvent   event, VkPipelineStageFlags   stageMask);
-typedef void (GLAD_API_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer   commandBuffer, VkQueryPool   queryPool, uint32_t   firstQuery, uint32_t   queryCount);
-typedef void (GLAD_API_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer   commandBuffer, VkImage   srcImage, VkImageLayout   srcImageLayout, VkImage   dstImage, VkImageLayout   dstImageLayout, uint32_t   regionCount, const  VkImageResolve *  pRegions);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetBlendConstants)(VkCommandBuffer   commandBuffer, const  float   blendConstants [4]);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthBias)(VkCommandBuffer   commandBuffer, float   depthBiasConstantFactor, float   depthBiasClamp, float   depthBiasSlopeFactor);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer   commandBuffer, float   minDepthBounds, float   maxDepthBounds);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetDeviceMask)(VkCommandBuffer   commandBuffer, uint32_t   deviceMask);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer   commandBuffer, VkEvent   event, VkPipelineStageFlags   stageMask);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer   commandBuffer, float   lineWidth);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer   commandBuffer, uint32_t   firstScissor, uint32_t   scissorCount, const  VkRect2D *  pScissors);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer   commandBuffer, VkStencilFaceFlags   faceMask, uint32_t   compareMask);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer   commandBuffer, VkStencilFaceFlags   faceMask, uint32_t   reference);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer   commandBuffer, VkStencilFaceFlags   faceMask, uint32_t   writeMask);
-typedef void (GLAD_API_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer   commandBuffer, uint32_t   firstViewport, uint32_t   viewportCount, const  VkViewport *  pViewports);
-typedef void (GLAD_API_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer   commandBuffer, VkBuffer   dstBuffer, VkDeviceSize   dstOffset, VkDeviceSize   dataSize, const  void *  pData);
-typedef void (GLAD_API_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer   commandBuffer, uint32_t   eventCount, const  VkEvent *  pEvents, VkPipelineStageFlags   srcStageMask, VkPipelineStageFlags   dstStageMask, uint32_t   memoryBarrierCount, const  VkMemoryBarrier *  pMemoryBarriers, uint32_t   bufferMemoryBarrierCount, const  VkBufferMemoryBarrier *  pBufferMemoryBarriers, uint32_t   imageMemoryBarrierCount, const  VkImageMemoryBarrier *  pImageMemoryBarriers);
-typedef void (GLAD_API_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer   commandBuffer, VkPipelineStageFlagBits   pipelineStage, VkQueryPool   queryPool, uint32_t   query);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateBuffer)(VkDevice   device, const  VkBufferCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkBuffer *  pBuffer);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateBufferView)(VkDevice   device, const  VkBufferViewCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkBufferView *  pView);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateCommandPool)(VkDevice   device, const  VkCommandPoolCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkCommandPool *  pCommandPool);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateComputePipelines)(VkDevice   device, VkPipelineCache   pipelineCache, uint32_t   createInfoCount, const  VkComputePipelineCreateInfo *  pCreateInfos, const  VkAllocationCallbacks *  pAllocator, VkPipeline *  pPipelines);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance   instance, const  VkDebugReportCallbackCreateInfoEXT *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkDebugReportCallbackEXT *  pCallback);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateDescriptorPool)(VkDevice   device, const  VkDescriptorPoolCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkDescriptorPool *  pDescriptorPool);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateDescriptorSetLayout)(VkDevice   device, const  VkDescriptorSetLayoutCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkDescriptorSetLayout *  pSetLayout);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateDescriptorUpdateTemplate)(VkDevice   device, const  VkDescriptorUpdateTemplateCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkDescriptorUpdateTemplate *  pDescriptorUpdateTemplate);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateDevice)(VkPhysicalDevice   physicalDevice, const  VkDeviceCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkDevice *  pDevice);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateEvent)(VkDevice   device, const  VkEventCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkEvent *  pEvent);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateFence)(VkDevice   device, const  VkFenceCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkFence *  pFence);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateFramebuffer)(VkDevice   device, const  VkFramebufferCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkFramebuffer *  pFramebuffer);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice   device, VkPipelineCache   pipelineCache, uint32_t   createInfoCount, const  VkGraphicsPipelineCreateInfo *  pCreateInfos, const  VkAllocationCallbacks *  pAllocator, VkPipeline *  pPipelines);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateImage)(VkDevice   device, const  VkImageCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkImage *  pImage);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateImageView)(VkDevice   device, const  VkImageViewCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkImageView *  pView);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateInstance)(const  VkInstanceCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkInstance *  pInstance);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreatePipelineCache)(VkDevice   device, const  VkPipelineCacheCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkPipelineCache *  pPipelineCache);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreatePipelineLayout)(VkDevice   device, const  VkPipelineLayoutCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkPipelineLayout *  pPipelineLayout);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateQueryPool)(VkDevice   device, const  VkQueryPoolCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkQueryPool *  pQueryPool);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateRenderPass)(VkDevice   device, const  VkRenderPassCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkRenderPass *  pRenderPass);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateSampler)(VkDevice   device, const  VkSamplerCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkSampler *  pSampler);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice   device, const  VkSamplerYcbcrConversionCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkSamplerYcbcrConversion *  pYcbcrConversion);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateSemaphore)(VkDevice   device, const  VkSemaphoreCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkSemaphore *  pSemaphore);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateShaderModule)(VkDevice   device, const  VkShaderModuleCreateInfo *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkShaderModule *  pShaderModule);
-typedef VkResult (GLAD_API_PTR *PFN_vkCreateSwapchainKHR)(VkDevice   device, const  VkSwapchainCreateInfoKHR *  pCreateInfo, const  VkAllocationCallbacks *  pAllocator, VkSwapchainKHR *  pSwapchain);
-typedef void (GLAD_API_PTR *PFN_vkDebugReportMessageEXT)(VkInstance   instance, VkDebugReportFlagsEXT   flags, VkDebugReportObjectTypeEXT   objectType, uint64_t   object, size_t   location, int32_t   messageCode, const  char *  pLayerPrefix, const  char *  pMessage);
-typedef void (GLAD_API_PTR *PFN_vkDestroyBuffer)(VkDevice   device, VkBuffer   buffer, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyBufferView)(VkDevice   device, VkBufferView   bufferView, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyCommandPool)(VkDevice   device, VkCommandPool   commandPool, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance   instance, VkDebugReportCallbackEXT   callback, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyDescriptorPool)(VkDevice   device, VkDescriptorPool   descriptorPool, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyDescriptorSetLayout)(VkDevice   device, VkDescriptorSetLayout   descriptorSetLayout, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyDescriptorUpdateTemplate)(VkDevice   device, VkDescriptorUpdateTemplate   descriptorUpdateTemplate, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyDevice)(VkDevice   device, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyEvent)(VkDevice   device, VkEvent   event, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyFence)(VkDevice   device, VkFence   fence, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyFramebuffer)(VkDevice   device, VkFramebuffer   framebuffer, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyImage)(VkDevice   device, VkImage   image, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyImageView)(VkDevice   device, VkImageView   imageView, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyInstance)(VkInstance   instance, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyPipeline)(VkDevice   device, VkPipeline   pipeline, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyPipelineCache)(VkDevice   device, VkPipelineCache   pipelineCache, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyPipelineLayout)(VkDevice   device, VkPipelineLayout   pipelineLayout, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyQueryPool)(VkDevice   device, VkQueryPool   queryPool, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyRenderPass)(VkDevice   device, VkRenderPass   renderPass, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroySampler)(VkDevice   device, VkSampler   sampler, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroySamplerYcbcrConversion)(VkDevice   device, VkSamplerYcbcrConversion   ycbcrConversion, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroySemaphore)(VkDevice   device, VkSemaphore   semaphore, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroyShaderModule)(VkDevice   device, VkShaderModule   shaderModule, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroySurfaceKHR)(VkInstance   instance, VkSurfaceKHR   surface, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkDestroySwapchainKHR)(VkDevice   device, VkSwapchainKHR   swapchain, const  VkAllocationCallbacks *  pAllocator);
-typedef VkResult (GLAD_API_PTR *PFN_vkDeviceWaitIdle)(VkDevice   device);
-typedef VkResult (GLAD_API_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer   commandBuffer);
-typedef VkResult (GLAD_API_PTR *PFN_vkEnumerateDeviceExtensionProperties)(VkPhysicalDevice   physicalDevice, const  char *  pLayerName, uint32_t *  pPropertyCount, VkExtensionProperties *  pProperties);
-typedef VkResult (GLAD_API_PTR *PFN_vkEnumerateDeviceLayerProperties)(VkPhysicalDevice   physicalDevice, uint32_t *  pPropertyCount, VkLayerProperties *  pProperties);
-typedef VkResult (GLAD_API_PTR *PFN_vkEnumerateInstanceExtensionProperties)(const  char *  pLayerName, uint32_t *  pPropertyCount, VkExtensionProperties *  pProperties);
-typedef VkResult (GLAD_API_PTR *PFN_vkEnumerateInstanceLayerProperties)(uint32_t *  pPropertyCount, VkLayerProperties *  pProperties);
-typedef VkResult (GLAD_API_PTR *PFN_vkEnumerateInstanceVersion)(uint32_t *  pApiVersion);
-typedef VkResult (GLAD_API_PTR *PFN_vkEnumeratePhysicalDeviceGroups)(VkInstance   instance, uint32_t *  pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties *  pPhysicalDeviceGroupProperties);
-typedef VkResult (GLAD_API_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance   instance, uint32_t *  pPhysicalDeviceCount, VkPhysicalDevice *  pPhysicalDevices);
-typedef VkResult (GLAD_API_PTR *PFN_vkFlushMappedMemoryRanges)(VkDevice   device, uint32_t   memoryRangeCount, const  VkMappedMemoryRange *  pMemoryRanges);
-typedef void (GLAD_API_PTR *PFN_vkFreeCommandBuffers)(VkDevice   device, VkCommandPool   commandPool, uint32_t   commandBufferCount, const  VkCommandBuffer *  pCommandBuffers);
-typedef VkResult (GLAD_API_PTR *PFN_vkFreeDescriptorSets)(VkDevice   device, VkDescriptorPool   descriptorPool, uint32_t   descriptorSetCount, const  VkDescriptorSet *  pDescriptorSets);
-typedef void (GLAD_API_PTR *PFN_vkFreeMemory)(VkDevice   device, VkDeviceMemory   memory, const  VkAllocationCallbacks *  pAllocator);
-typedef void (GLAD_API_PTR *PFN_vkGetBufferMemoryRequirements)(VkDevice   device, VkBuffer   buffer, VkMemoryRequirements *  pMemoryRequirements);
-typedef void (GLAD_API_PTR *PFN_vkGetBufferMemoryRequirements2)(VkDevice   device, const  VkBufferMemoryRequirementsInfo2 *  pInfo, VkMemoryRequirements2 *  pMemoryRequirements);
-typedef void (GLAD_API_PTR *PFN_vkGetDescriptorSetLayoutSupport)(VkDevice   device, const  VkDescriptorSetLayoutCreateInfo *  pCreateInfo, VkDescriptorSetLayoutSupport *  pSupport);
-typedef void (GLAD_API_PTR *PFN_vkGetDeviceGroupPeerMemoryFeatures)(VkDevice   device, uint32_t   heapIndex, uint32_t   localDeviceIndex, uint32_t   remoteDeviceIndex, VkPeerMemoryFeatureFlags *  pPeerMemoryFeatures);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice   device, VkDeviceGroupPresentCapabilitiesKHR *  pDeviceGroupPresentCapabilities);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice   device, VkSurfaceKHR   surface, VkDeviceGroupPresentModeFlagsKHR *  pModes);
-typedef void (GLAD_API_PTR *PFN_vkGetDeviceMemoryCommitment)(VkDevice   device, VkDeviceMemory   memory, VkDeviceSize *  pCommittedMemoryInBytes);
-typedef PFN_vkVoidFunction (GLAD_API_PTR *PFN_vkGetDeviceProcAddr)(VkDevice   device, const  char *  pName);
-typedef void (GLAD_API_PTR *PFN_vkGetDeviceQueue)(VkDevice   device, uint32_t   queueFamilyIndex, uint32_t   queueIndex, VkQueue *  pQueue);
-typedef void (GLAD_API_PTR *PFN_vkGetDeviceQueue2)(VkDevice   device, const  VkDeviceQueueInfo2 *  pQueueInfo, VkQueue *  pQueue);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetEventStatus)(VkDevice   device, VkEvent   event);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetFenceStatus)(VkDevice   device, VkFence   fence);
-typedef void (GLAD_API_PTR *PFN_vkGetImageMemoryRequirements)(VkDevice   device, VkImage   image, VkMemoryRequirements *  pMemoryRequirements);
-typedef void (GLAD_API_PTR *PFN_vkGetImageMemoryRequirements2)(VkDevice   device, const  VkImageMemoryRequirementsInfo2 *  pInfo, VkMemoryRequirements2 *  pMemoryRequirements);
-typedef void (GLAD_API_PTR *PFN_vkGetImageSparseMemoryRequirements)(VkDevice   device, VkImage   image, uint32_t *  pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements *  pSparseMemoryRequirements);
-typedef void (GLAD_API_PTR *PFN_vkGetImageSparseMemoryRequirements2)(VkDevice   device, const  VkImageSparseMemoryRequirementsInfo2 *  pInfo, uint32_t *  pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2 *  pSparseMemoryRequirements);
-typedef void (GLAD_API_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice   device, VkImage   image, const  VkImageSubresource *  pSubresource, VkSubresourceLayout *  pLayout);
-typedef PFN_vkVoidFunction (GLAD_API_PTR *PFN_vkGetInstanceProcAddr)(VkInstance   instance, const  char *  pName);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceExternalBufferProperties)(VkPhysicalDevice   physicalDevice, const  VkPhysicalDeviceExternalBufferInfo *  pExternalBufferInfo, VkExternalBufferProperties *  pExternalBufferProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceExternalFenceProperties)(VkPhysicalDevice   physicalDevice, const  VkPhysicalDeviceExternalFenceInfo *  pExternalFenceInfo, VkExternalFenceProperties *  pExternalFenceProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)(VkPhysicalDevice   physicalDevice, const  VkPhysicalDeviceExternalSemaphoreInfo *  pExternalSemaphoreInfo, VkExternalSemaphoreProperties *  pExternalSemaphoreProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice   physicalDevice, VkPhysicalDeviceFeatures *  pFeatures);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFeatures2)(VkPhysicalDevice   physicalDevice, VkPhysicalDeviceFeatures2 *  pFeatures);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice   physicalDevice, VkFormat   format, VkFormatProperties *  pFormatProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFormatProperties2)(VkPhysicalDevice   physicalDevice, VkFormat   format, VkFormatProperties2 *  pFormatProperties);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice   physicalDevice, VkFormat   format, VkImageType   type, VkImageTiling   tiling, VkImageUsageFlags   usage, VkImageCreateFlags   flags, VkImageFormatProperties *  pImageFormatProperties);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2)(VkPhysicalDevice   physicalDevice, const  VkPhysicalDeviceImageFormatInfo2 *  pImageFormatInfo, VkImageFormatProperties2 *  pImageFormatProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice   physicalDevice, VkPhysicalDeviceMemoryProperties *  pMemoryProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2)(VkPhysicalDevice   physicalDevice, VkPhysicalDeviceMemoryProperties2 *  pMemoryProperties);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice   physicalDevice, VkSurfaceKHR   surface, uint32_t *  pRectCount, VkRect2D *  pRects);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice   physicalDevice, VkPhysicalDeviceProperties *  pProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice   physicalDevice, VkPhysicalDeviceProperties2 *  pProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice   physicalDevice, uint32_t *  pQueueFamilyPropertyCount, VkQueueFamilyProperties *  pQueueFamilyProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2)(VkPhysicalDevice   physicalDevice, uint32_t *  pQueueFamilyPropertyCount, VkQueueFamilyProperties2 *  pQueueFamilyProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice   physicalDevice, VkFormat   format, VkImageType   type, VkSampleCountFlagBits   samples, VkImageUsageFlags   usage, VkImageTiling   tiling, uint32_t *  pPropertyCount, VkSparseImageFormatProperties *  pProperties);
-typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice   physicalDevice, const  VkPhysicalDeviceSparseImageFormatInfo2 *  pFormatInfo, uint32_t *  pPropertyCount, VkSparseImageFormatProperties2 *  pProperties);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice   physicalDevice, VkSurfaceKHR   surface, VkSurfaceCapabilitiesKHR *  pSurfaceCapabilities);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice   physicalDevice, VkSurfaceKHR   surface, uint32_t *  pSurfaceFormatCount, VkSurfaceFormatKHR *  pSurfaceFormats);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice   physicalDevice, VkSurfaceKHR   surface, uint32_t *  pPresentModeCount, VkPresentModeKHR *  pPresentModes);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice   physicalDevice, uint32_t   queueFamilyIndex, VkSurfaceKHR   surface, VkBool32 *  pSupported);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetPipelineCacheData)(VkDevice   device, VkPipelineCache   pipelineCache, size_t *  pDataSize, void *  pData);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetQueryPoolResults)(VkDevice   device, VkQueryPool   queryPool, uint32_t   firstQuery, uint32_t   queryCount, size_t   dataSize, void *  pData, VkDeviceSize   stride, VkQueryResultFlags   flags);
-typedef void (GLAD_API_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice   device, VkRenderPass   renderPass, VkExtent2D *  pGranularity);
-typedef VkResult (GLAD_API_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice   device, VkSwapchainKHR   swapchain, uint32_t *  pSwapchainImageCount, VkImage *  pSwapchainImages);
-typedef VkResult (GLAD_API_PTR *PFN_vkInvalidateMappedMemoryRanges)(VkDevice   device, uint32_t   memoryRangeCount, const  VkMappedMemoryRange *  pMemoryRanges);
-typedef VkResult (GLAD_API_PTR *PFN_vkMapMemory)(VkDevice   device, VkDeviceMemory   memory, VkDeviceSize   offset, VkDeviceSize   size, VkMemoryMapFlags   flags, void **  ppData);
-typedef VkResult (GLAD_API_PTR *PFN_vkMergePipelineCaches)(VkDevice   device, VkPipelineCache   dstCache, uint32_t   srcCacheCount, const  VkPipelineCache *  pSrcCaches);
-typedef VkResult (GLAD_API_PTR *PFN_vkQueueBindSparse)(VkQueue   queue, uint32_t   bindInfoCount, const  VkBindSparseInfo *  pBindInfo, VkFence   fence);
-typedef VkResult (GLAD_API_PTR *PFN_vkQueuePresentKHR)(VkQueue   queue, const  VkPresentInfoKHR *  pPresentInfo);
-typedef VkResult (GLAD_API_PTR *PFN_vkQueueSubmit)(VkQueue   queue, uint32_t   submitCount, const  VkSubmitInfo *  pSubmits, VkFence   fence);
-typedef VkResult (GLAD_API_PTR *PFN_vkQueueWaitIdle)(VkQueue   queue);
-typedef VkResult (GLAD_API_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer   commandBuffer, VkCommandBufferResetFlags   flags);
-typedef VkResult (GLAD_API_PTR *PFN_vkResetCommandPool)(VkDevice   device, VkCommandPool   commandPool, VkCommandPoolResetFlags   flags);
-typedef VkResult (GLAD_API_PTR *PFN_vkResetDescriptorPool)(VkDevice   device, VkDescriptorPool   descriptorPool, VkDescriptorPoolResetFlags   flags);
-typedef VkResult (GLAD_API_PTR *PFN_vkResetEvent)(VkDevice   device, VkEvent   event);
-typedef VkResult (GLAD_API_PTR *PFN_vkResetFences)(VkDevice   device, uint32_t   fenceCount, const  VkFence *  pFences);
-typedef VkResult (GLAD_API_PTR *PFN_vkSetEvent)(VkDevice   device, VkEvent   event);
-typedef void (GLAD_API_PTR *PFN_vkTrimCommandPool)(VkDevice   device, VkCommandPool   commandPool, VkCommandPoolTrimFlags   flags);
-typedef void (GLAD_API_PTR *PFN_vkUnmapMemory)(VkDevice   device, VkDeviceMemory   memory);
-typedef void (GLAD_API_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice   device, VkDescriptorSet   descriptorSet, VkDescriptorUpdateTemplate   descriptorUpdateTemplate, const  void *  pData);
-typedef void (GLAD_API_PTR *PFN_vkUpdateDescriptorSets)(VkDevice   device, uint32_t   descriptorWriteCount, const  VkWriteDescriptorSet *  pDescriptorWrites, uint32_t   descriptorCopyCount, const  VkCopyDescriptorSet *  pDescriptorCopies);
-typedef VkResult (GLAD_API_PTR *PFN_vkWaitForFences)(VkDevice   device, uint32_t   fenceCount, const  VkFence *  pFences, VkBool32   waitAll, uint64_t   timeout);
+typedef VkResult (GLAD_API_PTR *PFN_vkAcquireNextImage2KHR)(VkDevice device, const VkAcquireNextImageInfoKHR * pAcquireInfo, uint32_t * pImageIndex);
+typedef VkResult (GLAD_API_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t * pImageIndex);
+typedef VkResult (GLAD_API_PTR *PFN_vkAllocateCommandBuffers)(VkDevice device, const VkCommandBufferAllocateInfo * pAllocateInfo, VkCommandBuffer * pCommandBuffers);
+typedef VkResult (GLAD_API_PTR *PFN_vkAllocateDescriptorSets)(VkDevice device, const VkDescriptorSetAllocateInfo * pAllocateInfo, VkDescriptorSet * pDescriptorSets);
+typedef VkResult (GLAD_API_PTR *PFN_vkAllocateMemory)(VkDevice device, const VkMemoryAllocateInfo * pAllocateInfo, const VkAllocationCallbacks * pAllocator, VkDeviceMemory * pMemory);
+typedef VkResult (GLAD_API_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo * pBeginInfo);
+typedef VkResult (GLAD_API_PTR *PFN_vkBindBufferMemory)(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset);
+typedef VkResult (GLAD_API_PTR *PFN_vkBindBufferMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo * pBindInfos);
+typedef VkResult (GLAD_API_PTR *PFN_vkBindImageMemory)(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset);
+typedef VkResult (GLAD_API_PTR *PFN_vkBindImageMemory2)(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo * pBindInfos);
+typedef void (GLAD_API_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags);
+typedef void (GLAD_API_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo * pRenderPassBegin, VkSubpassContents contents);
+typedef void (GLAD_API_PTR *PFN_vkCmdBeginRenderPass2)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo * pRenderPassBegin, const VkSubpassBeginInfo * pSubpassBeginInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdBeginRendering)(VkCommandBuffer commandBuffer, const VkRenderingInfo * pRenderingInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet * pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t * pDynamicOffsets);
+typedef void (GLAD_API_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType);
+typedef void (GLAD_API_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline);
+typedef void (GLAD_API_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer * pBuffers, const VkDeviceSize * pOffsets);
+typedef void (GLAD_API_PTR *PFN_vkCmdBindVertexBuffers2)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer * pBuffers, const VkDeviceSize * pOffsets, const VkDeviceSize * pSizes, const VkDeviceSize * pStrides);
+typedef void (GLAD_API_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit * pRegions, VkFilter filter);
+typedef void (GLAD_API_PTR *PFN_vkCmdBlitImage2)(VkCommandBuffer commandBuffer, const VkBlitImageInfo2 * pBlitImageInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment * pAttachments, uint32_t rectCount, const VkClearRect * pRects);
+typedef void (GLAD_API_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue * pColor, uint32_t rangeCount, const VkImageSubresourceRange * pRanges);
+typedef void (GLAD_API_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue * pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange * pRanges);
+typedef void (GLAD_API_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy * pRegions);
+typedef void (GLAD_API_PTR *PFN_vkCmdCopyBuffer2)(VkCommandBuffer commandBuffer, const VkCopyBufferInfo2 * pCopyBufferInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy * pRegions);
+typedef void (GLAD_API_PTR *PFN_vkCmdCopyBufferToImage2)(VkCommandBuffer commandBuffer, const VkCopyBufferToImageInfo2 * pCopyBufferToImageInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy * pRegions);
+typedef void (GLAD_API_PTR *PFN_vkCmdCopyImage2)(VkCommandBuffer commandBuffer, const VkCopyImageInfo2 * pCopyImageInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy * pRegions);
+typedef void (GLAD_API_PTR *PFN_vkCmdCopyImageToBuffer2)(VkCommandBuffer commandBuffer, const VkCopyImageToBufferInfo2 * pCopyImageToBufferInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags);
+typedef void (GLAD_API_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+typedef void (GLAD_API_PTR *PFN_vkCmdDispatchBase)(VkCommandBuffer commandBuffer, uint32_t baseGroupX, uint32_t baseGroupY, uint32_t baseGroupZ, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+typedef void (GLAD_API_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset);
+typedef void (GLAD_API_PTR *PFN_vkCmdDraw)(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance);
+typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
+typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndexedIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+typedef void (GLAD_API_PTR *PFN_vkCmdDrawIndirectCount)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkBuffer countBuffer, VkDeviceSize countBufferOffset, uint32_t maxDrawCount, uint32_t stride);
+typedef void (GLAD_API_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query);
+typedef void (GLAD_API_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer commandBuffer);
+typedef void (GLAD_API_PTR *PFN_vkCmdEndRenderPass2)(VkCommandBuffer commandBuffer, const VkSubpassEndInfo * pSubpassEndInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdEndRendering)(VkCommandBuffer commandBuffer);
+typedef void (GLAD_API_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer * pCommandBuffers);
+typedef void (GLAD_API_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data);
+typedef void (GLAD_API_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer commandBuffer, VkSubpassContents contents);
+typedef void (GLAD_API_PTR *PFN_vkCmdNextSubpass2)(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo * pSubpassBeginInfo, const VkSubpassEndInfo * pSubpassEndInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier * pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier * pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier * pImageMemoryBarriers);
+typedef void (GLAD_API_PTR *PFN_vkCmdPipelineBarrier2)(VkCommandBuffer commandBuffer, const VkDependencyInfo * pDependencyInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void * pValues);
+typedef void (GLAD_API_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+typedef void (GLAD_API_PTR *PFN_vkCmdResetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags2 stageMask);
+typedef void (GLAD_API_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
+typedef void (GLAD_API_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve * pRegions);
+typedef void (GLAD_API_PTR *PFN_vkCmdResolveImage2)(VkCommandBuffer commandBuffer, const VkResolveImageInfo2 * pResolveImageInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetBlendConstants)(VkCommandBuffer commandBuffer, const float blendConstants [4]);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetCullMode)(VkCommandBuffer commandBuffer, VkCullModeFlags cullMode);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthBias)(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthBiasEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBiasEnable);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthBoundsTestEnable)(VkCommandBuffer commandBuffer, VkBool32 depthBoundsTestEnable);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthCompareOp)(VkCommandBuffer commandBuffer, VkCompareOp depthCompareOp);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthTestEnable)(VkCommandBuffer commandBuffer, VkBool32 depthTestEnable);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetDepthWriteEnable)(VkCommandBuffer commandBuffer, VkBool32 depthWriteEnable);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetDeviceMask)(VkCommandBuffer commandBuffer, uint32_t deviceMask);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetEvent2)(VkCommandBuffer commandBuffer, VkEvent event, const VkDependencyInfo * pDependencyInfo);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetFrontFace)(VkCommandBuffer commandBuffer, VkFrontFace frontFace);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer commandBuffer, float lineWidth);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetPrimitiveRestartEnable)(VkCommandBuffer commandBuffer, VkBool32 primitiveRestartEnable);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetPrimitiveTopology)(VkCommandBuffer commandBuffer, VkPrimitiveTopology primitiveTopology);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetRasterizerDiscardEnable)(VkCommandBuffer commandBuffer, VkBool32 rasterizerDiscardEnable);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D * pScissors);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetScissorWithCount)(VkCommandBuffer commandBuffer, uint32_t scissorCount, const VkRect2D * pScissors);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilOp)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, VkStencilOp failOp, VkStencilOp passOp, VkStencilOp depthFailOp, VkCompareOp compareOp);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilTestEnable)(VkCommandBuffer commandBuffer, VkBool32 stencilTestEnable);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport * pViewports);
+typedef void (GLAD_API_PTR *PFN_vkCmdSetViewportWithCount)(VkCommandBuffer commandBuffer, uint32_t viewportCount, const VkViewport * pViewports);
+typedef void (GLAD_API_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void * pData);
+typedef void (GLAD_API_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent * pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier * pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier * pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier * pImageMemoryBarriers);
+typedef void (GLAD_API_PTR *PFN_vkCmdWaitEvents2)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent * pEvents, const VkDependencyInfo * pDependencyInfos);
+typedef void (GLAD_API_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query);
+typedef void (GLAD_API_PTR *PFN_vkCmdWriteTimestamp2)(VkCommandBuffer commandBuffer, VkPipelineStageFlags2 stage, VkQueryPool queryPool, uint32_t query);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkBuffer * pBuffer);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkBufferView * pView);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkCommandPool * pCommandPool);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateComputePipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo * pCreateInfos, const VkAllocationCallbacks * pAllocator, VkPipeline * pPipelines);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkDebugReportCallbackEXT * pCallback);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateDescriptorPool)(VkDevice device, const VkDescriptorPoolCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkDescriptorPool * pDescriptorPool);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateDescriptorSetLayout)(VkDevice device, const VkDescriptorSetLayoutCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkDescriptorSetLayout * pSetLayout);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateDescriptorUpdateTemplate)(VkDevice device, const VkDescriptorUpdateTemplateCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkDescriptorUpdateTemplate * pDescriptorUpdateTemplate);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateDevice)(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkDevice * pDevice);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkEvent * pEvent);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateFence)(VkDevice device, const VkFenceCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkFence * pFence);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateFramebuffer)(VkDevice device, const VkFramebufferCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkFramebuffer * pFramebuffer);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo * pCreateInfos, const VkAllocationCallbacks * pAllocator, VkPipeline * pPipelines);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkImage * pImage);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateImageView)(VkDevice device, const VkImageViewCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkImageView * pView);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkInstance * pInstance);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkPipelineCache * pPipelineCache);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkPipelineLayout * pPipelineLayout);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreatePrivateDataSlot)(VkDevice device, const VkPrivateDataSlotCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkPrivateDataSlot * pPrivateDataSlot);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkQueryPool * pQueryPool);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkRenderPass * pRenderPass);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateRenderPass2)(VkDevice device, const VkRenderPassCreateInfo2 * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkRenderPass * pRenderPass);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateSampler)(VkDevice device, const VkSamplerCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkSampler * pSampler);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateSamplerYcbcrConversion)(VkDevice device, const VkSamplerYcbcrConversionCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkSamplerYcbcrConversion * pYcbcrConversion);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkSemaphore * pSemaphore);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateShaderModule)(VkDevice device, const VkShaderModuleCreateInfo * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkShaderModule * pShaderModule);
+typedef VkResult (GLAD_API_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR * pCreateInfo, const VkAllocationCallbacks * pAllocator, VkSwapchainKHR * pSwapchain);
+typedef void (GLAD_API_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char * pLayerPrefix, const char * pMessage);
+typedef void (GLAD_API_PTR *PFN_vkDestroyBuffer)(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyCommandPool)(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyDescriptorSetLayout)(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyDescriptorUpdateTemplate)(VkDevice device, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyDevice)(VkDevice device, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyEvent)(VkDevice device, VkEvent event, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyFence)(VkDevice device, VkFence fence, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyFramebuffer)(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyImage)(VkDevice device, VkImage image, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyImageView)(VkDevice device, VkImageView imageView, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyPipelineLayout)(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyPrivateDataSlot)(VkDevice device, VkPrivateDataSlot privateDataSlot, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroySampler)(VkDevice device, VkSampler sampler, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroySamplerYcbcrConversion)(VkDevice device, VkSamplerYcbcrConversion ycbcrConversion, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroySemaphore)(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroyShaderModule)(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks * pAllocator);
+typedef void (GLAD_API_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks * pAllocator);
+typedef VkResult (GLAD_API_PTR *PFN_vkDeviceWaitIdle)(VkDevice device);
+typedef VkResult (GLAD_API_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer commandBuffer);
+typedef VkResult (GLAD_API_PTR *PFN_vkEnumerateDeviceExtensionProperties)(VkPhysicalDevice physicalDevice, const char * pLayerName, uint32_t * pPropertyCount, VkExtensionProperties * pProperties);
+typedef VkResult (GLAD_API_PTR *PFN_vkEnumerateDeviceLayerProperties)(VkPhysicalDevice physicalDevice, uint32_t * pPropertyCount, VkLayerProperties * pProperties);
+typedef VkResult (GLAD_API_PTR *PFN_vkEnumerateInstanceExtensionProperties)(const char * pLayerName, uint32_t * pPropertyCount, VkExtensionProperties * pProperties);
+typedef VkResult (GLAD_API_PTR *PFN_vkEnumerateInstanceLayerProperties)(uint32_t * pPropertyCount, VkLayerProperties * pProperties);
+typedef VkResult (GLAD_API_PTR *PFN_vkEnumerateInstanceVersion)(uint32_t * pApiVersion);
+typedef VkResult (GLAD_API_PTR *PFN_vkEnumeratePhysicalDeviceGroups)(VkInstance instance, uint32_t * pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties * pPhysicalDeviceGroupProperties);
+typedef VkResult (GLAD_API_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t * pPhysicalDeviceCount, VkPhysicalDevice * pPhysicalDevices);
+typedef VkResult (GLAD_API_PTR *PFN_vkFlushMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange * pMemoryRanges);
+typedef void (GLAD_API_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer * pCommandBuffers);
+typedef VkResult (GLAD_API_PTR *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet * pDescriptorSets);
+typedef void (GLAD_API_PTR *PFN_vkFreeMemory)(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks * pAllocator);
+typedef VkDeviceAddress (GLAD_API_PTR *PFN_vkGetBufferDeviceAddress)(VkDevice device, const VkBufferDeviceAddressInfo * pInfo);
+typedef void (GLAD_API_PTR *PFN_vkGetBufferMemoryRequirements)(VkDevice device, VkBuffer buffer, VkMemoryRequirements * pMemoryRequirements);
+typedef void (GLAD_API_PTR *PFN_vkGetBufferMemoryRequirements2)(VkDevice device, const VkBufferMemoryRequirementsInfo2 * pInfo, VkMemoryRequirements2 * pMemoryRequirements);
+typedef uint64_t (GLAD_API_PTR *PFN_vkGetBufferOpaqueCaptureAddress)(VkDevice device, const VkBufferDeviceAddressInfo * pInfo);
+typedef void (GLAD_API_PTR *PFN_vkGetDescriptorSetLayoutSupport)(VkDevice device, const VkDescriptorSetLayoutCreateInfo * pCreateInfo, VkDescriptorSetLayoutSupport * pSupport);
+typedef void (GLAD_API_PTR *PFN_vkGetDeviceBufferMemoryRequirements)(VkDevice device, const VkDeviceBufferMemoryRequirements * pInfo, VkMemoryRequirements2 * pMemoryRequirements);
+typedef void (GLAD_API_PTR *PFN_vkGetDeviceGroupPeerMemoryFeatures)(VkDevice device, uint32_t heapIndex, uint32_t localDeviceIndex, uint32_t remoteDeviceIndex, VkPeerMemoryFeatureFlags * pPeerMemoryFeatures);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetDeviceGroupPresentCapabilitiesKHR)(VkDevice device, VkDeviceGroupPresentCapabilitiesKHR * pDeviceGroupPresentCapabilities);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetDeviceGroupSurfacePresentModesKHR)(VkDevice device, VkSurfaceKHR surface, VkDeviceGroupPresentModeFlagsKHR * pModes);
+typedef void (GLAD_API_PTR *PFN_vkGetDeviceImageMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements * pInfo, VkMemoryRequirements2 * pMemoryRequirements);
+typedef void (GLAD_API_PTR *PFN_vkGetDeviceImageSparseMemoryRequirements)(VkDevice device, const VkDeviceImageMemoryRequirements * pInfo, uint32_t * pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements);
+typedef void (GLAD_API_PTR *PFN_vkGetDeviceMemoryCommitment)(VkDevice device, VkDeviceMemory memory, VkDeviceSize * pCommittedMemoryInBytes);
+typedef uint64_t (GLAD_API_PTR *PFN_vkGetDeviceMemoryOpaqueCaptureAddress)(VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo * pInfo);
+typedef PFN_vkVoidFunction (GLAD_API_PTR *PFN_vkGetDeviceProcAddr)(VkDevice device, const char * pName);
+typedef void (GLAD_API_PTR *PFN_vkGetDeviceQueue)(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue * pQueue);
+typedef void (GLAD_API_PTR *PFN_vkGetDeviceQueue2)(VkDevice device, const VkDeviceQueueInfo2 * pQueueInfo, VkQueue * pQueue);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetEventStatus)(VkDevice device, VkEvent event);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetFenceStatus)(VkDevice device, VkFence fence);
+typedef void (GLAD_API_PTR *PFN_vkGetImageMemoryRequirements)(VkDevice device, VkImage image, VkMemoryRequirements * pMemoryRequirements);
+typedef void (GLAD_API_PTR *PFN_vkGetImageMemoryRequirements2)(VkDevice device, const VkImageMemoryRequirementsInfo2 * pInfo, VkMemoryRequirements2 * pMemoryRequirements);
+typedef void (GLAD_API_PTR *PFN_vkGetImageSparseMemoryRequirements)(VkDevice device, VkImage image, uint32_t * pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements * pSparseMemoryRequirements);
+typedef void (GLAD_API_PTR *PFN_vkGetImageSparseMemoryRequirements2)(VkDevice device, const VkImageSparseMemoryRequirementsInfo2 * pInfo, uint32_t * pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements);
+typedef void (GLAD_API_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource * pSubresource, VkSubresourceLayout * pLayout);
+typedef PFN_vkVoidFunction (GLAD_API_PTR *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char * pName);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceExternalBufferProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalBufferInfo * pExternalBufferInfo, VkExternalBufferProperties * pExternalBufferProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceExternalFenceProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalFenceInfo * pExternalFenceInfo, VkExternalFenceProperties * pExternalFenceProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceExternalSemaphoreProperties)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo * pExternalSemaphoreInfo, VkExternalSemaphoreProperties * pExternalSemaphoreProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures * pFeatures);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFeatures2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2 * pFeatures);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties * pFormatProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceFormatProperties2)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties2 * pFormatProperties);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties * pImageFormatProperties);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 * pImageFormatInfo, VkImageFormatProperties2 * pImageFormatProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties * pMemoryProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceMemoryProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties2 * pMemoryProperties);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDevicePresentRectanglesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t * pRectCount, VkRect2D * pRects);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties * pProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceProperties2)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 * pProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice physicalDevice, uint32_t * pQueueFamilyPropertyCount, VkQueueFamilyProperties * pQueueFamilyProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties2)(VkPhysicalDevice physicalDevice, uint32_t * pQueueFamilyPropertyCount, VkQueueFamilyProperties2 * pQueueFamilyProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t * pPropertyCount, VkSparseImageFormatProperties * pProperties);
+typedef void (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSparseImageFormatInfo2 * pFormatInfo, uint32_t * pPropertyCount, VkSparseImageFormatProperties2 * pProperties);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR * pSurfaceCapabilities);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t * pSurfaceFormatCount, VkSurfaceFormatKHR * pSurfaceFormats);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t * pPresentModeCount, VkPresentModeKHR * pPresentModes);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32 * pSupported);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetPhysicalDeviceToolProperties)(VkPhysicalDevice physicalDevice, uint32_t * pToolCount, VkPhysicalDeviceToolProperties * pToolProperties);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, size_t * pDataSize, void * pData);
+typedef void (GLAD_API_PTR *PFN_vkGetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t * pData);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void * pData, VkDeviceSize stride, VkQueryResultFlags flags);
+typedef void (GLAD_API_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D * pGranularity);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetSemaphoreCounterValue)(VkDevice device, VkSemaphore semaphore, uint64_t * pValue);
+typedef VkResult (GLAD_API_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t * pSwapchainImageCount, VkImage * pSwapchainImages);
+typedef VkResult (GLAD_API_PTR *PFN_vkInvalidateMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange * pMemoryRanges);
+typedef VkResult (GLAD_API_PTR *PFN_vkMapMemory)(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void ** ppData);
+typedef VkResult (GLAD_API_PTR *PFN_vkMergePipelineCaches)(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache * pSrcCaches);
+typedef VkResult (GLAD_API_PTR *PFN_vkQueueBindSparse)(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo * pBindInfo, VkFence fence);
+typedef VkResult (GLAD_API_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR * pPresentInfo);
+typedef VkResult (GLAD_API_PTR *PFN_vkQueueSubmit)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo * pSubmits, VkFence fence);
+typedef VkResult (GLAD_API_PTR *PFN_vkQueueSubmit2)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo2 * pSubmits, VkFence fence);
+typedef VkResult (GLAD_API_PTR *PFN_vkQueueWaitIdle)(VkQueue queue);
+typedef VkResult (GLAD_API_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags);
+typedef VkResult (GLAD_API_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags);
+typedef VkResult (GLAD_API_PTR *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags);
+typedef VkResult (GLAD_API_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event);
+typedef VkResult (GLAD_API_PTR *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, const VkFence * pFences);
+typedef void (GLAD_API_PTR *PFN_vkResetQueryPool)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
+typedef VkResult (GLAD_API_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event);
+typedef VkResult (GLAD_API_PTR *PFN_vkSetPrivateData)(VkDevice device, VkObjectType objectType, uint64_t objectHandle, VkPrivateDataSlot privateDataSlot, uint64_t data);
+typedef VkResult (GLAD_API_PTR *PFN_vkSignalSemaphore)(VkDevice device, const VkSemaphoreSignalInfo * pSignalInfo);
+typedef void (GLAD_API_PTR *PFN_vkTrimCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags);
+typedef void (GLAD_API_PTR *PFN_vkUnmapMemory)(VkDevice device, VkDeviceMemory memory);
+typedef void (GLAD_API_PTR *PFN_vkUpdateDescriptorSetWithTemplate)(VkDevice device, VkDescriptorSet descriptorSet, VkDescriptorUpdateTemplate descriptorUpdateTemplate, const void * pData);
+typedef void (GLAD_API_PTR *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet * pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet * pDescriptorCopies);
+typedef VkResult (GLAD_API_PTR *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence * pFences, VkBool32 waitAll, uint64_t timeout);
+typedef VkResult (GLAD_API_PTR *PFN_vkWaitSemaphores)(VkDevice device, const VkSemaphoreWaitInfo * pWaitInfo, uint64_t timeout);
 
 GLAD_API_CALL PFN_vkAcquireNextImage2KHR glad_vkAcquireNextImage2KHR;
 #define vkAcquireNextImage2KHR glad_vkAcquireNextImage2KHR
@@ -3124,6 +5052,10 @@
 #define vkCmdBeginQuery glad_vkCmdBeginQuery
 GLAD_API_CALL PFN_vkCmdBeginRenderPass glad_vkCmdBeginRenderPass;
 #define vkCmdBeginRenderPass glad_vkCmdBeginRenderPass
+GLAD_API_CALL PFN_vkCmdBeginRenderPass2 glad_vkCmdBeginRenderPass2;
+#define vkCmdBeginRenderPass2 glad_vkCmdBeginRenderPass2
+GLAD_API_CALL PFN_vkCmdBeginRendering glad_vkCmdBeginRendering;
+#define vkCmdBeginRendering glad_vkCmdBeginRendering
 GLAD_API_CALL PFN_vkCmdBindDescriptorSets glad_vkCmdBindDescriptorSets;
 #define vkCmdBindDescriptorSets glad_vkCmdBindDescriptorSets
 GLAD_API_CALL PFN_vkCmdBindIndexBuffer glad_vkCmdBindIndexBuffer;
@@ -3132,8 +5064,12 @@
 #define vkCmdBindPipeline glad_vkCmdBindPipeline
 GLAD_API_CALL PFN_vkCmdBindVertexBuffers glad_vkCmdBindVertexBuffers;
 #define vkCmdBindVertexBuffers glad_vkCmdBindVertexBuffers
+GLAD_API_CALL PFN_vkCmdBindVertexBuffers2 glad_vkCmdBindVertexBuffers2;
+#define vkCmdBindVertexBuffers2 glad_vkCmdBindVertexBuffers2
 GLAD_API_CALL PFN_vkCmdBlitImage glad_vkCmdBlitImage;
 #define vkCmdBlitImage glad_vkCmdBlitImage
+GLAD_API_CALL PFN_vkCmdBlitImage2 glad_vkCmdBlitImage2;
+#define vkCmdBlitImage2 glad_vkCmdBlitImage2
 GLAD_API_CALL PFN_vkCmdClearAttachments glad_vkCmdClearAttachments;
 #define vkCmdClearAttachments glad_vkCmdClearAttachments
 GLAD_API_CALL PFN_vkCmdClearColorImage glad_vkCmdClearColorImage;
@@ -3142,12 +5078,20 @@
 #define vkCmdClearDepthStencilImage glad_vkCmdClearDepthStencilImage
 GLAD_API_CALL PFN_vkCmdCopyBuffer glad_vkCmdCopyBuffer;
 #define vkCmdCopyBuffer glad_vkCmdCopyBuffer
+GLAD_API_CALL PFN_vkCmdCopyBuffer2 glad_vkCmdCopyBuffer2;
+#define vkCmdCopyBuffer2 glad_vkCmdCopyBuffer2
 GLAD_API_CALL PFN_vkCmdCopyBufferToImage glad_vkCmdCopyBufferToImage;
 #define vkCmdCopyBufferToImage glad_vkCmdCopyBufferToImage
+GLAD_API_CALL PFN_vkCmdCopyBufferToImage2 glad_vkCmdCopyBufferToImage2;
+#define vkCmdCopyBufferToImage2 glad_vkCmdCopyBufferToImage2
 GLAD_API_CALL PFN_vkCmdCopyImage glad_vkCmdCopyImage;
 #define vkCmdCopyImage glad_vkCmdCopyImage
+GLAD_API_CALL PFN_vkCmdCopyImage2 glad_vkCmdCopyImage2;
+#define vkCmdCopyImage2 glad_vkCmdCopyImage2
 GLAD_API_CALL PFN_vkCmdCopyImageToBuffer glad_vkCmdCopyImageToBuffer;
 #define vkCmdCopyImageToBuffer glad_vkCmdCopyImageToBuffer
+GLAD_API_CALL PFN_vkCmdCopyImageToBuffer2 glad_vkCmdCopyImageToBuffer2;
+#define vkCmdCopyImageToBuffer2 glad_vkCmdCopyImageToBuffer2
 GLAD_API_CALL PFN_vkCmdCopyQueryPoolResults glad_vkCmdCopyQueryPoolResults;
 #define vkCmdCopyQueryPoolResults glad_vkCmdCopyQueryPoolResults
 GLAD_API_CALL PFN_vkCmdDispatch glad_vkCmdDispatch;
@@ -3162,56 +5106,106 @@
 #define vkCmdDrawIndexed glad_vkCmdDrawIndexed
 GLAD_API_CALL PFN_vkCmdDrawIndexedIndirect glad_vkCmdDrawIndexedIndirect;
 #define vkCmdDrawIndexedIndirect glad_vkCmdDrawIndexedIndirect
+GLAD_API_CALL PFN_vkCmdDrawIndexedIndirectCount glad_vkCmdDrawIndexedIndirectCount;
+#define vkCmdDrawIndexedIndirectCount glad_vkCmdDrawIndexedIndirectCount
 GLAD_API_CALL PFN_vkCmdDrawIndirect glad_vkCmdDrawIndirect;
 #define vkCmdDrawIndirect glad_vkCmdDrawIndirect
+GLAD_API_CALL PFN_vkCmdDrawIndirectCount glad_vkCmdDrawIndirectCount;
+#define vkCmdDrawIndirectCount glad_vkCmdDrawIndirectCount
 GLAD_API_CALL PFN_vkCmdEndQuery glad_vkCmdEndQuery;
 #define vkCmdEndQuery glad_vkCmdEndQuery
 GLAD_API_CALL PFN_vkCmdEndRenderPass glad_vkCmdEndRenderPass;
 #define vkCmdEndRenderPass glad_vkCmdEndRenderPass
+GLAD_API_CALL PFN_vkCmdEndRenderPass2 glad_vkCmdEndRenderPass2;
+#define vkCmdEndRenderPass2 glad_vkCmdEndRenderPass2
+GLAD_API_CALL PFN_vkCmdEndRendering glad_vkCmdEndRendering;
+#define vkCmdEndRendering glad_vkCmdEndRendering
 GLAD_API_CALL PFN_vkCmdExecuteCommands glad_vkCmdExecuteCommands;
 #define vkCmdExecuteCommands glad_vkCmdExecuteCommands
 GLAD_API_CALL PFN_vkCmdFillBuffer glad_vkCmdFillBuffer;
 #define vkCmdFillBuffer glad_vkCmdFillBuffer
 GLAD_API_CALL PFN_vkCmdNextSubpass glad_vkCmdNextSubpass;
 #define vkCmdNextSubpass glad_vkCmdNextSubpass
+GLAD_API_CALL PFN_vkCmdNextSubpass2 glad_vkCmdNextSubpass2;
+#define vkCmdNextSubpass2 glad_vkCmdNextSubpass2
 GLAD_API_CALL PFN_vkCmdPipelineBarrier glad_vkCmdPipelineBarrier;
 #define vkCmdPipelineBarrier glad_vkCmdPipelineBarrier
+GLAD_API_CALL PFN_vkCmdPipelineBarrier2 glad_vkCmdPipelineBarrier2;
+#define vkCmdPipelineBarrier2 glad_vkCmdPipelineBarrier2
 GLAD_API_CALL PFN_vkCmdPushConstants glad_vkCmdPushConstants;
 #define vkCmdPushConstants glad_vkCmdPushConstants
 GLAD_API_CALL PFN_vkCmdResetEvent glad_vkCmdResetEvent;
 #define vkCmdResetEvent glad_vkCmdResetEvent
+GLAD_API_CALL PFN_vkCmdResetEvent2 glad_vkCmdResetEvent2;
+#define vkCmdResetEvent2 glad_vkCmdResetEvent2
 GLAD_API_CALL PFN_vkCmdResetQueryPool glad_vkCmdResetQueryPool;
 #define vkCmdResetQueryPool glad_vkCmdResetQueryPool
 GLAD_API_CALL PFN_vkCmdResolveImage glad_vkCmdResolveImage;
 #define vkCmdResolveImage glad_vkCmdResolveImage
+GLAD_API_CALL PFN_vkCmdResolveImage2 glad_vkCmdResolveImage2;
+#define vkCmdResolveImage2 glad_vkCmdResolveImage2
 GLAD_API_CALL PFN_vkCmdSetBlendConstants glad_vkCmdSetBlendConstants;
 #define vkCmdSetBlendConstants glad_vkCmdSetBlendConstants
+GLAD_API_CALL PFN_vkCmdSetCullMode glad_vkCmdSetCullMode;
+#define vkCmdSetCullMode glad_vkCmdSetCullMode
 GLAD_API_CALL PFN_vkCmdSetDepthBias glad_vkCmdSetDepthBias;
 #define vkCmdSetDepthBias glad_vkCmdSetDepthBias
+GLAD_API_CALL PFN_vkCmdSetDepthBiasEnable glad_vkCmdSetDepthBiasEnable;
+#define vkCmdSetDepthBiasEnable glad_vkCmdSetDepthBiasEnable
 GLAD_API_CALL PFN_vkCmdSetDepthBounds glad_vkCmdSetDepthBounds;
 #define vkCmdSetDepthBounds glad_vkCmdSetDepthBounds
+GLAD_API_CALL PFN_vkCmdSetDepthBoundsTestEnable glad_vkCmdSetDepthBoundsTestEnable;
+#define vkCmdSetDepthBoundsTestEnable glad_vkCmdSetDepthBoundsTestEnable
+GLAD_API_CALL PFN_vkCmdSetDepthCompareOp glad_vkCmdSetDepthCompareOp;
+#define vkCmdSetDepthCompareOp glad_vkCmdSetDepthCompareOp
+GLAD_API_CALL PFN_vkCmdSetDepthTestEnable glad_vkCmdSetDepthTestEnable;
+#define vkCmdSetDepthTestEnable glad_vkCmdSetDepthTestEnable
+GLAD_API_CALL PFN_vkCmdSetDepthWriteEnable glad_vkCmdSetDepthWriteEnable;
+#define vkCmdSetDepthWriteEnable glad_vkCmdSetDepthWriteEnable
 GLAD_API_CALL PFN_vkCmdSetDeviceMask glad_vkCmdSetDeviceMask;
 #define vkCmdSetDeviceMask glad_vkCmdSetDeviceMask
 GLAD_API_CALL PFN_vkCmdSetEvent glad_vkCmdSetEvent;
 #define vkCmdSetEvent glad_vkCmdSetEvent
+GLAD_API_CALL PFN_vkCmdSetEvent2 glad_vkCmdSetEvent2;
+#define vkCmdSetEvent2 glad_vkCmdSetEvent2
+GLAD_API_CALL PFN_vkCmdSetFrontFace glad_vkCmdSetFrontFace;
+#define vkCmdSetFrontFace glad_vkCmdSetFrontFace
 GLAD_API_CALL PFN_vkCmdSetLineWidth glad_vkCmdSetLineWidth;
 #define vkCmdSetLineWidth glad_vkCmdSetLineWidth
+GLAD_API_CALL PFN_vkCmdSetPrimitiveRestartEnable glad_vkCmdSetPrimitiveRestartEnable;
+#define vkCmdSetPrimitiveRestartEnable glad_vkCmdSetPrimitiveRestartEnable
+GLAD_API_CALL PFN_vkCmdSetPrimitiveTopology glad_vkCmdSetPrimitiveTopology;
+#define vkCmdSetPrimitiveTopology glad_vkCmdSetPrimitiveTopology
+GLAD_API_CALL PFN_vkCmdSetRasterizerDiscardEnable glad_vkCmdSetRasterizerDiscardEnable;
+#define vkCmdSetRasterizerDiscardEnable glad_vkCmdSetRasterizerDiscardEnable
 GLAD_API_CALL PFN_vkCmdSetScissor glad_vkCmdSetScissor;
 #define vkCmdSetScissor glad_vkCmdSetScissor
+GLAD_API_CALL PFN_vkCmdSetScissorWithCount glad_vkCmdSetScissorWithCount;
+#define vkCmdSetScissorWithCount glad_vkCmdSetScissorWithCount
 GLAD_API_CALL PFN_vkCmdSetStencilCompareMask glad_vkCmdSetStencilCompareMask;
 #define vkCmdSetStencilCompareMask glad_vkCmdSetStencilCompareMask
+GLAD_API_CALL PFN_vkCmdSetStencilOp glad_vkCmdSetStencilOp;
+#define vkCmdSetStencilOp glad_vkCmdSetStencilOp
 GLAD_API_CALL PFN_vkCmdSetStencilReference glad_vkCmdSetStencilReference;
 #define vkCmdSetStencilReference glad_vkCmdSetStencilReference
+GLAD_API_CALL PFN_vkCmdSetStencilTestEnable glad_vkCmdSetStencilTestEnable;
+#define vkCmdSetStencilTestEnable glad_vkCmdSetStencilTestEnable
 GLAD_API_CALL PFN_vkCmdSetStencilWriteMask glad_vkCmdSetStencilWriteMask;
 #define vkCmdSetStencilWriteMask glad_vkCmdSetStencilWriteMask
 GLAD_API_CALL PFN_vkCmdSetViewport glad_vkCmdSetViewport;
 #define vkCmdSetViewport glad_vkCmdSetViewport
+GLAD_API_CALL PFN_vkCmdSetViewportWithCount glad_vkCmdSetViewportWithCount;
+#define vkCmdSetViewportWithCount glad_vkCmdSetViewportWithCount
 GLAD_API_CALL PFN_vkCmdUpdateBuffer glad_vkCmdUpdateBuffer;
 #define vkCmdUpdateBuffer glad_vkCmdUpdateBuffer
 GLAD_API_CALL PFN_vkCmdWaitEvents glad_vkCmdWaitEvents;
 #define vkCmdWaitEvents glad_vkCmdWaitEvents
+GLAD_API_CALL PFN_vkCmdWaitEvents2 glad_vkCmdWaitEvents2;
+#define vkCmdWaitEvents2 glad_vkCmdWaitEvents2
 GLAD_API_CALL PFN_vkCmdWriteTimestamp glad_vkCmdWriteTimestamp;
 #define vkCmdWriteTimestamp glad_vkCmdWriteTimestamp
+GLAD_API_CALL PFN_vkCmdWriteTimestamp2 glad_vkCmdWriteTimestamp2;
+#define vkCmdWriteTimestamp2 glad_vkCmdWriteTimestamp2
 GLAD_API_CALL PFN_vkCreateBuffer glad_vkCreateBuffer;
 #define vkCreateBuffer glad_vkCreateBuffer
 GLAD_API_CALL PFN_vkCreateBufferView glad_vkCreateBufferView;
@@ -3248,10 +5242,14 @@
 #define vkCreatePipelineCache glad_vkCreatePipelineCache
 GLAD_API_CALL PFN_vkCreatePipelineLayout glad_vkCreatePipelineLayout;
 #define vkCreatePipelineLayout glad_vkCreatePipelineLayout
+GLAD_API_CALL PFN_vkCreatePrivateDataSlot glad_vkCreatePrivateDataSlot;
+#define vkCreatePrivateDataSlot glad_vkCreatePrivateDataSlot
 GLAD_API_CALL PFN_vkCreateQueryPool glad_vkCreateQueryPool;
 #define vkCreateQueryPool glad_vkCreateQueryPool
 GLAD_API_CALL PFN_vkCreateRenderPass glad_vkCreateRenderPass;
 #define vkCreateRenderPass glad_vkCreateRenderPass
+GLAD_API_CALL PFN_vkCreateRenderPass2 glad_vkCreateRenderPass2;
+#define vkCreateRenderPass2 glad_vkCreateRenderPass2
 GLAD_API_CALL PFN_vkCreateSampler glad_vkCreateSampler;
 #define vkCreateSampler glad_vkCreateSampler
 GLAD_API_CALL PFN_vkCreateSamplerYcbcrConversion glad_vkCreateSamplerYcbcrConversion;
@@ -3298,6 +5296,8 @@
 #define vkDestroyPipelineCache glad_vkDestroyPipelineCache
 GLAD_API_CALL PFN_vkDestroyPipelineLayout glad_vkDestroyPipelineLayout;
 #define vkDestroyPipelineLayout glad_vkDestroyPipelineLayout
+GLAD_API_CALL PFN_vkDestroyPrivateDataSlot glad_vkDestroyPrivateDataSlot;
+#define vkDestroyPrivateDataSlot glad_vkDestroyPrivateDataSlot
 GLAD_API_CALL PFN_vkDestroyQueryPool glad_vkDestroyQueryPool;
 #define vkDestroyQueryPool glad_vkDestroyQueryPool
 GLAD_API_CALL PFN_vkDestroyRenderPass glad_vkDestroyRenderPass;
@@ -3340,20 +5340,32 @@
 #define vkFreeDescriptorSets glad_vkFreeDescriptorSets
 GLAD_API_CALL PFN_vkFreeMemory glad_vkFreeMemory;
 #define vkFreeMemory glad_vkFreeMemory
+GLAD_API_CALL PFN_vkGetBufferDeviceAddress glad_vkGetBufferDeviceAddress;
+#define vkGetBufferDeviceAddress glad_vkGetBufferDeviceAddress
 GLAD_API_CALL PFN_vkGetBufferMemoryRequirements glad_vkGetBufferMemoryRequirements;
 #define vkGetBufferMemoryRequirements glad_vkGetBufferMemoryRequirements
 GLAD_API_CALL PFN_vkGetBufferMemoryRequirements2 glad_vkGetBufferMemoryRequirements2;
 #define vkGetBufferMemoryRequirements2 glad_vkGetBufferMemoryRequirements2
+GLAD_API_CALL PFN_vkGetBufferOpaqueCaptureAddress glad_vkGetBufferOpaqueCaptureAddress;
+#define vkGetBufferOpaqueCaptureAddress glad_vkGetBufferOpaqueCaptureAddress
 GLAD_API_CALL PFN_vkGetDescriptorSetLayoutSupport glad_vkGetDescriptorSetLayoutSupport;
 #define vkGetDescriptorSetLayoutSupport glad_vkGetDescriptorSetLayoutSupport
+GLAD_API_CALL PFN_vkGetDeviceBufferMemoryRequirements glad_vkGetDeviceBufferMemoryRequirements;
+#define vkGetDeviceBufferMemoryRequirements glad_vkGetDeviceBufferMemoryRequirements
 GLAD_API_CALL PFN_vkGetDeviceGroupPeerMemoryFeatures glad_vkGetDeviceGroupPeerMemoryFeatures;
 #define vkGetDeviceGroupPeerMemoryFeatures glad_vkGetDeviceGroupPeerMemoryFeatures
 GLAD_API_CALL PFN_vkGetDeviceGroupPresentCapabilitiesKHR glad_vkGetDeviceGroupPresentCapabilitiesKHR;
 #define vkGetDeviceGroupPresentCapabilitiesKHR glad_vkGetDeviceGroupPresentCapabilitiesKHR
 GLAD_API_CALL PFN_vkGetDeviceGroupSurfacePresentModesKHR glad_vkGetDeviceGroupSurfacePresentModesKHR;
 #define vkGetDeviceGroupSurfacePresentModesKHR glad_vkGetDeviceGroupSurfacePresentModesKHR
+GLAD_API_CALL PFN_vkGetDeviceImageMemoryRequirements glad_vkGetDeviceImageMemoryRequirements;
+#define vkGetDeviceImageMemoryRequirements glad_vkGetDeviceImageMemoryRequirements
+GLAD_API_CALL PFN_vkGetDeviceImageSparseMemoryRequirements glad_vkGetDeviceImageSparseMemoryRequirements;
+#define vkGetDeviceImageSparseMemoryRequirements glad_vkGetDeviceImageSparseMemoryRequirements
 GLAD_API_CALL PFN_vkGetDeviceMemoryCommitment glad_vkGetDeviceMemoryCommitment;
 #define vkGetDeviceMemoryCommitment glad_vkGetDeviceMemoryCommitment
+GLAD_API_CALL PFN_vkGetDeviceMemoryOpaqueCaptureAddress glad_vkGetDeviceMemoryOpaqueCaptureAddress;
+#define vkGetDeviceMemoryOpaqueCaptureAddress glad_vkGetDeviceMemoryOpaqueCaptureAddress
 GLAD_API_CALL PFN_vkGetDeviceProcAddr glad_vkGetDeviceProcAddr;
 #define vkGetDeviceProcAddr glad_vkGetDeviceProcAddr
 GLAD_API_CALL PFN_vkGetDeviceQueue glad_vkGetDeviceQueue;
@@ -3420,12 +5432,18 @@
 #define vkGetPhysicalDeviceSurfacePresentModesKHR glad_vkGetPhysicalDeviceSurfacePresentModesKHR
 GLAD_API_CALL PFN_vkGetPhysicalDeviceSurfaceSupportKHR glad_vkGetPhysicalDeviceSurfaceSupportKHR;
 #define vkGetPhysicalDeviceSurfaceSupportKHR glad_vkGetPhysicalDeviceSurfaceSupportKHR
+GLAD_API_CALL PFN_vkGetPhysicalDeviceToolProperties glad_vkGetPhysicalDeviceToolProperties;
+#define vkGetPhysicalDeviceToolProperties glad_vkGetPhysicalDeviceToolProperties
 GLAD_API_CALL PFN_vkGetPipelineCacheData glad_vkGetPipelineCacheData;
 #define vkGetPipelineCacheData glad_vkGetPipelineCacheData
+GLAD_API_CALL PFN_vkGetPrivateData glad_vkGetPrivateData;
+#define vkGetPrivateData glad_vkGetPrivateData
 GLAD_API_CALL PFN_vkGetQueryPoolResults glad_vkGetQueryPoolResults;
 #define vkGetQueryPoolResults glad_vkGetQueryPoolResults
 GLAD_API_CALL PFN_vkGetRenderAreaGranularity glad_vkGetRenderAreaGranularity;
 #define vkGetRenderAreaGranularity glad_vkGetRenderAreaGranularity
+GLAD_API_CALL PFN_vkGetSemaphoreCounterValue glad_vkGetSemaphoreCounterValue;
+#define vkGetSemaphoreCounterValue glad_vkGetSemaphoreCounterValue
 GLAD_API_CALL PFN_vkGetSwapchainImagesKHR glad_vkGetSwapchainImagesKHR;
 #define vkGetSwapchainImagesKHR glad_vkGetSwapchainImagesKHR
 GLAD_API_CALL PFN_vkInvalidateMappedMemoryRanges glad_vkInvalidateMappedMemoryRanges;
@@ -3440,6 +5458,8 @@
 #define vkQueuePresentKHR glad_vkQueuePresentKHR
 GLAD_API_CALL PFN_vkQueueSubmit glad_vkQueueSubmit;
 #define vkQueueSubmit glad_vkQueueSubmit
+GLAD_API_CALL PFN_vkQueueSubmit2 glad_vkQueueSubmit2;
+#define vkQueueSubmit2 glad_vkQueueSubmit2
 GLAD_API_CALL PFN_vkQueueWaitIdle glad_vkQueueWaitIdle;
 #define vkQueueWaitIdle glad_vkQueueWaitIdle
 GLAD_API_CALL PFN_vkResetCommandBuffer glad_vkResetCommandBuffer;
@@ -3452,8 +5472,14 @@
 #define vkResetEvent glad_vkResetEvent
 GLAD_API_CALL PFN_vkResetFences glad_vkResetFences;
 #define vkResetFences glad_vkResetFences
+GLAD_API_CALL PFN_vkResetQueryPool glad_vkResetQueryPool;
+#define vkResetQueryPool glad_vkResetQueryPool
 GLAD_API_CALL PFN_vkSetEvent glad_vkSetEvent;
 #define vkSetEvent glad_vkSetEvent
+GLAD_API_CALL PFN_vkSetPrivateData glad_vkSetPrivateData;
+#define vkSetPrivateData glad_vkSetPrivateData
+GLAD_API_CALL PFN_vkSignalSemaphore glad_vkSignalSemaphore;
+#define vkSignalSemaphore glad_vkSignalSemaphore
 GLAD_API_CALL PFN_vkTrimCommandPool glad_vkTrimCommandPool;
 #define vkTrimCommandPool glad_vkTrimCommandPool
 GLAD_API_CALL PFN_vkUnmapMemory glad_vkUnmapMemory;
@@ -3464,6 +5490,11 @@
 #define vkUpdateDescriptorSets glad_vkUpdateDescriptorSets
 GLAD_API_CALL PFN_vkWaitForFences glad_vkWaitForFences;
 #define vkWaitForFences glad_vkWaitForFences
+GLAD_API_CALL PFN_vkWaitSemaphores glad_vkWaitSemaphores;
+#define vkWaitSemaphores glad_vkWaitSemaphores
+
+
+
 
 
 GLAD_API_CALL int gladLoadVulkanUserPtr( VkPhysicalDevice physical_device, GLADuserptrloadfunc load, void *userptr);
@@ -3471,9 +5502,6 @@
 
 
 
-
-
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/deps/glad_vulkan.c b/deps/glad_vulkan.c
index 5adfbbb..6559df8 100644
--- a/deps/glad_vulkan.c
+++ b/deps/glad_vulkan.c
@@ -14,10 +14,18 @@
 
 #endif /* GLAD_IMPL_UTIL_C_ */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
 
 int GLAD_VK_VERSION_1_0 = 0;
 int GLAD_VK_VERSION_1_1 = 0;
+int GLAD_VK_VERSION_1_2 = 0;
+int GLAD_VK_VERSION_1_3 = 0;
 int GLAD_VK_EXT_debug_report = 0;
+int GLAD_VK_KHR_portability_enumeration = 0;
 int GLAD_VK_KHR_surface = 0;
 int GLAD_VK_KHR_swapchain = 0;
 
@@ -35,18 +43,26 @@
 PFN_vkBindImageMemory2 glad_vkBindImageMemory2 = NULL;
 PFN_vkCmdBeginQuery glad_vkCmdBeginQuery = NULL;
 PFN_vkCmdBeginRenderPass glad_vkCmdBeginRenderPass = NULL;
+PFN_vkCmdBeginRenderPass2 glad_vkCmdBeginRenderPass2 = NULL;
+PFN_vkCmdBeginRendering glad_vkCmdBeginRendering = NULL;
 PFN_vkCmdBindDescriptorSets glad_vkCmdBindDescriptorSets = NULL;
 PFN_vkCmdBindIndexBuffer glad_vkCmdBindIndexBuffer = NULL;
 PFN_vkCmdBindPipeline glad_vkCmdBindPipeline = NULL;
 PFN_vkCmdBindVertexBuffers glad_vkCmdBindVertexBuffers = NULL;
+PFN_vkCmdBindVertexBuffers2 glad_vkCmdBindVertexBuffers2 = NULL;
 PFN_vkCmdBlitImage glad_vkCmdBlitImage = NULL;
+PFN_vkCmdBlitImage2 glad_vkCmdBlitImage2 = NULL;
 PFN_vkCmdClearAttachments glad_vkCmdClearAttachments = NULL;
 PFN_vkCmdClearColorImage glad_vkCmdClearColorImage = NULL;
 PFN_vkCmdClearDepthStencilImage glad_vkCmdClearDepthStencilImage = NULL;
 PFN_vkCmdCopyBuffer glad_vkCmdCopyBuffer = NULL;
+PFN_vkCmdCopyBuffer2 glad_vkCmdCopyBuffer2 = NULL;
 PFN_vkCmdCopyBufferToImage glad_vkCmdCopyBufferToImage = NULL;
+PFN_vkCmdCopyBufferToImage2 glad_vkCmdCopyBufferToImage2 = NULL;
 PFN_vkCmdCopyImage glad_vkCmdCopyImage = NULL;
+PFN_vkCmdCopyImage2 glad_vkCmdCopyImage2 = NULL;
 PFN_vkCmdCopyImageToBuffer glad_vkCmdCopyImageToBuffer = NULL;
+PFN_vkCmdCopyImageToBuffer2 glad_vkCmdCopyImageToBuffer2 = NULL;
 PFN_vkCmdCopyQueryPoolResults glad_vkCmdCopyQueryPoolResults = NULL;
 PFN_vkCmdDispatch glad_vkCmdDispatch = NULL;
 PFN_vkCmdDispatchBase glad_vkCmdDispatchBase = NULL;
@@ -54,31 +70,56 @@
 PFN_vkCmdDraw glad_vkCmdDraw = NULL;
 PFN_vkCmdDrawIndexed glad_vkCmdDrawIndexed = NULL;
 PFN_vkCmdDrawIndexedIndirect glad_vkCmdDrawIndexedIndirect = NULL;
+PFN_vkCmdDrawIndexedIndirectCount glad_vkCmdDrawIndexedIndirectCount = NULL;
 PFN_vkCmdDrawIndirect glad_vkCmdDrawIndirect = NULL;
+PFN_vkCmdDrawIndirectCount glad_vkCmdDrawIndirectCount = NULL;
 PFN_vkCmdEndQuery glad_vkCmdEndQuery = NULL;
 PFN_vkCmdEndRenderPass glad_vkCmdEndRenderPass = NULL;
+PFN_vkCmdEndRenderPass2 glad_vkCmdEndRenderPass2 = NULL;
+PFN_vkCmdEndRendering glad_vkCmdEndRendering = NULL;
 PFN_vkCmdExecuteCommands glad_vkCmdExecuteCommands = NULL;
 PFN_vkCmdFillBuffer glad_vkCmdFillBuffer = NULL;
 PFN_vkCmdNextSubpass glad_vkCmdNextSubpass = NULL;
+PFN_vkCmdNextSubpass2 glad_vkCmdNextSubpass2 = NULL;
 PFN_vkCmdPipelineBarrier glad_vkCmdPipelineBarrier = NULL;
+PFN_vkCmdPipelineBarrier2 glad_vkCmdPipelineBarrier2 = NULL;
 PFN_vkCmdPushConstants glad_vkCmdPushConstants = NULL;
 PFN_vkCmdResetEvent glad_vkCmdResetEvent = NULL;
+PFN_vkCmdResetEvent2 glad_vkCmdResetEvent2 = NULL;
 PFN_vkCmdResetQueryPool glad_vkCmdResetQueryPool = NULL;
 PFN_vkCmdResolveImage glad_vkCmdResolveImage = NULL;
+PFN_vkCmdResolveImage2 glad_vkCmdResolveImage2 = NULL;
 PFN_vkCmdSetBlendConstants glad_vkCmdSetBlendConstants = NULL;
+PFN_vkCmdSetCullMode glad_vkCmdSetCullMode = NULL;
 PFN_vkCmdSetDepthBias glad_vkCmdSetDepthBias = NULL;
+PFN_vkCmdSetDepthBiasEnable glad_vkCmdSetDepthBiasEnable = NULL;
 PFN_vkCmdSetDepthBounds glad_vkCmdSetDepthBounds = NULL;
+PFN_vkCmdSetDepthBoundsTestEnable glad_vkCmdSetDepthBoundsTestEnable = NULL;
+PFN_vkCmdSetDepthCompareOp glad_vkCmdSetDepthCompareOp = NULL;
+PFN_vkCmdSetDepthTestEnable glad_vkCmdSetDepthTestEnable = NULL;
+PFN_vkCmdSetDepthWriteEnable glad_vkCmdSetDepthWriteEnable = NULL;
 PFN_vkCmdSetDeviceMask glad_vkCmdSetDeviceMask = NULL;
 PFN_vkCmdSetEvent glad_vkCmdSetEvent = NULL;
+PFN_vkCmdSetEvent2 glad_vkCmdSetEvent2 = NULL;
+PFN_vkCmdSetFrontFace glad_vkCmdSetFrontFace = NULL;
 PFN_vkCmdSetLineWidth glad_vkCmdSetLineWidth = NULL;
+PFN_vkCmdSetPrimitiveRestartEnable glad_vkCmdSetPrimitiveRestartEnable = NULL;
+PFN_vkCmdSetPrimitiveTopology glad_vkCmdSetPrimitiveTopology = NULL;
+PFN_vkCmdSetRasterizerDiscardEnable glad_vkCmdSetRasterizerDiscardEnable = NULL;
 PFN_vkCmdSetScissor glad_vkCmdSetScissor = NULL;
+PFN_vkCmdSetScissorWithCount glad_vkCmdSetScissorWithCount = NULL;
 PFN_vkCmdSetStencilCompareMask glad_vkCmdSetStencilCompareMask = NULL;
+PFN_vkCmdSetStencilOp glad_vkCmdSetStencilOp = NULL;
 PFN_vkCmdSetStencilReference glad_vkCmdSetStencilReference = NULL;
+PFN_vkCmdSetStencilTestEnable glad_vkCmdSetStencilTestEnable = NULL;
 PFN_vkCmdSetStencilWriteMask glad_vkCmdSetStencilWriteMask = NULL;
 PFN_vkCmdSetViewport glad_vkCmdSetViewport = NULL;
+PFN_vkCmdSetViewportWithCount glad_vkCmdSetViewportWithCount = NULL;
 PFN_vkCmdUpdateBuffer glad_vkCmdUpdateBuffer = NULL;
 PFN_vkCmdWaitEvents glad_vkCmdWaitEvents = NULL;
+PFN_vkCmdWaitEvents2 glad_vkCmdWaitEvents2 = NULL;
 PFN_vkCmdWriteTimestamp glad_vkCmdWriteTimestamp = NULL;
+PFN_vkCmdWriteTimestamp2 glad_vkCmdWriteTimestamp2 = NULL;
 PFN_vkCreateBuffer glad_vkCreateBuffer = NULL;
 PFN_vkCreateBufferView glad_vkCreateBufferView = NULL;
 PFN_vkCreateCommandPool glad_vkCreateCommandPool = NULL;
@@ -97,8 +138,10 @@
 PFN_vkCreateInstance glad_vkCreateInstance = NULL;
 PFN_vkCreatePipelineCache glad_vkCreatePipelineCache = NULL;
 PFN_vkCreatePipelineLayout glad_vkCreatePipelineLayout = NULL;
+PFN_vkCreatePrivateDataSlot glad_vkCreatePrivateDataSlot = NULL;
 PFN_vkCreateQueryPool glad_vkCreateQueryPool = NULL;
 PFN_vkCreateRenderPass glad_vkCreateRenderPass = NULL;
+PFN_vkCreateRenderPass2 glad_vkCreateRenderPass2 = NULL;
 PFN_vkCreateSampler glad_vkCreateSampler = NULL;
 PFN_vkCreateSamplerYcbcrConversion glad_vkCreateSamplerYcbcrConversion = NULL;
 PFN_vkCreateSemaphore glad_vkCreateSemaphore = NULL;
@@ -122,6 +165,7 @@
 PFN_vkDestroyPipeline glad_vkDestroyPipeline = NULL;
 PFN_vkDestroyPipelineCache glad_vkDestroyPipelineCache = NULL;
 PFN_vkDestroyPipelineLayout glad_vkDestroyPipelineLayout = NULL;
+PFN_vkDestroyPrivateDataSlot glad_vkDestroyPrivateDataSlot = NULL;
 PFN_vkDestroyQueryPool glad_vkDestroyQueryPool = NULL;
 PFN_vkDestroyRenderPass glad_vkDestroyRenderPass = NULL;
 PFN_vkDestroySampler glad_vkDestroySampler = NULL;
@@ -143,13 +187,19 @@
 PFN_vkFreeCommandBuffers glad_vkFreeCommandBuffers = NULL;
 PFN_vkFreeDescriptorSets glad_vkFreeDescriptorSets = NULL;
 PFN_vkFreeMemory glad_vkFreeMemory = NULL;
+PFN_vkGetBufferDeviceAddress glad_vkGetBufferDeviceAddress = NULL;
 PFN_vkGetBufferMemoryRequirements glad_vkGetBufferMemoryRequirements = NULL;
 PFN_vkGetBufferMemoryRequirements2 glad_vkGetBufferMemoryRequirements2 = NULL;
+PFN_vkGetBufferOpaqueCaptureAddress glad_vkGetBufferOpaqueCaptureAddress = NULL;
 PFN_vkGetDescriptorSetLayoutSupport glad_vkGetDescriptorSetLayoutSupport = NULL;
+PFN_vkGetDeviceBufferMemoryRequirements glad_vkGetDeviceBufferMemoryRequirements = NULL;
 PFN_vkGetDeviceGroupPeerMemoryFeatures glad_vkGetDeviceGroupPeerMemoryFeatures = NULL;
 PFN_vkGetDeviceGroupPresentCapabilitiesKHR glad_vkGetDeviceGroupPresentCapabilitiesKHR = NULL;
 PFN_vkGetDeviceGroupSurfacePresentModesKHR glad_vkGetDeviceGroupSurfacePresentModesKHR = NULL;
+PFN_vkGetDeviceImageMemoryRequirements glad_vkGetDeviceImageMemoryRequirements = NULL;
+PFN_vkGetDeviceImageSparseMemoryRequirements glad_vkGetDeviceImageSparseMemoryRequirements = NULL;
 PFN_vkGetDeviceMemoryCommitment glad_vkGetDeviceMemoryCommitment = NULL;
+PFN_vkGetDeviceMemoryOpaqueCaptureAddress glad_vkGetDeviceMemoryOpaqueCaptureAddress = NULL;
 PFN_vkGetDeviceProcAddr glad_vkGetDeviceProcAddr = NULL;
 PFN_vkGetDeviceQueue glad_vkGetDeviceQueue = NULL;
 PFN_vkGetDeviceQueue2 glad_vkGetDeviceQueue2 = NULL;
@@ -183,9 +233,12 @@
 PFN_vkGetPhysicalDeviceSurfaceFormatsKHR glad_vkGetPhysicalDeviceSurfaceFormatsKHR = NULL;
 PFN_vkGetPhysicalDeviceSurfacePresentModesKHR glad_vkGetPhysicalDeviceSurfacePresentModesKHR = NULL;
 PFN_vkGetPhysicalDeviceSurfaceSupportKHR glad_vkGetPhysicalDeviceSurfaceSupportKHR = NULL;
+PFN_vkGetPhysicalDeviceToolProperties glad_vkGetPhysicalDeviceToolProperties = NULL;
 PFN_vkGetPipelineCacheData glad_vkGetPipelineCacheData = NULL;
+PFN_vkGetPrivateData glad_vkGetPrivateData = NULL;
 PFN_vkGetQueryPoolResults glad_vkGetQueryPoolResults = NULL;
 PFN_vkGetRenderAreaGranularity glad_vkGetRenderAreaGranularity = NULL;
+PFN_vkGetSemaphoreCounterValue glad_vkGetSemaphoreCounterValue = NULL;
 PFN_vkGetSwapchainImagesKHR glad_vkGetSwapchainImagesKHR = NULL;
 PFN_vkInvalidateMappedMemoryRanges glad_vkInvalidateMappedMemoryRanges = NULL;
 PFN_vkMapMemory glad_vkMapMemory = NULL;
@@ -193,216 +246,277 @@
 PFN_vkQueueBindSparse glad_vkQueueBindSparse = NULL;
 PFN_vkQueuePresentKHR glad_vkQueuePresentKHR = NULL;
 PFN_vkQueueSubmit glad_vkQueueSubmit = NULL;
+PFN_vkQueueSubmit2 glad_vkQueueSubmit2 = NULL;
 PFN_vkQueueWaitIdle glad_vkQueueWaitIdle = NULL;
 PFN_vkResetCommandBuffer glad_vkResetCommandBuffer = NULL;
 PFN_vkResetCommandPool glad_vkResetCommandPool = NULL;
 PFN_vkResetDescriptorPool glad_vkResetDescriptorPool = NULL;
 PFN_vkResetEvent glad_vkResetEvent = NULL;
 PFN_vkResetFences glad_vkResetFences = NULL;
+PFN_vkResetQueryPool glad_vkResetQueryPool = NULL;
 PFN_vkSetEvent glad_vkSetEvent = NULL;
+PFN_vkSetPrivateData glad_vkSetPrivateData = NULL;
+PFN_vkSignalSemaphore glad_vkSignalSemaphore = NULL;
 PFN_vkTrimCommandPool glad_vkTrimCommandPool = NULL;
 PFN_vkUnmapMemory glad_vkUnmapMemory = NULL;
 PFN_vkUpdateDescriptorSetWithTemplate glad_vkUpdateDescriptorSetWithTemplate = NULL;
 PFN_vkUpdateDescriptorSets glad_vkUpdateDescriptorSets = NULL;
 PFN_vkWaitForFences glad_vkWaitForFences = NULL;
+PFN_vkWaitSemaphores glad_vkWaitSemaphores = NULL;
 
 
 static void glad_vk_load_VK_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
     if(!GLAD_VK_VERSION_1_0) return;
-    vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers) load("vkAllocateCommandBuffers", userptr);
-    vkAllocateDescriptorSets = (PFN_vkAllocateDescriptorSets) load("vkAllocateDescriptorSets", userptr);
-    vkAllocateMemory = (PFN_vkAllocateMemory) load("vkAllocateMemory", userptr);
-    vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer) load("vkBeginCommandBuffer", userptr);
-    vkBindBufferMemory = (PFN_vkBindBufferMemory) load("vkBindBufferMemory", userptr);
-    vkBindImageMemory = (PFN_vkBindImageMemory) load("vkBindImageMemory", userptr);
-    vkCmdBeginQuery = (PFN_vkCmdBeginQuery) load("vkCmdBeginQuery", userptr);
-    vkCmdBeginRenderPass = (PFN_vkCmdBeginRenderPass) load("vkCmdBeginRenderPass", userptr);
-    vkCmdBindDescriptorSets = (PFN_vkCmdBindDescriptorSets) load("vkCmdBindDescriptorSets", userptr);
-    vkCmdBindIndexBuffer = (PFN_vkCmdBindIndexBuffer) load("vkCmdBindIndexBuffer", userptr);
-    vkCmdBindPipeline = (PFN_vkCmdBindPipeline) load("vkCmdBindPipeline", userptr);
-    vkCmdBindVertexBuffers = (PFN_vkCmdBindVertexBuffers) load("vkCmdBindVertexBuffers", userptr);
-    vkCmdBlitImage = (PFN_vkCmdBlitImage) load("vkCmdBlitImage", userptr);
-    vkCmdClearAttachments = (PFN_vkCmdClearAttachments) load("vkCmdClearAttachments", userptr);
-    vkCmdClearColorImage = (PFN_vkCmdClearColorImage) load("vkCmdClearColorImage", userptr);
-    vkCmdClearDepthStencilImage = (PFN_vkCmdClearDepthStencilImage) load("vkCmdClearDepthStencilImage", userptr);
-    vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer) load("vkCmdCopyBuffer", userptr);
-    vkCmdCopyBufferToImage = (PFN_vkCmdCopyBufferToImage) load("vkCmdCopyBufferToImage", userptr);
-    vkCmdCopyImage = (PFN_vkCmdCopyImage) load("vkCmdCopyImage", userptr);
-    vkCmdCopyImageToBuffer = (PFN_vkCmdCopyImageToBuffer) load("vkCmdCopyImageToBuffer", userptr);
-    vkCmdCopyQueryPoolResults = (PFN_vkCmdCopyQueryPoolResults) load("vkCmdCopyQueryPoolResults", userptr);
-    vkCmdDispatch = (PFN_vkCmdDispatch) load("vkCmdDispatch", userptr);
-    vkCmdDispatchIndirect = (PFN_vkCmdDispatchIndirect) load("vkCmdDispatchIndirect", userptr);
-    vkCmdDraw = (PFN_vkCmdDraw) load("vkCmdDraw", userptr);
-    vkCmdDrawIndexed = (PFN_vkCmdDrawIndexed) load("vkCmdDrawIndexed", userptr);
-    vkCmdDrawIndexedIndirect = (PFN_vkCmdDrawIndexedIndirect) load("vkCmdDrawIndexedIndirect", userptr);
-    vkCmdDrawIndirect = (PFN_vkCmdDrawIndirect) load("vkCmdDrawIndirect", userptr);
-    vkCmdEndQuery = (PFN_vkCmdEndQuery) load("vkCmdEndQuery", userptr);
-    vkCmdEndRenderPass = (PFN_vkCmdEndRenderPass) load("vkCmdEndRenderPass", userptr);
-    vkCmdExecuteCommands = (PFN_vkCmdExecuteCommands) load("vkCmdExecuteCommands", userptr);
-    vkCmdFillBuffer = (PFN_vkCmdFillBuffer) load("vkCmdFillBuffer", userptr);
-    vkCmdNextSubpass = (PFN_vkCmdNextSubpass) load("vkCmdNextSubpass", userptr);
-    vkCmdPipelineBarrier = (PFN_vkCmdPipelineBarrier) load("vkCmdPipelineBarrier", userptr);
-    vkCmdPushConstants = (PFN_vkCmdPushConstants) load("vkCmdPushConstants", userptr);
-    vkCmdResetEvent = (PFN_vkCmdResetEvent) load("vkCmdResetEvent", userptr);
-    vkCmdResetQueryPool = (PFN_vkCmdResetQueryPool) load("vkCmdResetQueryPool", userptr);
-    vkCmdResolveImage = (PFN_vkCmdResolveImage) load("vkCmdResolveImage", userptr);
-    vkCmdSetBlendConstants = (PFN_vkCmdSetBlendConstants) load("vkCmdSetBlendConstants", userptr);
-    vkCmdSetDepthBias = (PFN_vkCmdSetDepthBias) load("vkCmdSetDepthBias", userptr);
-    vkCmdSetDepthBounds = (PFN_vkCmdSetDepthBounds) load("vkCmdSetDepthBounds", userptr);
-    vkCmdSetEvent = (PFN_vkCmdSetEvent) load("vkCmdSetEvent", userptr);
-    vkCmdSetLineWidth = (PFN_vkCmdSetLineWidth) load("vkCmdSetLineWidth", userptr);
-    vkCmdSetScissor = (PFN_vkCmdSetScissor) load("vkCmdSetScissor", userptr);
-    vkCmdSetStencilCompareMask = (PFN_vkCmdSetStencilCompareMask) load("vkCmdSetStencilCompareMask", userptr);
-    vkCmdSetStencilReference = (PFN_vkCmdSetStencilReference) load("vkCmdSetStencilReference", userptr);
-    vkCmdSetStencilWriteMask = (PFN_vkCmdSetStencilWriteMask) load("vkCmdSetStencilWriteMask", userptr);
-    vkCmdSetViewport = (PFN_vkCmdSetViewport) load("vkCmdSetViewport", userptr);
-    vkCmdUpdateBuffer = (PFN_vkCmdUpdateBuffer) load("vkCmdUpdateBuffer", userptr);
-    vkCmdWaitEvents = (PFN_vkCmdWaitEvents) load("vkCmdWaitEvents", userptr);
-    vkCmdWriteTimestamp = (PFN_vkCmdWriteTimestamp) load("vkCmdWriteTimestamp", userptr);
-    vkCreateBuffer = (PFN_vkCreateBuffer) load("vkCreateBuffer", userptr);
-    vkCreateBufferView = (PFN_vkCreateBufferView) load("vkCreateBufferView", userptr);
-    vkCreateCommandPool = (PFN_vkCreateCommandPool) load("vkCreateCommandPool", userptr);
-    vkCreateComputePipelines = (PFN_vkCreateComputePipelines) load("vkCreateComputePipelines", userptr);
-    vkCreateDescriptorPool = (PFN_vkCreateDescriptorPool) load("vkCreateDescriptorPool", userptr);
-    vkCreateDescriptorSetLayout = (PFN_vkCreateDescriptorSetLayout) load("vkCreateDescriptorSetLayout", userptr);
-    vkCreateDevice = (PFN_vkCreateDevice) load("vkCreateDevice", userptr);
-    vkCreateEvent = (PFN_vkCreateEvent) load("vkCreateEvent", userptr);
-    vkCreateFence = (PFN_vkCreateFence) load("vkCreateFence", userptr);
-    vkCreateFramebuffer = (PFN_vkCreateFramebuffer) load("vkCreateFramebuffer", userptr);
-    vkCreateGraphicsPipelines = (PFN_vkCreateGraphicsPipelines) load("vkCreateGraphicsPipelines", userptr);
-    vkCreateImage = (PFN_vkCreateImage) load("vkCreateImage", userptr);
-    vkCreateImageView = (PFN_vkCreateImageView) load("vkCreateImageView", userptr);
-    vkCreateInstance = (PFN_vkCreateInstance) load("vkCreateInstance", userptr);
-    vkCreatePipelineCache = (PFN_vkCreatePipelineCache) load("vkCreatePipelineCache", userptr);
-    vkCreatePipelineLayout = (PFN_vkCreatePipelineLayout) load("vkCreatePipelineLayout", userptr);
-    vkCreateQueryPool = (PFN_vkCreateQueryPool) load("vkCreateQueryPool", userptr);
-    vkCreateRenderPass = (PFN_vkCreateRenderPass) load("vkCreateRenderPass", userptr);
-    vkCreateSampler = (PFN_vkCreateSampler) load("vkCreateSampler", userptr);
-    vkCreateSemaphore = (PFN_vkCreateSemaphore) load("vkCreateSemaphore", userptr);
-    vkCreateShaderModule = (PFN_vkCreateShaderModule) load("vkCreateShaderModule", userptr);
-    vkDestroyBuffer = (PFN_vkDestroyBuffer) load("vkDestroyBuffer", userptr);
-    vkDestroyBufferView = (PFN_vkDestroyBufferView) load("vkDestroyBufferView", userptr);
-    vkDestroyCommandPool = (PFN_vkDestroyCommandPool) load("vkDestroyCommandPool", userptr);
-    vkDestroyDescriptorPool = (PFN_vkDestroyDescriptorPool) load("vkDestroyDescriptorPool", userptr);
-    vkDestroyDescriptorSetLayout = (PFN_vkDestroyDescriptorSetLayout) load("vkDestroyDescriptorSetLayout", userptr);
-    vkDestroyDevice = (PFN_vkDestroyDevice) load("vkDestroyDevice", userptr);
-    vkDestroyEvent = (PFN_vkDestroyEvent) load("vkDestroyEvent", userptr);
-    vkDestroyFence = (PFN_vkDestroyFence) load("vkDestroyFence", userptr);
-    vkDestroyFramebuffer = (PFN_vkDestroyFramebuffer) load("vkDestroyFramebuffer", userptr);
-    vkDestroyImage = (PFN_vkDestroyImage) load("vkDestroyImage", userptr);
-    vkDestroyImageView = (PFN_vkDestroyImageView) load("vkDestroyImageView", userptr);
-    vkDestroyInstance = (PFN_vkDestroyInstance) load("vkDestroyInstance", userptr);
-    vkDestroyPipeline = (PFN_vkDestroyPipeline) load("vkDestroyPipeline", userptr);
-    vkDestroyPipelineCache = (PFN_vkDestroyPipelineCache) load("vkDestroyPipelineCache", userptr);
-    vkDestroyPipelineLayout = (PFN_vkDestroyPipelineLayout) load("vkDestroyPipelineLayout", userptr);
-    vkDestroyQueryPool = (PFN_vkDestroyQueryPool) load("vkDestroyQueryPool", userptr);
-    vkDestroyRenderPass = (PFN_vkDestroyRenderPass) load("vkDestroyRenderPass", userptr);
-    vkDestroySampler = (PFN_vkDestroySampler) load("vkDestroySampler", userptr);
-    vkDestroySemaphore = (PFN_vkDestroySemaphore) load("vkDestroySemaphore", userptr);
-    vkDestroyShaderModule = (PFN_vkDestroyShaderModule) load("vkDestroyShaderModule", userptr);
-    vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle) load("vkDeviceWaitIdle", userptr);
-    vkEndCommandBuffer = (PFN_vkEndCommandBuffer) load("vkEndCommandBuffer", userptr);
-    vkEnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties) load("vkEnumerateDeviceExtensionProperties", userptr);
-    vkEnumerateDeviceLayerProperties = (PFN_vkEnumerateDeviceLayerProperties) load("vkEnumerateDeviceLayerProperties", userptr);
-    vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties) load("vkEnumerateInstanceExtensionProperties", userptr);
-    vkEnumerateInstanceLayerProperties = (PFN_vkEnumerateInstanceLayerProperties) load("vkEnumerateInstanceLayerProperties", userptr);
-    vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) load("vkEnumeratePhysicalDevices", userptr);
-    vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges) load("vkFlushMappedMemoryRanges", userptr);
-    vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers) load("vkFreeCommandBuffers", userptr);
-    vkFreeDescriptorSets = (PFN_vkFreeDescriptorSets) load("vkFreeDescriptorSets", userptr);
-    vkFreeMemory = (PFN_vkFreeMemory) load("vkFreeMemory", userptr);
-    vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements) load("vkGetBufferMemoryRequirements", userptr);
-    vkGetDeviceMemoryCommitment = (PFN_vkGetDeviceMemoryCommitment) load("vkGetDeviceMemoryCommitment", userptr);
-    vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) load("vkGetDeviceProcAddr", userptr);
-    vkGetDeviceQueue = (PFN_vkGetDeviceQueue) load("vkGetDeviceQueue", userptr);
-    vkGetEventStatus = (PFN_vkGetEventStatus) load("vkGetEventStatus", userptr);
-    vkGetFenceStatus = (PFN_vkGetFenceStatus) load("vkGetFenceStatus", userptr);
-    vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements) load("vkGetImageMemoryRequirements", userptr);
-    vkGetImageSparseMemoryRequirements = (PFN_vkGetImageSparseMemoryRequirements) load("vkGetImageSparseMemoryRequirements", userptr);
-    vkGetImageSubresourceLayout = (PFN_vkGetImageSubresourceLayout) load("vkGetImageSubresourceLayout", userptr);
-    vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) load("vkGetInstanceProcAddr", userptr);
-    vkGetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures) load("vkGetPhysicalDeviceFeatures", userptr);
-    vkGetPhysicalDeviceFormatProperties = (PFN_vkGetPhysicalDeviceFormatProperties) load("vkGetPhysicalDeviceFormatProperties", userptr);
-    vkGetPhysicalDeviceImageFormatProperties = (PFN_vkGetPhysicalDeviceImageFormatProperties) load("vkGetPhysicalDeviceImageFormatProperties", userptr);
-    vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties) load("vkGetPhysicalDeviceMemoryProperties", userptr);
-    vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties) load("vkGetPhysicalDeviceProperties", userptr);
-    vkGetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties) load("vkGetPhysicalDeviceQueueFamilyProperties", userptr);
-    vkGetPhysicalDeviceSparseImageFormatProperties = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties) load("vkGetPhysicalDeviceSparseImageFormatProperties", userptr);
-    vkGetPipelineCacheData = (PFN_vkGetPipelineCacheData) load("vkGetPipelineCacheData", userptr);
-    vkGetQueryPoolResults = (PFN_vkGetQueryPoolResults) load("vkGetQueryPoolResults", userptr);
-    vkGetRenderAreaGranularity = (PFN_vkGetRenderAreaGranularity) load("vkGetRenderAreaGranularity", userptr);
-    vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges) load("vkInvalidateMappedMemoryRanges", userptr);
-    vkMapMemory = (PFN_vkMapMemory) load("vkMapMemory", userptr);
-    vkMergePipelineCaches = (PFN_vkMergePipelineCaches) load("vkMergePipelineCaches", userptr);
-    vkQueueBindSparse = (PFN_vkQueueBindSparse) load("vkQueueBindSparse", userptr);
-    vkQueueSubmit = (PFN_vkQueueSubmit) load("vkQueueSubmit", userptr);
-    vkQueueWaitIdle = (PFN_vkQueueWaitIdle) load("vkQueueWaitIdle", userptr);
-    vkResetCommandBuffer = (PFN_vkResetCommandBuffer) load("vkResetCommandBuffer", userptr);
-    vkResetCommandPool = (PFN_vkResetCommandPool) load("vkResetCommandPool", userptr);
-    vkResetDescriptorPool = (PFN_vkResetDescriptorPool) load("vkResetDescriptorPool", userptr);
-    vkResetEvent = (PFN_vkResetEvent) load("vkResetEvent", userptr);
-    vkResetFences = (PFN_vkResetFences) load("vkResetFences", userptr);
-    vkSetEvent = (PFN_vkSetEvent) load("vkSetEvent", userptr);
-    vkUnmapMemory = (PFN_vkUnmapMemory) load("vkUnmapMemory", userptr);
-    vkUpdateDescriptorSets = (PFN_vkUpdateDescriptorSets) load("vkUpdateDescriptorSets", userptr);
-    vkWaitForFences = (PFN_vkWaitForFences) load("vkWaitForFences", userptr);
+    glad_vkAllocateCommandBuffers = (PFN_vkAllocateCommandBuffers) load(userptr, "vkAllocateCommandBuffers");
+    glad_vkAllocateDescriptorSets = (PFN_vkAllocateDescriptorSets) load(userptr, "vkAllocateDescriptorSets");
+    glad_vkAllocateMemory = (PFN_vkAllocateMemory) load(userptr, "vkAllocateMemory");
+    glad_vkBeginCommandBuffer = (PFN_vkBeginCommandBuffer) load(userptr, "vkBeginCommandBuffer");
+    glad_vkBindBufferMemory = (PFN_vkBindBufferMemory) load(userptr, "vkBindBufferMemory");
+    glad_vkBindImageMemory = (PFN_vkBindImageMemory) load(userptr, "vkBindImageMemory");
+    glad_vkCmdBeginQuery = (PFN_vkCmdBeginQuery) load(userptr, "vkCmdBeginQuery");
+    glad_vkCmdBeginRenderPass = (PFN_vkCmdBeginRenderPass) load(userptr, "vkCmdBeginRenderPass");
+    glad_vkCmdBindDescriptorSets = (PFN_vkCmdBindDescriptorSets) load(userptr, "vkCmdBindDescriptorSets");
+    glad_vkCmdBindIndexBuffer = (PFN_vkCmdBindIndexBuffer) load(userptr, "vkCmdBindIndexBuffer");
+    glad_vkCmdBindPipeline = (PFN_vkCmdBindPipeline) load(userptr, "vkCmdBindPipeline");
+    glad_vkCmdBindVertexBuffers = (PFN_vkCmdBindVertexBuffers) load(userptr, "vkCmdBindVertexBuffers");
+    glad_vkCmdBlitImage = (PFN_vkCmdBlitImage) load(userptr, "vkCmdBlitImage");
+    glad_vkCmdClearAttachments = (PFN_vkCmdClearAttachments) load(userptr, "vkCmdClearAttachments");
+    glad_vkCmdClearColorImage = (PFN_vkCmdClearColorImage) load(userptr, "vkCmdClearColorImage");
+    glad_vkCmdClearDepthStencilImage = (PFN_vkCmdClearDepthStencilImage) load(userptr, "vkCmdClearDepthStencilImage");
+    glad_vkCmdCopyBuffer = (PFN_vkCmdCopyBuffer) load(userptr, "vkCmdCopyBuffer");
+    glad_vkCmdCopyBufferToImage = (PFN_vkCmdCopyBufferToImage) load(userptr, "vkCmdCopyBufferToImage");
+    glad_vkCmdCopyImage = (PFN_vkCmdCopyImage) load(userptr, "vkCmdCopyImage");
+    glad_vkCmdCopyImageToBuffer = (PFN_vkCmdCopyImageToBuffer) load(userptr, "vkCmdCopyImageToBuffer");
+    glad_vkCmdCopyQueryPoolResults = (PFN_vkCmdCopyQueryPoolResults) load(userptr, "vkCmdCopyQueryPoolResults");
+    glad_vkCmdDispatch = (PFN_vkCmdDispatch) load(userptr, "vkCmdDispatch");
+    glad_vkCmdDispatchIndirect = (PFN_vkCmdDispatchIndirect) load(userptr, "vkCmdDispatchIndirect");
+    glad_vkCmdDraw = (PFN_vkCmdDraw) load(userptr, "vkCmdDraw");
+    glad_vkCmdDrawIndexed = (PFN_vkCmdDrawIndexed) load(userptr, "vkCmdDrawIndexed");
+    glad_vkCmdDrawIndexedIndirect = (PFN_vkCmdDrawIndexedIndirect) load(userptr, "vkCmdDrawIndexedIndirect");
+    glad_vkCmdDrawIndirect = (PFN_vkCmdDrawIndirect) load(userptr, "vkCmdDrawIndirect");
+    glad_vkCmdEndQuery = (PFN_vkCmdEndQuery) load(userptr, "vkCmdEndQuery");
+    glad_vkCmdEndRenderPass = (PFN_vkCmdEndRenderPass) load(userptr, "vkCmdEndRenderPass");
+    glad_vkCmdExecuteCommands = (PFN_vkCmdExecuteCommands) load(userptr, "vkCmdExecuteCommands");
+    glad_vkCmdFillBuffer = (PFN_vkCmdFillBuffer) load(userptr, "vkCmdFillBuffer");
+    glad_vkCmdNextSubpass = (PFN_vkCmdNextSubpass) load(userptr, "vkCmdNextSubpass");
+    glad_vkCmdPipelineBarrier = (PFN_vkCmdPipelineBarrier) load(userptr, "vkCmdPipelineBarrier");
+    glad_vkCmdPushConstants = (PFN_vkCmdPushConstants) load(userptr, "vkCmdPushConstants");
+    glad_vkCmdResetEvent = (PFN_vkCmdResetEvent) load(userptr, "vkCmdResetEvent");
+    glad_vkCmdResetQueryPool = (PFN_vkCmdResetQueryPool) load(userptr, "vkCmdResetQueryPool");
+    glad_vkCmdResolveImage = (PFN_vkCmdResolveImage) load(userptr, "vkCmdResolveImage");
+    glad_vkCmdSetBlendConstants = (PFN_vkCmdSetBlendConstants) load(userptr, "vkCmdSetBlendConstants");
+    glad_vkCmdSetDepthBias = (PFN_vkCmdSetDepthBias) load(userptr, "vkCmdSetDepthBias");
+    glad_vkCmdSetDepthBounds = (PFN_vkCmdSetDepthBounds) load(userptr, "vkCmdSetDepthBounds");
+    glad_vkCmdSetEvent = (PFN_vkCmdSetEvent) load(userptr, "vkCmdSetEvent");
+    glad_vkCmdSetLineWidth = (PFN_vkCmdSetLineWidth) load(userptr, "vkCmdSetLineWidth");
+    glad_vkCmdSetScissor = (PFN_vkCmdSetScissor) load(userptr, "vkCmdSetScissor");
+    glad_vkCmdSetStencilCompareMask = (PFN_vkCmdSetStencilCompareMask) load(userptr, "vkCmdSetStencilCompareMask");
+    glad_vkCmdSetStencilReference = (PFN_vkCmdSetStencilReference) load(userptr, "vkCmdSetStencilReference");
+    glad_vkCmdSetStencilWriteMask = (PFN_vkCmdSetStencilWriteMask) load(userptr, "vkCmdSetStencilWriteMask");
+    glad_vkCmdSetViewport = (PFN_vkCmdSetViewport) load(userptr, "vkCmdSetViewport");
+    glad_vkCmdUpdateBuffer = (PFN_vkCmdUpdateBuffer) load(userptr, "vkCmdUpdateBuffer");
+    glad_vkCmdWaitEvents = (PFN_vkCmdWaitEvents) load(userptr, "vkCmdWaitEvents");
+    glad_vkCmdWriteTimestamp = (PFN_vkCmdWriteTimestamp) load(userptr, "vkCmdWriteTimestamp");
+    glad_vkCreateBuffer = (PFN_vkCreateBuffer) load(userptr, "vkCreateBuffer");
+    glad_vkCreateBufferView = (PFN_vkCreateBufferView) load(userptr, "vkCreateBufferView");
+    glad_vkCreateCommandPool = (PFN_vkCreateCommandPool) load(userptr, "vkCreateCommandPool");
+    glad_vkCreateComputePipelines = (PFN_vkCreateComputePipelines) load(userptr, "vkCreateComputePipelines");
+    glad_vkCreateDescriptorPool = (PFN_vkCreateDescriptorPool) load(userptr, "vkCreateDescriptorPool");
+    glad_vkCreateDescriptorSetLayout = (PFN_vkCreateDescriptorSetLayout) load(userptr, "vkCreateDescriptorSetLayout");
+    glad_vkCreateDevice = (PFN_vkCreateDevice) load(userptr, "vkCreateDevice");
+    glad_vkCreateEvent = (PFN_vkCreateEvent) load(userptr, "vkCreateEvent");
+    glad_vkCreateFence = (PFN_vkCreateFence) load(userptr, "vkCreateFence");
+    glad_vkCreateFramebuffer = (PFN_vkCreateFramebuffer) load(userptr, "vkCreateFramebuffer");
+    glad_vkCreateGraphicsPipelines = (PFN_vkCreateGraphicsPipelines) load(userptr, "vkCreateGraphicsPipelines");
+    glad_vkCreateImage = (PFN_vkCreateImage) load(userptr, "vkCreateImage");
+    glad_vkCreateImageView = (PFN_vkCreateImageView) load(userptr, "vkCreateImageView");
+    glad_vkCreateInstance = (PFN_vkCreateInstance) load(userptr, "vkCreateInstance");
+    glad_vkCreatePipelineCache = (PFN_vkCreatePipelineCache) load(userptr, "vkCreatePipelineCache");
+    glad_vkCreatePipelineLayout = (PFN_vkCreatePipelineLayout) load(userptr, "vkCreatePipelineLayout");
+    glad_vkCreateQueryPool = (PFN_vkCreateQueryPool) load(userptr, "vkCreateQueryPool");
+    glad_vkCreateRenderPass = (PFN_vkCreateRenderPass) load(userptr, "vkCreateRenderPass");
+    glad_vkCreateSampler = (PFN_vkCreateSampler) load(userptr, "vkCreateSampler");
+    glad_vkCreateSemaphore = (PFN_vkCreateSemaphore) load(userptr, "vkCreateSemaphore");
+    glad_vkCreateShaderModule = (PFN_vkCreateShaderModule) load(userptr, "vkCreateShaderModule");
+    glad_vkDestroyBuffer = (PFN_vkDestroyBuffer) load(userptr, "vkDestroyBuffer");
+    glad_vkDestroyBufferView = (PFN_vkDestroyBufferView) load(userptr, "vkDestroyBufferView");
+    glad_vkDestroyCommandPool = (PFN_vkDestroyCommandPool) load(userptr, "vkDestroyCommandPool");
+    glad_vkDestroyDescriptorPool = (PFN_vkDestroyDescriptorPool) load(userptr, "vkDestroyDescriptorPool");
+    glad_vkDestroyDescriptorSetLayout = (PFN_vkDestroyDescriptorSetLayout) load(userptr, "vkDestroyDescriptorSetLayout");
+    glad_vkDestroyDevice = (PFN_vkDestroyDevice) load(userptr, "vkDestroyDevice");
+    glad_vkDestroyEvent = (PFN_vkDestroyEvent) load(userptr, "vkDestroyEvent");
+    glad_vkDestroyFence = (PFN_vkDestroyFence) load(userptr, "vkDestroyFence");
+    glad_vkDestroyFramebuffer = (PFN_vkDestroyFramebuffer) load(userptr, "vkDestroyFramebuffer");
+    glad_vkDestroyImage = (PFN_vkDestroyImage) load(userptr, "vkDestroyImage");
+    glad_vkDestroyImageView = (PFN_vkDestroyImageView) load(userptr, "vkDestroyImageView");
+    glad_vkDestroyInstance = (PFN_vkDestroyInstance) load(userptr, "vkDestroyInstance");
+    glad_vkDestroyPipeline = (PFN_vkDestroyPipeline) load(userptr, "vkDestroyPipeline");
+    glad_vkDestroyPipelineCache = (PFN_vkDestroyPipelineCache) load(userptr, "vkDestroyPipelineCache");
+    glad_vkDestroyPipelineLayout = (PFN_vkDestroyPipelineLayout) load(userptr, "vkDestroyPipelineLayout");
+    glad_vkDestroyQueryPool = (PFN_vkDestroyQueryPool) load(userptr, "vkDestroyQueryPool");
+    glad_vkDestroyRenderPass = (PFN_vkDestroyRenderPass) load(userptr, "vkDestroyRenderPass");
+    glad_vkDestroySampler = (PFN_vkDestroySampler) load(userptr, "vkDestroySampler");
+    glad_vkDestroySemaphore = (PFN_vkDestroySemaphore) load(userptr, "vkDestroySemaphore");
+    glad_vkDestroyShaderModule = (PFN_vkDestroyShaderModule) load(userptr, "vkDestroyShaderModule");
+    glad_vkDeviceWaitIdle = (PFN_vkDeviceWaitIdle) load(userptr, "vkDeviceWaitIdle");
+    glad_vkEndCommandBuffer = (PFN_vkEndCommandBuffer) load(userptr, "vkEndCommandBuffer");
+    glad_vkEnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties) load(userptr, "vkEnumerateDeviceExtensionProperties");
+    glad_vkEnumerateDeviceLayerProperties = (PFN_vkEnumerateDeviceLayerProperties) load(userptr, "vkEnumerateDeviceLayerProperties");
+    glad_vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties) load(userptr, "vkEnumerateInstanceExtensionProperties");
+    glad_vkEnumerateInstanceLayerProperties = (PFN_vkEnumerateInstanceLayerProperties) load(userptr, "vkEnumerateInstanceLayerProperties");
+    glad_vkEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices) load(userptr, "vkEnumeratePhysicalDevices");
+    glad_vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges) load(userptr, "vkFlushMappedMemoryRanges");
+    glad_vkFreeCommandBuffers = (PFN_vkFreeCommandBuffers) load(userptr, "vkFreeCommandBuffers");
+    glad_vkFreeDescriptorSets = (PFN_vkFreeDescriptorSets) load(userptr, "vkFreeDescriptorSets");
+    glad_vkFreeMemory = (PFN_vkFreeMemory) load(userptr, "vkFreeMemory");
+    glad_vkGetBufferMemoryRequirements = (PFN_vkGetBufferMemoryRequirements) load(userptr, "vkGetBufferMemoryRequirements");
+    glad_vkGetDeviceMemoryCommitment = (PFN_vkGetDeviceMemoryCommitment) load(userptr, "vkGetDeviceMemoryCommitment");
+    glad_vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr) load(userptr, "vkGetDeviceProcAddr");
+    glad_vkGetDeviceQueue = (PFN_vkGetDeviceQueue) load(userptr, "vkGetDeviceQueue");
+    glad_vkGetEventStatus = (PFN_vkGetEventStatus) load(userptr, "vkGetEventStatus");
+    glad_vkGetFenceStatus = (PFN_vkGetFenceStatus) load(userptr, "vkGetFenceStatus");
+    glad_vkGetImageMemoryRequirements = (PFN_vkGetImageMemoryRequirements) load(userptr, "vkGetImageMemoryRequirements");
+    glad_vkGetImageSparseMemoryRequirements = (PFN_vkGetImageSparseMemoryRequirements) load(userptr, "vkGetImageSparseMemoryRequirements");
+    glad_vkGetImageSubresourceLayout = (PFN_vkGetImageSubresourceLayout) load(userptr, "vkGetImageSubresourceLayout");
+    glad_vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) load(userptr, "vkGetInstanceProcAddr");
+    glad_vkGetPhysicalDeviceFeatures = (PFN_vkGetPhysicalDeviceFeatures) load(userptr, "vkGetPhysicalDeviceFeatures");
+    glad_vkGetPhysicalDeviceFormatProperties = (PFN_vkGetPhysicalDeviceFormatProperties) load(userptr, "vkGetPhysicalDeviceFormatProperties");
+    glad_vkGetPhysicalDeviceImageFormatProperties = (PFN_vkGetPhysicalDeviceImageFormatProperties) load(userptr, "vkGetPhysicalDeviceImageFormatProperties");
+    glad_vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties) load(userptr, "vkGetPhysicalDeviceMemoryProperties");
+    glad_vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties) load(userptr, "vkGetPhysicalDeviceProperties");
+    glad_vkGetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties) load(userptr, "vkGetPhysicalDeviceQueueFamilyProperties");
+    glad_vkGetPhysicalDeviceSparseImageFormatProperties = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties) load(userptr, "vkGetPhysicalDeviceSparseImageFormatProperties");
+    glad_vkGetPipelineCacheData = (PFN_vkGetPipelineCacheData) load(userptr, "vkGetPipelineCacheData");
+    glad_vkGetQueryPoolResults = (PFN_vkGetQueryPoolResults) load(userptr, "vkGetQueryPoolResults");
+    glad_vkGetRenderAreaGranularity = (PFN_vkGetRenderAreaGranularity) load(userptr, "vkGetRenderAreaGranularity");
+    glad_vkInvalidateMappedMemoryRanges = (PFN_vkInvalidateMappedMemoryRanges) load(userptr, "vkInvalidateMappedMemoryRanges");
+    glad_vkMapMemory = (PFN_vkMapMemory) load(userptr, "vkMapMemory");
+    glad_vkMergePipelineCaches = (PFN_vkMergePipelineCaches) load(userptr, "vkMergePipelineCaches");
+    glad_vkQueueBindSparse = (PFN_vkQueueBindSparse) load(userptr, "vkQueueBindSparse");
+    glad_vkQueueSubmit = (PFN_vkQueueSubmit) load(userptr, "vkQueueSubmit");
+    glad_vkQueueWaitIdle = (PFN_vkQueueWaitIdle) load(userptr, "vkQueueWaitIdle");
+    glad_vkResetCommandBuffer = (PFN_vkResetCommandBuffer) load(userptr, "vkResetCommandBuffer");
+    glad_vkResetCommandPool = (PFN_vkResetCommandPool) load(userptr, "vkResetCommandPool");
+    glad_vkResetDescriptorPool = (PFN_vkResetDescriptorPool) load(userptr, "vkResetDescriptorPool");
+    glad_vkResetEvent = (PFN_vkResetEvent) load(userptr, "vkResetEvent");
+    glad_vkResetFences = (PFN_vkResetFences) load(userptr, "vkResetFences");
+    glad_vkSetEvent = (PFN_vkSetEvent) load(userptr, "vkSetEvent");
+    glad_vkUnmapMemory = (PFN_vkUnmapMemory) load(userptr, "vkUnmapMemory");
+    glad_vkUpdateDescriptorSets = (PFN_vkUpdateDescriptorSets) load(userptr, "vkUpdateDescriptorSets");
+    glad_vkWaitForFences = (PFN_vkWaitForFences) load(userptr, "vkWaitForFences");
 }
 static void glad_vk_load_VK_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
     if(!GLAD_VK_VERSION_1_1) return;
-    vkBindBufferMemory2 = (PFN_vkBindBufferMemory2) load("vkBindBufferMemory2", userptr);
-    vkBindImageMemory2 = (PFN_vkBindImageMemory2) load("vkBindImageMemory2", userptr);
-    vkCmdDispatchBase = (PFN_vkCmdDispatchBase) load("vkCmdDispatchBase", userptr);
-    vkCmdSetDeviceMask = (PFN_vkCmdSetDeviceMask) load("vkCmdSetDeviceMask", userptr);
-    vkCreateDescriptorUpdateTemplate = (PFN_vkCreateDescriptorUpdateTemplate) load("vkCreateDescriptorUpdateTemplate", userptr);
-    vkCreateSamplerYcbcrConversion = (PFN_vkCreateSamplerYcbcrConversion) load("vkCreateSamplerYcbcrConversion", userptr);
-    vkDestroyDescriptorUpdateTemplate = (PFN_vkDestroyDescriptorUpdateTemplate) load("vkDestroyDescriptorUpdateTemplate", userptr);
-    vkDestroySamplerYcbcrConversion = (PFN_vkDestroySamplerYcbcrConversion) load("vkDestroySamplerYcbcrConversion", userptr);
-    vkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion) load("vkEnumerateInstanceVersion", userptr);
-    vkEnumeratePhysicalDeviceGroups = (PFN_vkEnumeratePhysicalDeviceGroups) load("vkEnumeratePhysicalDeviceGroups", userptr);
-    vkGetBufferMemoryRequirements2 = (PFN_vkGetBufferMemoryRequirements2) load("vkGetBufferMemoryRequirements2", userptr);
-    vkGetDescriptorSetLayoutSupport = (PFN_vkGetDescriptorSetLayoutSupport) load("vkGetDescriptorSetLayoutSupport", userptr);
-    vkGetDeviceGroupPeerMemoryFeatures = (PFN_vkGetDeviceGroupPeerMemoryFeatures) load("vkGetDeviceGroupPeerMemoryFeatures", userptr);
-    vkGetDeviceQueue2 = (PFN_vkGetDeviceQueue2) load("vkGetDeviceQueue2", userptr);
-    vkGetImageMemoryRequirements2 = (PFN_vkGetImageMemoryRequirements2) load("vkGetImageMemoryRequirements2", userptr);
-    vkGetImageSparseMemoryRequirements2 = (PFN_vkGetImageSparseMemoryRequirements2) load("vkGetImageSparseMemoryRequirements2", userptr);
-    vkGetPhysicalDeviceExternalBufferProperties = (PFN_vkGetPhysicalDeviceExternalBufferProperties) load("vkGetPhysicalDeviceExternalBufferProperties", userptr);
-    vkGetPhysicalDeviceExternalFenceProperties = (PFN_vkGetPhysicalDeviceExternalFenceProperties) load("vkGetPhysicalDeviceExternalFenceProperties", userptr);
-    vkGetPhysicalDeviceExternalSemaphoreProperties = (PFN_vkGetPhysicalDeviceExternalSemaphoreProperties) load("vkGetPhysicalDeviceExternalSemaphoreProperties", userptr);
-    vkGetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2) load("vkGetPhysicalDeviceFeatures2", userptr);
-    vkGetPhysicalDeviceFormatProperties2 = (PFN_vkGetPhysicalDeviceFormatProperties2) load("vkGetPhysicalDeviceFormatProperties2", userptr);
-    vkGetPhysicalDeviceImageFormatProperties2 = (PFN_vkGetPhysicalDeviceImageFormatProperties2) load("vkGetPhysicalDeviceImageFormatProperties2", userptr);
-    vkGetPhysicalDeviceMemoryProperties2 = (PFN_vkGetPhysicalDeviceMemoryProperties2) load("vkGetPhysicalDeviceMemoryProperties2", userptr);
-    vkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) load("vkGetPhysicalDeviceProperties2", userptr);
-    vkGetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2) load("vkGetPhysicalDeviceQueueFamilyProperties2", userptr);
-    vkGetPhysicalDeviceSparseImageFormatProperties2 = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2) load("vkGetPhysicalDeviceSparseImageFormatProperties2", userptr);
-    vkTrimCommandPool = (PFN_vkTrimCommandPool) load("vkTrimCommandPool", userptr);
-    vkUpdateDescriptorSetWithTemplate = (PFN_vkUpdateDescriptorSetWithTemplate) load("vkUpdateDescriptorSetWithTemplate", userptr);
+    glad_vkBindBufferMemory2 = (PFN_vkBindBufferMemory2) load(userptr, "vkBindBufferMemory2");
+    glad_vkBindImageMemory2 = (PFN_vkBindImageMemory2) load(userptr, "vkBindImageMemory2");
+    glad_vkCmdDispatchBase = (PFN_vkCmdDispatchBase) load(userptr, "vkCmdDispatchBase");
+    glad_vkCmdSetDeviceMask = (PFN_vkCmdSetDeviceMask) load(userptr, "vkCmdSetDeviceMask");
+    glad_vkCreateDescriptorUpdateTemplate = (PFN_vkCreateDescriptorUpdateTemplate) load(userptr, "vkCreateDescriptorUpdateTemplate");
+    glad_vkCreateSamplerYcbcrConversion = (PFN_vkCreateSamplerYcbcrConversion) load(userptr, "vkCreateSamplerYcbcrConversion");
+    glad_vkDestroyDescriptorUpdateTemplate = (PFN_vkDestroyDescriptorUpdateTemplate) load(userptr, "vkDestroyDescriptorUpdateTemplate");
+    glad_vkDestroySamplerYcbcrConversion = (PFN_vkDestroySamplerYcbcrConversion) load(userptr, "vkDestroySamplerYcbcrConversion");
+    glad_vkEnumerateInstanceVersion = (PFN_vkEnumerateInstanceVersion) load(userptr, "vkEnumerateInstanceVersion");
+    glad_vkEnumeratePhysicalDeviceGroups = (PFN_vkEnumeratePhysicalDeviceGroups) load(userptr, "vkEnumeratePhysicalDeviceGroups");
+    glad_vkGetBufferMemoryRequirements2 = (PFN_vkGetBufferMemoryRequirements2) load(userptr, "vkGetBufferMemoryRequirements2");
+    glad_vkGetDescriptorSetLayoutSupport = (PFN_vkGetDescriptorSetLayoutSupport) load(userptr, "vkGetDescriptorSetLayoutSupport");
+    glad_vkGetDeviceGroupPeerMemoryFeatures = (PFN_vkGetDeviceGroupPeerMemoryFeatures) load(userptr, "vkGetDeviceGroupPeerMemoryFeatures");
+    glad_vkGetDeviceQueue2 = (PFN_vkGetDeviceQueue2) load(userptr, "vkGetDeviceQueue2");
+    glad_vkGetImageMemoryRequirements2 = (PFN_vkGetImageMemoryRequirements2) load(userptr, "vkGetImageMemoryRequirements2");
+    glad_vkGetImageSparseMemoryRequirements2 = (PFN_vkGetImageSparseMemoryRequirements2) load(userptr, "vkGetImageSparseMemoryRequirements2");
+    glad_vkGetPhysicalDeviceExternalBufferProperties = (PFN_vkGetPhysicalDeviceExternalBufferProperties) load(userptr, "vkGetPhysicalDeviceExternalBufferProperties");
+    glad_vkGetPhysicalDeviceExternalFenceProperties = (PFN_vkGetPhysicalDeviceExternalFenceProperties) load(userptr, "vkGetPhysicalDeviceExternalFenceProperties");
+    glad_vkGetPhysicalDeviceExternalSemaphoreProperties = (PFN_vkGetPhysicalDeviceExternalSemaphoreProperties) load(userptr, "vkGetPhysicalDeviceExternalSemaphoreProperties");
+    glad_vkGetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2) load(userptr, "vkGetPhysicalDeviceFeatures2");
+    glad_vkGetPhysicalDeviceFormatProperties2 = (PFN_vkGetPhysicalDeviceFormatProperties2) load(userptr, "vkGetPhysicalDeviceFormatProperties2");
+    glad_vkGetPhysicalDeviceImageFormatProperties2 = (PFN_vkGetPhysicalDeviceImageFormatProperties2) load(userptr, "vkGetPhysicalDeviceImageFormatProperties2");
+    glad_vkGetPhysicalDeviceMemoryProperties2 = (PFN_vkGetPhysicalDeviceMemoryProperties2) load(userptr, "vkGetPhysicalDeviceMemoryProperties2");
+    glad_vkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) load(userptr, "vkGetPhysicalDeviceProperties2");
+    glad_vkGetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2) load(userptr, "vkGetPhysicalDeviceQueueFamilyProperties2");
+    glad_vkGetPhysicalDeviceSparseImageFormatProperties2 = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2) load(userptr, "vkGetPhysicalDeviceSparseImageFormatProperties2");
+    glad_vkTrimCommandPool = (PFN_vkTrimCommandPool) load(userptr, "vkTrimCommandPool");
+    glad_vkUpdateDescriptorSetWithTemplate = (PFN_vkUpdateDescriptorSetWithTemplate) load(userptr, "vkUpdateDescriptorSetWithTemplate");
+}
+static void glad_vk_load_VK_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_VK_VERSION_1_2) return;
+    glad_vkCmdBeginRenderPass2 = (PFN_vkCmdBeginRenderPass2) load(userptr, "vkCmdBeginRenderPass2");
+    glad_vkCmdDrawIndexedIndirectCount = (PFN_vkCmdDrawIndexedIndirectCount) load(userptr, "vkCmdDrawIndexedIndirectCount");
+    glad_vkCmdDrawIndirectCount = (PFN_vkCmdDrawIndirectCount) load(userptr, "vkCmdDrawIndirectCount");
+    glad_vkCmdEndRenderPass2 = (PFN_vkCmdEndRenderPass2) load(userptr, "vkCmdEndRenderPass2");
+    glad_vkCmdNextSubpass2 = (PFN_vkCmdNextSubpass2) load(userptr, "vkCmdNextSubpass2");
+    glad_vkCreateRenderPass2 = (PFN_vkCreateRenderPass2) load(userptr, "vkCreateRenderPass2");
+    glad_vkGetBufferDeviceAddress = (PFN_vkGetBufferDeviceAddress) load(userptr, "vkGetBufferDeviceAddress");
+    glad_vkGetBufferOpaqueCaptureAddress = (PFN_vkGetBufferOpaqueCaptureAddress) load(userptr, "vkGetBufferOpaqueCaptureAddress");
+    glad_vkGetDeviceMemoryOpaqueCaptureAddress = (PFN_vkGetDeviceMemoryOpaqueCaptureAddress) load(userptr, "vkGetDeviceMemoryOpaqueCaptureAddress");
+    glad_vkGetSemaphoreCounterValue = (PFN_vkGetSemaphoreCounterValue) load(userptr, "vkGetSemaphoreCounterValue");
+    glad_vkResetQueryPool = (PFN_vkResetQueryPool) load(userptr, "vkResetQueryPool");
+    glad_vkSignalSemaphore = (PFN_vkSignalSemaphore) load(userptr, "vkSignalSemaphore");
+    glad_vkWaitSemaphores = (PFN_vkWaitSemaphores) load(userptr, "vkWaitSemaphores");
+}
+static void glad_vk_load_VK_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_VK_VERSION_1_3) return;
+    glad_vkCmdBeginRendering = (PFN_vkCmdBeginRendering) load(userptr, "vkCmdBeginRendering");
+    glad_vkCmdBindVertexBuffers2 = (PFN_vkCmdBindVertexBuffers2) load(userptr, "vkCmdBindVertexBuffers2");
+    glad_vkCmdBlitImage2 = (PFN_vkCmdBlitImage2) load(userptr, "vkCmdBlitImage2");
+    glad_vkCmdCopyBuffer2 = (PFN_vkCmdCopyBuffer2) load(userptr, "vkCmdCopyBuffer2");
+    glad_vkCmdCopyBufferToImage2 = (PFN_vkCmdCopyBufferToImage2) load(userptr, "vkCmdCopyBufferToImage2");
+    glad_vkCmdCopyImage2 = (PFN_vkCmdCopyImage2) load(userptr, "vkCmdCopyImage2");
+    glad_vkCmdCopyImageToBuffer2 = (PFN_vkCmdCopyImageToBuffer2) load(userptr, "vkCmdCopyImageToBuffer2");
+    glad_vkCmdEndRendering = (PFN_vkCmdEndRendering) load(userptr, "vkCmdEndRendering");
+    glad_vkCmdPipelineBarrier2 = (PFN_vkCmdPipelineBarrier2) load(userptr, "vkCmdPipelineBarrier2");
+    glad_vkCmdResetEvent2 = (PFN_vkCmdResetEvent2) load(userptr, "vkCmdResetEvent2");
+    glad_vkCmdResolveImage2 = (PFN_vkCmdResolveImage2) load(userptr, "vkCmdResolveImage2");
+    glad_vkCmdSetCullMode = (PFN_vkCmdSetCullMode) load(userptr, "vkCmdSetCullMode");
+    glad_vkCmdSetDepthBiasEnable = (PFN_vkCmdSetDepthBiasEnable) load(userptr, "vkCmdSetDepthBiasEnable");
+    glad_vkCmdSetDepthBoundsTestEnable = (PFN_vkCmdSetDepthBoundsTestEnable) load(userptr, "vkCmdSetDepthBoundsTestEnable");
+    glad_vkCmdSetDepthCompareOp = (PFN_vkCmdSetDepthCompareOp) load(userptr, "vkCmdSetDepthCompareOp");
+    glad_vkCmdSetDepthTestEnable = (PFN_vkCmdSetDepthTestEnable) load(userptr, "vkCmdSetDepthTestEnable");
+    glad_vkCmdSetDepthWriteEnable = (PFN_vkCmdSetDepthWriteEnable) load(userptr, "vkCmdSetDepthWriteEnable");
+    glad_vkCmdSetEvent2 = (PFN_vkCmdSetEvent2) load(userptr, "vkCmdSetEvent2");
+    glad_vkCmdSetFrontFace = (PFN_vkCmdSetFrontFace) load(userptr, "vkCmdSetFrontFace");
+    glad_vkCmdSetPrimitiveRestartEnable = (PFN_vkCmdSetPrimitiveRestartEnable) load(userptr, "vkCmdSetPrimitiveRestartEnable");
+    glad_vkCmdSetPrimitiveTopology = (PFN_vkCmdSetPrimitiveTopology) load(userptr, "vkCmdSetPrimitiveTopology");
+    glad_vkCmdSetRasterizerDiscardEnable = (PFN_vkCmdSetRasterizerDiscardEnable) load(userptr, "vkCmdSetRasterizerDiscardEnable");
+    glad_vkCmdSetScissorWithCount = (PFN_vkCmdSetScissorWithCount) load(userptr, "vkCmdSetScissorWithCount");
+    glad_vkCmdSetStencilOp = (PFN_vkCmdSetStencilOp) load(userptr, "vkCmdSetStencilOp");
+    glad_vkCmdSetStencilTestEnable = (PFN_vkCmdSetStencilTestEnable) load(userptr, "vkCmdSetStencilTestEnable");
+    glad_vkCmdSetViewportWithCount = (PFN_vkCmdSetViewportWithCount) load(userptr, "vkCmdSetViewportWithCount");
+    glad_vkCmdWaitEvents2 = (PFN_vkCmdWaitEvents2) load(userptr, "vkCmdWaitEvents2");
+    glad_vkCmdWriteTimestamp2 = (PFN_vkCmdWriteTimestamp2) load(userptr, "vkCmdWriteTimestamp2");
+    glad_vkCreatePrivateDataSlot = (PFN_vkCreatePrivateDataSlot) load(userptr, "vkCreatePrivateDataSlot");
+    glad_vkDestroyPrivateDataSlot = (PFN_vkDestroyPrivateDataSlot) load(userptr, "vkDestroyPrivateDataSlot");
+    glad_vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements) load(userptr, "vkGetDeviceBufferMemoryRequirements");
+    glad_vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements) load(userptr, "vkGetDeviceImageMemoryRequirements");
+    glad_vkGetDeviceImageSparseMemoryRequirements = (PFN_vkGetDeviceImageSparseMemoryRequirements) load(userptr, "vkGetDeviceImageSparseMemoryRequirements");
+    glad_vkGetPhysicalDeviceToolProperties = (PFN_vkGetPhysicalDeviceToolProperties) load(userptr, "vkGetPhysicalDeviceToolProperties");
+    glad_vkGetPrivateData = (PFN_vkGetPrivateData) load(userptr, "vkGetPrivateData");
+    glad_vkQueueSubmit2 = (PFN_vkQueueSubmit2) load(userptr, "vkQueueSubmit2");
+    glad_vkSetPrivateData = (PFN_vkSetPrivateData) load(userptr, "vkSetPrivateData");
 }
 static void glad_vk_load_VK_EXT_debug_report( GLADuserptrloadfunc load, void* userptr) {
     if(!GLAD_VK_EXT_debug_report) return;
-    vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT) load("vkCreateDebugReportCallbackEXT", userptr);
-    vkDebugReportMessageEXT = (PFN_vkDebugReportMessageEXT) load("vkDebugReportMessageEXT", userptr);
-    vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT) load("vkDestroyDebugReportCallbackEXT", userptr);
+    glad_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT) load(userptr, "vkCreateDebugReportCallbackEXT");
+    glad_vkDebugReportMessageEXT = (PFN_vkDebugReportMessageEXT) load(userptr, "vkDebugReportMessageEXT");
+    glad_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT) load(userptr, "vkDestroyDebugReportCallbackEXT");
 }
 static void glad_vk_load_VK_KHR_surface( GLADuserptrloadfunc load, void* userptr) {
     if(!GLAD_VK_KHR_surface) return;
-    vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR) load("vkDestroySurfaceKHR", userptr);
-    vkGetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR) load("vkGetPhysicalDeviceSurfaceCapabilitiesKHR", userptr);
-    vkGetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR) load("vkGetPhysicalDeviceSurfaceFormatsKHR", userptr);
-    vkGetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) load("vkGetPhysicalDeviceSurfacePresentModesKHR", userptr);
-    vkGetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) load("vkGetPhysicalDeviceSurfaceSupportKHR", userptr);
+    glad_vkDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR) load(userptr, "vkDestroySurfaceKHR");
+    glad_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = (PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR) load(userptr, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
+    glad_vkGetPhysicalDeviceSurfaceFormatsKHR = (PFN_vkGetPhysicalDeviceSurfaceFormatsKHR) load(userptr, "vkGetPhysicalDeviceSurfaceFormatsKHR");
+    glad_vkGetPhysicalDeviceSurfacePresentModesKHR = (PFN_vkGetPhysicalDeviceSurfacePresentModesKHR) load(userptr, "vkGetPhysicalDeviceSurfacePresentModesKHR");
+    glad_vkGetPhysicalDeviceSurfaceSupportKHR = (PFN_vkGetPhysicalDeviceSurfaceSupportKHR) load(userptr, "vkGetPhysicalDeviceSurfaceSupportKHR");
 }
 static void glad_vk_load_VK_KHR_swapchain( GLADuserptrloadfunc load, void* userptr) {
     if(!GLAD_VK_KHR_swapchain) return;
-    vkAcquireNextImage2KHR = (PFN_vkAcquireNextImage2KHR) load("vkAcquireNextImage2KHR", userptr);
-    vkAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) load("vkAcquireNextImageKHR", userptr);
-    vkCreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) load("vkCreateSwapchainKHR", userptr);
-    vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) load("vkDestroySwapchainKHR", userptr);
-    vkGetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR) load("vkGetDeviceGroupPresentCapabilitiesKHR", userptr);
-    vkGetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR) load("vkGetDeviceGroupSurfacePresentModesKHR", userptr);
-    vkGetPhysicalDevicePresentRectanglesKHR = (PFN_vkGetPhysicalDevicePresentRectanglesKHR) load("vkGetPhysicalDevicePresentRectanglesKHR", userptr);
-    vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) load("vkGetSwapchainImagesKHR", userptr);
-    vkQueuePresentKHR = (PFN_vkQueuePresentKHR) load("vkQueuePresentKHR", userptr);
+    glad_vkAcquireNextImage2KHR = (PFN_vkAcquireNextImage2KHR) load(userptr, "vkAcquireNextImage2KHR");
+    glad_vkAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR) load(userptr, "vkAcquireNextImageKHR");
+    glad_vkCreateSwapchainKHR = (PFN_vkCreateSwapchainKHR) load(userptr, "vkCreateSwapchainKHR");
+    glad_vkDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR) load(userptr, "vkDestroySwapchainKHR");
+    glad_vkGetDeviceGroupPresentCapabilitiesKHR = (PFN_vkGetDeviceGroupPresentCapabilitiesKHR) load(userptr, "vkGetDeviceGroupPresentCapabilitiesKHR");
+    glad_vkGetDeviceGroupSurfacePresentModesKHR = (PFN_vkGetDeviceGroupSurfacePresentModesKHR) load(userptr, "vkGetDeviceGroupSurfacePresentModesKHR");
+    glad_vkGetPhysicalDevicePresentRectanglesKHR = (PFN_vkGetPhysicalDevicePresentRectanglesKHR) load(userptr, "vkGetPhysicalDevicePresentRectanglesKHR");
+    glad_vkGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR) load(userptr, "vkGetSwapchainImagesKHR");
+    glad_vkQueuePresentKHR = (PFN_vkQueuePresentKHR) load(userptr, "vkQueuePresentKHR");
 }
 
 
@@ -411,47 +525,49 @@
     uint32_t i;
     uint32_t instance_extension_count = 0;
     uint32_t device_extension_count = 0;
-    uint32_t max_extension_count;
-    uint32_t total_extension_count;
-    char **extensions;
-    VkExtensionProperties *ext_properties;
+    uint32_t max_extension_count = 0;
+    uint32_t total_extension_count = 0;
+    char **extensions = NULL;
+    VkExtensionProperties *ext_properties = NULL;
     VkResult result;
 
-    if (vkEnumerateInstanceExtensionProperties == NULL || (physical_device != NULL && vkEnumerateDeviceExtensionProperties == NULL)) {
+    if (glad_vkEnumerateInstanceExtensionProperties == NULL || (physical_device != NULL && glad_vkEnumerateDeviceExtensionProperties == NULL)) {
         return 0;
     }
 
-    result = vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, NULL);
+    result = glad_vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, NULL);
     if (result != VK_SUCCESS) {
         return 0;
     }
 
     if (physical_device != NULL) {
-        result = vkEnumerateDeviceExtensionProperties(physical_device, NULL, &device_extension_count, NULL);
+        result = glad_vkEnumerateDeviceExtensionProperties(physical_device, NULL, &device_extension_count, NULL);
         if (result != VK_SUCCESS) {
             return 0;
         }
     }
 
     total_extension_count = instance_extension_count + device_extension_count;
+    if (total_extension_count <= 0) {
+        return 0;
+    }
+
     max_extension_count = instance_extension_count > device_extension_count
         ? instance_extension_count : device_extension_count;
 
     ext_properties = (VkExtensionProperties*) malloc(max_extension_count * sizeof(VkExtensionProperties));
     if (ext_properties == NULL) {
-        return 0;
+        goto glad_vk_get_extensions_error;
     }
 
-    result = vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, ext_properties);
+    result = glad_vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, ext_properties);
     if (result != VK_SUCCESS) {
-        free((void*) ext_properties);
-        return 0;
+        goto glad_vk_get_extensions_error;
     }
 
     extensions = (char**) calloc(total_extension_count, sizeof(char*));
     if (extensions == NULL) {
-        free((void*) ext_properties);
-        return 0;
+        goto glad_vk_get_extensions_error;
     }
 
     for (i = 0; i < instance_extension_count; ++i) {
@@ -459,17 +575,16 @@
 
         size_t extension_name_length = strlen(ext.extensionName) + 1;
         extensions[i] = (char*) malloc(extension_name_length * sizeof(char));
+        if (extensions[i] == NULL) {
+            goto glad_vk_get_extensions_error;
+        }
         memcpy(extensions[i], ext.extensionName, extension_name_length * sizeof(char));
     }
 
     if (physical_device != NULL) {
-        result = vkEnumerateDeviceExtensionProperties(physical_device, NULL, &device_extension_count, ext_properties);
+        result = glad_vkEnumerateDeviceExtensionProperties(physical_device, NULL, &device_extension_count, ext_properties);
         if (result != VK_SUCCESS) {
-            for (i = 0; i < instance_extension_count; ++i) {
-                free((void*) extensions[i]);
-            }
-            free(extensions);
-            return 0;
+            goto glad_vk_get_extensions_error;
         }
 
         for (i = 0; i < device_extension_count; ++i) {
@@ -477,6 +592,9 @@
 
             size_t extension_name_length = strlen(ext.extensionName) + 1;
             extensions[instance_extension_count + i] = (char*) malloc(extension_name_length * sizeof(char));
+            if (extensions[instance_extension_count + i] == NULL) {
+                goto glad_vk_get_extensions_error;
+            }
             memcpy(extensions[instance_extension_count + i], ext.extensionName, extension_name_length * sizeof(char));
         }
     }
@@ -487,6 +605,16 @@
     *out_extensions = extensions;
 
     return 1;
+
+glad_vk_get_extensions_error:
+    free((void*) ext_properties);
+    if (extensions != NULL) {
+        for (i = 0; i < total_extension_count; ++i) {
+            free((void*) extensions[i]);
+        }
+        free(extensions);
+    }
+    return 0;
 }
 
 static void glad_vk_free_extensions(uint32_t extension_count, char **extensions) {
@@ -503,7 +631,7 @@
     uint32_t i;
 
     for (i = 0; i < extension_count; ++i) {
-        if(strcmp(name, extensions[i]) == 0) {
+        if(extensions[i] != NULL && strcmp(name, extensions[i]) == 0) {
             return 1;
         }
     }
@@ -511,7 +639,7 @@
     return 0;
 }
 
-static GLADapiproc glad_vk_get_proc_from_userptr(const char* name, void *userptr) {
+static GLADapiproc glad_vk_get_proc_from_userptr(void *userptr, const char* name) {
     return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
 }
 
@@ -521,9 +649,12 @@
     if (!glad_vk_get_extensions(physical_device, &extension_count, &extensions)) return 0;
 
     GLAD_VK_EXT_debug_report = glad_vk_has_extension("VK_EXT_debug_report", extension_count, extensions);
+    GLAD_VK_KHR_portability_enumeration = glad_vk_has_extension("VK_KHR_portability_enumeration", extension_count, extensions);
     GLAD_VK_KHR_surface = glad_vk_has_extension("VK_KHR_surface", extension_count, extensions);
     GLAD_VK_KHR_swapchain = glad_vk_has_extension("VK_KHR_swapchain", extension_count, extensions);
 
+    (void) glad_vk_has_extension;
+
     glad_vk_free_extensions(extension_count, extensions);
 
     return 1;
@@ -534,11 +665,11 @@
     int minor = 0;
 
 #ifdef VK_VERSION_1_1
-    if (vkEnumerateInstanceVersion  != NULL) {
+    if (glad_vkEnumerateInstanceVersion != NULL) {
         uint32_t version;
         VkResult result;
 
-        result = vkEnumerateInstanceVersion(&version);
+        result = glad_vkEnumerateInstanceVersion(&version);
         if (result == VK_SUCCESS) {
             major = (int) VK_VERSION_MAJOR(version);
             minor = (int) VK_VERSION_MINOR(version);
@@ -546,9 +677,9 @@
     }
 #endif
 
-    if (physical_device != NULL && vkGetPhysicalDeviceProperties  != NULL) {
+    if (physical_device != NULL && glad_vkGetPhysicalDeviceProperties != NULL) {
         VkPhysicalDeviceProperties properties;
-        vkGetPhysicalDeviceProperties(physical_device, &properties);
+        glad_vkGetPhysicalDeviceProperties(physical_device, &properties);
 
         major = (int) VK_VERSION_MAJOR(properties.apiVersion);
         minor = (int) VK_VERSION_MINOR(properties.apiVersion);
@@ -556,6 +687,8 @@
 
     GLAD_VK_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
     GLAD_VK_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
+    GLAD_VK_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
+    GLAD_VK_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
 
     return GLAD_MAKE_VERSION(major, minor);
 }
@@ -564,7 +697,7 @@
     int version;
 
 #ifdef VK_VERSION_1_1
-    vkEnumerateInstanceVersion  = (PFN_vkEnumerateInstanceVersion) load("vkEnumerateInstanceVersion", userptr);
+    glad_vkEnumerateInstanceVersion  = (PFN_vkEnumerateInstanceVersion) load(userptr, "vkEnumerateInstanceVersion");
 #endif
     version = glad_vk_find_core_vulkan( physical_device);
     if (!version) {
@@ -573,6 +706,8 @@
 
     glad_vk_load_VK_VERSION_1_0(load, userptr);
     glad_vk_load_VK_VERSION_1_1(load, userptr);
+    glad_vk_load_VK_VERSION_1_2(load, userptr);
+    glad_vk_load_VK_VERSION_1_3(load, userptr);
 
     if (!glad_vk_find_extensions_vulkan( physical_device)) return 0;
     glad_vk_load_VK_EXT_debug_report(load, userptr);
@@ -590,4 +725,9 @@
 
 
 
+ 
 
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/deps/stb_image_write.h b/deps/stb_image_write.h
index 4319c0d..e4b32ed 100644
--- a/deps/stb_image_write.h
+++ b/deps/stb_image_write.h
@@ -1,5 +1,5 @@
-/* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h
-   writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015
+/* stb_image_write - v1.16 - public domain - http://nothings.org/stb
+   writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
                                      no warranty implied; use at your own risk
 
    Before #including,
@@ -12,41 +12,64 @@
 
 ABOUT:
 
-   This header file is a library for writing images to C stdio. It could be
-   adapted to write to memory or a general streaming interface; let me know.
+   This header file is a library for writing images to C stdio or a callback.
 
    The PNG output is not optimal; it is 20-50% larger than the file
-   written by a decent optimizing implementation. This library is designed
-   for source code compactness and simplicity, not optimal image file size
-   or run-time performance.
+   written by a decent optimizing implementation; though providing a custom
+   zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that.
+   This library is designed for source code compactness and simplicity,
+   not optimal image file size or run-time performance.
 
 BUILDING:
 
    You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
    You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
    malloc,realloc,free.
-   You can define STBIW_MEMMOVE() to replace memmove()
+   You can #define STBIW_MEMMOVE() to replace memmove()
+   You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function
+   for PNG compression (instead of the builtin one), it must have the following signature:
+   unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality);
+   The returned data will be freed with STBIW_FREE() (free() by default),
+   so it must be heap allocated with STBIW_MALLOC() (malloc() by default),
+
+UNICODE:
+
+   If compiling for Windows and you wish to use Unicode filenames, compile
+   with
+       #define STBIW_WINDOWS_UTF8
+   and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert
+   Windows wchar_t filenames to utf8.
 
 USAGE:
 
-   There are four functions, one for each image file format:
+   There are five functions, one for each image file format:
 
      int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
      int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
      int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
+     int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality);
      int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
 
-   There are also four equivalent functions that use an arbitrary write function. You are
+     void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically
+
+   There are also five equivalent functions that use an arbitrary write function. You are
    expected to open/close your file-equivalent before and after calling these:
 
      int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data, int stride_in_bytes);
      int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
      int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
      int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
+     int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
 
    where the callback is:
       void stbi_write_func(void *context, void *data, int size);
 
+   You can configure it with these global variables:
+      int stbi_write_tga_with_rle;             // defaults to true; set to 0 to disable RLE
+      int stbi_write_png_compression_level;    // defaults to 8; set to higher for more compression
+      int stbi_write_force_png_filter;         // defaults to -1; set to 0..5 to force a filter mode
+
+
    You can define STBI_WRITE_NO_STDIO to disable the file variant of these
    functions, so the library will not use stdio.h at all. However, this will
    also disable HDR writing, because it requires stdio for formatted output.
@@ -73,6 +96,9 @@
    writer, both because it is in BGR order and because it may have padding
    at the end of the line.)
 
+   PNG allows you to set the deflate compression level by setting the global
+   variable 'stbi_write_png_compression_level' (it defaults to 8).
+
    HDR expects linear float data. Since the format is always 32-bit rgb(e)
    data, alpha (if provided) is discarded, and for monochrome data it is
    replicated across all three channels.
@@ -80,20 +106,23 @@
    TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
    data, set the global variable 'stbi_write_tga_with_rle' to 0.
 
+   JPEG does ignore alpha channels in input data; quality is between 1 and 100.
+   Higher quality looks better but results in a bigger image.
+   JPEG baseline (no JPEG progressive).
+
 CREDITS:
 
-   PNG/BMP/TGA
-      Sean Barrett
-   HDR
-      Baldur Karlsson
-   TGA monochrome:
-      Jean-Sebastien Guay
-   misc enhancements:
-      Tim Kelsey
-   TGA RLE
-      Alan Hickman
-   initial file IO callback implementation
-      Emmanuel Julien
+
+   Sean Barrett           -    PNG/BMP/TGA
+   Baldur Karlsson        -    HDR
+   Jean-Sebastien Guay    -    TGA monochrome
+   Tim Kelsey             -    misc enhancements
+   Alan Hickman           -    TGA RLE
+   Emmanuel Julien        -    initial file IO callback implementation
+   Jon Olick              -    original jo_jpeg.cpp code
+   Daniel Gibson          -    integrate JPEG, allow external zlib
+   Aarni Koskela          -    allow choosing PNG filter
+
    bugfixes:
       github:Chribba
       Guillaume Chereau
@@ -103,27 +132,44 @@
       Jonas Karlsson
       Filip Wasil
       Thatcher Ulrich
-      
+      github:poppolopoppo
+      Patrick Boettcher
+      github:xeekworx
+      Cap Petschulat
+      Simon Rodriguez
+      Ivan Tikhonov
+      github:ignotion
+      Adam Schackart
+      Andrew Kensler
+
 LICENSE
 
-This software is dual-licensed to the public domain and under the following
-license: you are granted a perpetual, irrevocable license to copy, modify,
-publish, and distribute this file as you see fit.
+  See end of file for license information.
 
 */
 
 #ifndef INCLUDE_STB_IMAGE_WRITE_H
 #define INCLUDE_STB_IMAGE_WRITE_H
 
+#include <stdlib.h>
+
+// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline'
+#ifndef STBIWDEF
+#ifdef STB_IMAGE_WRITE_STATIC
+#define STBIWDEF  static
+#else
 #ifdef __cplusplus
-extern "C" {
+#define STBIWDEF  extern "C"
+#else
+#define STBIWDEF  extern
+#endif
+#endif
 #endif
 
-#ifdef STB_IMAGE_WRITE_STATIC
-#define STBIWDEF static
-#else
-#define STBIWDEF extern
-extern int stbi_write_tga_with_rle;
+#ifndef STB_IMAGE_WRITE_STATIC  // C++ forbids static forward declarations
+STBIWDEF int stbi_write_tga_with_rle;
+STBIWDEF int stbi_write_png_compression_level;
+STBIWDEF int stbi_write_force_png_filter;
 #endif
 
 #ifndef STBI_WRITE_NO_STDIO
@@ -131,6 +177,11 @@
 STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void  *data);
 STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void  *data);
 STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
+STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void  *data, int quality);
+
+#ifdef STBIW_WINDOWS_UTF8
+STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
+#endif
 #endif
 
 typedef void stbi_write_func(void *context, void *data, int size);
@@ -139,10 +190,9 @@
 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
 STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
 STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
+STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void  *data, int quality);
 
-#ifdef __cplusplus
-}
-#endif
+STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean);
 
 #endif//INCLUDE_STB_IMAGE_WRITE_H
 
@@ -197,10 +247,29 @@
 
 #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
 
+#ifdef STB_IMAGE_WRITE_STATIC
+static int stbi_write_png_compression_level = 8;
+static int stbi_write_tga_with_rle = 1;
+static int stbi_write_force_png_filter = -1;
+#else
+int stbi_write_png_compression_level = 8;
+int stbi_write_tga_with_rle = 1;
+int stbi_write_force_png_filter = -1;
+#endif
+
+static int stbi__flip_vertically_on_write = 0;
+
+STBIWDEF void stbi_flip_vertically_on_write(int flag)
+{
+   stbi__flip_vertically_on_write = flag;
+}
+
 typedef struct
 {
    stbi_write_func *func;
    void *context;
+   unsigned char buffer[64];
+   int buf_used;
 } stbi__write_context;
 
 // initialize a callback-based context
@@ -217,9 +286,52 @@
    fwrite(data,1,size,(FILE*) context);
 }
 
+#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
+#ifdef __cplusplus
+#define STBIW_EXTERN extern "C"
+#else
+#define STBIW_EXTERN extern
+#endif
+STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
+STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);
+
+STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
+{
+   return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
+}
+#endif
+
+static FILE *stbiw__fopen(char const *filename, char const *mode)
+{
+   FILE *f;
+#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
+   wchar_t wMode[64];
+   wchar_t wFilename[1024];
+   if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
+      return 0;
+
+   if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
+      return 0;
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+   if (0 != _wfopen_s(&f, wFilename, wMode))
+      f = 0;
+#else
+   f = _wfopen(wFilename, wMode);
+#endif
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+   if (0 != fopen_s(&f, filename, mode))
+      f=0;
+#else
+   f = fopen(filename, mode);
+#endif
+   return f;
+}
+
 static int stbi__start_write_file(stbi__write_context *s, const char *filename)
 {
-   FILE *f = fopen(filename, "wb");
+   FILE *f = stbiw__fopen(filename, "wb");
    stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
    return f != NULL;
 }
@@ -234,12 +346,6 @@
 typedef unsigned int stbiw_uint32;
 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
 
-#ifdef STB_IMAGE_WRITE_STATIC
-static int stbi_write_tga_with_rle = 1;
-#else
-int stbi_write_tga_with_rle = 1;
-#endif
-
 static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
 {
    while (*fmt) {
@@ -277,11 +383,36 @@
    va_end(v);
 }
 
+static void stbiw__write_flush(stbi__write_context *s)
+{
+   if (s->buf_used) {
+      s->func(s->context, &s->buffer, s->buf_used);
+      s->buf_used = 0;
+   }
+}
+
+static void stbiw__putc(stbi__write_context *s, unsigned char c)
+{
+   s->func(s->context, &c, 1);
+}
+
+static void stbiw__write1(stbi__write_context *s, unsigned char a)
+{
+   if ((size_t)s->buf_used + 1 > sizeof(s->buffer))
+      stbiw__write_flush(s);
+   s->buffer[s->buf_used++] = a;
+}
+
 static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
 {
-   unsigned char arr[3];
-   arr[0] = a, arr[1] = b, arr[2] = c;
-   s->func(s->context, arr, 3);
+   int n;
+   if ((size_t)s->buf_used + 3 > sizeof(s->buffer))
+      stbiw__write_flush(s);
+   n = s->buf_used;
+   s->buf_used = n+3;
+   s->buffer[n+0] = a;
+   s->buffer[n+1] = b;
+   s->buffer[n+2] = c;
 }
 
 static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
@@ -290,17 +421,15 @@
    int k;
 
    if (write_alpha < 0)
-      s->func(s->context, &d[comp - 1], 1);
+      stbiw__write1(s, d[comp - 1]);
 
    switch (comp) {
+      case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
       case 1:
-         s->func(s->context,d,1);
-         break;
-      case 2:
          if (expand_mono)
             stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
          else
-            s->func(s->context, d, 1);  // monochrome TGA
+            stbiw__write1(s, d[0]);  // monochrome TGA
          break;
       case 4:
          if (!write_alpha) {
@@ -316,7 +445,7 @@
          break;
    }
    if (write_alpha > 0)
-      s->func(s->context, &d[comp - 1], 1);
+      stbiw__write1(s, d[comp - 1]);
 }
 
 static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
@@ -327,16 +456,21 @@
    if (y <= 0)
       return;
 
-   if (vdir < 0)
-      j_end = -1, j = y-1;
-   else
-      j_end =  y, j = 0;
+   if (stbi__flip_vertically_on_write)
+      vdir *= -1;
+
+   if (vdir < 0) {
+      j_end = -1; j = y-1;
+   } else {
+      j_end =  y; j = 0;
+   }
 
    for (; j != j_end; j += vdir) {
       for (i=0; i < x; ++i) {
          unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
          stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
       }
+      stbiw__write_flush(s);
       s->func(s->context, &zero, scanline_pad);
    }
 }
@@ -357,16 +491,27 @@
 
 static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
 {
-   int pad = (-x*3) & 3;
-   return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
-           "11 4 22 4" "4 44 22 444444",
-           'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,  // file header
-            40, x,y, 1,24, 0,0,0,0,0,0);             // bitmap header
+   if (comp != 4) {
+      // write RGB bitmap
+      int pad = (-x*3) & 3;
+      return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
+              "11 4 22 4" "4 44 22 444444",
+              'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,  // file header
+               40, x,y, 1,24, 0,0,0,0,0,0);             // bitmap header
+   } else {
+      // RGBA bitmaps need a v4 header
+      // use BI_BITFIELDS mode with 32bpp and alpha mask
+      // (straight BI_RGB with alpha mask doesn't work in most readers)
+      return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0,
+         "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
+         'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header
+         108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header
+   }
 }
 
 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
 {
-   stbi__write_context s;
+   stbi__write_context s = { 0 };
    stbi__start_write_callbacks(&s, func, context);
    return stbi_write_bmp_core(&s, x, y, comp, data);
 }
@@ -374,7 +519,7 @@
 #ifndef STBI_WRITE_NO_STDIO
 STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
 {
-   stbi__write_context s;
+   stbi__write_context s = { 0 };
    if (stbi__start_write_file(&s,filename)) {
       int r = stbi_write_bmp_core(&s, x, y, comp, data);
       stbi__end_write_file(&s);
@@ -398,11 +543,21 @@
          "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
    } else {
       int i,j,k;
+      int jend, jdir;
 
       stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8);
 
-      for (j = y - 1; j >= 0; --j) {
-          unsigned char *row = (unsigned char *) data + j * x * comp;
+      if (stbi__flip_vertically_on_write) {
+         j = 0;
+         jend = y;
+         jdir = 1;
+      } else {
+         j = y-1;
+         jend = -1;
+         jdir = -1;
+      }
+      for (; j != jend; j += jdir) {
+         unsigned char *row = (unsigned char *) data + j * x * comp;
          int len;
 
          for (i = 0; i < x; i += len) {
@@ -437,32 +592,33 @@
 
             if (diff) {
                unsigned char header = STBIW_UCHAR(len - 1);
-               s->func(s->context, &header, 1);
+               stbiw__write1(s, header);
                for (k = 0; k < len; ++k) {
                   stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
                }
             } else {
                unsigned char header = STBIW_UCHAR(len - 129);
-               s->func(s->context, &header, 1);
+               stbiw__write1(s, header);
                stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
             }
          }
       }
+      stbiw__write_flush(s);
    }
    return 1;
 }
 
-int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
+STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
 {
-   stbi__write_context s;
+   stbi__write_context s = { 0 };
    stbi__start_write_callbacks(&s, func, context);
    return stbi_write_tga_core(&s, x, y, comp, (void *) data);
 }
 
 #ifndef STBI_WRITE_NO_STDIO
-int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
+STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
 {
-   stbi__write_context s;
+   stbi__write_context s = { 0 };
    if (stbi__start_write_file(&s,filename)) {
       int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
       stbi__end_write_file(&s);
@@ -475,11 +631,12 @@
 // *************************************************************************************************
 // Radiance RGBE HDR writer
 // by Baldur Karlsson
-#ifndef STBI_WRITE_NO_STDIO
 
 #define stbiw__max(a, b)  ((a) > (b) ? (a) : (b))
 
-void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
+#ifndef STBI_WRITE_NO_STDIO
+
+static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
 {
    int exponent;
    float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
@@ -496,7 +653,7 @@
    }
 }
 
-void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
+static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
 {
    unsigned char lengthbyte = STBIW_UCHAR(length+128);
    STBIW_ASSERT(length+128 <= 255);
@@ -504,7 +661,7 @@
    s->func(s->context, &databyte, 1);
 }
 
-void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
+static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
 {
    unsigned char lengthbyte = STBIW_UCHAR(length);
    STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
@@ -512,7 +669,7 @@
    s->func(s->context, data, length);
 }
 
-void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
+static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
 {
    unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
    unsigned char rgbe[4];
@@ -613,26 +770,30 @@
       char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
       s->func(s->context, header, sizeof(header)-1);
 
+#ifdef __STDC_LIB_EXT1__
+      len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE=          1.0000000000000\n\n-Y %d +X %d\n", y, x);
+#else
       len = sprintf(buffer, "EXPOSURE=          1.0000000000000\n\n-Y %d +X %d\n", y, x);
+#endif
       s->func(s->context, buffer, len);
 
       for(i=0; i < y; i++)
-         stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x);
+         stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i));
       STBIW_FREE(scratch);
       return 1;
    }
 }
 
-int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
+STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
 {
-   stbi__write_context s;
+   stbi__write_context s = { 0 };
    stbi__start_write_callbacks(&s, func, context);
    return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
 }
 
-int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
+STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
 {
-   stbi__write_context s;
+   stbi__write_context s = { 0 };
    if (stbi__start_write_file(&s,filename)) {
       int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
       stbi__end_write_file(&s);
@@ -648,8 +809,9 @@
 // PNG writer
 //
 
+#ifndef STBIW_ZLIB_COMPRESS
 // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
-#define stbiw__sbraw(a) ((int *) (a) - 2)
+#define stbiw__sbraw(a) ((int *) (void *) (a) - 2)
 #define stbiw__sbm(a)   stbiw__sbraw(a)[0]
 #define stbiw__sbn(a)   stbiw__sbraw(a)[1]
 
@@ -728,8 +890,14 @@
 
 #define stbiw__ZHASH   16384
 
-unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
+#endif // STBIW_ZLIB_COMPRESS
+
+STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
 {
+#ifdef STBIW_ZLIB_COMPRESS
+   // user provided a zlib compress implementation, use that
+   return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
+#else // use builtin
    static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 };
    static unsigned char  lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,  4,  5,  5,  5,  5,  0 };
    static unsigned short distc[]   = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 };
@@ -737,7 +905,9 @@
    unsigned int bitbuf=0;
    int i,j, bitcount=0;
    unsigned char *out = NULL;
-   unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**));
+   unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**));
+   if (hash_table == NULL)
+      return NULL;
    if (quality < 5) quality = 5;
 
    stbiw__sbpush(out, 0x78);   // DEFLATE 32K window
@@ -758,7 +928,7 @@
       for (j=0; j < n; ++j) {
          if (hlist[j]-data > i-32768) { // if entry lies within window
             int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
-            if (d >= best) best=d,bestloc=hlist[j];
+            if (d >= best) { best=d; bestloc=hlist[j]; }
          }
       }
       // when hash table entry is too long, delete half the entries
@@ -811,14 +981,31 @@
       (void) stbiw__sbfree(hash_table[i]);
    STBIW_FREE(hash_table);
 
+   // store uncompressed instead if compression was worse
+   if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
+      stbiw__sbn(out) = 2;  // truncate to DEFLATE 32K window and FLEVEL = 1
+      for (j = 0; j < data_len;) {
+         int blocklen = data_len - j;
+         if (blocklen > 32767) blocklen = 32767;
+         stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression
+         stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN
+         stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
+         stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN
+         stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
+         memcpy(out+stbiw__sbn(out), data+j, blocklen);
+         stbiw__sbn(out) += blocklen;
+         j += blocklen;
+      }
+   }
+
    {
       // compute adler32 on input
       unsigned int s1=1, s2=0;
       int blocklen = (int) (data_len % 5552);
       j=0;
       while (j < data_len) {
-         for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
-         s1 %= 65521, s2 %= 65521;
+         for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
+         s1 %= 65521; s2 %= 65521;
          j += blocklen;
          blocklen = 5552;
       }
@@ -831,10 +1018,14 @@
    // make returned pointer freeable
    STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
    return (unsigned char *) stbiw__sbraw(out);
+#endif // STBIW_ZLIB_COMPRESS
 }
 
 static unsigned int stbiw__crc32(unsigned char *buffer, int len)
 {
+#ifdef STBIW_CRC32
+    return STBIW_CRC32(buffer, len);
+#else
    static unsigned int crc_table[256] =
    {
       0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
@@ -876,6 +1067,7 @@
    for (i=0; i < len; ++i)
       crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
    return ~crc;
+#endif
 }
 
 #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4)
@@ -896,61 +1088,92 @@
    return STBIW_UCHAR(c);
 }
 
-unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
+// @OPTIMIZE: provide an option that always forces left-predict or paeth predict
+static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer)
 {
+   static int mapping[] = { 0,1,2,3,4 };
+   static int firstmap[] = { 0,1,0,5,6 };
+   int *mymap = (y != 0) ? mapping : firstmap;
+   int i;
+   int type = mymap[filter_type];
+   unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
+   int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
+
+   if (type==0) {
+      memcpy(line_buffer, z, width*n);
+      return;
+   }
+
+   // first loop isn't optimized since it's just one pixel
+   for (i = 0; i < n; ++i) {
+      switch (type) {
+         case 1: line_buffer[i] = z[i]; break;
+         case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break;
+         case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break;
+         case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break;
+         case 5: line_buffer[i] = z[i]; break;
+         case 6: line_buffer[i] = z[i]; break;
+      }
+   }
+   switch (type) {
+      case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break;
+      case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break;
+      case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break;
+      case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break;
+      case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break;
+      case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
+   }
+}
+
+STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
+{
+   int force_filter = stbi_write_force_png_filter;
    int ctype[5] = { -1, 0, 4, 2, 6 };
    unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
    unsigned char *out,*o, *filt, *zlib;
    signed char *line_buffer;
-   int i,j,k,p,zlen;
+   int j,zlen;
 
    if (stride_bytes == 0)
       stride_bytes = x * n;
 
+   if (force_filter >= 5) {
+      force_filter = -1;
+   }
+
    filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
    line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
    for (j=0; j < y; ++j) {
-      static int mapping[] = { 0,1,2,3,4 };
-      static int firstmap[] = { 0,1,0,5,6 };
-      int *mymap = j ? mapping : firstmap;
-      int best = 0, bestval = 0x7fffffff;
-      for (p=0; p < 2; ++p) {
-         for (k= p?best:0; k < 5; ++k) {
-            int type = mymap[k],est=0;
-            unsigned char *z = pixels + stride_bytes*j;
-            for (i=0; i < n; ++i)
-               switch (type) {
-                  case 0: line_buffer[i] = z[i]; break;
-                  case 1: line_buffer[i] = z[i]; break;
-                  case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
-                  case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
-                  case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
-                  case 5: line_buffer[i] = z[i]; break;
-                  case 6: line_buffer[i] = z[i]; break;
-               }
-            for (i=n; i < x*n; ++i) {
-               switch (type) {
-                  case 0: line_buffer[i] = z[i]; break;
-                  case 1: line_buffer[i] = z[i] - z[i-n]; break;
-                  case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
-                  case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
-                  case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
-                  case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
-                  case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
-               }
-            }
-            if (p) break;
-            for (i=0; i < x*n; ++i)
+      int filter_type;
+      if (force_filter > -1) {
+         filter_type = force_filter;
+         stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
+      } else { // Estimate the best filter by running through all of them:
+         int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
+         for (filter_type = 0; filter_type < 5; filter_type++) {
+            stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
+
+            // Estimate the entropy of the line using this filter; the less, the better.
+            est = 0;
+            for (i = 0; i < x*n; ++i) {
                est += abs((signed char) line_buffer[i]);
-            if (est < bestval) { bestval = est; best = k; }
+            }
+            if (est < best_filter_val) {
+               best_filter_val = est;
+               best_filter = filter_type;
+            }
+         }
+         if (filter_type != best_filter) {  // If the last iteration already got us the best filter, don't redo it
+            stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
+            filter_type = best_filter;
          }
       }
-      // when we get here, best contains the filter type, and line_buffer contains the data
-      filt[j*(x*n+1)] = (unsigned char) best;
+      // when we get here, filter_type contains the filter type, and line_buffer contains the data
+      filt[j*(x*n+1)] = (unsigned char) filter_type;
       STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
    }
    STBIW_FREE(line_buffer);
-   zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
+   zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level);
    STBIW_FREE(filt);
    if (!zlib) return 0;
 
@@ -993,9 +1216,10 @@
 {
    FILE *f;
    int len;
-   unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
+   unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
    if (png == NULL) return 0;
-   f = fopen(filename, "wb");
+
+   f = stbiw__fopen(filename, "wb");
    if (!f) { STBIW_FREE(png); return 0; }
    fwrite(png, 1, len, f);
    fclose(f);
@@ -1007,16 +1231,426 @@
 STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
 {
    int len;
-   unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
+   unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
    if (png == NULL) return 0;
    func(context, png, len);
    STBIW_FREE(png);
    return 1;
 }
 
+
+/* ***************************************************************************
+ *
+ * JPEG writer
+ *
+ * This is based on Jon Olick's jo_jpeg.cpp:
+ * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html
+ */
+
+static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,
+      24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 };
+
+static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) {
+   int bitBuf = *bitBufP, bitCnt = *bitCntP;
+   bitCnt += bs[1];
+   bitBuf |= bs[0] << (24 - bitCnt);
+   while(bitCnt >= 8) {
+      unsigned char c = (bitBuf >> 16) & 255;
+      stbiw__putc(s, c);
+      if(c == 255) {
+         stbiw__putc(s, 0);
+      }
+      bitBuf <<= 8;
+      bitCnt -= 8;
+   }
+   *bitBufP = bitBuf;
+   *bitCntP = bitCnt;
+}
+
+static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) {
+   float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
+   float z1, z2, z3, z4, z5, z11, z13;
+
+   float tmp0 = d0 + d7;
+   float tmp7 = d0 - d7;
+   float tmp1 = d1 + d6;
+   float tmp6 = d1 - d6;
+   float tmp2 = d2 + d5;
+   float tmp5 = d2 - d5;
+   float tmp3 = d3 + d4;
+   float tmp4 = d3 - d4;
+
+   // Even part
+   float tmp10 = tmp0 + tmp3;   // phase 2
+   float tmp13 = tmp0 - tmp3;
+   float tmp11 = tmp1 + tmp2;
+   float tmp12 = tmp1 - tmp2;
+
+   d0 = tmp10 + tmp11;       // phase 3
+   d4 = tmp10 - tmp11;
+
+   z1 = (tmp12 + tmp13) * 0.707106781f; // c4
+   d2 = tmp13 + z1;       // phase 5
+   d6 = tmp13 - z1;
+
+   // Odd part
+   tmp10 = tmp4 + tmp5;       // phase 2
+   tmp11 = tmp5 + tmp6;
+   tmp12 = tmp6 + tmp7;
+
+   // The rotator is modified from fig 4-8 to avoid extra negations.
+   z5 = (tmp10 - tmp12) * 0.382683433f; // c6
+   z2 = tmp10 * 0.541196100f + z5; // c2-c6
+   z4 = tmp12 * 1.306562965f + z5; // c2+c6
+   z3 = tmp11 * 0.707106781f; // c4
+
+   z11 = tmp7 + z3;      // phase 5
+   z13 = tmp7 - z3;
+
+   *d5p = z13 + z2;         // phase 6
+   *d3p = z13 - z2;
+   *d1p = z11 + z4;
+   *d7p = z11 - z4;
+
+   *d0p = d0;  *d2p = d2;  *d4p = d4;  *d6p = d6;
+}
+
+static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
+   int tmp1 = val < 0 ? -val : val;
+   val = val < 0 ? val-1 : val;
+   bits[1] = 1;
+   while(tmp1 >>= 1) {
+      ++bits[1];
+   }
+   bits[0] = val & ((1<<bits[1])-1);
+}
+
+static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, int du_stride, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
+   const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
+   const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
+   int dataOff, i, j, n, diff, end0pos, x, y;
+   int DU[64];
+
+   // DCT rows
+   for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
+      stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]);
+   }
+   // DCT columns
+   for(dataOff=0; dataOff<8; ++dataOff) {
+      stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
+                     &CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
+   }
+   // Quantize/descale/zigzag the coefficients
+   for(y = 0, j=0; y < 8; ++y) {
+      for(x = 0; x < 8; ++x,++j) {
+         float v;
+         i = y*du_stride+x;
+         v = CDU[i]*fdtbl[j];
+         // DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
+         // ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
+         DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
+      }
+   }
+
+   // Encode DC
+   diff = DU[0] - DC;
+   if (diff == 0) {
+      stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
+   } else {
+      unsigned short bits[2];
+      stbiw__jpg_calcBits(diff, bits);
+      stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
+      stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
+   }
+   // Encode ACs
+   end0pos = 63;
+   for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
+   }
+   // end0pos = first element in reverse order !=0
+   if(end0pos == 0) {
+      stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
+      return DU[0];
+   }
+   for(i = 1; i <= end0pos; ++i) {
+      int startpos = i;
+      int nrzeroes;
+      unsigned short bits[2];
+      for (; DU[i]==0 && i<=end0pos; ++i) {
+      }
+      nrzeroes = i-startpos;
+      if ( nrzeroes >= 16 ) {
+         int lng = nrzeroes>>4;
+         int nrmarker;
+         for (nrmarker=1; nrmarker <= lng; ++nrmarker)
+            stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
+         nrzeroes &= 15;
+      }
+      stbiw__jpg_calcBits(DU[i], bits);
+      stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
+      stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
+   }
+   if(end0pos != 63) {
+      stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
+   }
+   return DU[0];
+}
+
+static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) {
+   // Constants that don't pollute global namespace
+   static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};
+   static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
+   static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};
+   static const unsigned char std_ac_luminance_values[] = {
+      0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
+      0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
+      0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
+      0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
+      0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
+      0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
+      0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
+   };
+   static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
+   static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
+   static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
+   static const unsigned char std_ac_chrominance_values[] = {
+      0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
+      0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
+      0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
+      0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
+      0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
+      0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
+      0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
+   };
+   // Huffman tables
+   static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}};
+   static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}};
+   static const unsigned short YAC_HT[256][2] = {
+      {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
+   };
+   static const unsigned short UVAC_HT[256][2] = {
+      {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0},
+      {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
+   };
+   static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22,
+                             37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99};
+   static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,
+                              99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
+   static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
+                                 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
+
+   int row, col, i, k, subsample;
+   float fdtbl_Y[64], fdtbl_UV[64];
+   unsigned char YTable[64], UVTable[64];
+
+   if(!data || !width || !height || comp > 4 || comp < 1) {
+      return 0;
+   }
+
+   quality = quality ? quality : 90;
+   subsample = quality <= 90 ? 1 : 0;
+   quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
+   quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
+
+   for(i = 0; i < 64; ++i) {
+      int uvti, yti = (YQT[i]*quality+50)/100;
+      YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
+      uvti = (UVQT[i]*quality+50)/100;
+      UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
+   }
+
+   for(row = 0, k = 0; row < 8; ++row) {
+      for(col = 0; col < 8; ++col, ++k) {
+         fdtbl_Y[k]  = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
+         fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
+      }
+   }
+
+   // Write Headers
+   {
+      static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
+      static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
+      const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
+                                      3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
+      s->func(s->context, (void*)head0, sizeof(head0));
+      s->func(s->context, (void*)YTable, sizeof(YTable));
+      stbiw__putc(s, 1);
+      s->func(s->context, UVTable, sizeof(UVTable));
+      s->func(s->context, (void*)head1, sizeof(head1));
+      s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1);
+      s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values));
+      stbiw__putc(s, 0x10); // HTYACinfo
+      s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1);
+      s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values));
+      stbiw__putc(s, 1); // HTUDCinfo
+      s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1);
+      s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
+      stbiw__putc(s, 0x11); // HTUACinfo
+      s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1);
+      s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
+      s->func(s->context, (void*)head2, sizeof(head2));
+   }
+
+   // Encode 8x8 macroblocks
+   {
+      static const unsigned short fillBits[] = {0x7F, 7};
+      int DCY=0, DCU=0, DCV=0;
+      int bitBuf=0, bitCnt=0;
+      // comp == 2 is grey+alpha (alpha is ignored)
+      int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
+      const unsigned char *dataR = (const unsigned char *)data;
+      const unsigned char *dataG = dataR + ofsG;
+      const unsigned char *dataB = dataR + ofsB;
+      int x, y, pos;
+      if(subsample) {
+         for(y = 0; y < height; y += 16) {
+            for(x = 0; x < width; x += 16) {
+               float Y[256], U[256], V[256];
+               for(row = y, pos = 0; row < y+16; ++row) {
+                  // row >= height => use last input row
+                  int clamped_row = (row < height) ? row : height - 1;
+                  int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
+                  for(col = x; col < x+16; ++col, ++pos) {
+                     // if col >= width => use pixel from last input column
+                     int p = base_p + ((col < width) ? col : (width-1))*comp;
+                     float r = dataR[p], g = dataG[p], b = dataB[p];
+                     Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
+                     U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
+                     V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
+                  }
+               }
+               DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0,   16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+               DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8,   16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+               DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+               DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
+
+               // subsample U,V
+               {
+                  float subU[64], subV[64];
+                  int yy, xx;
+                  for(yy = 0, pos = 0; yy < 8; ++yy) {
+                     for(xx = 0; xx < 8; ++xx, ++pos) {
+                        int j = yy*32+xx*2;
+                        subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
+                        subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
+                     }
+                  }
+                  DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
+                  DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
+               }
+            }
+         }
+      } else {
+         for(y = 0; y < height; y += 8) {
+            for(x = 0; x < width; x += 8) {
+               float Y[64], U[64], V[64];
+               for(row = y, pos = 0; row < y+8; ++row) {
+                  // row >= height => use last input row
+                  int clamped_row = (row < height) ? row : height - 1;
+                  int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
+                  for(col = x; col < x+8; ++col, ++pos) {
+                     // if col >= width => use pixel from last input column
+                     int p = base_p + ((col < width) ? col : (width-1))*comp;
+                     float r = dataR[p], g = dataG[p], b = dataB[p];
+                     Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
+                     U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
+                     V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
+                  }
+               }
+
+               DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y,  DCY, YDC_HT, YAC_HT);
+               DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
+               DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
+            }
+         }
+      }
+
+      // Do the bit alignment of the EOI marker
+      stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
+   }
+
+   // EOI
+   stbiw__putc(s, 0xFF);
+   stbiw__putc(s, 0xD9);
+
+   return 1;
+}
+
+STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
+{
+   stbi__write_context s = { 0 };
+   stbi__start_write_callbacks(&s, func, context);
+   return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
+}
+
+
+#ifndef STBI_WRITE_NO_STDIO
+STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
+{
+   stbi__write_context s = { 0 };
+   if (stbi__start_write_file(&s,filename)) {
+      int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
+      stbi__end_write_file(&s);
+      return r;
+   } else
+      return 0;
+}
+#endif
+
 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
 
 /* Revision history
+      1.16  (2021-07-11)
+             make Deflate code emit uncompressed blocks when it would otherwise expand
+             support writing BMPs with alpha channel
+      1.15  (2020-07-13) unknown
+      1.14  (2020-02-02) updated JPEG writer to downsample chroma channels
+      1.13
+      1.12
+      1.11  (2019-08-11)
+
+      1.10  (2019-02-07)
+             support utf8 filenames in Windows; fix warnings and platform ifdefs
+      1.09  (2018-02-11)
+             fix typo in zlib quality API, improve STB_I_W_STATIC in C++
+      1.08  (2018-01-29)
+             add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter
+      1.07  (2017-07-24)
+             doc fix
+      1.06 (2017-07-23)
+             writing JPEG (using Jon Olick's code)
+      1.05   ???
+      1.04 (2017-03-03)
+             monochrome BMP expansion
+      1.03   ???
       1.02 (2016-04-02)
              avoid allocating large structures on the stack
       1.01 (2016-01-16)
@@ -1035,7 +1669,7 @@
              add HDR output
              fix monochrome BMP
       0.95 (2014-08-17)
-		       add monochrome TGA output
+             add monochrome TGA output
       0.94 (2014-05-31)
              rename private functions to avoid conflicts with stb_image.h
       0.93 (2014-05-27)
@@ -1046,3 +1680,45 @@
              first public release
       0.90   first internal release
 */
+
+/*
+------------------------------------------------------------------------------
+This software is available under 2 licenses -- choose whichever you prefer.
+------------------------------------------------------------------------------
+ALTERNATIVE A - MIT License
+Copyright (c) 2017 Sean Barrett
+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.
+------------------------------------------------------------------------------
+ALTERNATIVE B - Public Domain (www.unlicense.org)
+This is free and unencumbered software released into the public domain.
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
+software, either in source code form or as a compiled binary, for any purpose,
+commercial or non-commercial, and by any means.
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and to
+the detriment of our heirs and successors. We intend this dedication to be an
+overt act of relinquishment in perpetuity of all present and future rights to
+this software under copyright law.
+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 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/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index 11ddf09..050c1be 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -351,8 +351,8 @@
 already is an open issue for it and if it's already being developed in an
 [experimental branch](https://github.com/glfw/glfw/branches/all).
 
-__There is no preferred patch size__.  A one character change is just as welcome
-as one adding a thousand line one, if that is the appropriate size for the
+__There is no preferred patch size__.  A one-character change is just as welcome
+as one adding a thousand lines, if that is the appropriate size for the
 feature.
 
 In addition to the code, a complete feature includes:
diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in
index 482b028..067619c 100644
--- a/docs/Doxyfile.in
+++ b/docs/Doxyfile.in
@@ -1,110 +1,151 @@
-# Doxyfile 1.8.3.1
+# Doxyfile 1.9.7
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project.
 #
-# All text after a hash (#) is considered a comment and will be ignored.
+# 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 (" ").
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables or CMake type
+# replacement variables:
+# doxygen -x_noenv [configFile]
 
 #---------------------------------------------------------------------------
 # Project related configuration options
 #---------------------------------------------------------------------------
 
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
+# 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
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
+# 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 sequence of words) that should
-# identify the project. Note that if you do not use Doxywizard you need
-# to put quotes around the project name if it contains spaces.
+# 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           = "GLFW"
 
-# 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.
+# 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         = @GLFW_VERSION@
 
 # 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.
+# 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          = "A multi-platform library for OpenGL, window and input"
 
-# With the PROJECT_LOGO tag one can specify an logo or 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.
+# 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)
-# base path where the generated documentation will be put.
-# 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.
+# 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       = "@GLFW_BINARY_DIR@/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 cause performance problems for the file system.
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 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. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
+# The default value is: NO.
 
 CREATE_SUBDIRS         = NO
 
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# number of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL   = 8
+
+# 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.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, 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
 
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) 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.
+# 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 (the default) 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
+# 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           = NO
 
-# 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" "the"
+# 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       =
 
 # 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
+# doxygen will generate a detailed section even if there is only a brief
 # description.
+# The default value is: NO.
 
 ALWAYS_DETAILED_SEC    = YES
 
@@ -112,88 +153,125 @@
 # 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 then 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.
+# 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        = NO
 
-# If the FULL_PATH_NAMES tag is set to YES then 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 specify absolute paths here, but also
-# relative paths, which will be relative from the directory where doxygen is
-# started.
+# 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 include paths that
-# are normally passed to the compiler using the -I flag.
+# 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 if your file system
-# doesn't support long names like on DOS, Mac, or CD-ROM.
+# 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
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
+# 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 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 comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
+# 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 behaviour.
-# 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 behaviour instead.
+# 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 (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING       = YES
+
+# 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.
+# 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.
+# 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               = 8
 
-# This tag can be used to specify a number of aliases that acts
-# 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.
+# 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:^^"
+# 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:". Note that you cannot 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                = "thread_safety=@par Thread safety^^" \
                          "pointer_lifetime=@par Pointer lifetime^^" \
@@ -208,483 +286,716 @@
                          "macos=__macOS:__" \
                          "linux=__Linux:__"
 
-# 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.
+# 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  = YES
 
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
+# 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 only. Doxygen will then generate output that is more tailored for
-# 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.
+# 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++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
-# C++. 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
-# that for custom extensions you also need to set FILE_PATTERNS otherwise the
-# files are not read by doxygen.
+# 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++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, 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). 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. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
 
 EXTENSION_MAPPING      =
 
-# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
-# comments according to the Markdown format, which allows for more readable
-# documentation. See http://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.
+# 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 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
+# 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   = 5
+
+# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to
+# generate identifiers for the Markdown headings. Note: Every identifier is
+# unique.
+# Possible values are: DOXYGEN Use a fixed 'autotoc_md' string followed by a
+# sequence number starting at 0. and GITHUB Use the lower case version of title
+# with any whitespace replaced by '-' and punctations characters removed..
+# The default value is: DOXYGEN.
+# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
+
+MARKDOWN_ID_STYLE      = DOXYGEN
+
+# 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); v.s.
-# func(std::string) {}). This also makes the inheritance and collaboration
+# 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 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.
+# 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 (the
-# default) will make doxygen 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.
+# 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   = NO
+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
+# 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
 
-# Set the SUBGROUPING tag to YES (the default) 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.
+# 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).
+# 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 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 (the default),
-# structs, classes, and unions are shown on a separate page (for HTML and Man
-# pages) or section (for LaTeX and RTF).
+# 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 is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
+# 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
+# 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
 
-# Similar to the SYMBOL_CACHE_SIZE 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 appear 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.
+# 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
 
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS       = 1
+
+# If the TIMESTAMP tag is set different from NO then each generated page will
+# contain the date or date and time when the page was generated. Setting this to
+# NO can help when comparing the output of multiple runs.
+# Possible values are: YES, NO, DATETIME and DATE.
+# The default value is: NO.
+
+TIMESTAMP              = NO
+
 #---------------------------------------------------------------------------
 # 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 and EXTRACT_STATIC tags are set to YES
+# 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.
+# 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_PACKAGE tag is set to YES all members with package or internal
+# 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.
+# 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.
+# 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. When 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 (the default) only methods in the interface are included.
+# 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 namespaces are hidden.
+# '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 of documented classes, files or namespaces.
-# If set to NO (the default) 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.
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
+# 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 (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
+# 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
+# will also hide undocumented C++ concepts if enabled. 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 (the default) these declarations will be included in the
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# 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 (the default) these blocks will be appended to the
-# function's detailed documentation block.
+# 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 (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
+# 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
-# and Mac users are advised to set this option to NO.
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# Possible values are: SYSTEM, NO and YES.
+# The default value is: SYSTEM.
 
-CASE_SENSE_NAMES       = YES
+CASE_SENSE_NAMES       = SYSTEM
 
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
+# 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 SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
+# 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_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE        = 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     = 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.
+# 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 (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
+# 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 (the default) 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.
+# 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       = NO
 
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
+# 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 default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to 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 default)
-# the group names will appear in their defined order.
+# 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       = YES
 
-# 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 default), the class list will be sorted only by class name,
-# not including the namespace part.
+# 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.
+# 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.
+# 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 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 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 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 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.
+# 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
-# the initial value of a variable or macro consists of 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 initializer of individual variables and macros in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
+# 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
+# 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 is 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 is 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        = NO
 
 # 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. See the manual for examples.
+# 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.
+# 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. See also section "Changing the
+# layout of pages" for information.
+#
+# 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            = "@GLFW_SOURCE_DIR@/docs/DoxygenLayout.xml"
 
-# The CITE_BIB_FILES tag can be used to specify one or more bib files
-# containing the references data. This must be a list of .bib files. The
-# .bib extension is automatically appended if omitted. Using this command
-# requires the bibtex tool to be installed. See also
-# http://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. Do not use
-# file names with spaces, bibtex cannot handle them.
+# 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
+# Configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
 
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
+# 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                  = YES
 
 # The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
+# 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 WARN_IF_UNDOCUMENTED 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.
+# 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 WARN_IF_DOC_ERROR 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.
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
+# The default value is: YES.
 
 WARN_IF_DOC_ERROR      = YES
 
-# The 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 (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = 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 parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
+# The default value is: NO.
 
 WARN_NO_PARAMDOC       = YES
 
-# 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)
+# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
+# undocumented enumeration values. If set to NO, doxygen will accept
+# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: NO.
+
+WARN_IF_UNDOC_ENUM_VAL = NO
+
+# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves
+# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not
+# write the warning messages in between other messages but write them at the end
+# of a run, in case a WARN_LOGFILE is defined the warning messages will be
+# besides being in the defined file also be shown at the end of a run, unless
+# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case
+# the behavior will remain as with the setting FAIL_ON_WARNINGS.
+# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT.
+# 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)
+# See also: WARN_LINE_FORMAT
+# 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 stderr.
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT       = "at line $line of file $file"
+
+# 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). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
 
 WARN_LOGFILE           = "@GLFW_BINARY_DIR@/docs/warnings.txt"
 
 #---------------------------------------------------------------------------
-# configuration options related to the input files
+# Configuration options related to the input files
 #---------------------------------------------------------------------------
 
-# The INPUT tag can be 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.
+# 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                  = @GLFW_DOXYGEN_INPUT@
 
 # This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
+# 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.
+# See also: INPUT_FILE_ENCODING
+# The default value is: UTF-8.
 
 INPUT_ENCODING         = UTF-8
 
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
+# character encoding on a per file pattern basis. Doxygen will compare the file
+# name with each pattern and apply the encoding instead of the default
+# INPUT_ENCODING) if there is a match. The character encodings are a list of the
+# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
+# "INPUT_ENCODING" for further information on supported encodings.
+
+INPUT_FILE_ENCODING    =
+
 # If the value of the INPUT tag contains directories, you can use the
-# FILE_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 the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
-# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
-# *.f90 *.f *.for *.vhd *.vhdl
+# 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.
+#
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
+# 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++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
 
 FILE_PATTERNS          = *.h *.dox
 
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
+# 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.
 
@@ -693,14 +1004,16 @@
 # 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/*
+# 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       =
 
@@ -708,795 +1021,1233 @@
 # (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
+# ANamespace::AClass, ANamespace::*Test
 
 EXCLUDE_SYMBOLS        = APIENTRY GLFWAPI
 
-# 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).
+# 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           = "@GLFW_SOURCE_DIR@/examples"
 
 # 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 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.
-# Possible values are YES and NO. If left blank NO is used.
+# 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 image that are included in the documentation (see
-# the \image command).
+# 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.
+# 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 doxygen will use the data processed and written to standard output
+# for further processing, therefore nothing else, like debug statements or used
+# commands (so in case of a Windows batch file always use @echo OFF), should be
+# written to standard output.
+#
+# 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
-# info on how filters are used. If FILTER_PATTERNS is empty or if
-# non of the patterns match the file name, INPUT_FILTER is applied.
+# 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 be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# 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 option only has effect when
-# FILTER_SOURCE_FILES is enabled.
+# 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_MD_FILE_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 reuse
-# the introduction page also for the doxygen output.
+# 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 =
 
+# The Fortran standard specifies that for fixed formatted Fortran code all
+# characters from position 72 are to be considered as comment. A common
+# extension is to allow longer lines before the automatic comment starts. The
+# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
+# be processed before the automatic comment starts.
+# Minimum value: 7, maximum value: 10000, default value: 72.
+
+FORTRAN_COMMENT_AFTER  = 72
+
 #---------------------------------------------------------------------------
-# configuration options related to source browsing
+# 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 also
-# VERBATIM_HEADERS is set to NO.
+# 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 and classes directly in the documentation.
+# 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 (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C, C++ and Fortran comments will always remain visible.
+# 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 function all documented
-# functions referencing it will be listed.
+# 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.
+# 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 (the default)
-# 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.
+# 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 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 http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
+# 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 to YES (the default) 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.
+# 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
 
 #---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
+# 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.
+# 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
 
-# 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 one or more prefixes that
-# should be ignored while generating the index headers.
+# 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. The IGNORE_PREFIX
+# tag works for classes, function and member names. The entity will be placed in
+# the alphabetical list under the first letter of the entity name that remains
+# after removing the prefix.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
 
 IGNORE_PREFIX          = glfw GLFW_
 
 #---------------------------------------------------------------------------
-# configuration options related to the HTML output
+# Configuration options related to the HTML output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate 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. If left blank `html' will be used as the default path.
+# 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). If it is left blank
-# doxygen will generate files with .html extension.
+# 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 personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header. Note that when using a custom header you are responsible
-#  for the proper inclusion of any scripts and style sheets that doxygen
-# needs, which is dependent on the configuration options used.
-# It is advised to generate a default header using "doxygen -w html
-# header.html footer.html stylesheet.css YourConfigFile" and then modify
-# that header. Note that the header is subject to change so you typically
-# have to redo this when upgrading to a newer version of doxygen or when
-# changing the value of configuration settings such as GENERATE_TREEVIEW!
+# 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            = "@GLFW_SOURCE_DIR@/docs/header.html"
 
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
+# 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            = "@GLFW_SOURCE_DIR@/docs/footer.html"
 
-# 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. Note that it is recommended to use
-# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
-# tag will in the future become obsolete.
+# 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 an additional
-# user-defined cascading style sheet that is 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 therefor more
-# robust against future updates. Doxygen will copy the style sheet file to
-# the output directory.
+# 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).
+# Note: Since the styling of scrollbars can currently not be overruled in
+# Webkit/Chromium, the styling will be left out of the default doxygen.css if
+# one or more extra stylesheets have been specified. So if scrollbar
+# customization is desired it has to be added explicitly. For an example see the
+# documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_EXTRA_STYLESHEET  = "@GLFW_SOURCE_DIR@/docs/extra.css"
 
 # 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.
+# $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       = "@GLFW_SOURCE_DIR@/docs/spaces.svg"
 
-# 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 http://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.
-# The allowed range is 0 to 359.
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme.
+# Possible values are: LIGHT always generate light mode output, DARK always
+# generate dark mode output, AUTO_LIGHT automatically set the mode according to
+# the user preference, use light mode if no preference is set (the default),
+# AUTO_DARK automatically set the mode according to the user preference, use
+# dark mode if no preference is set and TOGGLE allow to user to switch between
+# light and dark mode via a button.
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE        = LIGHT
+
+# 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 color-wheel, 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.
+# 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 gray-scales 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.
+# 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 NO can help when comparing the output of multiple runs.
+# 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_TIMESTAMP         = 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.
+# 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, 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 http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
+# 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
 
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# 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.
+# 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"
 
-# When GENERATE_DOCSET tag is set to YES, 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.
+# This tag determines the URL 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.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL         =
+
+# 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
 
-# When GENERATE_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 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 GENERATE_PUBLISHER_NAME tag identifies the documentation 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, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
+# 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
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
+#
+# 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
 
-# If the GENERATE_HTMLHELP tag is set to YES, 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
+# 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               =
 
-# If the GENERATE_HTMLHELP tag is set to YES, 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 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           =
 
-# If the GENERATE_HTMLHELP tag is set to YES, 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 GENERATE_CHI flag controls if a separate .chi index file is generated
+# (YES) or that it should be included in the main .chm file (NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
 GENERATE_CHI           = NO
 
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
+# 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     =
 
-# If the GENERATE_HTMLHELP tag is set to YES, 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.
+# 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 contents of the HTML help documentation and to the tree view.
+# 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
 
+# The SITEMAP_URL tag is used to specify the full URL of the place where the
+# generated documentation will be placed on the server by the user during the
+# deployment of the documentation. The generated sitemap is called sitemap.xml
+# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL
+# is specified no sitemap is generated. For information about the sitemap
+# protocol see https://www.sitemaps.org
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SITEMAP_URL            =
+
 # 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.
+# 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.
+# 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
-# http://doc.trolltech.com/qthelpproject.html#namespace
+# 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
-# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+# 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 QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
-# add. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#custom-filters
+# 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_FILT_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
-# Qt Help Project / Custom Filters</a>.
+# 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.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
-# Qt Help Project / Filter Attributes</a>.
+# 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  =
 
-# If the GENERATE_QHP tag is set to YES, 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.
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) 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, which together with the HTML files, 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.
+# 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.
+# 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
 
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
-# at top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it. Since the tabs have the same information as the
-# navigation tree you can set this option to NO if you already set
-# GENERATE_TREEVIEW to YES.
+# 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.
-# Since the tree basically has the same information as the tab index you
-# could consider to set DISABLE_INDEX to NO when enabling this option.
+# 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 (see "Fine-tuning the output"). 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
-# (range [0,1..20]) 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.
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR           = 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.
+# 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         = 300
+TREEVIEW_WIDTH         = 250
 
-# When 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.
+# 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. The default is 10. Note that
-# 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.
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS       = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT    = png
+
+# 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_TRANPARENT 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 before the changes have effect.
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
 
-FORMULA_TRANSPARENT    = YES
+FORMULA_MACROFILE      =
 
-# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
-# (see http://www.mathjax.org) which uses client side Javascript for the
-# rendering instead of using prerendered 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.
+# 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
 
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION        = MathJax_2
+
 # When MathJax is enabled you can set the default output format to be used for
-# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
-# SVG. The default value is HTML-CSS, which is slower, but has the best
-# compatibility.
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) 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 http://www.mathjax.org before deployment.
+# 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:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
+# This tag requires that the tag USE_MATHJAX is set to YES.
 
-MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+MATHJAX_RELPATH        =
 
-# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
-# names that should be enabled during MathJax rendering.
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
+# This tag requires that the tag USE_MATHJAX is set to YES.
 
 MATHJAX_EXTENSIONS     =
 
-# 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.
+# 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/v2.7-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 flavours of web server based search 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 manual for details.
+# 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 is enabled doxygen will no longer generate the PHP
+# 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 the manual for configuration details.
+# 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 returned the search results when EXTERNAL_SEARCH is enabled.
-# Doxygen ships with an example search engine (doxysearch) which is based on
-# the open source search engine library Xapian. See the manual for configuration
+# 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
+# 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 = id1=loc1 id2=loc2 ...
+# 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
+# Configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate 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. If left blank `latex' will be used as the default path.
+# 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. If left blank `latex' will be used as the default command name.
-# Note that when enabling USE_PDFLATEX this option is only used for
-# generating bitmaps for formulas in the HTML output, but not in the
-# Makefile that is written to the output directory.
+# 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
+LATEX_CMD_NAME         =
 
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
+# 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
 
-# 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 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, letter, legal and
-# executive. If left blank a4wide will be used.
+# 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 to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
+# 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. Notice: only use this tag if you know what you are doing!
+# The LATEX_HEADER tag can be used to specify a user-defined 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. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
+#
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
+# 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. Notice: only use this tag if you know what you are doing!
+# The LATEX_FOOTER tag can be used to specify a user-defined 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. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. 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           =
 
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). 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 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, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
-# higher quality PDF documentation.
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
+# 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 LATEX_BATCHMODE tag ignals the behavior of LaTeX in case of an error.
+# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch
+# mode nothing is printed on the terminal, errors are scrolled as if <return> is
+# hit at every error; missing files that TeX tries to input or request from
+# keyboard input (\read on a not open input stream) cause the job to abort,
+# NON_STOP In nonstop mode the diagnostic message will appear on the terminal,
+# but there is no possibility of user interaction just like in batch mode,
+# SCROLL In scroll mode, TeX will stop only for missing files to input or if
+# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at
+# each error, asking for user intervention.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_BATCHMODE        = NO
 
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
+# 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
 
 # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
-# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
-# http://en.wikipedia.org/wiki/BibTeX for more info.
+# 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
 
+# 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
+# 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 very pretty with
-# other RTF readers or editors.
+# 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. If left blank `rtf' will be used as the default path.
+# 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.
+# 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 other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
+# 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 style sheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
+# 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 config 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    =
 
 #---------------------------------------------------------------------------
-# configuration options related to the man page output
+# Configuration options related to the man page output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
+# 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. If left blank `man' will be used as the default path.
+# 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 (default is the subroutine's section .3)
+# 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
 
-# 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 is NO.
+# 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
+# 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.
+# 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. If left blank `xml' will be used as the default path.
+# 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.
+# 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 for the AutoGen Definitions output
+# Configuration options related to the DOCBOOK output
 #---------------------------------------------------------------------------
 
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
+# 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
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
+# AutoGen Definitions (see https://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
+# 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.
+# 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.
+# 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.
+# 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.
+# 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 =
 
@@ -1504,50 +2255,59 @@
 # Configuration options related to the preprocessor
 #---------------------------------------------------------------------------
 
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
+# 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 (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to 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.
+# 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 default) the includes files
-# pointed to by INCLUDE_PATH will be searched when a #include is found.
+# 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.
+# contain include files that are not input files but should be processed by the
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
+# 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.
+# 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
-# 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.
+# 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             = GLFWAPI=                   \
                          GLFW_EXPOSE_NATIVE_WIN32   \
@@ -1561,268 +2321,417 @@
                          GLFW_EXPOSE_NATIVE_OSMESA  \
                          VK_VERSION_1_0
 
-# 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.
+# 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 (the default) 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, because these will confuse the parser if not removed.
+# 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::additions related to external references
+# Configuration options related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES option can be used to specify one or more tagfiles. 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:
-#
+# 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. Note that 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.
+# 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.
+# 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 classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
+# 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.
+# 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
+# Configuration options related to diagram generator tools
 #---------------------------------------------------------------------------
 
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF 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.
-
-CLASS_DIAGRAMS         = YES
-
-# 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.
+# 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, 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)
+# available from the path. This tool is part of Graphviz (see:
+# https://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 (the default) 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.
+# 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
 
-# By default doxygen will use the Helvetica font for all dot files that
-# doxygen generates. When you want a differently looking font 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.
+# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
+# subgraphs. When you want a differently looking font in the dot files that
+# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
+# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
+# Edge and Graph Attributes specification</a> 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. Default graphviz fontsize is 14.
+# The default value is: fontname=Helvetica,fontsize=10.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
-DOT_FONTNAME           = Helvetica
+DOT_COMMON_ATTR        = "fontname=Helvetica,fontsize=10"
 
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
-# The default size is 10pt.
+# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
+# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
+# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
+# arrows shapes.</a>
+# The default value is: labelfontname=Helvetica,labelfontsize=10.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
-DOT_FONTSIZE           = 10
+DOT_EDGE_ATTR          = "labelfontname=Helvetica,labelfontsize=10"
 
-# By default doxygen will tell dot to use the Helvetica font.
-# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
-# set the path where dot can find it.
+# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
+# around nodes set 'shape=plain' or 'shape=plaintext' <a
+# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
+# The default value is: shape=box,height=0.2,width=0.4.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NODE_ATTR          = "shape=box,height=0.2,width=0.4"
+
+# You can set the path where dot can find font specified with fontname in
+# DOT_COMMON_ATTR and others dot attributes.
+# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_FONTPATH           =
 
-# If the CLASS_GRAPH and HAVE_DOT tags are 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.
+# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will
+# generate a graph for each documented class showing the direct and indirect
+# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and
+# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case
+# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the
+# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used.
+# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance
+# relations will be shown as texts / links.
+# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN.
+# The default value is: YES.
 
 CLASS_GRAPH            = YES
 
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are 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.
+# 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 and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies. See also the chapter Grouping
+# in the manual.
+# 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
+# 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.
+# 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 UML_LOOK is set to YES.
 
 UML_LIMIT_NUM_FIELDS   = 10
 
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS        = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD     = 17
+
+# 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 ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# 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.
+# 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 ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
+# 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 and HAVE_DOT options are 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.
+# 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 and HAVE_DOT tags are 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.
+# 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 and HAVE_DOT tags are set to YES then doxygen
-# will generate a graphical hierarchy of all classes instead of a textual one.
+# 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 and HAVE_DOT tags are 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.
+# 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 DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH    = 1
+
 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are svg, png, jpg, or gif.
-# If left blank png will be used. 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).
+# generated by dot. For an explanation of the image formats see the section
+# output formats in the documentation of the dot tool (Graphviz (see:
+# https://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. 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.
+#
+# 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 tag DOT_PATH can be used to specify the path where the dot tool can be
+# 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).
+# 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).
+# 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.
 
-MSCFILE_DIRS           =
+DIA_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.
+# 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 or to the filename of jar file
+# to be used. 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
+# 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).
-
-DOT_TRANSPARENT        = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# 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.
+# 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 (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
+# 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.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
+# 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 (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
+# files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
+# The default value is: YES.
 
 DOT_CLEANUP            = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. If the MSCGEN_TOOL tag is left empty (the default), then doxygen will
+# use a built-in version of mscgen tool to produce the charts. Alternatively,
+# the MSCGEN_TOOL tag can also specify the name an external tool. For instance,
+# specifying prog as the value, doxygen will call the tool as prog -T
+# <outfile_format> -o <outputfile> <inputfile>. The external tool should support
+# output file formats "png", "eps", "svg", and "ismap".
+
+MSCGEN_TOOL            =
+
+# 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           =
diff --git a/docs/build.dox b/docs/build.dox
index cb4d0f3..faa36b2 100644
--- a/docs/build.dox
+++ b/docs/build.dox
@@ -26,7 +26,7 @@
 @endcode
 
 This header defines all the constants and declares all the types and function
-prototypes of the GLFW API.  By default it also includes the OpenGL header from
+prototypes of the GLFW API.  By default, it also includes the OpenGL header from
 your development environment.  See [option macros](@ref build_macros) below for
 how to select OpenGL ES headers and more.
 
@@ -57,7 +57,7 @@
 
 Both of these mechanisms depend on the extension loader header defining a known
 macro.  If yours doesn't or you don't know which one your users will pick, the
-@ref GLFW_INCLUDE_NONE macro will explicitly to prevent the GLFW header from
+@ref GLFW_INCLUDE_NONE macro will explicitly prevent the GLFW header from
 including the OpenGL header.  This will also allow you to include the two
 headers in any order.
 
diff --git a/docs/compat.dox b/docs/compat.dox
index 288a956..0a5031f 100644
--- a/docs/compat.dox
+++ b/docs/compat.dox
@@ -111,11 +111,7 @@
 GLFW uses the [xdg-shell
 protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml)
 to provide better window management.  This protocol is part of
-wayland-protocols 1.12, and mandatory at build time.  If the running compositor
-does not support this protocol, the older [wl_shell
-interface](https://cgit.freedesktop.org/wayland/wayland/tree/protocol/wayland.xml#n972)
-will be used instead.  This will result in a worse integration with the
-desktop, especially on tiling compositors.
+wayland-protocols 1.12, and mandatory at build time.
 
 GLFW uses the [relative pointer
 protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/relative-pointer/relative-pointer-unstable-v1.xml)
@@ -133,6 +129,14 @@
 does not support this protocol, the screensaver may start even for full screen
 windows.
 
+GLFW uses the [libdecor library](https://gitlab.freedesktop.org/libdecor/libdecor)
+for window decorations, where available.  This in turn provides good quality
+client-side decorations (drawn by the application) on desktop systems that do
+not support server-side decorations (drawn by the window manager).  On systems
+that do not provide either libdecor or xdg-decoration, very basic window
+decorations are provided.  These do not include the window title or any caption
+buttons.
+
 GLFW uses the [xdg-decoration
 protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml)
 to request decorations to be drawn around its windows.  This protocol is part
@@ -157,7 +161,7 @@
 
 GLFW uses the `GLX_MESA_swap_control,` `GLX_EXT_swap_control` and
 `GLX_SGI_swap_control` extensions to provide vertical retrace synchronization
-(or _vsync_), in that order of preference.  Where none of these extension are
+(or _vsync_), in that order of preference.  When none of these extensions are
 available, calling @ref glfwSwapInterval will have no effect.
 
 GLFW uses the `GLX_ARB_multisample` extension to create contexts with
@@ -226,8 +230,8 @@
 effect and the context will always be flushed when released.
 
 GLFW uses the `WGL_ARB_framebuffer_sRGB` and `WGL_EXT_framebuffer_sRGB`
-extensions to provide support for sRGB framebuffers.  Where both of these
-extension are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
+extensions to provide support for sRGB framebuffers.  When both of these
+extensions are unavailable, the `GLFW_SRGB_CAPABLE` hint will have no effect.
 
 
 @section compat_osx OpenGL on macOS
diff --git a/docs/compile.dox b/docs/compile.dox
index ec458f4..99d5a68 100644
--- a/docs/compile.dox
+++ b/docs/compile.dox
@@ -45,7 +45,7 @@
 To compile GLFW for X11, you need to have the X11 development packages
 installed.  They are not needed to build or run programs that use GLFW.
 
-On Debian and derivates like Ubuntu and Linux Mint the `xorg-dev` meta-package
+On Debian and derivatives like Ubuntu and Linux Mint the `xorg-dev` meta-package
 pulls in the development packages for all of X11.
 
 @code{.sh}
@@ -82,8 +82,9 @@
 development packages installed.  They are not needed to build or run programs
 that use GLFW.
 
-On Debian and derivates like Ubuntu and Linux Mint you will need the `libwayland-dev`,
+On Debian and derivatives like Ubuntu and Linux Mint you will need the `libwayland-dev`,
 `libxkbcommon-dev`, `wayland-protocols` and `extra-cmake-modules` packages.
+These will pull in all other dependencies.
 
 @code{.sh}
 sudo apt install libwayland-dev libxkbcommon-dev wayland-protocols extra-cmake-modules
@@ -137,7 +138,7 @@
 _Generate_ to have the new values take effect.  The variable list will be
 populated after the first configure step.
 
-By default GLFW will use X11 on Linux and other Unix-like systems other
+By default, GLFW will use X11 on Linux and other Unix-like systems other
 than macOS.  To use Wayland instead, set the `GLFW_USE_WAYLAND` option in the
 GLFW section of the variable list, then apply the new value as described above.
 
@@ -171,7 +172,7 @@
 cmake -S path/to/glfw -B path/to/build -G Xcode
 @endcode
 
-By default GLFW will use X11 on Linux and other Unix-like systems other
+By default, GLFW will use X11 on Linux and other Unix-like systems other
 than macOS.  To use Wayland instead, set the `GLFW_USE_WAYLAND` CMake option.
 
 @code{.sh}
@@ -327,7 +328,7 @@
 @section compile_manual Compiling GLFW manually
 
 If you wish to compile GLFW without its CMake build environment then you will
-have to do at least some of the platform detection yourself.  GLFW needs
+have to do at least some of the platform-detection yourself.  GLFW needs
 a configuration macro to be defined in order to know what window system it is
 being compiled for and also has optional, platform-specific ones for various
 features.
diff --git a/docs/context.dox b/docs/context.dox
index 25de69f..2fd74ed 100644
--- a/docs/context.dox
+++ b/docs/context.dox
@@ -61,7 +61,7 @@
 versions and APIs, but has at times been named _Shared Objects and Multiple
 Contexts_.
 
-GLFW comes with a barebones object sharing example program called `sharing`.
+GLFW comes with a bare-bones object sharing example program called `sharing`.
 
 
 @subsection context_offscreen Offscreen contexts
@@ -92,9 +92,10 @@
 @subsection context_less Windows without contexts
 
 You can disable context creation by setting the
-[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`.  Windows
-without contexts must not be passed to @ref glfwMakeContextCurrent or @ref
-glfwSwapBuffers.
+[GLFW_CLIENT_API](@ref GLFW_CLIENT_API_hint) hint to `GLFW_NO_API`.
+
+Windows without contexts should not be passed to @ref glfwMakeContextCurrent or
+@ref glfwSwapBuffers.  Doing this generates a @ref GLFW_NO_WINDOW_CONTEXT error.
 
 
 @section context_current Current context
@@ -193,7 +194,7 @@
 #include <GLFW/glfw3.h>
 @endcode
 
-Finally you need to initialize glad once you have a suitable current context.
+Finally, you need to initialize glad once you have a suitable current context.
 
 @code
 window = glfwCreateWindow(640, 480, "My Window", NULL, NULL);
@@ -209,7 +210,7 @@
 
 Once glad has been loaded, you have access to all OpenGL core and extension
 functions supported by both the context you created and the glad loader you
-generated and you are ready to start rendering.
+generated. After that, you are ready to start rendering.
 
 You can specify a minimum required OpenGL or OpenGL ES version with
 [context hints](@ref window_hints_ctx).  If your needs are more complex, you can
diff --git a/docs/input.dox b/docs/input.dox
index dd7b434..495edb2 100644
--- a/docs/input.dox
+++ b/docs/input.dox
@@ -24,7 +24,7 @@
 or objects from your callbacks.
 
 To get a better feel for how the various events callbacks behave, run the
-`events` test program.  It register every callback supported by GLFW and prints
+`events` test program.  It registers every callback supported by GLFW and prints
 out all arguments provided for every event, along with time and sequence
 information.
 
@@ -95,7 +95,7 @@
 
 GLFW divides keyboard input into two categories; key events and character
 events.  Key events relate to actual physical keyboard keys, whereas character
-events relate to the Unicode code points generated by pressing some of them.
+events relate to the text that is generated by pressing some of them.
 
 Keys and characters do not map 1:1.  A single key press may produce several
 characters, and a single character may require several keys to produce.  This
@@ -123,23 +123,39 @@
 }
 @endcode
 
-The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`.  The key
-will be `GLFW_KEY_UNKNOWN` if GLFW lacks a key token for it, for example
-_E-mail_ and _Play_ keys.
+The action is one of `GLFW_PRESS`, `GLFW_REPEAT` or `GLFW_RELEASE`.  Events with
+`GLFW_PRESS` and `GLFW_RELEASE` actions are emitted for every key press.  Most
+keys will also emit events with `GLFW_REPEAT` actions while a key is held down.
+
+Note that many keyboards have a limit on how many keys being simultaneous held
+down that they can detect.  This limit is called
+[key rollover](https://en.wikipedia.org/wiki/Key_rollover).
+
+Key events with `GLFW_REPEAT` actions are intended for text input.  They are
+emitted at the rate set in the user's keyboard settings.  At most one key is
+repeated even if several keys are held down.  `GLFW_REPEAT` actions should not
+be relied on to know which keys are being held down or to drive animation.
+Instead you should either save the state of relevant keys based on `GLFW_PRESS`
+and `GLFW_RELEASE` actions, or call @ref glfwGetKey, which provides basic cached
+key state.
+
+The key will be one of the existing [key tokens](@ref keys), or
+`GLFW_KEY_UNKNOWN` if GLFW lacks a token for it, for example _E-mail_ and _Play_
+keys.
 
 The scancode is unique for every key, regardless of whether it has a key token.
 Scancodes are platform-specific but consistent over time, so keys will have
 different scancodes depending on the platform but they are safe to save to disk.
-You can query the scancode for any [named key](@ref keys) on the current
-platform with @ref glfwGetKeyScancode.
+You can query the scancode for any [key token](@ref keys) supported on the
+current platform with @ref glfwGetKeyScancode.
 
 @code
 const int scancode = glfwGetKeyScancode(GLFW_KEY_X);
 set_key_mapping(scancode, swap_weapons);
 @endcode
 
-The last reported state for every [named key](@ref keys) is also saved in
-per-window state arrays that can be polled with @ref glfwGetKey.
+The last reported state for every physical key with a [key token](@ref keys) is
+also saved in per-window state arrays that can be polled with @ref glfwGetKey.
 
 @code
 int state = glfwGetKey(window, GLFW_KEY_E);
@@ -152,7 +168,8 @@
 The returned state is one of `GLFW_PRESS` or `GLFW_RELEASE`.
 
 This function only returns cached key event state.  It does not poll the
-system for the current physical state of the key.
+system for the current state of the physical key.  It also does not provide any
+key repeat information.
 
 @anchor GLFW_STICKY_KEYS
 Whenever you poll state, you risk missing the state change you are looking for.
@@ -183,15 +200,15 @@
 Num Lock was on.
 
 The `GLFW_KEY_LAST` constant holds the highest value of any
-[named key](@ref keys).
+[key token](@ref keys).
 
 
 @subsection input_char Text input
 
 GLFW supports text input in the form of a stream of
 [Unicode code points](https://en.wikipedia.org/wiki/Unicode), as produced by the
-operating system text input system.  Unlike key input, text input obeys keyboard
-layouts and modifier keys and supports composing characters using
+operating system text input system.  Unlike key input, text input is affected by
+keyboard layouts and modifier keys and supports composing characters using
 [dead keys](https://en.wikipedia.org/wiki/Dead_key).  Once received, you can
 encode the code points into UTF-8 or any other encoding you prefer.
 
@@ -370,7 +387,7 @@
 @subsubsection cursor_standard Standard cursor creation
 
 A cursor with a [standard shape](@ref shapes) from the current system cursor
-theme can be can be created with @ref glfwCreateStandardCursor.
+theme can be created with @ref glfwCreateStandardCursor.
 
 @code
 GLFWcursor* url_cursor = glfwCreateStandardCursor(GLFW_POINTING_HAND_CURSOR);
@@ -478,8 +495,9 @@
 
 The action is one of `GLFW_PRESS` or `GLFW_RELEASE`.
 
-Mouse button states for [named buttons](@ref buttons) are also saved in
-per-window state arrays that can be polled with @ref glfwGetMouseButton.
+The last reported state for every [supported mouse button](@ref buttons) is also
+saved in per-window state arrays that can be polled with @ref
+glfwGetMouseButton.
 
 @code
 int state = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT);
@@ -512,7 +530,7 @@
 otherwise it will remain `GLFW_PRESS`.
 
 The `GLFW_MOUSE_BUTTON_LAST` constant holds the highest value of any
-[named button](@ref buttons).
+[supported mouse button](@ref buttons).
 
 
 @subsection scrolling Scroll input
diff --git a/docs/intro.dox b/docs/intro.dox
index e563b50..57f86c0 100644
--- a/docs/intro.dox
+++ b/docs/intro.dox
@@ -102,6 +102,30 @@
 initialized.  Set this with @ref glfwInitHint.
 
 
+@subsubsection init_hints_wayland Wayland specific init hints
+
+@anchor GLFW_WAYLAND_LIBDECOR_hint
+__GLFW_WAYLAND_LIBDECOR__ specifies whether to use
+[libdecor](https://gitlab.freedesktop.org/libdecor/libdecor) for window
+decorations where available.  Possible values are `GLFW_WAYLAND_PREFER_LIBDECOR`
+and `GLFW_WAYLAND_DISABLE_LIBDECOR`.  This is ignored on other platforms.
+
+@note This init hint was added in 3.3.9 and is not present in earlier patch releases.  It
+is safe to attempt to set this hint on earlier versions of GLFW 3.3 but it will emit
+a harmless @ref GLFW_INVALID_ENUM error.  If you need to avoid causing any errors, you can
+check the library version first with @ref glfwGetVersion.
+
+@note To set this hint while also building against earlier versions of GLFW 3.3, you can
+use the numerical constants directly.
+
+@note @code
+int minor, patch;
+glfwGetVersion(NULL, &minor, &patch);
+if (minor > 3 || (minor == 3 && patch >= 9))
+    glfwInitHint(0x00053001 /*GLFW_WAYLAND_LIBDECOR*/, 0x00038002 /*GLFW_WAYLAND_DISABLE_LIBDECOR*/);
+@endcode
+
+
 @subsubsection init_hints_values Supported and default values
 
 Initialization hint             | Default value | Supported values
@@ -109,6 +133,7 @@
 @ref GLFW_JOYSTICK_HAT_BUTTONS  | `GLFW_TRUE`   | `GLFW_TRUE` or `GLFW_FALSE`
 @ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE`   | `GLFW_TRUE` or `GLFW_FALSE`
 @ref GLFW_COCOA_MENUBAR         | `GLFW_TRUE`   | `GLFW_TRUE` or `GLFW_FALSE`
+@ref GLFW_WAYLAND_LIBDECOR      | `GLFW_WAYLAND_PREFER_LIBDECOR`  | `GLFW_WAYLAND_PREFER_LIBDECOR` or `GLFW_WAYLAND_DISABLE_LIBDECOR`
 
 
 @subsection intro_init_terminate Terminating GLFW
@@ -124,9 +149,9 @@
 modified gamma ramps, re-enable the screensaver if it had been disabled and free
 any other resources allocated by GLFW.
 
-Once the library is terminated, it is as if it had never been initialized and
+Once the library is terminated, it is as if it had never been initialized, therefore
 you will need to initialize it again before being able to use GLFW.  If the
-library was not initialized or had already been terminated, it return
+library was not initialized or had already been terminated, it returns
 immediately.
 
 
@@ -246,14 +271,14 @@
 
 This section describes the conditions under which GLFW can be expected to
 function, barring bugs in the operating system or drivers.  Use of GLFW outside
-of these limits may work on some platforms, or on some machines, or some of the
+these limits may work on some platforms, or on some machines, or some of the
 time, or on some versions of GLFW, but it may break at any time and this will
 not be considered a bug.
 
 
 @subsection lifetime Pointer lifetimes
 
-GLFW will never free any pointer you provide to it and you must never free any
+GLFW will never free any pointer you provide to it, and you must never free any
 pointer it provides to you.
 
 Many GLFW functions return pointers to dynamically allocated structures, strings
@@ -444,11 +469,11 @@
  - The name of the context creation API
  - Any additional options or APIs
 
-For example, when compiling GLFW 3.0 with MinGW using the Win32 and WGL
-back ends, the version string may look something like this:
+For example, when compiling GLFW 3.3.9 with MinGW for Windows, may result in
+a version string like this:
 
 @code
-3.0.0 Win32 WGL MinGW
+3.3.9 Win32 WGL EGL OSMesa MinGW
 @endcode
 
 */
diff --git a/docs/monitor.dox b/docs/monitor.dox
index 86eb454..b4099db 100644
--- a/docs/monitor.dox
+++ b/docs/monitor.dox
@@ -138,7 +138,7 @@
 @endcode
 
 While this can be used to calculate the raw DPI of a monitor, this is often not
-useful.  Instead use the [monitor content scale](@ref monitor_scale) and
+useful.  Instead, use the [monitor content scale](@ref monitor_scale) and
 [window content scale](@ref window_scale) to scale your content.
 
 
@@ -261,7 +261,7 @@
 `gamma` test program.
 
 @note The software controlled gamma ramp is applied _in addition_ to the
-hardware gamma correction, which today is usually an approximation of sRGB
+hardware gamma correction, which today is typically an approximation of sRGB
 gamma.  This means that setting a perfectly linear ramp, or gamma 1.0, will
 produce the default (usually sRGB-like) behavior.
 
diff --git a/docs/moving.dox b/docs/moving.dox
index b80d84a..705b4fa 100644
--- a/docs/moving.dox
+++ b/docs/moving.dox
@@ -243,7 +243,7 @@
 @endcode
 
 The close callback no longer returns a value.  Instead, it is called after the
-close flag has been set so it can override its value, if it chooses to, before
+close flag has been set, so it can optionally override its value, before
 event processing completes.  You may however not call @ref glfwDestroyWindow
 from the close callback (or any other window related callback).
 
@@ -350,11 +350,11 @@
 
 GLFW 3 key tokens map to physical keys, unlike in GLFW 2 where they mapped to
 the values generated by the current keyboard layout.  The tokens are named
-according to the values they would have using the standard US layout, but this
+according to the values they would have in the standard US layout, but this
 is only a convenience, as most programmers are assumed to know that layout.
 This means that (for example) `GLFW_KEY_LEFT_BRACKET` is always a single key and
 is the same key in the same place regardless of what keyboard layouts the users
-of your program has.
+of your program have.
 
 The key input facility was never meant for text input, although using it that
 way worked slightly better in GLFW 2.  If you were using it to input text, you
diff --git a/docs/news.dox b/docs/news.dox
index b5421c1..103224f 100644
--- a/docs/news.dox
+++ b/docs/news.dox
@@ -37,6 +37,16 @@
 For more information see @ref vulkan_guide.
 
 
+@subsubsection wayland_libdecor_33 Wayland libdecor decorations
+
+GLFW now supports improved fallback window decorations via
+[libdecor](https://gitlab.freedesktop.org/libdecor/libdecor).
+
+Support for libdecor can be toggled before GLFW is initialized with the
+[GLFW_WAYLAND_LIBDECOR](@ref GLFW_WAYLAND_LIBDECOR_hint) init hint.  It is
+enabled by default.
+
+
 @subsubsection content_scale_33 Content scale queries for DPI-aware rendering
 
 GLFW now provides content scales for windows and monitors, i.e. the ratio
@@ -312,6 +322,19 @@
 unnamed pipe instead of sending an X11 client event to the helper window.
 
 
+@subsubsection wayland_alpha_34 Frambuffer may lack alpha channel on older Wayland systems
+
+On Wayland, when creating an EGL context on a machine lacking the new
+`EGL_EXT_present_opaque` extension, the @ref GLFW_ALPHA_BITS window hint will be
+ignored and the framebuffer will have no alpha channel.  This is because some
+Wayland compositors treat any buffer with an alpha channel as per-pixel
+transparent.
+
+If you want a per-pixel transparent window, see the
+[GLFW_TRANSPARENT_FRAMEBUFFER](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) window
+hint.
+
+
 @subsection deprecations_33 Deprecations in version 3.3
 
 @subsubsection charmods_callback_33 Character with modifiers callback
@@ -378,6 +401,13 @@
 suffix chosen by the GNUInstallDirs package and the option will be ignored.
 
 
+@subsubsection wl_shell_33 Support for the wl_shell protocol
+
+Support for the wl_shell protocol has been removed and GLFW now only supports
+the XDG-Shell protocol.  If your Wayland compositor does not support XDG-Shell
+then GLFW will fail to initialize.
+
+
 @subsubsection mir_removed_33 Mir support
 
 The experimental Mir support has been completely removed as the Mir project has
@@ -423,6 +453,9 @@
  - @ref GLFWwindowmaximizefun
  - @ref GLFWwindowcontentscalefun
  - @ref GLFWgamepadstate
+ - @ref GLFW_WAYLAND_LIBDECOR
+ - @ref GLFW_WAYLAND_PREFER_LIBDECOR
+ - @ref GLFW_WAYLAND_DISABLE_LIBDECOR
 
 
 @subsubsection constants_33 New constants in version 3.3
diff --git a/docs/quick.dox b/docs/quick.dox
index 3645fc0..2cce29f 100644
--- a/docs/quick.dox
+++ b/docs/quick.dox
@@ -144,10 +144,6 @@
 }
 @endcode
 
-The window handle is passed to all window related functions and is provided to
-along to all window related callbacks, so they can tell which window received
-the event.
-
 When a window and context is no longer needed, destroy it.
 
 @code
@@ -233,7 +229,7 @@
 @subsection quick_render Rendering with OpenGL
 
 Once you have a current OpenGL context, you can use OpenGL normally.  In this
-tutorial, a multi-colored rotating triangle will be rendered.  The framebuffer
+tutorial, a multicolored rotating triangle will be rendered.  The framebuffer
 size needs to be retrieved for `glViewport`.
 
 @code
diff --git a/docs/vulkan.dox b/docs/vulkan.dox
index 68e3d5f..7e4a0f0 100644
--- a/docs/vulkan.dox
+++ b/docs/vulkan.dox
@@ -42,9 +42,9 @@
 directly instead of dynamically loading it at runtime.  Not linking against the
 Vulkan loader will then be a compile-time error.
 
-@macos Because the Vulkan loader and ICD are not installed globally on macOS,
-you need to set up the application bundle according to the LunarG SDK
-documentation.  This is explained in more detail in the
+@macos To make your application be redistributable you will need to set up the
+application bundle according to the LunarG SDK documentation.  This is explained
+in more detail in the
 [SDK documentation for macOS](https://vulkan.lunarg.com/doc/sdk/latest/mac/getting_started.html).
 
 
@@ -131,7 +131,7 @@
     glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr");
 @endcode
 
-Device-specific functions may execute a little bit faster, due to not having to
+Device-specific functions may execute a little faster, due to not having to
 dispatch internally based on the device passed to them.  For more information
 about `vkGetDeviceProcAddr`, see the Vulkan documentation.
 
@@ -177,6 +177,13 @@
 array, as it is an error to specify an extension more than once in the
 `VkInstanceCreateInfo` struct.
 
+@macos MoltenVK is (as of July 2022) not yet a fully conformant implementation
+of Vulkan.  As of Vulkan SDK 1.3.216.0, this means you must also enable the
+`VK_KHR_portability_enumeration` instance extension and set the
+`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` bit in the instance creation
+info flags for MoltenVK to show up in the list of physical devices.  For more
+information, see the Vulkan and MoltenVK documentation.
+
 
 @section vulkan_present Querying for Vulkan presentation support
 
diff --git a/docs/window.dox b/docs/window.dox
index 2fcf11f..a0b4be6 100644
--- a/docs/window.dox
+++ b/docs/window.dox
@@ -471,7 +471,8 @@
 @anchor GLFW_X11_CLASS_NAME_hint
 @anchor GLFW_X11_INSTANCE_NAME_hint
 __GLFW_X11_CLASS_NAME__ and __GLFW_X11_INSTANCE_NAME__ specifies the desired
-ASCII encoded class and instance parts of the ICCCM `WM_CLASS` window property.
+ASCII encoded class and instance parts of the ICCCM `WM_CLASS` window property.  Both
+hints need to be set to something other than an empty string for them to take effect.
 These are set with @ref glfwWindowHintString.
 
 
diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h
index cea8a85..24270df 100644
--- a/include/GLFW/glfw3.h
+++ b/include/GLFW/glfw3.h
@@ -262,13 +262,12 @@
  /* We are building GLFW as a Win32 DLL */
  #define GLFWAPI __declspec(dllexport)
 #elif defined(_WIN32) && defined(GLFW_DLL)
- /* We are calling GLFW as a Win32 DLL */
+ /* We are calling a GLFW Win32 DLL */
  #define GLFWAPI __declspec(dllimport)
 #elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL)
- /* We are building GLFW as a shared / dynamic library */
+ /* We are building GLFW as a Unix shared library */
  #define GLFWAPI __attribute__((visibility("default")))
 #else
- /* We are building or calling GLFW as a static library */
  #define GLFWAPI
 #endif
 
@@ -299,7 +298,7 @@
  *  release is made that does not contain any API changes.
  *  @ingroup init
  */
-#define GLFW_VERSION_REVISION       7
+#define GLFW_VERSION_REVISION       9
 /*! @} */
 
 /*! @brief One.
@@ -362,10 +361,15 @@
 #define GLFW_HAT_RIGHT_DOWN         (GLFW_HAT_RIGHT | GLFW_HAT_DOWN)
 #define GLFW_HAT_LEFT_UP            (GLFW_HAT_LEFT  | GLFW_HAT_UP)
 #define GLFW_HAT_LEFT_DOWN          (GLFW_HAT_LEFT  | GLFW_HAT_DOWN)
+
+/*! @ingroup input
+ */
+#define GLFW_KEY_UNKNOWN            -1
+
 /*! @} */
 
-/*! @defgroup keys Keyboard keys
- *  @brief Keyboard key IDs.
+/*! @defgroup keys Keyboard key tokens
+ *  @brief Keyboard key tokens.
  *
  *  See [key input](@ref input_key) for how these are used.
  *
@@ -388,9 +392,6 @@
  *  @{
  */
 
-/* The unknown key */
-#define GLFW_KEY_UNKNOWN            -1
-
 /* Printable keys */
 #define GLFW_KEY_SPACE              32
 #define GLFW_KEY_APOSTROPHE         39  /* ' */
@@ -1075,6 +1076,9 @@
 #define GLFW_EGL_CONTEXT_API        0x00036002
 #define GLFW_OSMESA_CONTEXT_API     0x00036003
 
+#define GLFW_WAYLAND_PREFER_LIBDECOR    0x00038001
+#define GLFW_WAYLAND_DISABLE_LIBDECOR   0x00038002
+
 /*! @defgroup shapes Standard cursor shapes
  *  @brief Standard system cursor shapes.
  *
@@ -1201,6 +1205,11 @@
  *  macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint).
  */
 #define GLFW_COCOA_MENUBAR          0x00051002
+/*! @brief Wayland specific init hint.
+ *
+ *  Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint).
+ */
+#define GLFW_WAYLAND_LIBDECOR       0x00053001
 /*! @} */
 
 #define GLFW_DONT_CARE              -1
@@ -2885,8 +2894,8 @@
  *  @param[in] images The images to create the icon from.  This is ignored if
  *  count is zero.
  *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_PLATFORM_ERROR.
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ *  GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
  *
  *  @pointer_lifetime The specified image data is copied before this function
  *  returns.
@@ -3296,18 +3305,15 @@
  *  previously restored.  If the window is already iconified, this function does
  *  nothing.
  *
- *  If the specified window is a full screen window, the original monitor
- *  resolution is restored until the window is restored.
+ *  If the specified window is a full screen window, GLFW restores the original
+ *  video mode of the monitor.  The window's desired video mode is set again
+ *  when the window is restored.
  *
  *  @param[in] window The window to iconify.
  *
  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
  *  GLFW_PLATFORM_ERROR.
  *
- *  @remark @wayland There is no concept of iconification in wl_shell, this
- *  function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated
- *  protocol.
- *
  *  @thread_safety This function must only be called from the main thread.
  *
  *  @sa @ref window_iconify
@@ -3327,8 +3333,8 @@
  *  (minimized) or maximized.  If the window is already restored, this function
  *  does nothing.
  *
- *  If the specified window is a full screen window, the resolution chosen for
- *  the window is restored on the selected monitor.
+ *  If the specified window is an iconified full screen window, its desired
+ *  video mode is set again for its monitor when the window is restored.
  *
  *  @param[in] window The window to restore.
  *
@@ -3596,6 +3602,9 @@
  *  errors.  However, this function should not fail as long as it is passed
  *  valid arguments and the library has been [initialized](@ref intro_init).
  *
+ *  @remark @wayland The Wayland protocol provides no way to check whether a
+ *  window is iconfied, so @ref GLFW_ICONIFIED always returns `GLFW_FALSE`.
+ *
  *  @thread_safety This function must only be called from the main thread.
  *
  *  @sa @ref window_attribs
@@ -3887,8 +3896,8 @@
  *
  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
  *
- *  @remark @wayland The wl_shell protocol has no concept of iconification,
- *  this callback will never be called when using this deprecated protocol.
+ *  @remark @wayland The XDG-shell protocol has no event for iconification, so
+ *  this callback will never be called.
  *
  *  @thread_safety This function must only be called from the main thread.
  *
@@ -4308,8 +4317,8 @@
  *  @param[in] scancode The scancode of the key to query.
  *  @return The UTF-8 encoded, layout-specific name of the key, or `NULL`.
  *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_PLATFORM_ERROR.
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ *  GLFW_INVALID_VALUE, @ref GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
  *
  *  @remark The contents of the returned string may change when a keyboard
  *  layout change event is received.
@@ -4331,15 +4340,18 @@
  *
  *  This function returns the platform-specific scancode of the specified key.
  *
- *  If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this
- *  method will return `-1`.
+ *  If the specified [key token](@ref keys) corresponds to a physical key not
+ *  supported on the current platform then this method will return `-1`.
+ *  Calling this function with anything other than a key token will return `-1`
+ *  and generate a @ref GLFW_INVALID_ENUM error.
  *
- *  @param[in] key Any [named key](@ref keys).
- *  @return The platform-specific scancode for the key, or `-1` if an
- *  [error](@ref error_handling) occurred.
+ *  @param[in] key Any [key token](@ref keys).
+ *  @return The platform-specific scancode for the key, or `-1` if the key is
+ *  not supported on the current platform or an [error](@ref error_handling)
+ *  occurred.
  *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
- *  GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ *  GLFW_INVALID_ENUM.
  *
  *  @thread_safety This function may be called from any thread.
  *
@@ -4356,8 +4368,7 @@
  *
  *  This function returns the last state reported for the specified key to the
  *  specified window.  The returned state is one of `GLFW_PRESS` or
- *  `GLFW_RELEASE`.  The higher-level action `GLFW_REPEAT` is only reported to
- *  the key callback.
+ *  `GLFW_RELEASE`.  The action `GLFW_REPEAT` is only reported to the key callback.
  *
  *  If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns
  *  `GLFW_PRESS` the first time you call it for a key that was pressed, even if
@@ -4518,8 +4529,8 @@
  *  @return The handle of the created cursor, or `NULL` if an
  *  [error](@ref error_handling) occurred.
  *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_PLATFORM_ERROR.
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ *  GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
  *
  *  @pointer_lifetime The specified image data is copied before this function
  *  returns.
@@ -4649,9 +4660,9 @@
  *  [character callback](@ref glfwSetCharCallback) instead.
  *
  *  When a window loses input focus, it will generate synthetic key release
- *  events for all pressed keys.  You can tell these events from user-generated
- *  events by the fact that the synthetic ones are generated after the focus
- *  loss event has been processed, i.e. after the
+ *  events for all pressed keys with associated key tokens.  You can tell these
+ *  events from user-generated events by the fact that the synthetic ones are
+ *  generated after the focus loss event has been processed, i.e. after the
  *  [window focus callback](@ref glfwSetWindowFocusCallback) has been called.
  *
  *  The scancode of a key is specific to that platform or sometimes even to that
@@ -5550,12 +5561,15 @@
  *  thread.
  *
  *  This function makes the OpenGL or OpenGL ES context of the specified window
- *  current on the calling thread.  A context must only be made current on
- *  a single thread at a time and each thread can have only a single current
- *  context at a time.
+ *  current on the calling thread.  It can also detach the current context from
+ *  the calling thread without making a new one current by passing in `NULL`.
  *
- *  When moving a context between threads, you must make it non-current on the
- *  old thread before making it current on the new one.
+ *  A context must only be made current on a single thread at a time and each
+ *  thread can have only a single current context at a time.  Making a context
+ *  current detaches any previously current context on the calling thread.
+ *
+ *  When moving a context between threads, you must detach it (make it
+ *  non-current) on the old thread before making it current on the new one.
  *
  *  By default, making a context non-current implicitly forces a pipeline flush.
  *  On machines that support `GL_KHR_context_flush_control`, you can control
@@ -5570,6 +5584,10 @@
  *  @param[in] window The window whose context to make current, or `NULL` to
  *  detach the current context.
  *
+ *  @remarks If the previously current context was created via a different
+ *  context creation API than the one passed to this function, GLFW will still
+ *  detach the previous one from its API before making the new one current.
+ *
  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
  *  GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.
  *
@@ -6002,6 +6020,7 @@
  */
 #ifndef GLAPIENTRY
  #define GLAPIENTRY APIENTRY
+ #define GLFW_GLAPIENTRY_DEFINED
 #endif
 
 /* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
diff --git a/include/GLFW/glfw3native.h b/include/GLFW/glfw3native.h
index fe74c73..7e09389 100644
--- a/include/GLFW/glfw3native.h
+++ b/include/GLFW/glfw3native.h
@@ -74,6 +74,16 @@
  *  and which platform-specific headers to include.  It is then up your (by
  *  definition platform-specific) code to handle which of these should be
  *  defined.
+ *
+ *  If you do not want the platform-specific headers to be included, define
+ *  `GLFW_NATIVE_INCLUDE_NONE` before including the @ref glfw3native.h header.
+ *
+ *  @code
+ *  #define GLFW_EXPOSE_NATIVE_WIN32
+ *  #define GLFW_EXPOSE_NATIVE_WGL
+ *  #define GLFW_NATIVE_INCLUDE_NONE
+ *  #include <GLFW/glfw3native.h>
+ *  @endcode
  */
 
 
@@ -81,44 +91,71 @@
  * System headers and types
  *************************************************************************/
 
-#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
- // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
- // example to allow applications to correctly declare a GL_KHR_debug callback)
- // but windows.h assumes no one will define APIENTRY before it does
- #if defined(GLFW_APIENTRY_DEFINED)
-  #undef APIENTRY
-  #undef GLFW_APIENTRY_DEFINED
- #endif
- #include <windows.h>
-#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
- #if defined(__OBJC__)
-  #import <Cocoa/Cocoa.h>
- #else
-  #include <ApplicationServices/ApplicationServices.h>
-  typedef void* id;
- #endif
-#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
- #include <X11/Xlib.h>
- #include <X11/extensions/Xrandr.h>
-#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)
- #include <wayland-client.h>
-#endif
+#if !defined(GLFW_NATIVE_INCLUDE_NONE)
 
-#if defined(GLFW_EXPOSE_NATIVE_WGL)
- /* WGL is declared by windows.h */
-#endif
-#if defined(GLFW_EXPOSE_NATIVE_NSGL)
- /* NSGL is declared by Cocoa.h */
-#endif
-#if defined(GLFW_EXPOSE_NATIVE_GLX)
- #include <GL/glx.h>
-#endif
-#if defined(GLFW_EXPOSE_NATIVE_EGL)
- #include <EGL/egl.h>
-#endif
-#if defined(GLFW_EXPOSE_NATIVE_OSMESA)
- #include <GL/osmesa.h>
-#endif
+ #if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL)
+  /* This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
+   * example to allow applications to correctly declare a GL_KHR_debug callback)
+   * but windows.h assumes no one will define APIENTRY before it does
+   */
+  #if defined(GLFW_APIENTRY_DEFINED)
+   #undef APIENTRY
+   #undef GLFW_APIENTRY_DEFINED
+  #endif
+  #include <windows.h>
+ #endif
+
+ #if defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL)
+  #if defined(__OBJC__)
+   #import <Cocoa/Cocoa.h>
+  #else
+   #include <ApplicationServices/ApplicationServices.h>
+   #include <objc/objc.h>
+  #endif
+ #endif
+
+ #if defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX)
+  #include <X11/Xlib.h>
+  #include <X11/extensions/Xrandr.h>
+ #endif
+
+ #if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
+  #include <wayland-client.h>
+ #endif
+
+ #if defined(GLFW_EXPOSE_NATIVE_WGL)
+  /* WGL is declared by windows.h */
+ #endif
+ #if defined(GLFW_EXPOSE_NATIVE_NSGL)
+  /* NSGL is declared by Cocoa.h */
+ #endif
+ #if defined(GLFW_EXPOSE_NATIVE_GLX)
+  /* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
+   * default it also acts as an OpenGL header
+   * However, glx.h will include gl.h, which will define it unconditionally
+   */
+  #if defined(GLFW_GLAPIENTRY_DEFINED)
+   #undef GLAPIENTRY
+   #undef GLFW_GLAPIENTRY_DEFINED
+  #endif
+  #include <GL/glx.h>
+ #endif
+ #if defined(GLFW_EXPOSE_NATIVE_EGL)
+  #include <EGL/egl.h>
+ #endif
+ #if defined(GLFW_EXPOSE_NATIVE_OSMESA)
+  /* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by
+   * default it also acts as an OpenGL header
+   * However, osmesa.h will include gl.h, which will define it unconditionally
+   */
+  #if defined(GLFW_GLAPIENTRY_DEFINED)
+   #undef GLAPIENTRY
+   #undef GLFW_GLAPIENTRY_DEFINED
+  #endif
+  #include <GL/osmesa.h>
+ #endif
+
+#endif /*GLFW_NATIVE_INCLUDE_NONE*/
 
 
 /*************************************************************************
@@ -475,6 +512,9 @@
  *
  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
  *
+ *  @remark Because EGL is initialized on demand, this function will return
+ *  `EGL_NO_DISPLAY` until the first context has been created via EGL.
+ *
  *  @thread_safety This function may be called from any thread.  Access is not
  *  synchronized.
  *
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b6dd86c..efd6592 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -168,6 +168,7 @@
             # Add a suffix to the import library to avoid naming conflicts
             set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.lib")
         endif()
+        set (GLFW_LIB_NAME_SUFFIX "dll")
 
         target_compile_definitions(glfw INTERFACE GLFW_DLL)
     elseif (APPLE)
diff --git a/src/cocoa_init.m b/src/cocoa_init.m
index 209639e..fb094d3 100644
--- a/src/cocoa_init.m
+++ b/src/cocoa_init.m
@@ -251,7 +251,7 @@
     _glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
     _glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
     _glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
-    _glfw.ns.keycodes[0x69] = GLFW_KEY_F13;
+    _glfw.ns.keycodes[0x69] = GLFW_KEY_PRINT_SCREEN;
     _glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
     _glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
     _glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
@@ -475,18 +475,26 @@
     if (!bundle)
         return NULL;
 
-    CFURLRef url =
-        CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib"));
-    if (!url)
+    CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle);
+    if (!frameworksUrl)
         return NULL;
 
+    CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent(
+        kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false);
+    if (!loaderUrl)
+    {
+        CFRelease(frameworksUrl);
+        return NULL;
+    }
+
     char path[PATH_MAX];
     void* handle = NULL;
 
-    if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1))
+    if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1))
         handle = _glfw_dlopen(path);
 
-    CFRelease(url);
+    CFRelease(loaderUrl);
+    CFRelease(frameworksUrl);
     return handle;
 }
 
@@ -607,6 +615,8 @@
     free(_glfw.ns.clipboardString);
 
     _glfwTerminateNSGL();
+    _glfwTerminateEGL();
+    _glfwTerminateOSMesa();
     _glfwTerminateJoysticksNS();
 
     } // autoreleasepool
diff --git a/src/cocoa_joystick.m b/src/cocoa_joystick.m
index 2c8d82d..f91cf2f 100644
--- a/src/cocoa_joystick.m
+++ b/src/cocoa_joystick.m
@@ -98,8 +98,7 @@
 {
     int i;
 
-    if (!js->present)
-        return;
+    _glfwInputJoystick(js, GLFW_DISCONNECTED);
 
     for (i = 0;  i < CFArrayGetCount(js->ns.axes);  i++)
         free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
@@ -114,7 +113,6 @@
     CFRelease(js->ns.hats);
 
     _glfwFreeJoystick(js);
-    _glfwInputJoystick(js, GLFW_DISCONNECTED);
 }
 
 // Callback for user-initiated joystick addition
@@ -139,6 +137,14 @@
             return;
     }
 
+    CFArrayRef elements =
+        IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
+
+    // It is reportedly possible for this to fail on macOS 13 Ventura
+    // if the application does not have input monitoring permissions
+    if (!elements)
+        return;
+
     axes    = CFArrayCreateMutable(NULL, 0, NULL);
     buttons = CFArrayCreateMutable(NULL, 0, NULL);
     hats    = CFArrayCreateMutable(NULL, 0, NULL);
@@ -182,9 +188,6 @@
                 name[8], name[9], name[10]);
     }
 
-    CFArrayRef elements =
-        IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
-
     for (i = 0;  i < CFArrayGetCount(elements);  i++)
     {
         IOHIDElementRef native = (IOHIDElementRef)
@@ -294,9 +297,9 @@
 
     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
     {
-        if (_glfw.joysticks[jid].ns.device == device)
+        if (_glfw.joysticks[jid].connected && _glfw.joysticks[jid].ns.device == device)
         {
-            closeJoystick(_glfw.joysticks + jid);
+            closeJoystick(&_glfw.joysticks[jid]);
             break;
         }
     }
@@ -392,7 +395,10 @@
     int jid;
 
     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-        closeJoystick(_glfw.joysticks + jid);
+    {
+        if (_glfw.joysticks[jid].connected)
+            closeJoystick(&_glfw.joysticks[jid]);
+    }
 
     CFRelease(_glfw.ns.hidManager);
     _glfw.ns.hidManager = NULL;
@@ -470,7 +476,7 @@
         }
     }
 
-    return js->present;
+    return js->connected;
 }
 
 void _glfwPlatformUpdateGamepadGUID(char* guid)
diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m
index dadae30..7769bb7 100644
--- a/src/cocoa_monitor.m
+++ b/src/cocoa_monitor.m
@@ -98,11 +98,7 @@
     IOObjectRelease(it);
 
     if (!service)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Failed to find service port for display");
         return _glfw_strdup("Display");
-    }
 
     CFDictionaryRef names =
         CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
diff --git a/src/cocoa_window.m b/src/cocoa_window.m
index 0630645..057604b 100644
--- a/src/cocoa_window.m
+++ b/src/cocoa_window.m
@@ -31,25 +31,9 @@
 #include <float.h>
 #include <string.h>
 
-// Returns the style mask corresponding to the window settings
-//
-static NSUInteger getStyleMask(_GLFWwindow* window)
-{
-    NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
-
-    if (window->monitor || !window->decorated)
-        styleMask |= NSWindowStyleMaskBorderless;
-    else
-    {
-        styleMask |= NSWindowStyleMaskTitled |
-                     NSWindowStyleMaskClosable;
-
-        if (window->resizable)
-            styleMask |= NSWindowStyleMaskResizable;
-    }
-
-    return styleMask;
-}
+// HACK: This enum value is missing from framework headers on OS X 10.11 despite
+//       having been (according to documentation) added in Mac OS X 10.7
+#define NSWindowCollectionBehaviorFullScreenNone (1 << 9)
 
 // Returns whether the cursor is in the content area of the specified window
 //
@@ -325,10 +309,15 @@
 
 - (void)windowDidChangeOcclusionState:(NSNotification* )notification
 {
-    if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
-        window->ns.occluded = GLFW_FALSE;
-    else
-        window->ns.occluded = GLFW_TRUE;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
+    if ([window->ns.object respondsToSelector:@selector(occlusionState)])
+    {
+        if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)
+            window->ns.occluded = GLFW_FALSE;
+        else
+            window->ns.occluded = GLFW_TRUE;
+    }
+#endif
 }
 
 @end
@@ -809,9 +798,21 @@
     else
         contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height);
 
+    NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
+
+    if (window->monitor || !window->decorated)
+        styleMask |= NSWindowStyleMaskBorderless;
+    else
+    {
+        styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
+
+        if (window->resizable)
+            styleMask |= NSWindowStyleMaskResizable;
+    }
+
     window->ns.object = [[GLFWWindow alloc]
         initWithContentRect:contentRect
-                  styleMask:getStyleMask(window)
+                  styleMask:styleMask
                     backing:NSBackingStoreBuffered
                       defer:NO];
 
@@ -837,6 +838,12 @@
                 NSWindowCollectionBehaviorManaged;
             [window->ns.object setCollectionBehavior:behavior];
         }
+        else
+        {
+            const NSWindowCollectionBehavior behavior =
+                NSWindowCollectionBehaviorFullScreenNone;
+            [window->ns.object setCollectionBehavior:behavior];
+        }
 
         if (wndconfig->floating)
             [window->ns.object setLevel:NSFloatingWindowLevel];
@@ -934,6 +941,9 @@
             if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
                 return GLFW_FALSE;
         }
+
+        if (!_glfwRefreshContextAttribs(window, ctxconfig))
+            return GLFW_FALSE;
     }
 
     if (window->monitor)
@@ -941,6 +951,18 @@
         _glfwPlatformShowWindow(window);
         _glfwPlatformFocusWindow(window);
         acquireMonitor(window);
+
+        if (wndconfig->centerCursor)
+            _glfwCenterCursorInContentArea(window);
+    }
+    else
+    {
+        if (wndconfig->visible)
+        {
+            _glfwPlatformShowWindow(window);
+            if (wndconfig->focused)
+                _glfwPlatformFocusWindow(window);
+        }
     }
 
     return GLFW_TRUE;
@@ -1219,9 +1241,10 @@
         {
             const NSRect contentRect =
                 NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1), width, height);
+            const NSUInteger styleMask = [window->ns.object styleMask];
             const NSRect frameRect =
                 [window->ns.object frameRectForContentRect:contentRect
-                                                 styleMask:getStyleMask(window)];
+                                                 styleMask:styleMask];
 
             [window->ns.object setFrame:frameRect display:YES];
         }
@@ -1238,7 +1261,27 @@
     // TODO: Solve this in a less terrible way
     _glfwPlatformPollEvents();
 
-    const NSUInteger styleMask = getStyleMask(window);
+    NSUInteger styleMask = [window->ns.object styleMask];
+
+    if (window->monitor)
+    {
+        styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable);
+        styleMask |= NSWindowStyleMaskBorderless;
+    }
+    else
+    {
+        if (window->decorated)
+        {
+            styleMask &= ~NSWindowStyleMaskBorderless;
+            styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
+        }
+
+        if (window->resizable)
+            styleMask |= NSWindowStyleMaskResizable;
+        else
+            styleMask &= ~NSWindowStyleMaskResizable;
+    }
+
     [window->ns.object setStyleMask:styleMask];
     // HACK: Changing the style mask can cause the first responder to be cleared
     [window->ns.object makeFirstResponder:window->ns.view];
@@ -1284,6 +1327,20 @@
         else
             [window->ns.object setLevel:NSNormalWindowLevel];
 
+        if (window->resizable)
+        {
+            const NSWindowCollectionBehavior behavior =
+                NSWindowCollectionBehaviorFullScreenPrimary |
+                NSWindowCollectionBehaviorManaged;
+            [window->ns.object setCollectionBehavior:behavior];
+        }
+        else
+        {
+            const NSWindowCollectionBehavior behavior =
+                NSWindowCollectionBehaviorFullScreenNone;
+            [window->ns.object setCollectionBehavior:behavior];
+        }
+
         [window->ns.object setHasShadow:YES];
         // HACK: Clearing NSWindowStyleMaskTitled resets and disables the window
         //       title property but the miniwindow title property is unaffected
@@ -1317,7 +1374,12 @@
 int _glfwPlatformWindowMaximized(_GLFWwindow* window)
 {
     @autoreleasepool {
-    return [window->ns.object isZoomed];
+
+    if (window->resizable)
+        return [window->ns.object isZoomed];
+    else
+        return GLFW_FALSE;
+
     } // autoreleasepool
 }
 
@@ -1349,15 +1411,46 @@
 void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
 {
     @autoreleasepool {
-    [window->ns.object setStyleMask:getStyleMask(window)];
+
+    const NSUInteger styleMask = [window->ns.object styleMask];
+    if (enabled)
+    {
+        [window->ns.object setStyleMask:(styleMask | NSWindowStyleMaskResizable)];
+        const NSWindowCollectionBehavior behavior =
+            NSWindowCollectionBehaviorFullScreenPrimary |
+            NSWindowCollectionBehaviorManaged;
+        [window->ns.object setCollectionBehavior:behavior];
+    }
+    else
+    {
+        [window->ns.object setStyleMask:(styleMask & ~NSWindowStyleMaskResizable)];
+        const NSWindowCollectionBehavior behavior =
+            NSWindowCollectionBehaviorFullScreenNone;
+        [window->ns.object setCollectionBehavior:behavior];
+    }
+
     } // autoreleasepool
 }
 
 void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
 {
     @autoreleasepool {
-    [window->ns.object setStyleMask:getStyleMask(window)];
+
+    NSUInteger styleMask = [window->ns.object styleMask];
+    if (enabled)
+    {
+        styleMask |= (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
+        styleMask &= ~NSWindowStyleMaskBorderless;
+    }
+    else
+    {
+        styleMask |= NSWindowStyleMaskBorderless;
+        styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable);
+    }
+
+    [window->ns.object setStyleMask:styleMask];
     [window->ns.object makeFirstResponder:window->ns.view];
+
     } // autoreleasepool
 }
 
diff --git a/src/context.c b/src/context.c
index b3c78e8..b81934b 100644
--- a/src/context.c
+++ b/src/context.c
@@ -48,16 +48,6 @@
 //
 GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
 {
-    if (ctxconfig->share)
-    {
-        if (ctxconfig->client == GLFW_NO_API ||
-            ctxconfig->share->context.client == GLFW_NO_API)
-        {
-            _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
-            return GLFW_FALSE;
-        }
-    }
-
     if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
         ctxconfig->source != GLFW_EGL_CONTEXT_API &&
         ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
@@ -78,6 +68,23 @@
         return GLFW_FALSE;
     }
 
+    if (ctxconfig->share)
+    {
+        if (ctxconfig->client == GLFW_NO_API ||
+            ctxconfig->share->context.client == GLFW_NO_API)
+        {
+            _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+            return GLFW_FALSE;
+        }
+
+        if (ctxconfig->source != ctxconfig->share->context.source)
+        {
+            _glfwInputError(GLFW_INVALID_ENUM,
+                            "Context creation APIs do not match between contexts");
+            return GLFW_FALSE;
+        }
+    }
+
     if (ctxconfig->client == GLFW_OPENGL_API)
     {
         if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
@@ -356,6 +363,8 @@
 
     previous = _glfwPlatformGetTls(&_glfw.contextSlot);
     glfwMakeContextCurrent((GLFWwindow*) window);
+    if (_glfwPlatformGetTls(&_glfw.contextSlot) != window)
+        return GLFW_FALSE;
 
     window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
         window->context.getProcAddress("glGetIntegerv");
@@ -609,10 +618,12 @@
 GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
 {
     _GLFWwindow* window = (_GLFWwindow*) handle;
-    _GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
+    _GLFWwindow* previous;
 
     _GLFW_REQUIRE_INIT();
 
+    previous = _glfwPlatformGetTls(&_glfw.contextSlot);
+
     if (window && window->context.client == GLFW_NO_API)
     {
         _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
diff --git a/src/egl_context.c b/src/egl_context.c
index 58d9557..a37f3d3 100644
--- a/src/egl_context.c
+++ b/src/egl_context.c
@@ -88,13 +88,30 @@
 // Return the EGLConfig most closely matching the specified hints
 //
 static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
-                                const _GLFWfbconfig* desired,
+                                const _GLFWfbconfig* fbconfig,
                                 EGLConfig* result)
 {
     EGLConfig* nativeConfigs;
     _GLFWfbconfig* usableConfigs;
     const _GLFWfbconfig* closest;
-    int i, nativeCount, usableCount;
+    int i, nativeCount, usableCount, apiBit;
+    GLFWbool wrongApiAvailable = GLFW_FALSE;
+
+    if (ctxconfig->client == GLFW_OPENGL_ES_API)
+    {
+        if (ctxconfig->major == 1)
+            apiBit = EGL_OPENGL_ES_BIT;
+        else
+            apiBit = EGL_OPENGL_ES2_BIT;
+    }
+    else
+        apiBit = EGL_OPENGL_BIT;
+
+    if (fbconfig->stereo)
+    {
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported");
+        return GLFW_FALSE;
+    }
 
     eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
     if (!nativeCount)
@@ -131,7 +148,7 @@
             if (!vi.visualid)
                 continue;
 
-            if (desired->transparent)
+            if (fbconfig->transparent)
             {
                 int count;
                 XVisualInfo* vis =
@@ -145,23 +162,10 @@
         }
 #endif // _GLFW_X11
 
-        if (ctxconfig->client == GLFW_OPENGL_ES_API)
+        if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & apiBit))
         {
-            if (ctxconfig->major == 1)
-            {
-                if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
-                    continue;
-            }
-            else
-            {
-                if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
-                    continue;
-            }
-        }
-        else if (ctxconfig->client == GLFW_OPENGL_API)
-        {
-            if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
-                continue;
+            wrongApiAvailable = GLFW_TRUE;
+            continue;
         }
 
         u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
@@ -172,16 +176,57 @@
         u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
         u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
 
+#if defined(_GLFW_WAYLAND)
+        // NOTE: The wl_surface opaque region is no guarantee that its buffer
+        //       is presented as opaque, if it also has an alpha channel
+        // HACK: If EGL_EXT_present_opaque is unavailable, ignore any config
+        //       with an alpha channel to ensure the buffer is opaque
+        if (!_glfw.egl.EXT_present_opaque)
+        {
+            if (!fbconfig->transparent && u->alphaBits > 0)
+                continue;
+        }
+#endif // _GLFW_WAYLAND
+
         u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
-        u->doublebuffer = desired->doublebuffer;
+        u->doublebuffer = fbconfig->doublebuffer;
 
         u->handle = (uintptr_t) n;
         usableCount++;
     }
 
-    closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
+    closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
     if (closest)
         *result = (EGLConfig) closest->handle;
+    else
+    {
+        if (wrongApiAvailable)
+        {
+            if (ctxconfig->client == GLFW_OPENGL_ES_API)
+            {
+                if (ctxconfig->major == 1)
+                {
+                    _glfwInputError(GLFW_API_UNAVAILABLE,
+                                    "EGL: Failed to find support for OpenGL ES 1.x");
+                }
+                else
+                {
+                    _glfwInputError(GLFW_API_UNAVAILABLE,
+                                    "EGL: Failed to find support for OpenGL ES 2 or later");
+                }
+            }
+            else
+            {
+                _glfwInputError(GLFW_API_UNAVAILABLE,
+                                "EGL: Failed to find support for OpenGL");
+            }
+        }
+        else
+        {
+            _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                            "EGL: Failed to find a suitable EGLConfig");
+        }
+    }
 
     free(nativeConfigs);
     free(usableConfigs);
@@ -259,6 +304,7 @@
 static GLFWglproc getProcAddressEGL(const char* procname)
 {
     _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
+    assert(window != NULL);
 
     if (window->context.egl.client)
     {
@@ -485,11 +531,7 @@
         share = ctxconfig->share->context.egl.handle;
 
     if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "EGL: Failed to find a suitable EGLConfig");
         return GLFW_FALSE;
-    }
 
     if (ctxconfig->client == GLFW_OPENGL_ES_API)
     {
@@ -546,18 +588,18 @@
             flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
         }
 
-        if (ctxconfig->noerror)
-        {
-            if (_glfw.egl.KHR_create_context_no_error)
-                setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
-        }
-
         if (ctxconfig->major != 1 || ctxconfig->minor != 0)
         {
             setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
             setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
         }
 
+        if (ctxconfig->noerror)
+        {
+            if (_glfw.egl.KHR_create_context_no_error)
+                setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
+        }
+
         if (mask)
             setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
 
@@ -609,8 +651,10 @@
     if (!fbconfig->doublebuffer)
         setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER);
 
+#if defined(_GLFW_WAYLAND)
     if (_glfw.egl.EXT_present_opaque)
         setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent);
+#endif // _GLFW_WAYLAND
 
     setAttrib(EGL_NONE, EGL_NONE);
 
@@ -678,6 +722,7 @@
 #elif defined(__OpenBSD__) || defined(__NetBSD__)
             "libGL.so",
 #else
+            "libOpenGL.so.0",
             "libGL.so.1",
 #endif
             NULL
@@ -740,11 +785,7 @@
     const long vimask = VisualScreenMask | VisualIDMask;
 
     if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "EGL: Failed to find a suitable EGLConfig");
         return GLFW_FALSE;
-    }
 
     eglGetConfigAttrib(_glfw.egl.display, native,
                        EGL_NATIVE_VISUAL_ID, &visualID);
diff --git a/src/glfw3.pc.in b/src/glfw3.pc.in
index f74298d..17779ac 100644
--- a/src/glfw3.pc.in
+++ b/src/glfw3.pc.in
@@ -8,6 +8,6 @@
 Version: @GLFW_VERSION@
 URL: https://www.glfw.org/
 Requires.private: @GLFW_PKG_DEPS@
-Libs: -L${libdir} -l@GLFW_LIB_NAME@
+Libs: -L${libdir} -l@GLFW_LIB_NAME@@GLFW_LIB_NAME_SUFFIX@
 Libs.private: @GLFW_PKG_LIBS@
 Cflags: -I${includedir}
diff --git a/src/glx_context.c b/src/glx_context.c
index 1b1b3f9..220e3d0 100644
--- a/src/glx_context.c
+++ b/src/glx_context.c
@@ -190,6 +190,7 @@
 static void swapIntervalGLX(int interval)
 {
     _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
+    assert(window != NULL);
 
     if (_glfw.glx.EXT_swap_control)
     {
@@ -226,7 +227,10 @@
     else if (_glfw.glx.GetProcAddressARB)
         return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
     else
+    {
+        // NOTE: glvnd provides GLX 1.4, so this can only happen with libGL
         return _glfw_dlsym(_glfw.glx.handle, procname);
+    }
 }
 
 static void destroyContextGLX(_GLFWwindow* window)
@@ -263,6 +267,7 @@
 #elif defined(__OpenBSD__) || defined(__NetBSD__)
         "libGL.so",
 #else
+        "libGLX.so.0",
         "libGL.so.1",
         "libGL.so",
 #endif
diff --git a/src/glx_context.h b/src/glx_context.h
index df0233e..2ea17d1 100644
--- a/src/glx_context.h
+++ b/src/glx_context.h
@@ -127,7 +127,6 @@
     int             eventBase;
     int             errorBase;
 
-    // dlopen handle for libGL.so.1
     void*           handle;
 
     // GLX 1.3 functions
diff --git a/src/init.c b/src/init.c
index a9c9361..a11db4a 100644
--- a/src/init.c
+++ b/src/init.c
@@ -54,7 +54,10 @@
     {
         GLFW_TRUE,  // macOS menu bar
         GLFW_TRUE   // macOS bundle chdir
-    }
+    },
+    {
+        GLFW_WAYLAND_PREFER_LIBDECOR // Wayland libdecor mode
+    },
 };
 
 // Terminate the library
@@ -142,6 +145,59 @@
     return count;
 }
 
+// Splits and translates a text/uri-list into separate file paths
+// NOTE: This function destroys the provided string
+//
+char** _glfwParseUriList(char* text, int* count)
+{
+    const char* prefix = "file://";
+    char** paths = NULL;
+    char* line;
+
+    *count = 0;
+
+    while ((line = strtok(text, "\r\n")))
+    {
+        char* path;
+
+        text = NULL;
+
+        if (line[0] == '#')
+            continue;
+
+        if (strncmp(line, prefix, strlen(prefix)) == 0)
+        {
+            line += strlen(prefix);
+            // TODO: Validate hostname
+            while (*line != '/')
+                line++;
+        }
+
+        (*count)++;
+
+        path = calloc(strlen(line) + 1, 1);
+        paths = realloc(paths, *count * sizeof(char*));
+        paths[*count - 1] = path;
+
+        while (*line)
+        {
+            if (line[0] == '%' && line[1] && line[2])
+            {
+                const char digits[3] = { line[1], line[2], '\0' };
+                *path = (char) strtol(digits, NULL, 16);
+                line += 2;
+            }
+            else
+                *path = *line;
+
+            path++;
+            line++;
+        }
+    }
+
+    return paths;
+}
+
 char* _glfw_strdup(const char* source)
 {
     const size_t length = strlen(source);
@@ -150,6 +206,16 @@
     return result;
 }
 
+int _glfw_min(int a, int b)
+{
+    return a < b ? a : b;
+}
+
+int _glfw_max(int a, int b)
+{
+    return a > b ? a : b;
+}
+
 float _glfw_fminf(float a, float b)
 {
     if (a != a)
@@ -306,6 +372,9 @@
         case GLFW_COCOA_MENUBAR:
             _glfwInitHints.ns.menubar = value;
             return;
+        case GLFW_WAYLAND_LIBDECOR:
+            _glfwInitHints.wl.libdecorMode = value;
+            return;
     }
 
     _glfwInputError(GLFW_INVALID_ENUM,
diff --git a/src/input.c b/src/input.c
index 0d04571..11a5246 100644
--- a/src/input.c
+++ b/src/input.c
@@ -360,6 +360,11 @@
 {
     const int jid = (int) (js - _glfw.joysticks);
 
+    if (event == GLFW_CONNECTED)
+        js->connected = GLFW_TRUE;
+    else if (event == GLFW_DISCONNECTED)
+        js->connected = GLFW_FALSE;
+
     if (_glfw.callbacks.joystick)
         _glfw.callbacks.joystick(jid, event);
 }
@@ -415,7 +420,7 @@
     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
     {
         _GLFWjoystick* js = _glfw.joysticks + jid;
-        if (js->present)
+        if (js->connected)
             js->mapping = findValidMapping(js);
     }
 }
@@ -433,7 +438,7 @@
 
     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
     {
-        if (!_glfw.joysticks[jid].present)
+        if (!_glfw.joysticks[jid].allocated)
             break;
     }
 
@@ -441,7 +446,7 @@
         return NULL;
 
     js = _glfw.joysticks + jid;
-    js->present     = GLFW_TRUE;
+    js->allocated   = GLFW_TRUE;
     js->axes        = calloc(axisCount, sizeof(float));
     js->buttons     = calloc(buttonCount + (size_t) hatCount * 4, 1);
     js->hats        = calloc(hatCount, 1);
@@ -611,6 +616,12 @@
 
     if (key != GLFW_KEY_UNKNOWN)
     {
+        if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
+        {
+            _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
+            return NULL;
+        }
+
         if (key != GLFW_KEY_KP_EQUAL &&
             (key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
             (key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
@@ -631,7 +642,7 @@
     if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
     {
         _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
-        return GLFW_RELEASE;
+        return -1;
     }
 
     return _glfwPlatformGetKeyScancode(key);
@@ -743,9 +754,16 @@
     _GLFWcursor* cursor;
 
     assert(image != NULL);
+    assert(image->pixels != NULL);
 
     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
 
+    if (image->width <= 0 || image->height <= 0)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid image dimensions for cursor");
+        return NULL;
+    }
+
     cursor = calloc(1, sizeof(_GLFWcursor));
     cursor->next = _glfw.cursorListHead;
     _glfw.cursorListHead = cursor;
@@ -941,7 +959,7 @@
     }
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->connected)
         return GLFW_FALSE;
 
     return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
@@ -966,7 +984,7 @@
     }
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->connected)
         return NULL;
 
     if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_AXES))
@@ -995,7 +1013,7 @@
     }
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->connected)
         return NULL;
 
     if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
@@ -1028,7 +1046,7 @@
     }
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->connected)
         return NULL;
 
     if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
@@ -1054,7 +1072,7 @@
     }
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->connected)
         return NULL;
 
     if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
@@ -1079,7 +1097,7 @@
     }
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->connected)
         return NULL;
 
     if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
@@ -1098,7 +1116,7 @@
     _GLFW_REQUIRE_INIT();
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->allocated)
         return;
 
     js->userPointer = pointer;
@@ -1114,7 +1132,7 @@
     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->allocated)
         return NULL;
 
     return js->userPointer;
@@ -1180,7 +1198,7 @@
     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
     {
         _GLFWjoystick* js = _glfw.joysticks + jid;
-        if (js->present)
+        if (js->connected)
             js->mapping = findValidMapping(js);
     }
 
@@ -1203,7 +1221,7 @@
     }
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->connected)
         return GLFW_FALSE;
 
     if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
@@ -1228,7 +1246,7 @@
     }
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->connected)
         return NULL;
 
     if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
@@ -1260,7 +1278,7 @@
     }
 
     js = _glfw.joysticks + jid;
-    if (!js->present)
+    if (!js->connected)
         return GLFW_FALSE;
 
     if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))
@@ -1369,3 +1387,4 @@
     _GLFW_REQUIRE_INIT_OR_RETURN(0);
     return _glfwPlatformGetTimerFrequency();
 }
+
diff --git a/src/internal.h b/src/internal.h
index 561f4c1..3f081bf 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -244,6 +244,9 @@
         GLFWbool  menubar;
         GLFWbool  chdir;
     } ns;
+    struct {
+        int       libdecorMode;
+    } wl;
 };
 
 // Window configuration
@@ -478,7 +481,8 @@
 //
 struct _GLFWjoystick
 {
-    GLFWbool        present;
+    GLFWbool        allocated;
+    GLFWbool        connected;
     float*          axes;
     int             axisCount;
     unsigned char*  buttons;
@@ -775,8 +779,11 @@
 const char* _glfwGetVulkanResultString(VkResult result);
 
 size_t _glfwEncodeUTF8(char* s, uint32_t codepoint);
+char** _glfwParseUriList(char* text, int* count);
 
 char* _glfw_strdup(const char* source);
+int _glfw_min(int a, int b);
+int _glfw_max(int a, int b);
 float _glfw_fminf(float a, float b);
 float _glfw_fmaxf(float a, float b);
 
diff --git a/src/linux_joystick.c b/src/linux_joystick.c
index 5a3b806..63b43da 100644
--- a/src/linux_joystick.c
+++ b/src/linux_joystick.c
@@ -128,7 +128,7 @@
 {
     for (int jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
     {
-        if (!_glfw.joysticks[jid].present)
+        if (!_glfw.joysticks[jid].connected)
             continue;
         if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
             return GLFW_FALSE;
@@ -157,7 +157,7 @@
     }
 
     // Ensure this device supports the events expected of a joystick
-    if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
+    if (!isBitSet(EV_ABS, evBits))
     {
         close(linjs.fd);
         return GLFW_FALSE;
@@ -245,9 +245,9 @@
 //
 static void closeJoystick(_GLFWjoystick* js)
 {
+    _glfwInputJoystick(js, GLFW_DISCONNECTED);
     close(js->linjs.fd);
     _glfwFreeJoystick(js);
-    _glfwInputJoystick(js, GLFW_DISCONNECTED);
 }
 
 // Lexically compare joysticks by name; used by qsort
@@ -283,7 +283,8 @@
 
     // Continue without device connection notifications if inotify fails
 
-    if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
+    _glfw.linjs.regexCompiled = (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) == 0);
+    if (!_glfw.linjs.regexCompiled)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
         return GLFW_FALSE;
@@ -329,7 +330,7 @@
     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
     {
         _GLFWjoystick* js = _glfw.joysticks + jid;
-        if (js->present)
+        if (js->connected)
             closeJoystick(js);
     }
 
@@ -342,6 +343,9 @@
 
         close(_glfw.linjs.inotify);
     }
+
+    if (_glfw.linjs.regexCompiled)
+        regfree(&_glfw.linjs.regex);
 }
 
 void _glfwDetectJoystickConnectionLinux(void)
@@ -424,7 +428,7 @@
             handleAbsEvent(js, e.code, e.value);
     }
 
-    return js->present;
+    return js->connected;
 }
 
 void _glfwPlatformUpdateGamepadGUID(char* guid)
diff --git a/src/linux_joystick.h b/src/linux_joystick.h
index 25a2a2e..50df677 100644
--- a/src/linux_joystick.h
+++ b/src/linux_joystick.h
@@ -53,6 +53,7 @@
     int                     inotify;
     int                     watch;
     regex_t                 regex;
+    GLFWbool                regexCompiled;
     GLFWbool                dropped;
 } _GLFWlibraryLinux;
 
diff --git a/src/monitor.c b/src/monitor.c
index 7341141..2601d11 100644
--- a/src/monitor.c
+++ b/src/monitor.c
@@ -521,6 +521,8 @@
     assert(ramp->green != NULL);
     assert(ramp->blue != NULL);
 
+    _GLFW_REQUIRE_INIT();
+
     if (ramp->size <= 0)
     {
         _glfwInputError(GLFW_INVALID_VALUE,
@@ -529,8 +531,6 @@
         return;
     }
 
-    _GLFW_REQUIRE_INIT();
-
     if (!monitor->originalRamp.size)
     {
         if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp))
diff --git a/src/nsgl_context.m b/src/nsgl_context.m
index 78d688c..e984cae 100644
--- a/src/nsgl_context.m
+++ b/src/nsgl_context.m
@@ -81,11 +81,10 @@
     @autoreleasepool {
 
     _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
-    if (window)
-    {
-        [window->context.nsgl.object setValues:&interval
-                                  forParameter:NSOpenGLContextParameterSwapInterval];
-    }
+    assert(window != NULL);
+
+    [window->context.nsgl.object setValues:&interval
+                              forParameter:NSOpenGLContextParameterSwapInterval];
 
     } // autoreleasepool
 }
diff --git a/src/null_window.c b/src/null_window.c
index 045c76a..e61c2bd 100644
--- a/src/null_window.c
+++ b/src/null_window.c
@@ -67,6 +67,9 @@
             _glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
             return GLFW_FALSE;
         }
+
+        if (!_glfwRefreshContextAttribs(window, ctxconfig))
+            return GLFW_FALSE;
     }
 
     return GLFW_TRUE;
diff --git a/src/wgl_context.c b/src/wgl_context.c
index 72ad11d..eebf6cd 100644
--- a/src/wgl_context.c
+++ b/src/wgl_context.c
@@ -73,18 +73,13 @@
     int attribs[40];
     int values[sizeof(attribs) / sizeof(attribs[0])];
 
+    nativeCount = DescribePixelFormat(window->context.wgl.dc,
+                                      1,
+                                      sizeof(PIXELFORMATDESCRIPTOR),
+                                      NULL);
+
     if (_glfw.wgl.ARB_pixel_format)
     {
-        const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;
-
-        if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
-                                          1, 0, 1, &attrib, &nativeCount))
-        {
-            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                                 "WGL: Failed to retrieve pixel format attribute");
-            return 0;
-        }
-
         addAttrib(WGL_SUPPORT_OPENGL_ARB);
         addAttrib(WGL_DRAW_TO_WINDOW_ARB);
         addAttrib(WGL_PIXEL_TYPE_ARB);
@@ -122,13 +117,6 @@
                 addAttrib(WGL_COLORSPACE_EXT);
         }
     }
-    else
-    {
-        nativeCount = DescribePixelFormat(window->context.wgl.dc,
-                                          1,
-                                          sizeof(PIXELFORMATDESCRIPTOR),
-                                          NULL);
-    }
 
     usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
 
@@ -345,6 +333,7 @@
 static void swapIntervalWGL(int interval)
 {
     _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
+    assert(window != NULL);
 
     window->context.wgl.interval = interval;
 
diff --git a/src/win32_init.c b/src/win32_init.c
index 4923b26..885f32f 100644
--- a/src/win32_init.c
+++ b/src/win32_init.c
@@ -72,6 +72,16 @@
 //
 static GLFWbool loadLibraries(void)
 {
+    if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
+                                GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+                            (const WCHAR*) &_glfw,
+                            (HMODULE*) &_glfw.win32.instance))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to retrieve own module handle");
+        return GLFW_FALSE;
+    }
+
     _glfw.win32.user32.instance = LoadLibraryA("user32.dll");
     if (!_glfw.win32.user32.instance)
     {
@@ -254,7 +264,6 @@
     _glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
     _glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
     _glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
-    _glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
     _glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
     _glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
     _glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
@@ -336,7 +345,7 @@
                         WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
                         0, 0, 1, 1,
                         NULL, NULL,
-                        GetModuleHandleW(NULL),
+                        _glfw.win32.instance,
                         NULL);
 
     if (!_glfw.win32.helperWindowHandle)
@@ -494,6 +503,8 @@
 
         if (length == -1)
         {
+            // This is a dead key, so we need a second simulated key press
+            // to make it output its own character (usually a diacritic)
             length = ToUnicode(vk, scancode, state,
                                chars, sizeof(chars) / sizeof(WCHAR),
                                0);
@@ -601,6 +612,7 @@
 
     _glfwTerminateWGL();
     _glfwTerminateEGL();
+    _glfwTerminateOSMesa();
 
     _glfwTerminateJoysticksWin32();
 
diff --git a/src/win32_joystick.c b/src/win32_joystick.c
index f54d570..2eb25da 100644
--- a/src/win32_joystick.c
+++ b/src/win32_joystick.c
@@ -256,6 +256,8 @@
 //
 static void closeJoystick(_GLFWjoystick* js)
 {
+    _glfwInputJoystick(js, GLFW_DISCONNECTED);
+
     if (js->win32.device)
     {
         IDirectInputDevice8_Unacquire(js->win32.device);
@@ -263,9 +265,7 @@
     }
 
     free(js->win32.objects);
-
     _glfwFreeJoystick(js);
-    _glfwInputJoystick(js, GLFW_DISCONNECTED);
 }
 
 // DirectInput device object enumeration callback
@@ -357,7 +357,7 @@
     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
     {
         js = _glfw.joysticks + jid;
-        if (js->present)
+        if (js->connected)
         {
             if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
                 return DIENUM_CONTINUE;
@@ -497,7 +497,7 @@
 {
     if (_glfw.win32.dinput8.instance)
     {
-        if (FAILED(DirectInput8Create(GetModuleHandleW(NULL),
+        if (FAILED(DirectInput8Create(_glfw.win32.instance,
                                       DIRECTINPUT_VERSION,
                                       &IID_IDirectInput8W,
                                       (void**) &_glfw.win32.dinput8.api,
@@ -541,7 +541,7 @@
 
             for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
             {
-                if (_glfw.joysticks[jid].present &&
+                if (_glfw.joysticks[jid].connected &&
                     _glfw.joysticks[jid].win32.device == NULL &&
                     _glfw.joysticks[jid].win32.index == index)
                 {
@@ -593,7 +593,7 @@
     for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
     {
         _GLFWjoystick* js = _glfw.joysticks + jid;
-        if (js->present)
+        if (js->connected)
             _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
     }
 }
@@ -609,7 +609,7 @@
     {
         int i, ai = 0, bi = 0, pi = 0;
         HRESULT result;
-        DIJOYSTATE state;
+        DIJOYSTATE state = {0};
 
         IDirectInputDevice8_Poll(js->win32.device);
         result = IDirectInputDevice8_GetDeviceState(js->win32.device,
@@ -736,6 +736,13 @@
         if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
             dpad |= GLFW_HAT_LEFT;
 
+        // Treat invalid combinations as neither being pressed
+        // while preserving what data can be preserved
+        if ((dpad & GLFW_HAT_RIGHT) && (dpad & GLFW_HAT_LEFT))
+            dpad &= ~(GLFW_HAT_RIGHT | GLFW_HAT_LEFT);
+        if ((dpad & GLFW_HAT_UP) && (dpad & GLFW_HAT_DOWN))
+            dpad &= ~(GLFW_HAT_UP | GLFW_HAT_DOWN);
+
         _glfwInputJoystickHat(js, 0, dpad);
     }
 
diff --git a/src/win32_platform.h b/src/win32_platform.h
index 92d43d0..e729709 100644
--- a/src/win32_platform.h
+++ b/src/win32_platform.h
@@ -334,6 +334,7 @@
 //
 typedef struct _GLFWlibraryWin32
 {
+    HINSTANCE           instance;
     HWND                helperWindowHandle;
     HDEVNOTIFY          deviceNotificationHandle;
     DWORD               foregroundLockTimeout;
@@ -346,6 +347,8 @@
     double              restoreCursorPosX, restoreCursorPosY;
     // The window whose disabled cursor mode is active
     _GLFWwindow*        disabledCursorWindow;
+    // The window the cursor is captured in
+    _GLFWwindow*        capturedCursorWindow;
     RAWINPUT*           rawInput;
     int                 rawInputSize;
     UINT                mouseTrailSize;
diff --git a/src/win32_window.c b/src/win32_window.c
index 188b0d4..a10f4ce 100644
--- a/src/win32_window.c
+++ b/src/win32_window.c
@@ -186,53 +186,38 @@
     return handle;
 }
 
-// Translate content area size to full window size according to styles and DPI
-//
-static void getFullWindowSize(DWORD style, DWORD exStyle,
-                              int contentWidth, int contentHeight,
-                              int* fullWidth, int* fullHeight,
-                              UINT dpi)
-{
-    RECT rect = { 0, 0, contentWidth, contentHeight };
-
-    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-        AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
-    else
-        AdjustWindowRectEx(&rect, style, FALSE, exStyle);
-
-    *fullWidth = rect.right - rect.left;
-    *fullHeight = rect.bottom - rect.top;
-}
-
 // Enforce the content area aspect ratio based on which edge is being dragged
 //
 static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
 {
-    int xoff, yoff;
-    UINT dpi = USER_DEFAULT_SCREEN_DPI;
+    RECT frame = {0};
     const float ratio = (float) window->numer / (float) window->denom;
+    const DWORD style = getWindowStyle(window);
+    const DWORD exStyle = getWindowExStyle(window);
 
     if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-        dpi = GetDpiForWindow(window->win32.handle);
-
-    getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
-                      0, 0, &xoff, &yoff, dpi);
+    {
+        AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle,
+                                 GetDpiForWindow(window->win32.handle));
+    }
+    else
+        AdjustWindowRectEx(&frame, style, FALSE, exStyle);
 
     if (edge == WMSZ_LEFT  || edge == WMSZ_BOTTOMLEFT ||
         edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
     {
-        area->bottom = area->top + yoff +
-            (int) ((area->right - area->left - xoff) / ratio);
+        area->bottom = area->top + (frame.bottom - frame.top) +
+            (int) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
     }
     else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT)
     {
-        area->top = area->bottom - yoff -
-            (int) ((area->right - area->left - xoff) / ratio);
+        area->top = area->bottom - (frame.bottom - frame.top) -
+            (int) (((area->right - area->left) - (frame.right - frame.left)) / ratio);
     }
     else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM)
     {
-        area->right = area->left + xoff +
-            (int) ((area->bottom - area->top - yoff) * ratio);
+        area->right = area->left + (frame.right - frame.left) +
+            (int) (((area->bottom - area->top) - (frame.bottom - frame.top)) * ratio);
     }
 }
 
@@ -251,20 +236,24 @@
         SetCursor(NULL);
 }
 
-// Updates the cursor clip rect
+// Sets the cursor clip rect to the window content area
 //
-static void updateClipRect(_GLFWwindow* window)
+static void captureCursor(_GLFWwindow* window)
 {
-    if (window)
-    {
-        RECT clipRect;
-        GetClientRect(window->win32.handle, &clipRect);
-        ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
-        ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
-        ClipCursor(&clipRect);
-    }
-    else
-        ClipCursor(NULL);
+    RECT clipRect;
+    GetClientRect(window->win32.handle, &clipRect);
+    ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
+    ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
+    ClipCursor(&clipRect);
+    _glfw.win32.capturedCursorWindow = window;
+}
+
+// Disabled clip cursor
+//
+static void releaseCursor(void)
+{
+    ClipCursor(NULL);
+    _glfw.win32.capturedCursorWindow = NULL;
 }
 
 // Enables WM_INPUT messages for the mouse for the specified window
@@ -303,7 +292,7 @@
                               &_glfw.win32.restoreCursorPosY);
     updateCursorImage(window);
     _glfwCenterCursorInContentArea(window);
-    updateClipRect(window);
+    captureCursor(window);
 
     if (window->rawMouseMotion)
         enableRawMouseMotion(window);
@@ -317,7 +306,7 @@
         disableRawMouseMotion(window);
 
     _glfw.win32.disabledCursorWindow = NULL;
-    updateClipRect(NULL);
+    releaseCursor();
     _glfwPlatformSetCursorPos(window,
                               _glfw.win32.restoreCursorPosX,
                               _glfw.win32.restoreCursorPosY);
@@ -504,10 +493,8 @@
 
     if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
     {
-        if (rect.right - rect.left > window->maxwidth)
-            rect.right = rect.left + window->maxwidth;
-        if (rect.bottom - rect.top > window->maxheight)
-            rect.bottom = rect.top + window->maxheight;
+        rect.right = _glfw_min(rect.right, rect.left + window->maxwidth);
+        rect.bottom = _glfw_min(rect.bottom, rect.top + window->maxheight);
     }
 
     style = GetWindowLongW(window->win32.handle, GWL_STYLE);
@@ -530,8 +517,7 @@
             OffsetRect(&rect, 0, GetSystemMetrics(SM_CYCAPTION));
         }
 
-        if (rect.bottom > mi.rcWork.bottom)
-            rect.bottom = mi.rcWork.bottom;
+        rect.bottom = _glfw_min(rect.bottom, mi.rcWork.bottom);
     }
 
     SetWindowPos(window->win32.handle, HWND_TOP,
@@ -751,6 +737,18 @@
                 scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
             }
 
+            // HACK: Alt+PrtSc has a different scancode than just PrtSc
+            if (scancode == 0x54)
+                scancode = 0x137;
+
+            // HACK: Ctrl+Pause has a different scancode than just Pause
+            if (scancode == 0x146)
+                scancode = 0x45;
+
+            // HACK: CJK IME sets the extended bit for right Shift
+            if (scancode == 0x136)
+                scancode = 0x36;
+
             key = _glfw.win32.keycodes[scancode];
 
             // The Ctrl keys require special handling
@@ -1024,8 +1022,8 @@
                                        (window->win32.maximized &&
                                         wParam != SIZE_RESTORED);
 
-            if (_glfw.win32.disabledCursorWindow == window)
-                updateClipRect(window);
+            if (_glfw.win32.capturedCursorWindow == window)
+                captureCursor(window);
 
             if (window->win32.iconified != iconified)
                 _glfwInputWindowIconify(window, iconified);
@@ -1060,8 +1058,8 @@
 
         case WM_MOVE:
         {
-            if (_glfw.win32.disabledCursorWindow == window)
-                updateClipRect(window);
+            if (_glfw.win32.capturedCursorWindow == window)
+                captureCursor(window);
 
             // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as
             // those macros do not handle negative window positions correctly
@@ -1085,31 +1083,34 @@
 
         case WM_GETMINMAXINFO:
         {
-            int xoff, yoff;
-            UINT dpi = USER_DEFAULT_SCREEN_DPI;
+            RECT frame = {0};
             MINMAXINFO* mmi = (MINMAXINFO*) lParam;
+            const DWORD style = getWindowStyle(window);
+            const DWORD exStyle = getWindowExStyle(window);
 
             if (window->monitor)
                 break;
 
             if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-                dpi = GetDpiForWindow(window->win32.handle);
-
-            getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
-                              0, 0, &xoff, &yoff, dpi);
+            {
+                AdjustWindowRectExForDpi(&frame, style, FALSE, exStyle,
+                                         GetDpiForWindow(window->win32.handle));
+            }
+            else
+                AdjustWindowRectEx(&frame, style, FALSE, exStyle);
 
             if (window->minwidth != GLFW_DONT_CARE &&
                 window->minheight != GLFW_DONT_CARE)
             {
-                mmi->ptMinTrackSize.x = window->minwidth + xoff;
-                mmi->ptMinTrackSize.y = window->minheight + yoff;
+                mmi->ptMinTrackSize.x = window->minwidth + frame.right - frame.left;
+                mmi->ptMinTrackSize.y = window->minheight + frame.bottom - frame.top;
             }
 
             if (window->maxwidth != GLFW_DONT_CARE &&
                 window->maxheight != GLFW_DONT_CARE)
             {
-                mmi->ptMaxTrackSize.x = window->maxwidth + xoff;
-                mmi->ptMaxTrackSize.y = window->maxheight + yoff;
+                mmi->ptMaxTrackSize.x = window->maxwidth + frame.right - frame.left;
+                mmi->ptMaxTrackSize.y = window->maxheight + frame.bottom - frame.top;
             }
 
             if (!window->decorated)
@@ -1268,36 +1269,38 @@
                               const _GLFWwndconfig* wndconfig,
                               const _GLFWfbconfig* fbconfig)
 {
-    int xpos, ypos, fullWidth, fullHeight;
+    int frameX, frameY, frameWidth, frameHeight;
     WCHAR* wideTitle;
     DWORD style = getWindowStyle(window);
     DWORD exStyle = getWindowExStyle(window);
 
     if (window->monitor)
     {
-        GLFWvidmode mode;
+        MONITORINFO mi = { sizeof(mi) };
+        GetMonitorInfoW(window->monitor->win32.handle, &mi);
 
         // NOTE: This window placement is temporary and approximate, as the
         //       correct position and size cannot be known until the monitor
         //       video mode has been picked in _glfwSetVideoModeWin32
-        _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
-        _glfwPlatformGetVideoMode(window->monitor, &mode);
-        fullWidth  = mode.width;
-        fullHeight = mode.height;
+        frameX = mi.rcMonitor.left;
+        frameY = mi.rcMonitor.top;
+        frameWidth  = mi.rcMonitor.right - mi.rcMonitor.left;
+        frameHeight = mi.rcMonitor.bottom - mi.rcMonitor.top;
     }
     else
     {
-        xpos = CW_USEDEFAULT;
-        ypos = CW_USEDEFAULT;
+        RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
 
         window->win32.maximized = wndconfig->maximized;
         if (wndconfig->maximized)
             style |= WS_MAXIMIZE;
 
-        getFullWindowSize(style, exStyle,
-                          wndconfig->width, wndconfig->height,
-                          &fullWidth, &fullHeight,
-                          USER_DEFAULT_SCREEN_DPI);
+        AdjustWindowRectEx(&rect, style, FALSE, exStyle);
+
+        frameX = CW_USEDEFAULT;
+        frameY = CW_USEDEFAULT;
+        frameWidth  = rect.right - rect.left;
+        frameHeight = rect.bottom - rect.top;
     }
 
     wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
@@ -1308,11 +1311,11 @@
                                            _GLFW_WNDCLASSNAME,
                                            wideTitle,
                                            style,
-                                           xpos, ypos,
-                                           fullWidth, fullHeight,
+                                           frameX, frameY,
+                                           frameWidth, frameHeight,
                                            NULL, // No parent window
                                            NULL, // No window menu
-                                           GetModuleHandleW(NULL),
+                                           _glfw.win32.instance,
                                            (LPVOID) wndconfig);
 
     free(wideTitle);
@@ -1423,8 +1426,8 @@
     ZeroMemory(&wc, sizeof(wc));
     wc.cbSize        = sizeof(wc);
     wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
-    wc.lpfnWndProc   = (WNDPROC) windowProc;
-    wc.hInstance     = GetModuleHandleW(NULL);
+    wc.lpfnWndProc   = windowProc;
+    wc.hInstance     = _glfw.win32.instance;
     wc.hCursor       = LoadCursorW(NULL, IDC_ARROW);
     wc.lpszClassName = _GLFW_WNDCLASSNAME;
 
@@ -1454,7 +1457,7 @@
 //
 void _glfwUnregisterWindowClassWin32(void)
 {
-    UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
+    UnregisterClassW(_GLFW_WNDCLASSNAME, _glfw.win32.instance);
 }
 
 
@@ -1493,6 +1496,9 @@
             if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
                 return GLFW_FALSE;
         }
+
+        if (!_glfwRefreshContextAttribs(window, ctxconfig))
+            return GLFW_FALSE;
     }
 
     if (window->monitor)
@@ -1501,6 +1507,18 @@
         _glfwPlatformFocusWindow(window);
         acquireMonitor(window);
         fitToMonitor(window);
+
+        if (wndconfig->centerCursor)
+            _glfwCenterCursorInContentArea(window);
+    }
+    else
+    {
+        if (wndconfig->visible)
+        {
+            _glfwPlatformShowWindow(window);
+            if (wndconfig->focused)
+                _glfwPlatformFocusWindow(window);
+        }
     }
 
     return GLFW_TRUE;
@@ -1515,7 +1533,10 @@
         window->context.destroy(window);
 
     if (_glfw.win32.disabledCursorWindow == window)
-        _glfw.win32.disabledCursorWindow = NULL;
+        enableCursor(window);
+
+    if (_glfw.win32.capturedCursorWindow == window)
+        releaseCursor();
 
     if (window->win32.handle)
     {
@@ -2092,7 +2113,7 @@
 
 void _glfwPlatformWaitEventsTimeout(double timeout)
 {
-    MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLEVENTS);
+    MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLINPUT);
 
     _glfwPlatformPollEvents();
 }
@@ -2131,14 +2152,40 @@
 
 void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
 {
-    if (mode == GLFW_CURSOR_DISABLED)
+    if (_glfwPlatformWindowFocused(window))
     {
-        if (_glfwPlatformWindowFocused(window))
-            disableCursor(window);
+        if (mode == GLFW_CURSOR_DISABLED)
+        {
+            _glfwPlatformGetCursorPos(window,
+                                      &_glfw.win32.restoreCursorPosX,
+                                      &_glfw.win32.restoreCursorPosY);
+            _glfwCenterCursorInContentArea(window);
+            if (window->rawMouseMotion)
+                enableRawMouseMotion(window);
+        }
+        else if (_glfw.win32.disabledCursorWindow == window)
+        {
+            if (window->rawMouseMotion)
+                disableRawMouseMotion(window);
+        }
+
+        if (mode == GLFW_CURSOR_DISABLED)
+            captureCursor(window);
+        else
+            releaseCursor();
+
+        if (mode == GLFW_CURSOR_DISABLED)
+            _glfw.win32.disabledCursorWindow = window;
+        else if (_glfw.win32.disabledCursorWindow == window)
+        {
+            _glfw.win32.disabledCursorWindow = NULL;
+            _glfwPlatformSetCursorPos(window,
+                                      _glfw.win32.restoreCursorPosX,
+                                      _glfw.win32.restoreCursorPosY);
+        }
     }
-    else if (_glfw.win32.disabledCursorWindow == window)
-        enableCursor(window);
-    else if (cursorInContentArea(window))
+
+    if (cursorInContentArea(window))
         updateCursorImage(window);
 }
 
@@ -2354,7 +2401,7 @@
 
     memset(&sci, 0, sizeof(sci));
     sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
-    sci.hinstance = GetModuleHandleW(NULL);
+    sci.hinstance = _glfw.win32.instance;
     sci.hwnd = window->win32.handle;
 
     err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
diff --git a/src/window.c b/src/window.c
index b87a260..5d80e43 100644
--- a/src/window.c
+++ b/src/window.c
@@ -221,30 +221,6 @@
         return NULL;
     }
 
-    if (ctxconfig.client != GLFW_NO_API)
-    {
-        if (!_glfwRefreshContextAttribs(window, &ctxconfig))
-        {
-            glfwDestroyWindow((GLFWwindow*) window);
-            return NULL;
-        }
-    }
-
-    if (window->monitor)
-    {
-        if (wndconfig.centerCursor)
-            _glfwCenterCursorInContentArea(window);
-    }
-    else
-    {
-        if (wndconfig.visible)
-        {
-            _glfwPlatformShowWindow(window);
-            if (wndconfig.focused)
-                _glfwPlatformFocusWindow(window);
-        }
-    }
-
     return (GLFWwindow*) window;
 }
 
@@ -504,12 +480,33 @@
 GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,
                                int count, const GLFWimage* images)
 {
+    int i;
     _GLFWwindow* window = (_GLFWwindow*) handle;
+
     assert(window != NULL);
     assert(count >= 0);
     assert(count == 0 || images != NULL);
 
     _GLFW_REQUIRE_INIT();
+
+    if (count < 0)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid image count for window icon");
+        return;
+    }
+
+    for (i = 0; i < count; i++)
+    {
+        assert(images[i].pixels != NULL);
+
+        if (images[i].width <= 0 || images[i].height <= 0)
+        {
+            _glfwInputError(GLFW_INVALID_VALUE,
+                            "Invalid image dimensions for window icon");
+            return;
+        }
+    }
+
     _glfwPlatformSetWindowIcon(window, count, images);
 }
 
diff --git a/src/wl_init.c b/src/wl_init.c
index 0ec9910..bc78667 100644
--- a/src/wl_init.c
+++ b/src/wl_init.c
@@ -30,7 +30,6 @@
 
 #include "internal.h"
 
-#include <assert.h>
 #include <errno.h>
 #include <limits.h>
 #include <linux/input.h>
@@ -41,742 +40,21 @@
 #include <sys/timerfd.h>
 #include <unistd.h>
 #include <wayland-client.h>
+#include <assert.h>
 
-
-static inline int min(int n1, int n2)
-{
-    return n1 < n2 ? n1 : n2;
-}
-
-static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
-                                                    int* which)
-{
-    int focus;
-    _GLFWwindow* window = _glfw.windowListHead;
-    if (!which)
-        which = &focus;
-    while (window)
-    {
-        if (surface == window->wl.decorations.top.surface)
-        {
-            *which = topDecoration;
-            break;
-        }
-        if (surface == window->wl.decorations.left.surface)
-        {
-            *which = leftDecoration;
-            break;
-        }
-        if (surface == window->wl.decorations.right.surface)
-        {
-            *which = rightDecoration;
-            break;
-        }
-        if (surface == window->wl.decorations.bottom.surface)
-        {
-            *which = bottomDecoration;
-            break;
-        }
-        window = window->next;
-    }
-    return window;
-}
-
-static void pointerHandleEnter(void* data,
-                               struct wl_pointer* pointer,
-                               uint32_t serial,
-                               struct wl_surface* surface,
-                               wl_fixed_t sx,
-                               wl_fixed_t sy)
-{
-    // Happens in the case we just destroyed the surface.
-    if (!surface)
-        return;
-
-    int focus = 0;
-    _GLFWwindow* window = wl_surface_get_user_data(surface);
-    if (!window)
-    {
-        window = findWindowFromDecorationSurface(surface, &focus);
-        if (!window)
-            return;
-    }
-
-    window->wl.decorations.focus = focus;
-    _glfw.wl.serial = serial;
-    _glfw.wl.pointerEnterSerial = serial;
-    _glfw.wl.pointerFocus = window;
-
-    window->wl.hovered = GLFW_TRUE;
-
-    _glfwPlatformSetCursor(window, window->wl.currentCursor);
-    _glfwInputCursorEnter(window, GLFW_TRUE);
-}
-
-static void pointerHandleLeave(void* data,
-                               struct wl_pointer* pointer,
-                               uint32_t serial,
-                               struct wl_surface* surface)
-{
-    _GLFWwindow* window = _glfw.wl.pointerFocus;
-
-    if (!window)
-        return;
-
-    window->wl.hovered = GLFW_FALSE;
-
-    _glfw.wl.serial = serial;
-    _glfw.wl.pointerFocus = NULL;
-    _glfwInputCursorEnter(window, GLFW_FALSE);
-    _glfw.wl.cursorPreviousName = NULL;
-}
-
-static void setCursor(_GLFWwindow* window, const char* name)
-{
-    struct wl_buffer* buffer;
-    struct wl_cursor* cursor;
-    struct wl_cursor_image* image;
-    struct wl_surface* surface = _glfw.wl.cursorSurface;
-    struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
-    int scale = 1;
-
-    if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI)
-    {
-        // We only support up to scale=2 for now, since libwayland-cursor
-        // requires us to load a different theme for each size.
-        scale = 2;
-        theme = _glfw.wl.cursorThemeHiDPI;
-    }
-
-    cursor = wl_cursor_theme_get_cursor(theme, name);
-    if (!cursor)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Standard cursor not found");
-        return;
-    }
-    // TODO: handle animated cursors too.
-    image = cursor->images[0];
-
-    if (!image)
-        return;
-
-    buffer = wl_cursor_image_get_buffer(image);
-    if (!buffer)
-        return;
-    wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
-                          surface,
-                          image->hotspot_x / scale,
-                          image->hotspot_y / scale);
-    wl_surface_set_buffer_scale(surface, scale);
-    wl_surface_attach(surface, buffer, 0, 0);
-    wl_surface_damage(surface, 0, 0,
-                      image->width, image->height);
-    wl_surface_commit(surface);
-    _glfw.wl.cursorPreviousName = name;
-}
-
-static void pointerHandleMotion(void* data,
-                                struct wl_pointer* pointer,
-                                uint32_t time,
-                                wl_fixed_t sx,
-                                wl_fixed_t sy)
-{
-    _GLFWwindow* window = _glfw.wl.pointerFocus;
-    const char* cursorName = NULL;
-    double x, y;
-
-    if (!window)
-        return;
-
-    if (window->cursorMode == GLFW_CURSOR_DISABLED)
-        return;
-    x = wl_fixed_to_double(sx);
-    y = wl_fixed_to_double(sy);
-    window->wl.cursorPosX = x;
-    window->wl.cursorPosY = y;
-
-    switch (window->wl.decorations.focus)
-    {
-        case mainWindow:
-            _glfwInputCursorPos(window, x, y);
-            _glfw.wl.cursorPreviousName = NULL;
-            return;
-        case topDecoration:
-            if (y < _GLFW_DECORATION_WIDTH)
-                cursorName = "n-resize";
-            else
-                cursorName = "left_ptr";
-            break;
-        case leftDecoration:
-            if (y < _GLFW_DECORATION_WIDTH)
-                cursorName = "nw-resize";
-            else
-                cursorName = "w-resize";
-            break;
-        case rightDecoration:
-            if (y < _GLFW_DECORATION_WIDTH)
-                cursorName = "ne-resize";
-            else
-                cursorName = "e-resize";
-            break;
-        case bottomDecoration:
-            if (x < _GLFW_DECORATION_WIDTH)
-                cursorName = "sw-resize";
-            else if (x > window->wl.width + _GLFW_DECORATION_WIDTH)
-                cursorName = "se-resize";
-            else
-                cursorName = "s-resize";
-            break;
-        default:
-            assert(0);
-    }
-    if (_glfw.wl.cursorPreviousName != cursorName)
-        setCursor(window, cursorName);
-}
-
-static void pointerHandleButton(void* data,
-                                struct wl_pointer* pointer,
-                                uint32_t serial,
-                                uint32_t time,
-                                uint32_t button,
-                                uint32_t state)
-{
-    _GLFWwindow* window = _glfw.wl.pointerFocus;
-    int glfwButton;
-
-    // Both xdg-shell and wl_shell use the same values.
-    uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE;
-
-    if (!window)
-        return;
-    if (button == BTN_LEFT)
-    {
-        switch (window->wl.decorations.focus)
-        {
-            case mainWindow:
-                break;
-            case topDecoration:
-                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
-                    edges = WL_SHELL_SURFACE_RESIZE_TOP;
-                else
-                {
-                    if (window->wl.xdg.toplevel)
-                        xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
-                    else
-                        wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, serial);
-                }
-                break;
-            case leftDecoration:
-                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
-                    edges = WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
-                else
-                    edges = WL_SHELL_SURFACE_RESIZE_LEFT;
-                break;
-            case rightDecoration:
-                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
-                    edges = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;
-                else
-                    edges = WL_SHELL_SURFACE_RESIZE_RIGHT;
-                break;
-            case bottomDecoration:
-                if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
-                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;
-                else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
-                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
-                else
-                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM;
-                break;
-            default:
-                assert(0);
-        }
-        if (edges != WL_SHELL_SURFACE_RESIZE_NONE)
-        {
-            if (window->wl.xdg.toplevel)
-                xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
-                                    serial, edges);
-            else
-                wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,
-                                        serial, edges);
-            return;
-        }
-    }
-    else if (button == BTN_RIGHT)
-    {
-        if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel)
-        {
-            xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
-                                          _glfw.wl.seat, serial,
-                                          window->wl.cursorPosX,
-                                          window->wl.cursorPosY);
-            return;
-        }
-    }
-
-    // Don’t pass the button to the user if it was related to a decoration.
-    if (window->wl.decorations.focus != mainWindow)
-        return;
-
-    _glfw.wl.serial = serial;
-
-    /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
-     * codes. */
-    glfwButton = button - BTN_LEFT;
-
-    _glfwInputMouseClick(window,
-                         glfwButton,
-                         state == WL_POINTER_BUTTON_STATE_PRESSED
-                                ? GLFW_PRESS
-                                : GLFW_RELEASE,
-                         _glfw.wl.xkb.modifiers);
-}
-
-static void pointerHandleAxis(void* data,
-                              struct wl_pointer* pointer,
-                              uint32_t time,
-                              uint32_t axis,
-                              wl_fixed_t value)
-{
-    _GLFWwindow* window = _glfw.wl.pointerFocus;
-    double x = 0.0, y = 0.0;
-    // Wayland scroll events are in pointer motion coordinate space (think two
-    // finger scroll).  The factor 10 is commonly used to convert to "scroll
-    // step means 1.0.
-    const double scrollFactor = 1.0 / 10.0;
-
-    if (!window)
-        return;
-
-    assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
-           axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
-
-    if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
-        x = -wl_fixed_to_double(value) * scrollFactor;
-    else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
-        y = -wl_fixed_to_double(value) * scrollFactor;
-
-    _glfwInputScroll(window, x, y);
-}
-
-static const struct wl_pointer_listener pointerListener = {
-    pointerHandleEnter,
-    pointerHandleLeave,
-    pointerHandleMotion,
-    pointerHandleButton,
-    pointerHandleAxis,
-};
-
-static void keyboardHandleKeymap(void* data,
-                                 struct wl_keyboard* keyboard,
-                                 uint32_t format,
-                                 int fd,
-                                 uint32_t size)
-{
-    struct xkb_keymap* keymap;
-    struct xkb_state* state;
-    struct xkb_compose_table* composeTable;
-    struct xkb_compose_state* composeState;
-    char* mapStr;
-    const char* locale;
-
-    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
-    {
-        close(fd);
-        return;
-    }
-
-    mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
-    if (mapStr == MAP_FAILED) {
-        close(fd);
-        return;
-    }
-
-    keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
-                                        mapStr,
-                                        XKB_KEYMAP_FORMAT_TEXT_V1,
-                                        0);
-    munmap(mapStr, size);
-    close(fd);
-
-    if (!keymap)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to compile keymap");
-        return;
-    }
-
-    state = xkb_state_new(keymap);
-    if (!state)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to create XKB state");
-        xkb_keymap_unref(keymap);
-        return;
-    }
-
-    // Look up the preferred locale, falling back to "C" as default.
-    locale = getenv("LC_ALL");
-    if (!locale)
-        locale = getenv("LC_CTYPE");
-    if (!locale)
-        locale = getenv("LANG");
-    if (!locale)
-        locale = "C";
-
-    composeTable =
-        xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
-                                          XKB_COMPOSE_COMPILE_NO_FLAGS);
-    if (composeTable)
-    {
-        composeState =
-            xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
-        xkb_compose_table_unref(composeTable);
-        if (composeState)
-            _glfw.wl.xkb.composeState = composeState;
-        else
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Failed to create XKB compose state");
-    }
-    else
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to create XKB compose table");
-    }
-
-    xkb_keymap_unref(_glfw.wl.xkb.keymap);
-    xkb_state_unref(_glfw.wl.xkb.state);
-    _glfw.wl.xkb.keymap = keymap;
-    _glfw.wl.xkb.state = state;
-
-    _glfw.wl.xkb.controlMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
-    _glfw.wl.xkb.altMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
-    _glfw.wl.xkb.shiftMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
-    _glfw.wl.xkb.superMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
-    _glfw.wl.xkb.capsLockMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");
-    _glfw.wl.xkb.numLockMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");
-}
-
-static void keyboardHandleEnter(void* data,
-                                struct wl_keyboard* keyboard,
-                                uint32_t serial,
-                                struct wl_surface* surface,
-                                struct wl_array* keys)
-{
-    // Happens in the case we just destroyed the surface.
-    if (!surface)
-        return;
-
-    _GLFWwindow* window = wl_surface_get_user_data(surface);
-    if (!window)
-    {
-        window = findWindowFromDecorationSurface(surface, NULL);
-        if (!window)
-            return;
-    }
-
-    _glfw.wl.serial = serial;
-    _glfw.wl.keyboardFocus = window;
-    _glfwInputWindowFocus(window, GLFW_TRUE);
-}
-
-static void keyboardHandleLeave(void* data,
-                                struct wl_keyboard* keyboard,
-                                uint32_t serial,
-                                struct wl_surface* surface)
-{
-    _GLFWwindow* window = _glfw.wl.keyboardFocus;
-
-    if (!window)
-        return;
-
-    struct itimerspec timer = {};
-    timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
-
-    _glfw.wl.serial = serial;
-    _glfw.wl.keyboardFocus = NULL;
-    _glfwInputWindowFocus(window, GLFW_FALSE);
-}
-
-static int translateKey(uint32_t scancode)
-{
-    if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
-        return _glfw.wl.keycodes[scancode];
-
-    return GLFW_KEY_UNKNOWN;
-}
-
-static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
-{
-    if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
-        return sym;
-    if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
-            != XKB_COMPOSE_FEED_ACCEPTED)
-        return sym;
-    switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
-    {
-        case XKB_COMPOSE_COMPOSED:
-            return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
-        case XKB_COMPOSE_COMPOSING:
-        case XKB_COMPOSE_CANCELLED:
-            return XKB_KEY_NoSymbol;
-        case XKB_COMPOSE_NOTHING:
-        default:
-            return sym;
-    }
-}
-
-GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode)
-{
-    const xkb_keysym_t* keysyms;
-    const xkb_keycode_t keycode = scancode + 8;
-
-    if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1)
-    {
-        const xkb_keysym_t keysym = composeSymbol(keysyms[0]);
-        const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
-        if (codepoint != GLFW_INVALID_CODEPOINT)
-        {
-            const int mods = _glfw.wl.xkb.modifiers;
-            const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
-            _glfwInputChar(window, codepoint, mods, plain);
-        }
-    }
-
-    return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode);
-}
-
-static void keyboardHandleKey(void* data,
-                              struct wl_keyboard* keyboard,
-                              uint32_t serial,
-                              uint32_t time,
-                              uint32_t scancode,
-                              uint32_t state)
-{
-    _GLFWwindow* window = _glfw.wl.keyboardFocus;
-    if (!window)
-        return;
-
-    const int key = translateKey(scancode);
-    const int action =
-        state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
-
-    _glfw.wl.serial = serial;
-    _glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
-
-    struct itimerspec timer = {};
-
-    if (action == GLFW_PRESS)
-    {
-        const GLFWbool shouldRepeat = _glfwInputTextWayland(window, scancode);
-
-        if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
-        {
-            _glfw.wl.keyboardLastKey = key;
-            _glfw.wl.keyboardLastScancode = scancode;
-            if (_glfw.wl.keyboardRepeatRate > 1)
-                timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;
-            else
-                timer.it_interval.tv_sec = 1;
-
-            timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
-            timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
-        }
-    }
-
-    timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
-}
-
-static void keyboardHandleModifiers(void* data,
-                                    struct wl_keyboard* keyboard,
-                                    uint32_t serial,
-                                    uint32_t modsDepressed,
-                                    uint32_t modsLatched,
-                                    uint32_t modsLocked,
-                                    uint32_t group)
-{
-    _glfw.wl.serial = serial;
-
-    if (!_glfw.wl.xkb.keymap)
-        return;
-
-    xkb_state_update_mask(_glfw.wl.xkb.state,
-                          modsDepressed,
-                          modsLatched,
-                          modsLocked,
-                          0,
-                          0,
-                          group);
-
-    const xkb_mod_mask_t mask =
-        xkb_state_serialize_mods(_glfw.wl.xkb.state,
-                                 XKB_STATE_MODS_DEPRESSED |
-                                 XKB_STATE_LAYOUT_DEPRESSED |
-                                 XKB_STATE_MODS_LATCHED |
-                                 XKB_STATE_LAYOUT_LATCHED);
-
-    unsigned int mods = 0;
-
-    if (mask & _glfw.wl.xkb.controlMask)
-        mods |= GLFW_MOD_CONTROL;
-    if (mask & _glfw.wl.xkb.altMask)
-        mods |= GLFW_MOD_ALT;
-    if (mask & _glfw.wl.xkb.shiftMask)
-        mods |= GLFW_MOD_SHIFT;
-    if (mask & _glfw.wl.xkb.superMask)
-        mods |= GLFW_MOD_SUPER;
-    if (mask & _glfw.wl.xkb.capsLockMask)
-        mods |= GLFW_MOD_CAPS_LOCK;
-    if (mask & _glfw.wl.xkb.numLockMask)
-        mods |= GLFW_MOD_NUM_LOCK;
-
-    _glfw.wl.xkb.modifiers = mods;
-}
-
-#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
-static void keyboardHandleRepeatInfo(void* data,
-                                     struct wl_keyboard* keyboard,
-                                     int32_t rate,
-                                     int32_t delay)
-{
-    if (keyboard != _glfw.wl.keyboard)
-        return;
-
-    _glfw.wl.keyboardRepeatRate = rate;
-    _glfw.wl.keyboardRepeatDelay = delay;
-}
-#endif
-
-static const struct wl_keyboard_listener keyboardListener = {
-    keyboardHandleKeymap,
-    keyboardHandleEnter,
-    keyboardHandleLeave,
-    keyboardHandleKey,
-    keyboardHandleModifiers,
-#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
-    keyboardHandleRepeatInfo,
-#endif
-};
-
-static void seatHandleCapabilities(void* data,
-                                   struct wl_seat* seat,
-                                   enum wl_seat_capability caps)
-{
-    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)
-    {
-        _glfw.wl.pointer = wl_seat_get_pointer(seat);
-        wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);
-    }
-    else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
-    {
-        wl_pointer_destroy(_glfw.wl.pointer);
-        _glfw.wl.pointer = NULL;
-    }
-
-    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)
-    {
-        _glfw.wl.keyboard = wl_seat_get_keyboard(seat);
-        wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
-    }
-    else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
-    {
-        wl_keyboard_destroy(_glfw.wl.keyboard);
-        _glfw.wl.keyboard = NULL;
-    }
-}
-
-static void seatHandleName(void* data,
-                           struct wl_seat* seat,
-                           const char* name)
-{
-}
-
-static const struct wl_seat_listener seatListener = {
-    seatHandleCapabilities,
-    seatHandleName,
-};
-
-static void dataOfferHandleOffer(void* data,
-                                 struct wl_data_offer* dataOffer,
-                                 const char* mimeType)
-{
-}
-
-static const struct wl_data_offer_listener dataOfferListener = {
-    dataOfferHandleOffer,
-};
-
-static void dataDeviceHandleDataOffer(void* data,
-                                      struct wl_data_device* dataDevice,
-                                      struct wl_data_offer* id)
-{
-    if (_glfw.wl.dataOffer)
-        wl_data_offer_destroy(_glfw.wl.dataOffer);
-
-    _glfw.wl.dataOffer = id;
-    wl_data_offer_add_listener(_glfw.wl.dataOffer, &dataOfferListener, NULL);
-}
-
-static void dataDeviceHandleEnter(void* data,
-                                  struct wl_data_device* dataDevice,
-                                  uint32_t serial,
-                                  struct wl_surface *surface,
-                                  wl_fixed_t x,
-                                  wl_fixed_t y,
-                                  struct wl_data_offer *id)
-{
-}
-
-static void dataDeviceHandleLeave(void* data,
-                                  struct wl_data_device* dataDevice)
-{
-}
-
-static void dataDeviceHandleMotion(void* data,
-                                   struct wl_data_device* dataDevice,
-                                   uint32_t time,
-                                   wl_fixed_t x,
-                                   wl_fixed_t y)
-{
-}
-
-static void dataDeviceHandleDrop(void* data,
-                                 struct wl_data_device* dataDevice)
-{
-}
-
-static void dataDeviceHandleSelection(void* data,
-                                      struct wl_data_device* dataDevice,
-                                      struct wl_data_offer* id)
-{
-}
-
-static const struct wl_data_device_listener dataDeviceListener = {
-    dataDeviceHandleDataOffer,
-    dataDeviceHandleEnter,
-    dataDeviceHandleLeave,
-    dataDeviceHandleMotion,
-    dataDeviceHandleDrop,
-    dataDeviceHandleSelection,
-};
-
-static void wmBaseHandlePing(void* data,
+static void wmBaseHandlePing(void* userData,
                              struct xdg_wm_base* wmBase,
                              uint32_t serial)
 {
     xdg_wm_base_pong(wmBase, serial);
 }
 
-static const struct xdg_wm_base_listener wmBaseListener = {
+static const struct xdg_wm_base_listener wmBaseListener =
+{
     wmBaseHandlePing
 };
 
-static void registryHandleGlobal(void* data,
+static void registryHandleGlobal(void* userData,
                                  struct wl_registry* registry,
                                  uint32_t name,
                                  const char* interface,
@@ -784,10 +62,9 @@
 {
     if (strcmp(interface, "wl_compositor") == 0)
     {
-        _glfw.wl.compositorVersion = min(3, version);
         _glfw.wl.compositor =
             wl_registry_bind(registry, name, &wl_compositor_interface,
-                             _glfw.wl.compositorVersion);
+                             _glfw_min(3, version));
     }
     else if (strcmp(interface, "wl_subcompositor") == 0)
     {
@@ -799,11 +76,6 @@
         _glfw.wl.shm =
             wl_registry_bind(registry, name, &wl_shm_interface, 1);
     }
-    else if (strcmp(interface, "wl_shell") == 0)
-    {
-        _glfw.wl.shell =
-            wl_registry_bind(registry, name, &wl_shell_interface, 1);
-    }
     else if (strcmp(interface, "wl_output") == 0)
     {
         _glfwAddOutputWayland(name, version);
@@ -812,11 +84,10 @@
     {
         if (!_glfw.wl.seat)
         {
-            _glfw.wl.seatVersion = min(4, version);
             _glfw.wl.seat =
                 wl_registry_bind(registry, name, &wl_seat_interface,
-                                 _glfw.wl.seatVersion);
-            wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
+                                 _glfw_min(4, version));
+            _glfwAddSeatListenerWayland(_glfw.wl.seat);
         }
     }
     else if (strcmp(interface, "wl_data_device_manager") == 0)
@@ -869,16 +140,15 @@
     }
 }
 
-static void registryHandleGlobalRemove(void *data,
-                                       struct wl_registry *registry,
+static void registryHandleGlobalRemove(void* userData,
+                                       struct wl_registry* registry,
                                        uint32_t name)
 {
     int i;
-    _GLFWmonitor* monitor;
 
     for (i = 0; i < _glfw.monitorCount; ++i)
     {
-        monitor = _glfw.monitors[i];
+        _GLFWmonitor* monitor = _glfw.monitors[i];
         if (monitor->wl.name == name)
         {
             _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
@@ -888,11 +158,42 @@
 }
 
 
-static const struct wl_registry_listener registryListener = {
+static const struct wl_registry_listener registryListener =
+{
     registryHandleGlobal,
     registryHandleGlobalRemove
 };
 
+void libdecorHandleError(struct libdecor* context,
+                         enum libdecor_error error,
+                         const char* message)
+{
+    _glfwInputError(GLFW_PLATFORM_ERROR,
+                    "Wayland: libdecor error %u: %s",
+                    error, message);
+}
+
+static const struct libdecor_interface libdecorInterface =
+{
+    libdecorHandleError
+};
+
+static void libdecorReadyCallback(void* userData,
+                                  struct wl_callback* callback,
+                                  uint32_t time)
+{
+    _glfw.wl.libdecor.ready = GLFW_TRUE;
+
+    assert(_glfw.wl.libdecor.callback == callback);
+    wl_callback_destroy(_glfw.wl.libdecor.callback);
+    _glfw.wl.libdecor.callback = NULL;
+}
+
+static const struct wl_callback_listener libdecorReadyListener =
+{
+    libdecorReadyCallback
+};
+
 // Create key code translation tables
 //
 static void createKeyTables(void)
@@ -1028,6 +329,38 @@
     }
 }
 
+static GLFWbool loadCursorTheme(void)
+{
+    int cursorSize = 16;
+
+    const char* sizeString = getenv("XCURSOR_SIZE");
+    if (sizeString)
+    {
+        errno = 0;
+        const long cursorSizeLong = strtol(sizeString, NULL, 10);
+        if (errno == 0 && cursorSizeLong > 0 && cursorSizeLong < INT_MAX)
+            cursorSize = (int) cursorSizeLong;
+    }
+
+    const char* themeName = getenv("XCURSOR_THEME");
+
+    _glfw.wl.cursorTheme = wl_cursor_theme_load(themeName, cursorSize, _glfw.wl.shm);
+    if (!_glfw.wl.cursorTheme)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to load default cursor theme");
+        return GLFW_FALSE;
+    }
+
+    // If this happens to be NULL, we just fallback to the scale=1 version.
+    _glfw.wl.cursorThemeHiDPI =
+        wl_cursor_theme_load(themeName, cursorSize * 2, _glfw.wl.shm);
+
+    _glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor);
+    _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
+    return GLFW_TRUE;
+}
+
 
 //////////////////////////////////////////////////////////////////////////
 //////                       GLFW platform API                      //////
@@ -1035,17 +368,17 @@
 
 int _glfwPlatformInit(void)
 {
-    const char *cursorTheme;
-    const char *cursorSizeStr;
-    char *cursorSizeEnd;
-    long cursorSizeLong;
-    int cursorSize;
+    // These must be set before any failure checks
+    _glfw.wl.keyRepeatTimerfd = -1;
+    _glfw.wl.cursorTimerfd = -1;
+
+    _glfw.wl.tag = glfwGetVersionString();
 
     _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
     if (!_glfw.wl.cursor.handle)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to open libwayland-cursor");
+                        "Wayland: Failed to load libwayland-cursor");
         return GLFW_FALSE;
     }
 
@@ -1062,7 +395,7 @@
     if (!_glfw.wl.egl.handle)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to open libwayland-egl");
+                        "Wayland: Failed to load libwayland-egl");
         return GLFW_FALSE;
     }
 
@@ -1077,7 +410,7 @@
     if (!_glfw.wl.xkb.handle)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to open libxkbcommon");
+                        "Wayland: Failed to load libxkbcommon");
         return GLFW_FALSE;
     }
 
@@ -1103,10 +436,10 @@
         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
     _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
-    _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
     _glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout)
         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_layout");
+    _glfw.wl.xkb.state_mod_index_is_active = (PFN_xkb_state_mod_index_is_active)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_mod_index_is_active");
 
     _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
         _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
@@ -1131,6 +464,93 @@
         return GLFW_FALSE;
     }
 
+    if (_glfw.hints.init.wl.libdecorMode == GLFW_WAYLAND_PREFER_LIBDECOR)
+        _glfw.wl.libdecor.handle = _glfw_dlopen("libdecor-0.so.0");
+
+    if (_glfw.wl.libdecor.handle)
+    {
+        _glfw.wl.libdecor.libdecor_new_ = (PFN_libdecor_new)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_new");
+        _glfw.wl.libdecor.libdecor_unref_ = (PFN_libdecor_unref)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_unref");
+        _glfw.wl.libdecor.libdecor_get_fd_ = (PFN_libdecor_get_fd)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_get_fd");
+        _glfw.wl.libdecor.libdecor_dispatch_ = (PFN_libdecor_dispatch)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_dispatch");
+        _glfw.wl.libdecor.libdecor_decorate_ = (PFN_libdecor_decorate)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_decorate");
+        _glfw.wl.libdecor.libdecor_frame_unref_ = (PFN_libdecor_frame_unref)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unref");
+        _glfw.wl.libdecor.libdecor_frame_set_app_id_ = (PFN_libdecor_frame_set_app_id)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_app_id");
+        _glfw.wl.libdecor.libdecor_frame_set_title_ = (PFN_libdecor_frame_set_title)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_title");
+        _glfw.wl.libdecor.libdecor_frame_set_minimized_ = (PFN_libdecor_frame_set_minimized)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_minimized");
+        _glfw.wl.libdecor.libdecor_frame_set_fullscreen_ = (PFN_libdecor_frame_set_fullscreen)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_fullscreen");
+        _glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ = (PFN_libdecor_frame_unset_fullscreen)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unset_fullscreen");
+        _glfw.wl.libdecor.libdecor_frame_map_ = (PFN_libdecor_frame_map)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_map");
+        _glfw.wl.libdecor.libdecor_frame_commit_ = (PFN_libdecor_frame_commit)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_commit");
+        _glfw.wl.libdecor.libdecor_frame_set_min_content_size_ = (PFN_libdecor_frame_set_min_content_size)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_min_content_size");
+        _glfw.wl.libdecor.libdecor_frame_set_max_content_size_ = (PFN_libdecor_frame_set_max_content_size)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_max_content_size");
+        _glfw.wl.libdecor.libdecor_frame_set_maximized_ = (PFN_libdecor_frame_set_maximized)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_maximized");
+        _glfw.wl.libdecor.libdecor_frame_unset_maximized_ = (PFN_libdecor_frame_unset_maximized)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unset_maximized");
+        _glfw.wl.libdecor.libdecor_frame_set_capabilities_ = (PFN_libdecor_frame_set_capabilities)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_capabilities");
+        _glfw.wl.libdecor.libdecor_frame_unset_capabilities_ = (PFN_libdecor_frame_unset_capabilities)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unset_capabilities");
+        _glfw.wl.libdecor.libdecor_frame_set_visibility_ = (PFN_libdecor_frame_set_visibility)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_visibility");
+        _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ = (PFN_libdecor_frame_get_xdg_toplevel)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_get_xdg_toplevel");
+        _glfw.wl.libdecor.libdecor_configuration_get_content_size_ = (PFN_libdecor_configuration_get_content_size)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_configuration_get_content_size");
+        _glfw.wl.libdecor.libdecor_configuration_get_window_state_ = (PFN_libdecor_configuration_get_window_state)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_configuration_get_window_state");
+        _glfw.wl.libdecor.libdecor_state_new_ = (PFN_libdecor_state_new)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_state_new");
+        _glfw.wl.libdecor.libdecor_state_free_ = (PFN_libdecor_state_free)
+            _glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_state_free");
+
+        if (!_glfw.wl.libdecor.libdecor_new_ ||
+            !_glfw.wl.libdecor.libdecor_unref_ ||
+            !_glfw.wl.libdecor.libdecor_get_fd_ ||
+            !_glfw.wl.libdecor.libdecor_dispatch_ ||
+            !_glfw.wl.libdecor.libdecor_decorate_ ||
+            !_glfw.wl.libdecor.libdecor_frame_unref_ ||
+            !_glfw.wl.libdecor.libdecor_frame_set_app_id_ ||
+            !_glfw.wl.libdecor.libdecor_frame_set_title_ ||
+            !_glfw.wl.libdecor.libdecor_frame_set_minimized_ ||
+            !_glfw.wl.libdecor.libdecor_frame_set_fullscreen_ ||
+            !_glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ ||
+            !_glfw.wl.libdecor.libdecor_frame_map_ ||
+            !_glfw.wl.libdecor.libdecor_frame_commit_ ||
+            !_glfw.wl.libdecor.libdecor_frame_set_min_content_size_ ||
+            !_glfw.wl.libdecor.libdecor_frame_set_max_content_size_ ||
+            !_glfw.wl.libdecor.libdecor_frame_set_maximized_ ||
+            !_glfw.wl.libdecor.libdecor_frame_unset_maximized_ ||
+            !_glfw.wl.libdecor.libdecor_frame_set_capabilities_ ||
+            !_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ ||
+            !_glfw.wl.libdecor.libdecor_frame_set_visibility_ ||
+            !_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ ||
+            !_glfw.wl.libdecor.libdecor_configuration_get_content_size_ ||
+            !_glfw.wl.libdecor.libdecor_configuration_get_window_state_ ||
+            !_glfw.wl.libdecor.libdecor_state_new_ ||
+            !_glfw.wl.libdecor.libdecor_state_free_)
+        {
+            _glfw_dlclose(_glfw.wl.libdecor.handle);
+            memset(&_glfw.wl.libdecor, 0, sizeof(_glfw.wl.libdecor));
+        }
+    }
+
     _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
     wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
 
@@ -1157,53 +577,53 @@
 
     _glfwInitTimerPOSIX();
 
-    _glfw.wl.timerfd = -1;
-    if (_glfw.wl.seatVersion >= 4)
-        _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
-
-    if (_glfw.wl.pointer && _glfw.wl.shm)
+    if (_glfw.wl.libdecor.handle)
     {
-        cursorTheme = getenv("XCURSOR_THEME");
-        cursorSizeStr = getenv("XCURSOR_SIZE");
-        cursorSize = 32;
-        if (cursorSizeStr)
+        _glfw.wl.libdecor.context = libdecor_new(_glfw.wl.display, &libdecorInterface);
+        if (_glfw.wl.libdecor.context)
         {
-            errno = 0;
-            cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
-            if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
-                cursorSize = (int)cursorSizeLong;
+            // Perform an initial dispatch and flush to get the init started
+            libdecor_dispatch(_glfw.wl.libdecor.context, 0);
+
+            // Create sync point to "know" when libdecor is ready for use
+            _glfw.wl.libdecor.callback = wl_display_sync(_glfw.wl.display);
+            wl_callback_add_listener(_glfw.wl.libdecor.callback,
+                                     &libdecorReadyListener,
+                                     NULL);
         }
-        _glfw.wl.cursorTheme =
-            wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
-        if (!_glfw.wl.cursorTheme)
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Unable to load default cursor theme");
-            return GLFW_FALSE;
-        }
-        // If this happens to be NULL, we just fallback to the scale=1 version.
-        _glfw.wl.cursorThemeHiDPI =
-            wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
-        _glfw.wl.cursorSurface =
-            wl_compositor_create_surface(_glfw.wl.compositor);
-        _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
     }
 
+#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
+    if (wl_seat_get_version(_glfw.wl.seat) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
+    {
+        _glfw.wl.keyRepeatTimerfd =
+            timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
+    }
+#endif
+
+    if (!_glfw.wl.wmBase)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to find xdg-shell in your compositor");
+        return GLFW_FALSE;
+    }
+
+    if (!_glfw.wl.shm)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to find wl_shm in your compositor");
+        return GLFW_FALSE;
+    }
+
+    if (!loadCursorTheme())
+        return GLFW_FALSE;
+
     if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
     {
         _glfw.wl.dataDevice =
             wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
                                                    _glfw.wl.seat);
-        wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
-
-        _glfw.wl.clipboardSize = 4096;
-        _glfw.wl.clipboardString = calloc(_glfw.wl.clipboardSize, 1);
-        if (!_glfw.wl.clipboardString)
-        {
-            _glfwInputError(GLFW_OUT_OF_MEMORY,
-                            "Wayland: Unable to allocate clipboard memory");
-            return GLFW_FALSE;
-        }
+        _glfwAddDataDeviceListenerWayland(_glfw.wl.dataDevice);
     }
 
     return GLFW_TRUE;
@@ -1215,6 +635,19 @@
     _glfwTerminateJoysticksLinux();
 #endif
     _glfwTerminateEGL();
+    _glfwTerminateOSMesa();
+
+    if (_glfw.wl.libdecor.callback)
+        wl_callback_destroy(_glfw.wl.libdecor.callback);
+    if (_glfw.wl.libdecor.context)
+        libdecor_unref(_glfw.wl.libdecor.context);
+
+    if (_glfw.wl.libdecor.handle)
+    {
+        _glfw_dlclose(_glfw.wl.libdecor.handle);
+        _glfw.wl.libdecor.handle = NULL;
+    }
+
     if (_glfw.wl.egl.handle)
     {
         _glfw_dlclose(_glfw.wl.egl.handle);
@@ -1245,6 +678,11 @@
         _glfw.wl.cursor.handle = NULL;
     }
 
+    for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
+        wl_data_offer_destroy(_glfw.wl.offers[i].offer);
+
+    free(_glfw.wl.offers);
+
     if (_glfw.wl.cursorSurface)
         wl_surface_destroy(_glfw.wl.cursorSurface);
     if (_glfw.wl.subcompositor)
@@ -1253,20 +691,20 @@
         wl_compositor_destroy(_glfw.wl.compositor);
     if (_glfw.wl.shm)
         wl_shm_destroy(_glfw.wl.shm);
-    if (_glfw.wl.shell)
-        wl_shell_destroy(_glfw.wl.shell);
     if (_glfw.wl.viewporter)
         wp_viewporter_destroy(_glfw.wl.viewporter);
     if (_glfw.wl.decorationManager)
         zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
     if (_glfw.wl.wmBase)
         xdg_wm_base_destroy(_glfw.wl.wmBase);
-    if (_glfw.wl.dataSource)
-        wl_data_source_destroy(_glfw.wl.dataSource);
+    if (_glfw.wl.selectionOffer)
+        wl_data_offer_destroy(_glfw.wl.selectionOffer);
+    if (_glfw.wl.dragOffer)
+        wl_data_offer_destroy(_glfw.wl.dragOffer);
+    if (_glfw.wl.selectionSource)
+        wl_data_source_destroy(_glfw.wl.selectionSource);
     if (_glfw.wl.dataDevice)
         wl_data_device_destroy(_glfw.wl.dataDevice);
-    if (_glfw.wl.dataOffer)
-        wl_data_offer_destroy(_glfw.wl.dataOffer);
     if (_glfw.wl.dataDeviceManager)
         wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
     if (_glfw.wl.pointer)
@@ -1289,13 +727,12 @@
         wl_display_disconnect(_glfw.wl.display);
     }
 
-    if (_glfw.wl.timerfd >= 0)
-        close(_glfw.wl.timerfd);
+    if (_glfw.wl.keyRepeatTimerfd >= 0)
+        close(_glfw.wl.keyRepeatTimerfd);
     if (_glfw.wl.cursorTimerfd >= 0)
         close(_glfw.wl.cursorTimerfd);
 
     free(_glfw.wl.clipboardString);
-    free(_glfw.wl.clipboardSendString);
 }
 
 const char* _glfwPlatformGetVersionString(void)
diff --git a/src/wl_monitor.c b/src/wl_monitor.c
index d1448a2..6f785a3 100644
--- a/src/wl_monitor.c
+++ b/src/wl_monitor.c
@@ -35,7 +35,7 @@
 #include <math.h>
 
 
-static void outputHandleGeometry(void* data,
+static void outputHandleGeometry(void* userData,
                                  struct wl_output* output,
                                  int32_t x,
                                  int32_t y,
@@ -46,24 +46,25 @@
                                  const char* model,
                                  int32_t transform)
 {
-    struct _GLFWmonitor *monitor = data;
+    struct _GLFWmonitor* monitor = userData;
 
     monitor->wl.x = x;
     monitor->wl.y = y;
     monitor->widthMM = physicalWidth;
     monitor->heightMM = physicalHeight;
 
-    snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model);
+    if (strlen(monitor->name) == 0)
+        snprintf(monitor->name, sizeof(monitor->name), "%s %s", make, model);
 }
 
-static void outputHandleMode(void* data,
+static void outputHandleMode(void* userData,
                              struct wl_output* output,
                              uint32_t flags,
                              int32_t width,
                              int32_t height,
                              int32_t refresh)
 {
-    struct _GLFWmonitor *monitor = data;
+    struct _GLFWmonitor* monitor = userData;
     GLFWvidmode mode;
 
     mode.width = width;
@@ -82,9 +83,9 @@
         monitor->wl.currentMode = monitor->modeCount - 1;
 }
 
-static void outputHandleDone(void* data, struct wl_output* output)
+static void outputHandleDone(void* userData, struct wl_output* output)
 {
-    struct _GLFWmonitor *monitor = data;
+    struct _GLFWmonitor* monitor = userData;
 
     if (monitor->widthMM <= 0 || monitor->heightMM <= 0)
     {
@@ -94,23 +95,64 @@
         monitor->heightMM = (int) (mode->height * 25.4f / 96.f);
     }
 
+    for (int i = 0; i < _glfw.monitorCount; i++)
+    {
+        if (_glfw.monitors[i] == monitor)
+            return;
+    }
+
     _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
 }
 
-static void outputHandleScale(void* data,
+static void outputHandleScale(void* userData,
                               struct wl_output* output,
                               int32_t factor)
 {
-    struct _GLFWmonitor *monitor = data;
+    struct _GLFWmonitor* monitor = userData;
 
-    monitor->wl.scale = factor;
+    monitor->wl.contentScale = factor;
+
+    for (_GLFWwindow* window = _glfw.windowListHead; window; window = window->next)
+    {
+        for (int i = 0; i < window->wl.scaleCount; i++)
+        {
+            if (window->wl.scales[i].output == monitor->wl.output)
+            {
+                window->wl.scales[i].factor = monitor->wl.contentScale;
+                _glfwUpdateContentScaleWayland(window);
+                break;
+            }
+        }
+    }
 }
 
-static const struct wl_output_listener outputListener = {
+#ifdef WL_OUTPUT_NAME_SINCE_VERSION
+
+void outputHandleName(void* userData, struct wl_output* wl_output, const char* name)
+{
+    struct _GLFWmonitor* monitor = userData;
+
+    strncpy(monitor->name, name, sizeof(monitor->name) - 1);
+}
+
+void outputHandleDescription(void* userData,
+                             struct wl_output* wl_output,
+                             const char* description)
+{
+}
+
+#endif // WL_OUTPUT_NAME_SINCE_VERSION
+
+static const struct wl_output_listener outputListener =
+{
     outputHandleGeometry,
     outputHandleMode,
     outputHandleDone,
     outputHandleScale,
+#ifdef WL_OUTPUT_NAME_SINCE_VERSION
+    outputHandleName,
+    outputHandleDescription,
+#endif
 };
 
 
@@ -120,9 +162,6 @@
 
 void _glfwAddOutputWayland(uint32_t name, uint32_t version)
 {
-    _GLFWmonitor *monitor;
-    struct wl_output *output;
-
     if (version < 2)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR,
@@ -130,23 +169,26 @@
         return;
     }
 
-    // The actual name of this output will be set in the geometry handler.
-    monitor = _glfwAllocMonitor("", 0, 0);
+#ifdef WL_OUTPUT_NAME_SINCE_VERSION
+    version = _glfw_min(version, WL_OUTPUT_NAME_SINCE_VERSION);
+#else
+    version = 2;
+#endif
 
-    output = wl_registry_bind(_glfw.wl.registry,
-                              name,
-                              &wl_output_interface,
-                              2);
+    struct wl_output* output = wl_registry_bind(_glfw.wl.registry,
+                                                name,
+                                                &wl_output_interface,
+                                                version);
     if (!output)
-    {
-        _glfwFreeMonitor(monitor);
         return;
-    }
 
-    monitor->wl.scale = 1;
+    // The actual name of this output will be set in the geometry handler
+    _GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0);
+    monitor->wl.contentScale = 1;
     monitor->wl.output = output;
     monitor->wl.name = name;
 
+    wl_proxy_set_tag((struct wl_proxy*) output, &_glfw.wl.tag);
     wl_output_add_listener(output, &outputListener, monitor);
 }
 
@@ -173,9 +215,9 @@
                                          float* xscale, float* yscale)
 {
     if (xscale)
-        *xscale = (float) monitor->wl.scale;
+        *xscale = (float) monitor->wl.contentScale;
     if (yscale)
-        *yscale = (float) monitor->wl.scale;
+        *yscale = (float) monitor->wl.contentScale;
 }
 
 void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
diff --git a/src/wl_platform.h b/src/wl_platform.h
index dab4c0a..8affdd1 100644
--- a/src/wl_platform.h
+++ b/src/wl_platform.h
@@ -29,6 +29,8 @@
 #include <xkbcommon/xkbcommon-compose.h>
 #include <dlfcn.h>
 
+#include <stdbool.h>
+
 typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
 
 typedef struct VkWaylandSurfaceCreateInfoKHR
@@ -65,7 +67,7 @@
 #define _glfw_dlclose(handle) dlclose(handle)
 #define _glfw_dlsym(handle, name) dlsym(handle, name)
 
-#define _GLFW_EGL_NATIVE_WINDOW         ((EGLNativeWindowType) window->wl.native)
+#define _GLFW_EGL_NATIVE_WINDOW         ((EGLNativeWindowType) window->wl.egl.window)
 #define _GLFW_EGL_NATIVE_DISPLAY        ((EGLNativeDisplayType) _glfw.wl.display)
 
 #define _GLFW_PLATFORM_WINDOW_STATE         _GLFWwindowWayland  wl
@@ -115,8 +117,8 @@
 typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
 typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
 typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
-typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
 typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t);
+typedef int (* PFN_xkb_state_mod_index_is_active)(struct xkb_state*,xkb_mod_index_t,enum xkb_state_component);
 #define xkb_context_new _glfw.wl.xkb.context_new
 #define xkb_context_unref _glfw.wl.xkb.context_unref
 #define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
@@ -128,8 +130,8 @@
 #define xkb_state_unref _glfw.wl.xkb.state_unref
 #define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
 #define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
-#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
 #define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout
+#define xkb_state_mod_index_is_active _glfw.wl.xkb.state_mod_index_is_active
 
 typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
 typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
@@ -146,18 +148,129 @@
 #define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
 #define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
 
-#define _GLFW_DECORATION_WIDTH 4
-#define _GLFW_DECORATION_TOP 24
-#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
-#define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH)
+struct libdecor;
+struct libdecor_frame;
+struct libdecor_state;
+struct libdecor_configuration;
+
+enum libdecor_error
+{
+	LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
+	LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
+};
+
+enum libdecor_window_state
+{
+	LIBDECOR_WINDOW_STATE_NONE = 0,
+	LIBDECOR_WINDOW_STATE_ACTIVE = 1,
+	LIBDECOR_WINDOW_STATE_MAXIMIZED = 2,
+	LIBDECOR_WINDOW_STATE_FULLSCREEN = 4,
+	LIBDECOR_WINDOW_STATE_TILED_LEFT = 8,
+	LIBDECOR_WINDOW_STATE_TILED_RIGHT = 16,
+	LIBDECOR_WINDOW_STATE_TILED_TOP = 32,
+	LIBDECOR_WINDOW_STATE_TILED_BOTTOM = 64
+};
+
+enum libdecor_capabilities
+{
+	LIBDECOR_ACTION_MOVE = 1,
+	LIBDECOR_ACTION_RESIZE = 2,
+	LIBDECOR_ACTION_MINIMIZE = 4,
+	LIBDECOR_ACTION_FULLSCREEN = 8,
+	LIBDECOR_ACTION_CLOSE = 16
+};
+
+struct libdecor_interface
+{
+	void (* error)(struct libdecor*,enum libdecor_error,const char*);
+	void (* reserved0)(void);
+	void (* reserved1)(void);
+	void (* reserved2)(void);
+	void (* reserved3)(void);
+	void (* reserved4)(void);
+	void (* reserved5)(void);
+	void (* reserved6)(void);
+	void (* reserved7)(void);
+	void (* reserved8)(void);
+	void (* reserved9)(void);
+};
+
+struct libdecor_frame_interface
+{
+	void (* configure)(struct libdecor_frame*,struct libdecor_configuration*,void*);
+	void (* close)(struct libdecor_frame*,void*);
+	void (* commit)(struct libdecor_frame*,void*);
+	void (* dismiss_popup)(struct libdecor_frame*,const char*,void*);
+	void (* reserved0)(void);
+	void (* reserved1)(void);
+	void (* reserved2)(void);
+	void (* reserved3)(void);
+	void (* reserved4)(void);
+	void (* reserved5)(void);
+	void (* reserved6)(void);
+	void (* reserved7)(void);
+	void (* reserved8)(void);
+	void (* reserved9)(void);
+};
+
+typedef struct libdecor* (* PFN_libdecor_new)(struct wl_display*,const struct libdecor_interface*);
+typedef void (* PFN_libdecor_unref)(struct libdecor*);
+typedef int (* PFN_libdecor_get_fd)(struct libdecor*);
+typedef int (* PFN_libdecor_dispatch)(struct libdecor*,int);
+typedef struct libdecor_frame* (* PFN_libdecor_decorate)(struct libdecor*,struct wl_surface*,const struct libdecor_frame_interface*,void*);
+typedef void (* PFN_libdecor_frame_unref)(struct libdecor_frame*);
+typedef void (* PFN_libdecor_frame_set_app_id)(struct libdecor_frame*,const char*);
+typedef void (* PFN_libdecor_frame_set_title)(struct libdecor_frame*,const char*);
+typedef void (* PFN_libdecor_frame_set_minimized)(struct libdecor_frame*);
+typedef void (* PFN_libdecor_frame_set_fullscreen)(struct libdecor_frame*,struct wl_output*);
+typedef void (* PFN_libdecor_frame_unset_fullscreen)(struct libdecor_frame*);
+typedef void (* PFN_libdecor_frame_map)(struct libdecor_frame*);
+typedef void (* PFN_libdecor_frame_commit)(struct libdecor_frame*,struct libdecor_state*,struct libdecor_configuration*);
+typedef void (* PFN_libdecor_frame_set_min_content_size)(struct libdecor_frame*,int,int);
+typedef void (* PFN_libdecor_frame_set_max_content_size)(struct libdecor_frame*,int,int);
+typedef void (* PFN_libdecor_frame_set_maximized)(struct libdecor_frame*);
+typedef void (* PFN_libdecor_frame_unset_maximized)(struct libdecor_frame*);
+typedef void (* PFN_libdecor_frame_set_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
+typedef void (* PFN_libdecor_frame_unset_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
+typedef void (* PFN_libdecor_frame_set_visibility)(struct libdecor_frame*,bool visible);
+typedef struct xdg_toplevel* (* PFN_libdecor_frame_get_xdg_toplevel)(struct libdecor_frame*);
+typedef bool (* PFN_libdecor_configuration_get_content_size)(struct libdecor_configuration*,struct libdecor_frame*,int*,int*);
+typedef bool (* PFN_libdecor_configuration_get_window_state)(struct libdecor_configuration*,enum libdecor_window_state*);
+typedef struct libdecor_state* (* PFN_libdecor_state_new)(int,int);
+typedef void (* PFN_libdecor_state_free)(struct libdecor_state*);
+#define libdecor_new _glfw.wl.libdecor.libdecor_new_
+#define libdecor_unref _glfw.wl.libdecor.libdecor_unref_
+#define libdecor_get_fd _glfw.wl.libdecor.libdecor_get_fd_
+#define libdecor_dispatch _glfw.wl.libdecor.libdecor_dispatch_
+#define libdecor_decorate _glfw.wl.libdecor.libdecor_decorate_
+#define libdecor_frame_unref _glfw.wl.libdecor.libdecor_frame_unref_
+#define libdecor_frame_set_app_id _glfw.wl.libdecor.libdecor_frame_set_app_id_
+#define libdecor_frame_set_title _glfw.wl.libdecor.libdecor_frame_set_title_
+#define libdecor_frame_set_minimized _glfw.wl.libdecor.libdecor_frame_set_minimized_
+#define libdecor_frame_set_fullscreen _glfw.wl.libdecor.libdecor_frame_set_fullscreen_
+#define libdecor_frame_unset_fullscreen _glfw.wl.libdecor.libdecor_frame_unset_fullscreen_
+#define libdecor_frame_map _glfw.wl.libdecor.libdecor_frame_map_
+#define libdecor_frame_commit _glfw.wl.libdecor.libdecor_frame_commit_
+#define libdecor_frame_set_min_content_size _glfw.wl.libdecor.libdecor_frame_set_min_content_size_
+#define libdecor_frame_set_max_content_size _glfw.wl.libdecor.libdecor_frame_set_max_content_size_
+#define libdecor_frame_set_maximized _glfw.wl.libdecor.libdecor_frame_set_maximized_
+#define libdecor_frame_unset_maximized _glfw.wl.libdecor.libdecor_frame_unset_maximized_
+#define libdecor_frame_set_capabilities _glfw.wl.libdecor.libdecor_frame_set_capabilities_
+#define libdecor_frame_unset_capabilities _glfw.wl.libdecor.libdecor_frame_unset_capabilities_
+#define libdecor_frame_set_visibility _glfw.wl.libdecor.libdecor_frame_set_visibility_
+#define libdecor_frame_get_xdg_toplevel _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_
+#define libdecor_configuration_get_content_size _glfw.wl.libdecor.libdecor_configuration_get_content_size_
+#define libdecor_configuration_get_window_state _glfw.wl.libdecor.libdecor_configuration_get_window_state_
+#define libdecor_state_new _glfw.wl.libdecor.libdecor_state_new_
+#define libdecor_state_free _glfw.wl.libdecor.libdecor_state_free_
 
 typedef enum _GLFWdecorationSideWayland
 {
-    mainWindow,
-    topDecoration,
-    leftDecoration,
-    rightDecoration,
-    bottomDecoration,
+    GLFW_MAIN_WINDOW,
+    GLFW_TOP_DECORATION,
+    GLFW_LEFT_DECORATION,
+    GLFW_RIGHT_DECORATION,
+    GLFW_BOTTOM_DECORATION
 } _GLFWdecorationSideWayland;
 
 typedef struct _GLFWdecorationWayland
@@ -167,6 +280,19 @@
     struct wp_viewport*         viewport;
 } _GLFWdecorationWayland;
 
+typedef struct _GLFWofferWayland
+{
+    struct wl_data_offer*       offer;
+    GLFWbool                    text_plain_utf8;
+    GLFWbool                    text_uri_list;
+} _GLFWofferWayland;
+
+typedef struct _GLFWscaleWayland
+{
+    struct wl_output*           output;
+    int                         factor;
+} _GLFWscaleWayland;
+
 // Wayland-specific per-window data
 //
 typedef struct _GLFWwindowWayland
@@ -174,19 +300,37 @@
     int                         width, height;
     GLFWbool                    visible;
     GLFWbool                    maximized;
+    GLFWbool                    activated;
+    GLFWbool                    fullscreen;
     GLFWbool                    hovered;
     GLFWbool                    transparent;
     struct wl_surface*          surface;
-    struct wl_egl_window*       native;
-    struct wl_shell_surface*    shellSurface;
     struct wl_callback*         callback;
 
     struct {
+        struct wl_egl_window*   window;
+    } egl;
+
+    struct {
+        int                     width, height;
+        GLFWbool                maximized;
+        GLFWbool                iconified;
+        GLFWbool                activated;
+        GLFWbool                fullscreen;
+    } pending;
+
+    struct {
         struct xdg_surface*     surface;
         struct xdg_toplevel*    toplevel;
         struct zxdg_toplevel_decoration_v1* decoration;
+        uint32_t                decorationMode;
     } xdg;
 
+    struct {
+        struct libdecor_frame*  frame;
+        int                     mode;
+    } libdecor;
+
     _GLFWcursor*                currentCursor;
     double                      cursorPosX, cursorPosY;
 
@@ -194,25 +338,20 @@
 
     // We need to track the monitors the window spans on to calculate the
     // optimal scaling factor.
-    int                         scale;
-    _GLFWmonitor**              monitors;
-    int                         monitorsCount;
-    int                         monitorsSize;
+    int                         contentScale;
+    _GLFWscaleWayland*          scales;
+    int                         scaleCount;
+    int                         scaleSize;
 
-    struct {
-        struct zwp_relative_pointer_v1*    relativePointer;
-        struct zwp_locked_pointer_v1*      lockedPointer;
-    } pointerLock;
+    struct zwp_relative_pointer_v1* relativePointer;
+    struct zwp_locked_pointer_v1*   lockedPointer;
 
     struct zwp_idle_inhibitor_v1*          idleInhibitor;
 
-    GLFWbool                    wasFullscreen;
-
     struct {
-        GLFWbool                           serverSide;
         struct wl_buffer*                  buffer;
         _GLFWdecorationWayland             top, left, right, bottom;
-        int                                focus;
+        _GLFWdecorationSideWayland         focus;
     } decorations;
 } _GLFWwindowWayland;
 
@@ -224,15 +363,12 @@
     struct wl_registry*         registry;
     struct wl_compositor*       compositor;
     struct wl_subcompositor*    subcompositor;
-    struct wl_shell*            shell;
     struct wl_shm*              shm;
     struct wl_seat*             seat;
     struct wl_pointer*          pointer;
     struct wl_keyboard*         keyboard;
     struct wl_data_device_manager*          dataDeviceManager;
     struct wl_data_device*      dataDevice;
-    struct wl_data_offer*       dataOffer;
-    struct wl_data_source*      dataSource;
     struct xdg_wm_base*         wmBase;
     struct zxdg_decoration_manager_v1*      decorationManager;
     struct wp_viewporter*       viewporter;
@@ -240,8 +376,17 @@
     struct zwp_pointer_constraints_v1*      pointerConstraints;
     struct zwp_idle_inhibit_manager_v1*     idleInhibitManager;
 
-    int                         compositorVersion;
-    int                         seatVersion;
+    _GLFWofferWayland*          offers;
+    unsigned int                offerCount;
+
+    struct wl_data_offer*       selectionOffer;
+    struct wl_data_source*      selectionSource;
+
+    struct wl_data_offer*       dragOffer;
+    _GLFWwindow*                dragFocus;
+    uint32_t                    dragSerial;
+
+    const char*                 tag;
 
     struct wl_cursor_theme*     cursorTheme;
     struct wl_cursor_theme*     cursorThemeHiDPI;
@@ -251,15 +396,12 @@
     uint32_t                    serial;
     uint32_t                    pointerEnterSerial;
 
-    int32_t                     keyboardRepeatRate;
-    int32_t                     keyboardRepeatDelay;
-    int                         keyboardLastKey;
-    int                         keyboardLastScancode;
+    int                         keyRepeatTimerfd;
+    int32_t                     keyRepeatRate;
+    int32_t                     keyRepeatDelay;
+    int                         keyRepeatScancode;
+
     char*                       clipboardString;
-    size_t                      clipboardSize;
-    char*                       clipboardSendString;
-    size_t                      clipboardSendSize;
-    int                         timerfd;
     short int                   keycodes[256];
     short int                   scancodes[GLFW_KEY_LAST + 1];
     char                        keynames[GLFW_KEY_LAST + 1][5];
@@ -271,12 +413,12 @@
         struct xkb_state*       state;
         struct xkb_compose_state* composeState;
 
-        xkb_mod_mask_t          controlMask;
-        xkb_mod_mask_t          altMask;
-        xkb_mod_mask_t          shiftMask;
-        xkb_mod_mask_t          superMask;
-        xkb_mod_mask_t          capsLockMask;
-        xkb_mod_mask_t          numLockMask;
+        xkb_mod_index_t         controlIndex;
+        xkb_mod_index_t         altIndex;
+        xkb_mod_index_t         shiftIndex;
+        xkb_mod_index_t         superIndex;
+        xkb_mod_index_t         capsLockIndex;
+        xkb_mod_index_t         numLockIndex;
         unsigned int            modifiers;
 
         PFN_xkb_context_new context_new;
@@ -290,8 +432,8 @@
         PFN_xkb_state_unref state_unref;
         PFN_xkb_state_key_get_syms state_key_get_syms;
         PFN_xkb_state_update_mask state_update_mask;
-        PFN_xkb_state_serialize_mods state_serialize_mods;
         PFN_xkb_state_key_get_layout state_key_get_layout;
+        PFN_xkb_state_mod_index_is_active state_mod_index_is_active;
 
         PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
         PFN_xkb_compose_table_unref compose_table_unref;
@@ -321,6 +463,38 @@
         PFN_wl_egl_window_destroy window_destroy;
         PFN_wl_egl_window_resize window_resize;
     } egl;
+
+    struct {
+        void*                   handle;
+        struct libdecor*        context;
+        struct wl_callback*     callback;
+        GLFWbool                ready;
+        PFN_libdecor_new        libdecor_new_;
+        PFN_libdecor_unref      libdecor_unref_;
+        PFN_libdecor_get_fd     libdecor_get_fd_;
+        PFN_libdecor_dispatch   libdecor_dispatch_;
+        PFN_libdecor_decorate   libdecor_decorate_;
+        PFN_libdecor_frame_unref libdecor_frame_unref_;
+        PFN_libdecor_frame_set_app_id libdecor_frame_set_app_id_;
+        PFN_libdecor_frame_set_title libdecor_frame_set_title_;
+        PFN_libdecor_frame_set_minimized libdecor_frame_set_minimized_;
+        PFN_libdecor_frame_set_fullscreen libdecor_frame_set_fullscreen_;
+        PFN_libdecor_frame_unset_fullscreen libdecor_frame_unset_fullscreen_;
+        PFN_libdecor_frame_map libdecor_frame_map_;
+        PFN_libdecor_frame_commit libdecor_frame_commit_;
+        PFN_libdecor_frame_set_min_content_size libdecor_frame_set_min_content_size_;
+        PFN_libdecor_frame_set_max_content_size libdecor_frame_set_max_content_size_;
+        PFN_libdecor_frame_set_maximized libdecor_frame_set_maximized_;
+        PFN_libdecor_frame_unset_maximized libdecor_frame_unset_maximized_;
+        PFN_libdecor_frame_set_capabilities libdecor_frame_set_capabilities_;
+        PFN_libdecor_frame_unset_capabilities libdecor_frame_unset_capabilities_;
+        PFN_libdecor_frame_set_visibility libdecor_frame_set_visibility_;
+        PFN_libdecor_frame_get_xdg_toplevel libdecor_frame_get_xdg_toplevel_;
+        PFN_libdecor_configuration_get_content_size libdecor_configuration_get_content_size_;
+        PFN_libdecor_configuration_get_window_state libdecor_configuration_get_window_state_;
+        PFN_libdecor_state_new libdecor_state_new_;
+        PFN_libdecor_state_free libdecor_state_free_;
+    } libdecor;
 } _GLFWlibraryWayland;
 
 // Wayland-specific per-monitor data
@@ -333,7 +507,7 @@
 
     int                         x;
     int                         y;
-    int                         scale;
+    int                         contentScale;
 } _GLFWmonitorWayland;
 
 // Wayland-specific per-cursor data
@@ -348,7 +522,9 @@
     int                         currentImage;
 } _GLFWcursorWayland;
 
-
 void _glfwAddOutputWayland(uint32_t name, uint32_t version);
-GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode);
+void _glfwUpdateContentScaleWayland(_GLFWwindow* window);
+
+void _glfwAddSeatListenerWayland(struct wl_seat* seat);
+void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device);
 
diff --git a/src/wl_window.c b/src/wl_window.c
index 9c9e910..2e5f386 100644
--- a/src/wl_window.c
+++ b/src/wl_window.c
@@ -33,6 +33,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
+#include <assert.h>
 #include <unistd.h>
 #include <string.h>
 #include <fcntl.h>
@@ -42,71 +43,8 @@
 #include <signal.h>
 #include <time.h>
 
-static void shellSurfaceHandlePing(void* data,
-                                   struct wl_shell_surface* shellSurface,
-                                   uint32_t serial)
-{
-    wl_shell_surface_pong(shellSurface, serial);
-}
-
-static void shellSurfaceHandleConfigure(void* data,
-                                        struct wl_shell_surface* shellSurface,
-                                        uint32_t edges,
-                                        int32_t width,
-                                        int32_t height)
-{
-    _GLFWwindow* window = data;
-    float aspectRatio;
-    float targetRatio;
-
-    if (!window->monitor)
-    {
-        if (_glfw.wl.viewporter && window->decorated)
-        {
-            width -= _GLFW_DECORATION_HORIZONTAL;
-            height -= _GLFW_DECORATION_VERTICAL;
-        }
-        if (width < 1)
-            width = 1;
-        if (height < 1)
-            height = 1;
-
-        if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
-        {
-            aspectRatio = (float)width / (float)height;
-            targetRatio = (float)window->numer / (float)window->denom;
-            if (aspectRatio < targetRatio)
-                height = width / targetRatio;
-            else if (aspectRatio > targetRatio)
-                width = height * targetRatio;
-        }
-
-        if (window->minwidth != GLFW_DONT_CARE && width < window->minwidth)
-            width = window->minwidth;
-        else if (window->maxwidth != GLFW_DONT_CARE && width > window->maxwidth)
-            width = window->maxwidth;
-
-        if (window->minheight != GLFW_DONT_CARE && height < window->minheight)
-            height = window->minheight;
-        else if (window->maxheight != GLFW_DONT_CARE && height > window->maxheight)
-            height = window->maxheight;
-    }
-
-    _glfwInputWindowSize(window, width, height);
-    _glfwPlatformSetWindowSize(window, width, height);
-    _glfwInputWindowDamage(window);
-}
-
-static void shellSurfaceHandlePopupDone(void* data,
-                                        struct wl_shell_surface* shellSurface)
-{
-}
-
-static const struct wl_shell_surface_listener shellSurfaceListener = {
-    shellSurfaceHandlePing,
-    shellSurfaceHandleConfigure,
-    shellSurfaceHandlePopupDone
-};
+#define GLFW_BORDER_SIZE    4
+#define GLFW_CAPTION_HEIGHT 24
 
 static int createTmpfileCloexec(char* tmpname)
 {
@@ -198,37 +136,34 @@
 
 static struct wl_buffer* createShmBuffer(const GLFWimage* image)
 {
-    struct wl_shm_pool* pool;
-    struct wl_buffer* buffer;
-    int stride = image->width * 4;
-    int length = image->width * image->height * 4;
-    void* data;
-    int fd, i;
+    const int stride = image->width * 4;
+    const int length = image->width * image->height * 4;
 
-    fd = createAnonymousFile(length);
+    const int fd = createAnonymousFile(length);
     if (fd < 0)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Creating a buffer file for %d B failed: %s",
+                        "Wayland: Failed to create buffer file of size %d: %s",
                         length, strerror(errno));
         return NULL;
     }
 
-    data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+    void* data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     if (data == MAP_FAILED)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: mmap failed: %s", strerror(errno));
+                        "Wayland: Failed to map file: %s", strerror(errno));
         close(fd);
         return NULL;
     }
 
-    pool = wl_shm_create_pool(_glfw.wl.shm, fd, length);
+    struct wl_shm_pool* pool = wl_shm_create_pool(_glfw.wl.shm, fd, length);
 
     close(fd);
+
     unsigned char* source = (unsigned char*) image->pixels;
     unsigned char* target = data;
-    for (i = 0;  i < image->width * image->height;  i++, source += 4)
+    for (int i = 0;  i < image->width * image->height;  i++, source += 4)
     {
         unsigned int alpha = source[3];
 
@@ -238,7 +173,7 @@
         *target++ = (unsigned char) alpha;
     }
 
-    buffer =
+    struct wl_buffer* buffer =
         wl_shm_pool_create_buffer(pool, 0,
                                   image->width,
                                   image->height,
@@ -296,15 +231,16 @@
     }
 }
 
-static void createDecoration(_GLFWdecorationWayland* decoration,
-                             struct wl_surface* parent,
-                             struct wl_buffer* buffer, GLFWbool opaque,
-                             int x, int y,
-                             int width, int height)
+static void createFallbackDecoration(_GLFWwindow* window,
+                                     _GLFWdecorationWayland* decoration,
+                                     struct wl_surface* parent,
+                                     struct wl_buffer* buffer,
+                                     int x, int y,
+                                     int width, int height)
 {
-    struct wl_region* region;
-
     decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor);
+    wl_surface_set_user_data(decoration->surface, window);
+    wl_proxy_set_tag((struct wl_proxy*) decoration->surface, &_glfw.wl.tag);
     decoration->subsurface =
         wl_subcompositor_get_subsurface(_glfw.wl.subcompositor,
                                         decoration->surface, parent);
@@ -314,25 +250,19 @@
     wp_viewport_set_destination(decoration->viewport, width, height);
     wl_surface_attach(decoration->surface, buffer, 0, 0);
 
-    if (opaque)
-    {
-        region = wl_compositor_create_region(_glfw.wl.compositor);
-        wl_region_add(region, 0, 0, width, height);
-        wl_surface_set_opaque_region(decoration->surface, region);
-        wl_surface_commit(decoration->surface);
-        wl_region_destroy(region);
-    }
-    else
-        wl_surface_commit(decoration->surface);
+    struct wl_region* region = wl_compositor_create_region(_glfw.wl.compositor);
+    wl_region_add(region, 0, 0, width, height);
+    wl_surface_set_opaque_region(decoration->surface, region);
+    wl_surface_commit(decoration->surface);
+    wl_region_destroy(region);
 }
 
-static void createDecorations(_GLFWwindow* window)
+static void createFallbackDecorations(_GLFWwindow* window)
 {
     unsigned char data[] = { 224, 224, 224, 255 };
     const GLFWimage image = { 1, 1, data };
-    GLFWbool opaque = (data[3] == 255);
 
-    if (!_glfw.wl.viewporter || !window->decorated || window->wl.decorations.serverSide)
+    if (!_glfw.wl.viewporter)
         return;
 
     if (!window->wl.decorations.buffer)
@@ -340,25 +270,25 @@
     if (!window->wl.decorations.buffer)
         return;
 
-    createDecoration(&window->wl.decorations.top, window->wl.surface,
-                     window->wl.decorations.buffer, opaque,
-                     0, -_GLFW_DECORATION_TOP,
-                     window->wl.width, _GLFW_DECORATION_TOP);
-    createDecoration(&window->wl.decorations.left, window->wl.surface,
-                     window->wl.decorations.buffer, opaque,
-                     -_GLFW_DECORATION_WIDTH, -_GLFW_DECORATION_TOP,
-                     _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
-    createDecoration(&window->wl.decorations.right, window->wl.surface,
-                     window->wl.decorations.buffer, opaque,
-                     window->wl.width, -_GLFW_DECORATION_TOP,
-                     _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
-    createDecoration(&window->wl.decorations.bottom, window->wl.surface,
-                     window->wl.decorations.buffer, opaque,
-                     -_GLFW_DECORATION_WIDTH, window->wl.height,
-                     window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);
+    createFallbackDecoration(window, &window->wl.decorations.top, window->wl.surface,
+                             window->wl.decorations.buffer,
+                             0, -GLFW_CAPTION_HEIGHT,
+                             window->wl.width, GLFW_CAPTION_HEIGHT);
+    createFallbackDecoration(window, &window->wl.decorations.left, window->wl.surface,
+                             window->wl.decorations.buffer,
+                             -GLFW_BORDER_SIZE, -GLFW_CAPTION_HEIGHT,
+                             GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
+    createFallbackDecoration(window, &window->wl.decorations.right, window->wl.surface,
+                             window->wl.decorations.buffer,
+                             window->wl.width, -GLFW_CAPTION_HEIGHT,
+                             GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
+    createFallbackDecoration(window, &window->wl.decorations.bottom, window->wl.surface,
+                             window->wl.decorations.buffer,
+                             -GLFW_BORDER_SIZE, window->wl.height,
+                             window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE);
 }
 
-static void destroyDecoration(_GLFWdecorationWayland* decoration)
+static void destroyFallbackDecoration(_GLFWdecorationWayland* decoration)
 {
     if (decoration->subsurface)
         wl_subsurface_destroy(decoration->subsurface);
@@ -371,32 +301,38 @@
     decoration->viewport = NULL;
 }
 
-static void destroyDecorations(_GLFWwindow* window)
+static void destroyFallbackDecorations(_GLFWwindow* window)
 {
-    destroyDecoration(&window->wl.decorations.top);
-    destroyDecoration(&window->wl.decorations.left);
-    destroyDecoration(&window->wl.decorations.right);
-    destroyDecoration(&window->wl.decorations.bottom);
+    destroyFallbackDecoration(&window->wl.decorations.top);
+    destroyFallbackDecoration(&window->wl.decorations.left);
+    destroyFallbackDecoration(&window->wl.decorations.right);
+    destroyFallbackDecoration(&window->wl.decorations.bottom);
 }
 
-static void xdgDecorationHandleConfigure(void* data,
+static void xdgDecorationHandleConfigure(void* userData,
                                          struct zxdg_toplevel_decoration_v1* decoration,
                                          uint32_t mode)
 {
-    _GLFWwindow* window = data;
+    _GLFWwindow* window = userData;
 
-    window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
+    window->wl.xdg.decorationMode = mode;
 
-    if (!window->wl.decorations.serverSide)
-        createDecorations(window);
+    if (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE)
+    {
+        if (window->decorated && !window->monitor)
+            createFallbackDecorations(window);
+    }
+    else
+        destroyFallbackDecorations(window);
 }
 
-static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = {
+static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener =
+{
     xdgDecorationHandleConfigure,
 };
 
 // Makes the surface considered as XRGB instead of ARGB.
-static void setOpaqueRegion(_GLFWwindow* window)
+static void setContentAreaOpaque(_GLFWwindow* window)
 {
     struct wl_region* region;
 
@@ -406,117 +342,124 @@
 
     wl_region_add(region, 0, 0, window->wl.width, window->wl.height);
     wl_surface_set_opaque_region(window->wl.surface, region);
-    wl_surface_commit(window->wl.surface);
     wl_region_destroy(region);
 }
 
 
 static void resizeWindow(_GLFWwindow* window)
 {
-    int scale = window->wl.scale;
+    int scale = window->wl.contentScale;
     int scaledWidth = window->wl.width * scale;
     int scaledHeight = window->wl.height * scale;
-    wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
+
+    if (window->wl.egl.window)
+        wl_egl_window_resize(window->wl.egl.window, scaledWidth, scaledHeight, 0, 0);
     if (!window->wl.transparent)
-        setOpaqueRegion(window);
+        setContentAreaOpaque(window);
     _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
-    _glfwInputWindowContentScale(window, scale, scale);
 
     if (!window->wl.decorations.top.surface)
         return;
 
-    // Top decoration.
     wp_viewport_set_destination(window->wl.decorations.top.viewport,
-                                window->wl.width, _GLFW_DECORATION_TOP);
+                                window->wl.width, GLFW_CAPTION_HEIGHT);
     wl_surface_commit(window->wl.decorations.top.surface);
 
-    // Left decoration.
     wp_viewport_set_destination(window->wl.decorations.left.viewport,
-                                _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
+                                GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
     wl_surface_commit(window->wl.decorations.left.surface);
 
-    // Right decoration.
     wl_subsurface_set_position(window->wl.decorations.right.subsurface,
-                               window->wl.width, -_GLFW_DECORATION_TOP);
+                               window->wl.width, -GLFW_CAPTION_HEIGHT);
     wp_viewport_set_destination(window->wl.decorations.right.viewport,
-                                _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
+                                GLFW_BORDER_SIZE, window->wl.height + GLFW_CAPTION_HEIGHT);
     wl_surface_commit(window->wl.decorations.right.surface);
 
-    // Bottom decoration.
     wl_subsurface_set_position(window->wl.decorations.bottom.subsurface,
-                               -_GLFW_DECORATION_WIDTH, window->wl.height);
+                               -GLFW_BORDER_SIZE, window->wl.height);
     wp_viewport_set_destination(window->wl.decorations.bottom.viewport,
-                                window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);
+                                window->wl.width + GLFW_BORDER_SIZE * 2, GLFW_BORDER_SIZE);
     wl_surface_commit(window->wl.decorations.bottom.surface);
 }
 
-static void checkScaleChange(_GLFWwindow* window)
+void _glfwUpdateContentScaleWayland(_GLFWwindow* window)
 {
-    // Check if we will be able to set the buffer scale or not.
-    if (_glfw.wl.compositorVersion < 3)
+    if (wl_compositor_get_version(_glfw.wl.compositor) <
+        WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
+    {
         return;
+    }
 
     // Get the scale factor from the highest scale monitor.
     int maxScale = 1;
 
-    for (int i = 0; i < window->wl.monitorsCount; i++)
-    {
-        const int scale = window->wl.monitors[i]->wl.scale;
-        if (maxScale < scale)
-            maxScale = scale;
-    }
+    for (int i = 0; i < window->wl.scaleCount; i++)
+        maxScale = _glfw_max(window->wl.scales[i].factor, maxScale);
 
     // Only change the framebuffer size if the scale changed.
-    if (window->wl.scale != maxScale)
+    if (window->wl.contentScale != maxScale)
     {
-        window->wl.scale = maxScale;
+        window->wl.contentScale = maxScale;
         wl_surface_set_buffer_scale(window->wl.surface, maxScale);
+        _glfwInputWindowContentScale(window, maxScale, maxScale);
         resizeWindow(window);
+
+        if (window->wl.visible)
+            _glfwInputWindowDamage(window);
     }
 }
 
-static void surfaceHandleEnter(void *data,
-                               struct wl_surface *surface,
-                               struct wl_output *output)
+static void surfaceHandleEnter(void* userData,
+                               struct wl_surface* surface,
+                               struct wl_output* output)
 {
-    _GLFWwindow* window = data;
-    _GLFWmonitor* monitor = wl_output_get_user_data(output);
+    if (wl_proxy_get_tag((struct wl_proxy*) output) != &_glfw.wl.tag)
+        return;
 
-    if (window->wl.monitorsCount + 1 > window->wl.monitorsSize)
+    _GLFWwindow* window = userData;
+    _GLFWmonitor* monitor = wl_output_get_user_data(output);
+    if (!window || !monitor)
+        return;
+
+    if (window->wl.scaleCount + 1 > window->wl.scaleSize)
     {
-        ++window->wl.monitorsSize;
-        window->wl.monitors =
-            realloc(window->wl.monitors,
-                    window->wl.monitorsSize * sizeof(_GLFWmonitor*));
+        window->wl.scaleSize++;
+        window->wl.scales =
+            realloc(window->wl.scales,
+                    window->wl.scaleSize * sizeof(_GLFWscaleWayland));
     }
 
-    window->wl.monitors[window->wl.monitorsCount++] = monitor;
+    window->wl.scaleCount++;
+    window->wl.scales[window->wl.scaleCount - 1].factor = monitor->wl.contentScale;
+    window->wl.scales[window->wl.scaleCount - 1].output = output;
 
-    checkScaleChange(window);
+    _glfwUpdateContentScaleWayland(window);
 }
 
-static void surfaceHandleLeave(void *data,
-                               struct wl_surface *surface,
-                               struct wl_output *output)
+static void surfaceHandleLeave(void* userData,
+                               struct wl_surface* surface,
+                               struct wl_output* output)
 {
-    _GLFWwindow* window = data;
-    _GLFWmonitor* monitor = wl_output_get_user_data(output);
-    GLFWbool found;
-    int i;
+    if (wl_proxy_get_tag((struct wl_proxy*) output) != &_glfw.wl.tag)
+        return;
 
-    for (i = 0, found = GLFW_FALSE; i < window->wl.monitorsCount - 1; ++i)
+    _GLFWwindow* window = userData;
+
+    for (int i = 0; i < window->wl.scaleCount; i++)
     {
-        if (monitor == window->wl.monitors[i])
-            found = GLFW_TRUE;
-        if (found)
-            window->wl.monitors[i] = window->wl.monitors[i + 1];
+        if (window->wl.scales[i].output == output)
+        {
+            window->wl.scales[i] = window->wl.scales[window->wl.scaleCount - 1];
+            window->wl.scaleCount--;
+            break;
+        }
     }
-    window->wl.monitors[--window->wl.monitorsCount] = NULL;
 
-    checkScaleChange(window);
+    _glfwUpdateContentScaleWayland(window);
 }
 
-static const struct wl_surface_listener surfaceListener = {
+static const struct wl_surface_listener surfaceListener =
+{
     surfaceHandleEnter,
     surfaceHandleLeave
 };
@@ -530,7 +473,7 @@
                 _glfw.wl.idleInhibitManager, window->wl.surface);
         if (!window->wl.idleInhibitor)
             _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Idle inhibitor creation failed");
+                            "Wayland: Failed to create idle inhibitor");
     }
     else if (!enable && window->wl.idleInhibitor)
     {
@@ -539,164 +482,404 @@
     }
 }
 
-static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
-                          int refreshRate)
+// Make the specified window and its video mode active on its monitor
+//
+static void acquireMonitor(_GLFWwindow* window)
 {
-    if (window->wl.xdg.toplevel)
+    if (window->wl.libdecor.frame)
     {
-        xdg_toplevel_set_fullscreen(
-            window->wl.xdg.toplevel,
-            monitor->wl.output);
+        libdecor_frame_set_fullscreen(window->wl.libdecor.frame,
+                                      window->monitor->wl.output);
     }
-    else if (window->wl.shellSurface)
+    else if (window->wl.xdg.toplevel)
     {
-        wl_shell_surface_set_fullscreen(
-            window->wl.shellSurface,
-            WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
-            refreshRate * 1000, // Convert Hz to mHz.
-            monitor->wl.output);
+        xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,
+                                    window->monitor->wl.output);
     }
+
     setIdleInhibitor(window, GLFW_TRUE);
-    if (!window->wl.decorations.serverSide)
-        destroyDecorations(window);
+
+    if (window->wl.decorations.top.surface)
+        destroyFallbackDecorations(window);
 }
 
-static GLFWbool createShellSurface(_GLFWwindow* window)
+// Remove the window and restore the original video mode
+//
+static void releaseMonitor(_GLFWwindow* window)
 {
-    if (!_glfw.wl.shell)
+    if (window->wl.libdecor.frame)
+        libdecor_frame_unset_fullscreen(window->wl.libdecor.frame);
+    else if (window->wl.xdg.toplevel)
+        xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
+
+    setIdleInhibitor(window, GLFW_FALSE);
+
+    if (!window->wl.libdecor.frame &&
+        window->wl.xdg.decorationMode != ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE)
     {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: wl_shell protocol not available");
-        return GLFW_FALSE;
+        if (window->decorated)
+            createFallbackDecorations(window);
     }
-
-    window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,
-                                                         window->wl.surface);
-    if (!window->wl.shellSurface)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Shell surface creation failed");
-        return GLFW_FALSE;
-    }
-
-    wl_shell_surface_add_listener(window->wl.shellSurface,
-                                  &shellSurfaceListener,
-                                  window);
-
-    if (window->wl.title)
-        wl_shell_surface_set_title(window->wl.shellSurface, window->wl.title);
-
-    if (window->monitor)
-    {
-        setFullscreen(window, window->monitor, 0);
-    }
-    else if (window->wl.maximized)
-    {
-        wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
-        setIdleInhibitor(window, GLFW_FALSE);
-        createDecorations(window);
-    }
-    else
-    {
-        wl_shell_surface_set_toplevel(window->wl.shellSurface);
-        setIdleInhibitor(window, GLFW_FALSE);
-        createDecorations(window);
-    }
-
-    wl_surface_commit(window->wl.surface);
-
-    return GLFW_TRUE;
 }
 
-static void xdgToplevelHandleConfigure(void* data,
+static void xdgToplevelHandleConfigure(void* userData,
                                        struct xdg_toplevel* toplevel,
                                        int32_t width,
                                        int32_t height,
                                        struct wl_array* states)
 {
-    _GLFWwindow* window = data;
-    float aspectRatio;
-    float targetRatio;
+    _GLFWwindow* window = userData;
     uint32_t* state;
-    GLFWbool maximized = GLFW_FALSE;
-    GLFWbool fullscreen = GLFW_FALSE;
-    GLFWbool activated = GLFW_FALSE;
+
+    window->wl.pending.activated  = GLFW_FALSE;
+    window->wl.pending.maximized  = GLFW_FALSE;
+    window->wl.pending.fullscreen = GLFW_FALSE;
 
     wl_array_for_each(state, states)
     {
         switch (*state)
         {
             case XDG_TOPLEVEL_STATE_MAXIMIZED:
-                maximized = GLFW_TRUE;
+                window->wl.pending.maximized = GLFW_TRUE;
                 break;
             case XDG_TOPLEVEL_STATE_FULLSCREEN:
-                fullscreen = GLFW_TRUE;
+                window->wl.pending.fullscreen = GLFW_TRUE;
                 break;
             case XDG_TOPLEVEL_STATE_RESIZING:
                 break;
             case XDG_TOPLEVEL_STATE_ACTIVATED:
-                activated = GLFW_TRUE;
+                window->wl.pending.activated = GLFW_TRUE;
                 break;
         }
     }
 
-    if (width != 0 && height != 0)
+    if (width && height)
     {
-        if (!maximized && !fullscreen)
+        if (window->wl.decorations.top.surface)
         {
-            if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
-            {
-                aspectRatio = (float)width / (float)height;
-                targetRatio = (float)window->numer / (float)window->denom;
-                if (aspectRatio < targetRatio)
-                    height = width / targetRatio;
-                else if (aspectRatio > targetRatio)
-                    width = height * targetRatio;
-            }
+            window->wl.pending.width  = _glfw_max(0, width - GLFW_BORDER_SIZE * 2);
+            window->wl.pending.height =
+                _glfw_max(0, height - GLFW_BORDER_SIZE - GLFW_CAPTION_HEIGHT);
         }
-
-        _glfwInputWindowSize(window, width, height);
-        _glfwPlatformSetWindowSize(window, width, height);
-        _glfwInputWindowDamage(window);
-    }
-
-    if (window->wl.wasFullscreen && window->autoIconify)
-    {
-        if (!activated || !fullscreen)
+        else
         {
-            _glfwPlatformIconifyWindow(window);
-            window->wl.wasFullscreen = GLFW_FALSE;
+            window->wl.pending.width  = width;
+            window->wl.pending.height = height;
         }
     }
-    if (fullscreen && activated)
-        window->wl.wasFullscreen = GLFW_TRUE;
+    else
+    {
+        window->wl.pending.width  = window->wl.width;
+        window->wl.pending.height = window->wl.height;
+    }
 }
 
-static void xdgToplevelHandleClose(void* data,
+static void xdgToplevelHandleClose(void* userData,
                                    struct xdg_toplevel* toplevel)
 {
-    _GLFWwindow* window = data;
+    _GLFWwindow* window = userData;
     _glfwInputWindowCloseRequest(window);
 }
 
-static const struct xdg_toplevel_listener xdgToplevelListener = {
+static const struct xdg_toplevel_listener xdgToplevelListener =
+{
     xdgToplevelHandleConfigure,
     xdgToplevelHandleClose
 };
 
-static void xdgSurfaceHandleConfigure(void* data,
+static void xdgSurfaceHandleConfigure(void* userData,
                                       struct xdg_surface* surface,
                                       uint32_t serial)
 {
+    _GLFWwindow* window = userData;
+
     xdg_surface_ack_configure(surface, serial);
+
+    if (window->wl.activated != window->wl.pending.activated)
+    {
+        window->wl.activated = window->wl.pending.activated;
+        if (!window->wl.activated)
+        {
+            if (window->monitor && window->autoIconify)
+                xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
+        }
+    }
+
+    if (window->wl.maximized != window->wl.pending.maximized)
+    {
+        window->wl.maximized = window->wl.pending.maximized;
+        _glfwInputWindowMaximize(window, window->wl.maximized);
+    }
+
+    window->wl.fullscreen = window->wl.pending.fullscreen;
+
+    int width  = window->wl.pending.width;
+    int height = window->wl.pending.height;
+
+    if (!window->wl.maximized && !window->wl.fullscreen)
+    {
+        if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
+        {
+            const float aspectRatio = (float) width / (float) height;
+            const float targetRatio = (float) window->numer / (float) window->denom;
+            if (aspectRatio < targetRatio)
+                height = width / targetRatio;
+            else if (aspectRatio > targetRatio)
+                width = height * targetRatio;
+        }
+    }
+
+    if (width != window->wl.width || height != window->wl.height)
+    {
+        window->wl.width = width;
+        window->wl.height = height;
+        resizeWindow(window);
+
+        _glfwInputWindowSize(window, width, height);
+
+        if (window->wl.visible)
+            _glfwInputWindowDamage(window);
+    }
+
+    if (!window->wl.visible)
+    {
+        // Allow the window to be mapped only if it either has no XDG
+        // decorations or they have already received a configure event
+        if (!window->wl.xdg.decoration || window->wl.xdg.decorationMode)
+        {
+            window->wl.visible = GLFW_TRUE;
+            _glfwInputWindowDamage(window);
+        }
+    }
 }
 
-static const struct xdg_surface_listener xdgSurfaceListener = {
+static const struct xdg_surface_listener xdgSurfaceListener =
+{
     xdgSurfaceHandleConfigure
 };
 
-static void setXdgDecorations(_GLFWwindow* window)
+void libdecorFrameHandleConfigure(struct libdecor_frame* frame,
+                                  struct libdecor_configuration* config,
+                                  void* userData)
 {
+    _GLFWwindow* window = userData;
+    int width, height;
+
+    enum libdecor_window_state windowState;
+    GLFWbool fullscreen, activated, maximized;
+
+    if (libdecor_configuration_get_window_state(config, &windowState))
+    {
+        fullscreen = (windowState & LIBDECOR_WINDOW_STATE_FULLSCREEN) != 0;
+        activated = (windowState & LIBDECOR_WINDOW_STATE_ACTIVE) != 0;
+        maximized = (windowState & LIBDECOR_WINDOW_STATE_MAXIMIZED) != 0;
+    }
+    else
+    {
+        fullscreen = window->wl.fullscreen;
+        activated = window->wl.activated;
+        maximized = window->wl.maximized;
+    }
+
+    if (!libdecor_configuration_get_content_size(config, frame, &width, &height))
+    {
+        width = window->wl.width;
+        height = window->wl.height;
+    }
+
+    if (!maximized && !fullscreen)
+    {
+        if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
+        {
+            const float aspectRatio = (float) width / (float) height;
+            const float targetRatio = (float) window->numer / (float) window->denom;
+            if (aspectRatio < targetRatio)
+                height = width / targetRatio;
+            else if (aspectRatio > targetRatio)
+                width = height * targetRatio;
+        }
+    }
+
+    struct libdecor_state* frameState = libdecor_state_new(width, height);
+    libdecor_frame_commit(frame, frameState, config);
+    libdecor_state_free(frameState);
+
+    if (window->wl.activated != activated)
+    {
+        window->wl.activated = activated;
+        if (!window->wl.activated)
+        {
+            if (window->monitor && window->autoIconify)
+                libdecor_frame_set_minimized(window->wl.libdecor.frame);
+        }
+    }
+
+    if (window->wl.maximized != maximized)
+    {
+        window->wl.maximized = maximized;
+        _glfwInputWindowMaximize(window, window->wl.maximized);
+    }
+
+    window->wl.fullscreen = fullscreen;
+
+    GLFWbool damaged = GLFW_FALSE;
+
+    if (!window->wl.visible)
+    {
+        window->wl.visible = GLFW_TRUE;
+        damaged = GLFW_TRUE;
+    }
+
+    if (width != window->wl.width || height != window->wl.height)
+    {
+        window->wl.width = width;
+        window->wl.height = height;
+        resizeWindow(window);
+
+        _glfwInputWindowSize(window, width, height);
+        damaged = GLFW_TRUE;
+    }
+
+    if (damaged)
+        _glfwInputWindowDamage(window);
+    else
+        wl_surface_commit(window->wl.surface);
+}
+
+void libdecorFrameHandleClose(struct libdecor_frame* frame, void* userData)
+{
+    _GLFWwindow* window = userData;
+    _glfwInputWindowCloseRequest(window);
+}
+
+void libdecorFrameHandleCommit(struct libdecor_frame* frame, void* userData)
+{
+    _GLFWwindow* window = userData;
+    wl_surface_commit(window->wl.surface);
+}
+
+void libdecorFrameHandleDismissPopup(struct libdecor_frame* frame,
+                                     const char* seatName,
+                                     void* userData)
+{
+}
+
+static const struct libdecor_frame_interface libdecorFrameInterface =
+{
+    libdecorFrameHandleConfigure,
+    libdecorFrameHandleClose,
+    libdecorFrameHandleCommit,
+    libdecorFrameHandleDismissPopup
+};
+
+static GLFWbool createLibdecorFrame(_GLFWwindow* window)
+{
+    // Allow libdecor to finish initialization of itself and its plugin
+    while (!_glfw.wl.libdecor.ready)
+        _glfwPlatformWaitEvents();
+
+    window->wl.libdecor.frame = libdecor_decorate(_glfw.wl.libdecor.context,
+                                                  window->wl.surface,
+                                                  &libdecorFrameInterface,
+                                                  window);
+    if (!window->wl.libdecor.frame)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to create libdecor frame");
+        return GLFW_FALSE;
+    }
+
+    struct libdecor_state* frameState =
+        libdecor_state_new(window->wl.width, window->wl.height);
+    libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
+    libdecor_state_free(frameState);
+
+    if (strlen(window->wl.title))
+        libdecor_frame_set_title(window->wl.libdecor.frame, window->wl.title);
+
+    if (window->minwidth != GLFW_DONT_CARE &&
+        window->minheight != GLFW_DONT_CARE)
+    {
+        libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
+                                            window->minwidth,
+                                            window->minheight);
+    }
+
+    if (window->maxwidth != GLFW_DONT_CARE &&
+        window->maxheight != GLFW_DONT_CARE)
+    {
+        libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
+                                            window->maxwidth,
+                                            window->maxheight);
+    }
+
+    if (!window->resizable)
+    {
+        libdecor_frame_unset_capabilities(window->wl.libdecor.frame,
+                                          LIBDECOR_ACTION_RESIZE);
+    }
+
+    if (window->monitor)
+    {
+        libdecor_frame_set_fullscreen(window->wl.libdecor.frame,
+                                      window->monitor->wl.output);
+        setIdleInhibitor(window, GLFW_TRUE);
+    }
+    else
+    {
+        if (window->wl.maximized)
+            libdecor_frame_set_maximized(window->wl.libdecor.frame);
+
+        if (!window->decorated)
+            libdecor_frame_set_visibility(window->wl.libdecor.frame, false);
+
+        setIdleInhibitor(window, GLFW_FALSE);
+    }
+
+    libdecor_frame_map(window->wl.libdecor.frame);
+    wl_display_roundtrip(_glfw.wl.display);
+    return GLFW_TRUE;
+}
+
+static GLFWbool createXdgShellObjects(_GLFWwindow* window)
+{
+    window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
+                                                         window->wl.surface);
+    if (!window->wl.xdg.surface)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to create xdg-surface for window");
+        return GLFW_FALSE;
+    }
+
+    xdg_surface_add_listener(window->wl.xdg.surface, &xdgSurfaceListener, window);
+
+    window->wl.xdg.toplevel = xdg_surface_get_toplevel(window->wl.xdg.surface);
+    if (!window->wl.xdg.toplevel)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to create xdg-toplevel for window");
+        return GLFW_FALSE;
+    }
+
+    xdg_toplevel_add_listener(window->wl.xdg.toplevel, &xdgToplevelListener, window);
+
+    if (window->wl.title)
+        xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
+
+    if (window->monitor)
+    {
+        xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel, window->monitor->wl.output);
+        setIdleInhibitor(window, GLFW_TRUE);
+    }
+    else
+    {
+        if (window->wl.maximized)
+            xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
+
+        setIdleInhibitor(window, GLFW_FALSE);
+    }
+
     if (_glfw.wl.decorationManager)
     {
         window->wl.xdg.decoration =
@@ -705,114 +888,115 @@
         zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration,
                                                  &xdgDecorationListener,
                                                  window);
-        zxdg_toplevel_decoration_v1_set_mode(
-            window->wl.xdg.decoration,
-            ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
+
+        uint32_t mode;
+
+        if (window->decorated)
+            mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
+        else
+            mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
+
+        zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode);
     }
     else
     {
-        window->wl.decorations.serverSide = GLFW_FALSE;
-        createDecorations(window);
+        if (window->decorated && !window->monitor)
+            createFallbackDecorations(window);
     }
-}
-
-static GLFWbool createXdgSurface(_GLFWwindow* window)
-{
-    window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
-                                                         window->wl.surface);
-    if (!window->wl.xdg.surface)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: xdg-surface creation failed");
-        return GLFW_FALSE;
-    }
-
-    xdg_surface_add_listener(window->wl.xdg.surface,
-                             &xdgSurfaceListener,
-                             window);
-
-    window->wl.xdg.toplevel = xdg_surface_get_toplevel(window->wl.xdg.surface);
-    if (!window->wl.xdg.toplevel)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: xdg-toplevel creation failed");
-        return GLFW_FALSE;
-    }
-
-    xdg_toplevel_add_listener(window->wl.xdg.toplevel,
-                              &xdgToplevelListener,
-                              window);
-
-    if (window->wl.title)
-        xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
 
     if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE)
-        xdg_toplevel_set_min_size(window->wl.xdg.toplevel,
-                                  window->minwidth, window->minheight);
-    if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
-        xdg_toplevel_set_max_size(window->wl.xdg.toplevel,
-                                  window->maxwidth, window->maxheight);
+    {
+        int minwidth  = window->minwidth;
+        int minheight = window->minheight;
 
-    if (window->monitor)
-    {
-        xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,
-                                    window->monitor->wl.output);
-        setIdleInhibitor(window, GLFW_TRUE);
+        if (window->wl.decorations.top.surface)
+        {
+            minwidth  += GLFW_BORDER_SIZE * 2;
+            minheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE;
+        }
+
+        xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);
     }
-    else if (window->wl.maximized)
+
+    if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
     {
-        xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
-        setIdleInhibitor(window, GLFW_FALSE);
-        setXdgDecorations(window);
-    }
-    else
-    {
-        setIdleInhibitor(window, GLFW_FALSE);
-        setXdgDecorations(window);
+        int maxwidth  = window->maxwidth;
+        int maxheight = window->maxheight;
+
+        if (window->wl.decorations.top.surface)
+        {
+            maxwidth  += GLFW_BORDER_SIZE * 2;
+            maxheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE;
+        }
+
+        xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);
     }
 
     wl_surface_commit(window->wl.surface);
     wl_display_roundtrip(_glfw.wl.display);
-
     return GLFW_TRUE;
 }
 
-static GLFWbool createSurface(_GLFWwindow* window,
-                              const _GLFWwndconfig* wndconfig,
-                              const _GLFWfbconfig* fbconfig)
+static GLFWbool createShellObjects(_GLFWwindow* window)
+{
+    if (_glfw.wl.libdecor.context)
+    {
+        if (createLibdecorFrame(window))
+            return GLFW_TRUE;
+    }
+
+    return createXdgShellObjects(window);
+}
+
+static void destroyShellObjects(_GLFWwindow* window)
+{
+    destroyFallbackDecorations(window);
+
+    if (window->wl.libdecor.frame)
+        libdecor_frame_unref(window->wl.libdecor.frame);
+
+    if (window->wl.xdg.decoration)
+        zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
+
+    if (window->wl.xdg.toplevel)
+        xdg_toplevel_destroy(window->wl.xdg.toplevel);
+
+    if (window->wl.xdg.surface)
+        xdg_surface_destroy(window->wl.xdg.surface);
+
+    window->wl.libdecor.frame = NULL;
+    window->wl.xdg.decoration = NULL;
+    window->wl.xdg.decorationMode = 0;
+    window->wl.xdg.toplevel = NULL;
+    window->wl.xdg.surface = NULL;
+}
+
+static GLFWbool createNativeSurface(_GLFWwindow* window,
+                                    const _GLFWwndconfig* wndconfig,
+                                    const _GLFWfbconfig* fbconfig)
 {
     window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
     if (!window->wl.surface)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create window surface");
         return GLFW_FALSE;
+    }
 
+    wl_proxy_set_tag((struct wl_proxy*) window->wl.surface, &_glfw.wl.tag);
     wl_surface_add_listener(window->wl.surface,
                             &surfaceListener,
                             window);
 
-    wl_surface_set_user_data(window->wl.surface, window);
-
-    window->wl.native = wl_egl_window_create(window->wl.surface,
-                                             wndconfig->width,
-                                             wndconfig->height);
-    if (!window->wl.native)
-        return GLFW_FALSE;
-
     window->wl.width = wndconfig->width;
     window->wl.height = wndconfig->height;
-    window->wl.scale = 1;
+    window->wl.contentScale = 1;
     window->wl.title = _glfw_strdup(wndconfig->title);
 
+    window->wl.maximized = wndconfig->maximized;
+
     window->wl.transparent = fbconfig->transparent;
     if (!window->wl.transparent)
-        setOpaqueRegion(window);
-
-    if (window->monitor || wndconfig->visible)
-    {
-        if (!createXdgSurface(window))
-            return GLFW_FALSE;
-
-        window->wl.visible = GLFW_TRUE;
-    }
+        setContentAreaOpaque(window);
 
     return GLFW_TRUE;
 }
@@ -820,7 +1004,7 @@
 static void setCursorImage(_GLFWwindow* window,
                            _GLFWcursorWayland* cursorWayland)
 {
-    struct itimerspec timer = {};
+    struct itimerspec timer = {0};
     struct wl_cursor* wlCursor = cursorWayland->cursor;
     struct wl_cursor_image* image;
     struct wl_buffer* buffer;
@@ -831,7 +1015,7 @@
         buffer = cursorWayland->buffer;
     else
     {
-        if (window->wl.scale > 1 && cursorWayland->cursorHiDPI)
+        if (window->wl.contentScale > 1 && cursorWayland->cursorHiDPI)
         {
             wlCursor = cursorWayland->cursorHiDPI;
             scale = 2;
@@ -867,7 +1051,7 @@
 {
     _GLFWcursor* cursor;
 
-    if (!window || window->wl.decorations.focus != mainWindow)
+    if (!window || window->wl.decorations.focus != GLFW_MAIN_WINDOW)
         return;
 
     cursor = window->wl.currentCursor;
@@ -898,20 +1082,77 @@
     return GLFW_TRUE;
 }
 
+static int translateKey(uint32_t scancode)
+{
+    if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
+        return _glfw.wl.keycodes[scancode];
+
+    return GLFW_KEY_UNKNOWN;
+}
+
+static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
+{
+    if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
+        return sym;
+    if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
+            != XKB_COMPOSE_FEED_ACCEPTED)
+        return sym;
+    switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
+    {
+        case XKB_COMPOSE_COMPOSED:
+            return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
+        case XKB_COMPOSE_COMPOSING:
+        case XKB_COMPOSE_CANCELLED:
+            return XKB_KEY_NoSymbol;
+        case XKB_COMPOSE_NOTHING:
+        default:
+            return sym;
+    }
+}
+
+static void inputText(_GLFWwindow* window, uint32_t scancode)
+{
+    const xkb_keysym_t* keysyms;
+    const xkb_keycode_t keycode = scancode + 8;
+
+    if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1)
+    {
+        const xkb_keysym_t keysym = composeSymbol(keysyms[0]);
+        const uint32_t codepoint = _glfwKeySym2Unicode(keysym);
+        if (codepoint != GLFW_INVALID_CODEPOINT)
+        {
+            const int mods = _glfw.wl.xkb.modifiers;
+            const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
+            _glfwInputChar(window, codepoint, mods, plain);
+        }
+    }
+}
+
 static void handleEvents(double* timeout)
 {
+#if defined(__linux__)
+    _glfwDetectJoystickConnectionLinux();
+#endif
+
     GLFWbool event = GLFW_FALSE;
-    struct pollfd fds[] =
+    struct pollfd fds[4] =
     {
         { wl_display_get_fd(_glfw.wl.display), POLLIN },
-        { _glfw.wl.timerfd, POLLIN },
+        { _glfw.wl.keyRepeatTimerfd, POLLIN },
         { _glfw.wl.cursorTimerfd, POLLIN },
+        { -1, POLLIN }
     };
 
+    if (_glfw.wl.libdecor.context)
+        fds[3].fd = libdecor_get_fd(_glfw.wl.libdecor.context);
+
     while (!event)
     {
         while (wl_display_prepare_read(_glfw.wl.display) != 0)
-            wl_display_dispatch_pending(_glfw.wl.display);
+        {
+            if (wl_display_dispatch_pending(_glfw.wl.display) > 0)
+                return;
+        }
 
         // If an error other than EAGAIN happens, we have likely been disconnected
         // from the Wayland session; try to handle that the best we can.
@@ -929,7 +1170,7 @@
             return;
         }
 
-        if (!waitForData(fds, 3, timeout))
+        if (!waitForData(fds, sizeof(fds) / sizeof(fds[0]), timeout))
         {
             wl_display_cancel_read(_glfw.wl.display);
             return;
@@ -948,17 +1189,16 @@
         {
             uint64_t repeats;
 
-            if (read(_glfw.wl.timerfd, &repeats, sizeof(repeats)) == 8)
+            if (read(_glfw.wl.keyRepeatTimerfd, &repeats, sizeof(repeats)) == 8)
             {
                 for (uint64_t i = 0; i < repeats; i++)
                 {
                     _glfwInputKey(_glfw.wl.keyboardFocus,
-                                  _glfw.wl.keyboardLastKey,
-                                  _glfw.wl.keyboardLastScancode,
+                                  translateKey(_glfw.wl.keyRepeatScancode),
+                                  _glfw.wl.keyRepeatScancode,
                                   GLFW_PRESS,
                                   _glfw.wl.xkb.modifiers);
-                    _glfwInputTextWayland(_glfw.wl.keyboardFocus,
-                                          _glfw.wl.keyboardLastScancode);
+                    inputText(_glfw.wl.keyboardFocus, _glfw.wl.keyRepeatScancode);
                 }
 
                 event = GLFW_TRUE;
@@ -970,14 +1210,834 @@
             uint64_t repeats;
 
             if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8)
-            {
                 incrementCursorImage(_glfw.wl.pointerFocus);
+        }
+
+        if (fds[3].revents & POLLIN)
+        {
+            if (libdecor_dispatch(_glfw.wl.libdecor.context, 0) > 0)
                 event = GLFW_TRUE;
-            }
         }
     }
 }
 
+// Reads the specified data offer as the specified MIME type
+//
+static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mimeType)
+{
+    int fds[2];
+
+    if (pipe2(fds, O_CLOEXEC) == -1)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to create pipe for data offer: %s",
+                        strerror(errno));
+        return NULL;
+    }
+
+    wl_data_offer_receive(offer, mimeType, fds[1]);
+    flushDisplay();
+    close(fds[1]);
+
+    char* string = NULL;
+    size_t size = 0;
+    size_t length = 0;
+
+    for (;;)
+    {
+        const size_t readSize = 4096;
+        const size_t requiredSize = length + readSize + 1;
+        if (requiredSize > size)
+        {
+            char* longer = realloc(string, requiredSize);
+            if (!longer)
+            {
+                _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
+                close(fds[0]);
+                return NULL;
+            }
+
+            string = longer;
+            size = requiredSize;
+        }
+
+        const ssize_t result = read(fds[0], string + length, readSize);
+        if (result == 0)
+            break;
+        else if (result == -1)
+        {
+            if (errno == EINTR)
+                continue;
+
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Wayland: Failed to read from data offer pipe: %s",
+                            strerror(errno));
+            close(fds[0]);
+            return NULL;
+        }
+
+        length += result;
+    }
+
+    close(fds[0]);
+
+    string[length] = '\0';
+    return string;
+}
+
+static void pointerHandleEnter(void* userData,
+                               struct wl_pointer* pointer,
+                               uint32_t serial,
+                               struct wl_surface* surface,
+                               wl_fixed_t sx,
+                               wl_fixed_t sy)
+{
+    // Happens in the case we just destroyed the surface.
+    if (!surface)
+        return;
+
+    if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
+        return;
+
+    _GLFWwindow* window = wl_surface_get_user_data(surface);
+
+    if (surface == window->wl.decorations.top.surface)
+        window->wl.decorations.focus = GLFW_TOP_DECORATION;
+    else if (surface == window->wl.decorations.left.surface)
+        window->wl.decorations.focus = GLFW_LEFT_DECORATION;
+    else if (surface == window->wl.decorations.right.surface)
+        window->wl.decorations.focus = GLFW_RIGHT_DECORATION;
+    else if (surface == window->wl.decorations.bottom.surface)
+        window->wl.decorations.focus = GLFW_BOTTOM_DECORATION;
+    else
+        window->wl.decorations.focus = GLFW_MAIN_WINDOW;
+
+    _glfw.wl.serial = serial;
+    _glfw.wl.pointerEnterSerial = serial;
+    _glfw.wl.pointerFocus = window;
+
+    window->wl.hovered = GLFW_TRUE;
+
+    _glfwPlatformSetCursor(window, window->wl.currentCursor);
+    _glfwInputCursorEnter(window, GLFW_TRUE);
+}
+
+static void pointerHandleLeave(void* userData,
+                               struct wl_pointer* pointer,
+                               uint32_t serial,
+                               struct wl_surface* surface)
+{
+    if (!surface)
+        return;
+
+    if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
+        return;
+
+    _GLFWwindow* window = _glfw.wl.pointerFocus;
+    if (!window)
+        return;
+
+    window->wl.hovered = GLFW_FALSE;
+
+    _glfw.wl.serial = serial;
+    _glfw.wl.pointerFocus = NULL;
+    _glfw.wl.cursorPreviousName = NULL;
+    _glfwInputCursorEnter(window, GLFW_FALSE);
+}
+
+static void pointerHandleMotion(void* userData,
+                                struct wl_pointer* pointer,
+                                uint32_t time,
+                                wl_fixed_t sx,
+                                wl_fixed_t sy)
+{
+    _GLFWwindow* window = _glfw.wl.pointerFocus;
+    if (!window)
+        return;
+
+    if (window->cursorMode == GLFW_CURSOR_DISABLED)
+        return;
+
+    const double xpos = wl_fixed_to_double(sx);
+    const double ypos = wl_fixed_to_double(sy);
+    window->wl.cursorPosX = xpos;
+    window->wl.cursorPosY = ypos;
+
+    const char* cursorName = NULL;
+
+    switch (window->wl.decorations.focus)
+    {
+        case GLFW_MAIN_WINDOW:
+            _glfw.wl.cursorPreviousName = NULL;
+            _glfwInputCursorPos(window, xpos, ypos);
+            return;
+        case GLFW_TOP_DECORATION:
+            if (ypos < GLFW_BORDER_SIZE)
+                cursorName = "n-resize";
+            else
+                cursorName = "left_ptr";
+            break;
+        case GLFW_LEFT_DECORATION:
+            if (ypos < GLFW_BORDER_SIZE)
+                cursorName = "nw-resize";
+            else
+                cursorName = "w-resize";
+            break;
+        case GLFW_RIGHT_DECORATION:
+            if (ypos < GLFW_BORDER_SIZE)
+                cursorName = "ne-resize";
+            else
+                cursorName = "e-resize";
+            break;
+        case GLFW_BOTTOM_DECORATION:
+            if (xpos < GLFW_BORDER_SIZE)
+                cursorName = "sw-resize";
+            else if (xpos > window->wl.width + GLFW_BORDER_SIZE)
+                cursorName = "se-resize";
+            else
+                cursorName = "s-resize";
+            break;
+        default:
+            assert(0);
+    }
+
+    if (_glfw.wl.cursorPreviousName != cursorName)
+    {
+        struct wl_surface* surface = _glfw.wl.cursorSurface;
+        struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
+        int scale = 1;
+
+        if (window->wl.contentScale > 1 && _glfw.wl.cursorThemeHiDPI)
+        {
+            // We only support up to scale=2 for now, since libwayland-cursor
+            // requires us to load a different theme for each size.
+            scale = 2;
+            theme = _glfw.wl.cursorThemeHiDPI;
+        }
+
+        struct wl_cursor* cursor = wl_cursor_theme_get_cursor(theme, cursorName);
+        if (!cursor)
+            return;
+
+        // TODO: handle animated cursors too.
+        struct wl_cursor_image* image = cursor->images[0];
+        if (!image)
+            return;
+
+        struct wl_buffer* buffer = wl_cursor_image_get_buffer(image);
+        if (!buffer)
+            return;
+
+        wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
+                              surface,
+                              image->hotspot_x / scale,
+                              image->hotspot_y / scale);
+        wl_surface_set_buffer_scale(surface, scale);
+        wl_surface_attach(surface, buffer, 0, 0);
+        wl_surface_damage(surface, 0, 0, image->width, image->height);
+        wl_surface_commit(surface);
+
+        _glfw.wl.cursorPreviousName = cursorName;
+    }
+}
+
+static void pointerHandleButton(void* userData,
+                                struct wl_pointer* pointer,
+                                uint32_t serial,
+                                uint32_t time,
+                                uint32_t button,
+                                uint32_t state)
+{
+    _GLFWwindow* window = _glfw.wl.pointerFocus;
+    int glfwButton;
+
+    uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
+
+    if (!window)
+        return;
+    if (button == BTN_LEFT)
+    {
+        switch (window->wl.decorations.focus)
+        {
+            case GLFW_MAIN_WINDOW:
+                break;
+            case GLFW_TOP_DECORATION:
+                if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
+                else
+                {
+                    xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
+                }
+                break;
+            case GLFW_LEFT_DECORATION:
+                if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
+                else
+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
+                break;
+            case GLFW_RIGHT_DECORATION:
+                if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
+                else
+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
+                break;
+            case GLFW_BOTTOM_DECORATION:
+                if (window->wl.cursorPosX < GLFW_BORDER_SIZE)
+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
+                else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE)
+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
+                else
+                    edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
+                break;
+            default:
+                assert(0);
+        }
+        if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE)
+        {
+            xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
+                                serial, edges);
+            return;
+        }
+    }
+    else if (button == BTN_RIGHT)
+    {
+        if (window->wl.decorations.focus != GLFW_MAIN_WINDOW &&
+            window->wl.xdg.toplevel)
+        {
+            xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
+                                          _glfw.wl.seat, serial,
+                                          window->wl.cursorPosX,
+                                          window->wl.cursorPosY);
+            return;
+        }
+    }
+
+    // Don’t pass the button to the user if it was related to a decoration.
+    if (window->wl.decorations.focus != GLFW_MAIN_WINDOW)
+        return;
+
+    _glfw.wl.serial = serial;
+
+    /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
+     * codes. */
+    glfwButton = button - BTN_LEFT;
+
+    _glfwInputMouseClick(window,
+                         glfwButton,
+                         state == WL_POINTER_BUTTON_STATE_PRESSED
+                                ? GLFW_PRESS
+                                : GLFW_RELEASE,
+                         _glfw.wl.xkb.modifiers);
+}
+
+static void pointerHandleAxis(void* userData,
+                              struct wl_pointer* pointer,
+                              uint32_t time,
+                              uint32_t axis,
+                              wl_fixed_t value)
+{
+    _GLFWwindow* window = _glfw.wl.pointerFocus;
+    double x = 0.0, y = 0.0;
+    // Wayland scroll events are in pointer motion coordinate space (think two
+    // finger scroll).  The factor 10 is commonly used to convert to "scroll
+    // step means 1.0.
+    const double scrollFactor = 1.0 / 10.0;
+
+    if (!window)
+        return;
+
+    assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
+           axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
+
+    if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
+        x = -wl_fixed_to_double(value) * scrollFactor;
+    else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
+        y = -wl_fixed_to_double(value) * scrollFactor;
+
+    _glfwInputScroll(window, x, y);
+}
+
+static const struct wl_pointer_listener pointerListener =
+{
+    pointerHandleEnter,
+    pointerHandleLeave,
+    pointerHandleMotion,
+    pointerHandleButton,
+    pointerHandleAxis,
+};
+
+static void keyboardHandleKeymap(void* userData,
+                                 struct wl_keyboard* keyboard,
+                                 uint32_t format,
+                                 int fd,
+                                 uint32_t size)
+{
+    struct xkb_keymap* keymap;
+    struct xkb_state* state;
+    struct xkb_compose_table* composeTable;
+    struct xkb_compose_state* composeState;
+    char* mapStr;
+    const char* locale;
+
+    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
+    {
+        close(fd);
+        return;
+    }
+
+    mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+    if (mapStr == MAP_FAILED) {
+        close(fd);
+        return;
+    }
+
+    keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
+                                        mapStr,
+                                        XKB_KEYMAP_FORMAT_TEXT_V1,
+                                        0);
+    munmap(mapStr, size);
+    close(fd);
+
+    if (!keymap)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to compile keymap");
+        return;
+    }
+
+    state = xkb_state_new(keymap);
+    if (!state)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to create XKB state");
+        xkb_keymap_unref(keymap);
+        return;
+    }
+
+    // Look up the preferred locale, falling back to "C" as default.
+    locale = getenv("LC_ALL");
+    if (!locale)
+        locale = getenv("LC_CTYPE");
+    if (!locale)
+        locale = getenv("LANG");
+    if (!locale)
+        locale = "C";
+
+    composeTable =
+        xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
+                                          XKB_COMPOSE_COMPILE_NO_FLAGS);
+    if (composeTable)
+    {
+        composeState =
+            xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
+        xkb_compose_table_unref(composeTable);
+        if (composeState)
+            _glfw.wl.xkb.composeState = composeState;
+        else
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Wayland: Failed to create XKB compose state");
+    }
+    else
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to create XKB compose table");
+    }
+
+    xkb_keymap_unref(_glfw.wl.xkb.keymap);
+    xkb_state_unref(_glfw.wl.xkb.state);
+    _glfw.wl.xkb.keymap = keymap;
+    _glfw.wl.xkb.state = state;
+
+    _glfw.wl.xkb.controlIndex  = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
+    _glfw.wl.xkb.altIndex      = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
+    _glfw.wl.xkb.shiftIndex    = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
+    _glfw.wl.xkb.superIndex    = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
+    _glfw.wl.xkb.capsLockIndex = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");
+    _glfw.wl.xkb.numLockIndex  = xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");
+}
+
+static void keyboardHandleEnter(void* userData,
+                                struct wl_keyboard* keyboard,
+                                uint32_t serial,
+                                struct wl_surface* surface,
+                                struct wl_array* keys)
+{
+    // Happens in the case we just destroyed the surface.
+    if (!surface)
+        return;
+
+    if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
+        return;
+
+    _GLFWwindow* window = wl_surface_get_user_data(surface);
+    if (surface != window->wl.surface)
+        return;
+
+    _glfw.wl.serial = serial;
+    _glfw.wl.keyboardFocus = window;
+    _glfwInputWindowFocus(window, GLFW_TRUE);
+}
+
+static void keyboardHandleLeave(void* userData,
+                                struct wl_keyboard* keyboard,
+                                uint32_t serial,
+                                struct wl_surface* surface)
+{
+    _GLFWwindow* window = _glfw.wl.keyboardFocus;
+
+    if (!window)
+        return;
+
+    struct itimerspec timer = {0};
+    timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
+
+    _glfw.wl.serial = serial;
+    _glfw.wl.keyboardFocus = NULL;
+    _glfwInputWindowFocus(window, GLFW_FALSE);
+}
+
+static void keyboardHandleKey(void* userData,
+                              struct wl_keyboard* keyboard,
+                              uint32_t serial,
+                              uint32_t time,
+                              uint32_t scancode,
+                              uint32_t state)
+{
+    _GLFWwindow* window = _glfw.wl.keyboardFocus;
+    if (!window)
+        return;
+
+    const int key = translateKey(scancode);
+    const int action =
+        state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE;
+
+    _glfw.wl.serial = serial;
+
+    struct itimerspec timer = {0};
+
+    if (action == GLFW_PRESS)
+    {
+        const xkb_keycode_t keycode = scancode + 8;
+
+        if (xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode) &&
+            _glfw.wl.keyRepeatRate > 0)
+        {
+            _glfw.wl.keyRepeatScancode = scancode;
+            if (_glfw.wl.keyRepeatRate > 1)
+                timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyRepeatRate;
+            else
+                timer.it_interval.tv_sec = 1;
+
+            timer.it_value.tv_sec = _glfw.wl.keyRepeatDelay / 1000;
+            timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000;
+        }
+    }
+
+    timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
+
+    _glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
+
+    if (action == GLFW_PRESS)
+        inputText(window, scancode);
+}
+
+static void keyboardHandleModifiers(void* userData,
+                                    struct wl_keyboard* keyboard,
+                                    uint32_t serial,
+                                    uint32_t modsDepressed,
+                                    uint32_t modsLatched,
+                                    uint32_t modsLocked,
+                                    uint32_t group)
+{
+    _glfw.wl.serial = serial;
+
+    if (!_glfw.wl.xkb.keymap)
+        return;
+
+    xkb_state_update_mask(_glfw.wl.xkb.state,
+                          modsDepressed,
+                          modsLatched,
+                          modsLocked,
+                          0,
+                          0,
+                          group);
+
+    _glfw.wl.xkb.modifiers = 0;
+
+    struct
+    {
+        xkb_mod_index_t index;
+        unsigned int bit;
+    } modifiers[] =
+    {
+        { _glfw.wl.xkb.controlIndex,  GLFW_MOD_CONTROL },
+        { _glfw.wl.xkb.altIndex,      GLFW_MOD_ALT },
+        { _glfw.wl.xkb.shiftIndex,    GLFW_MOD_SHIFT },
+        { _glfw.wl.xkb.superIndex,    GLFW_MOD_SUPER },
+        { _glfw.wl.xkb.capsLockIndex, GLFW_MOD_CAPS_LOCK },
+        { _glfw.wl.xkb.numLockIndex,  GLFW_MOD_NUM_LOCK }
+    };
+
+    for (size_t i = 0; i < sizeof(modifiers) / sizeof(modifiers[0]); i++)
+    {
+        if (xkb_state_mod_index_is_active(_glfw.wl.xkb.state,
+                                          modifiers[i].index,
+                                          XKB_STATE_MODS_EFFECTIVE) == 1)
+        {
+            _glfw.wl.xkb.modifiers |= modifiers[i].bit;
+        }
+    }
+}
+
+#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
+static void keyboardHandleRepeatInfo(void* userData,
+                                     struct wl_keyboard* keyboard,
+                                     int32_t rate,
+                                     int32_t delay)
+{
+    if (keyboard != _glfw.wl.keyboard)
+        return;
+
+    _glfw.wl.keyRepeatRate = rate;
+    _glfw.wl.keyRepeatDelay = delay;
+}
+#endif
+
+static const struct wl_keyboard_listener keyboardListener =
+{
+    keyboardHandleKeymap,
+    keyboardHandleEnter,
+    keyboardHandleLeave,
+    keyboardHandleKey,
+    keyboardHandleModifiers,
+#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
+    keyboardHandleRepeatInfo,
+#endif
+};
+
+static void seatHandleCapabilities(void* userData,
+                                   struct wl_seat* seat,
+                                   enum wl_seat_capability caps)
+{
+    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)
+    {
+        _glfw.wl.pointer = wl_seat_get_pointer(seat);
+        wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);
+    }
+    else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
+    {
+        wl_pointer_destroy(_glfw.wl.pointer);
+        _glfw.wl.pointer = NULL;
+    }
+
+    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)
+    {
+        _glfw.wl.keyboard = wl_seat_get_keyboard(seat);
+        wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
+    }
+    else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
+    {
+        wl_keyboard_destroy(_glfw.wl.keyboard);
+        _glfw.wl.keyboard = NULL;
+    }
+}
+
+static void seatHandleName(void* userData,
+                           struct wl_seat* seat,
+                           const char* name)
+{
+}
+
+static const struct wl_seat_listener seatListener =
+{
+    seatHandleCapabilities,
+    seatHandleName,
+};
+
+static void dataOfferHandleOffer(void* userData,
+                                 struct wl_data_offer* offer,
+                                 const char* mimeType)
+{
+    for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
+    {
+        if (_glfw.wl.offers[i].offer == offer)
+        {
+            if (strcmp(mimeType, "text/plain;charset=utf-8") == 0)
+                _glfw.wl.offers[i].text_plain_utf8 = GLFW_TRUE;
+            else if (strcmp(mimeType, "text/uri-list") == 0)
+                _glfw.wl.offers[i].text_uri_list = GLFW_TRUE;
+
+            break;
+        }
+    }
+}
+
+static const struct wl_data_offer_listener dataOfferListener =
+{
+    dataOfferHandleOffer
+};
+
+static void dataDeviceHandleDataOffer(void* userData,
+                                      struct wl_data_device* device,
+                                      struct wl_data_offer* offer)
+{
+    _GLFWofferWayland* offers =
+        realloc(_glfw.wl.offers,
+                sizeof(_GLFWofferWayland) * (_glfw.wl.offerCount + 1));
+    if (!offers)
+    {
+        _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
+        return;
+    }
+
+    _glfw.wl.offers = offers;
+    _glfw.wl.offerCount++;
+
+    _glfw.wl.offers[_glfw.wl.offerCount - 1] = (_GLFWofferWayland) { offer };
+    wl_data_offer_add_listener(offer, &dataOfferListener, NULL);
+}
+
+static void dataDeviceHandleEnter(void* userData,
+                                  struct wl_data_device* device,
+                                  uint32_t serial,
+                                  struct wl_surface* surface,
+                                  wl_fixed_t x,
+                                  wl_fixed_t y,
+                                  struct wl_data_offer* offer)
+{
+    if (_glfw.wl.dragOffer)
+    {
+        wl_data_offer_destroy(_glfw.wl.dragOffer);
+        _glfw.wl.dragOffer = NULL;
+        _glfw.wl.dragFocus = NULL;
+    }
+
+    for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
+    {
+        if (_glfw.wl.offers[i].offer == offer)
+        {
+            _GLFWwindow* window = NULL;
+
+            if (surface)
+            {
+                if (wl_proxy_get_tag((struct wl_proxy*) surface) == &_glfw.wl.tag)
+                    window = wl_surface_get_user_data(surface);
+            }
+
+            if (surface == window->wl.surface && _glfw.wl.offers[i].text_uri_list)
+            {
+                _glfw.wl.dragOffer = offer;
+                _glfw.wl.dragFocus = window;
+                _glfw.wl.dragSerial = serial;
+            }
+
+            _glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1];
+            _glfw.wl.offerCount--;
+            break;
+        }
+    }
+
+    if (wl_proxy_get_tag((struct wl_proxy*) surface) != &_glfw.wl.tag)
+        return;
+
+    if (_glfw.wl.dragOffer)
+        wl_data_offer_accept(offer, serial, "text/uri-list");
+    else
+    {
+        wl_data_offer_accept(offer, serial, NULL);
+        wl_data_offer_destroy(offer);
+    }
+}
+
+static void dataDeviceHandleLeave(void* userData,
+                                  struct wl_data_device* device)
+{
+    if (_glfw.wl.dragOffer)
+    {
+        wl_data_offer_destroy(_glfw.wl.dragOffer);
+        _glfw.wl.dragOffer = NULL;
+        _glfw.wl.dragFocus = NULL;
+    }
+}
+
+static void dataDeviceHandleMotion(void* userData,
+                                   struct wl_data_device* device,
+                                   uint32_t time,
+                                   wl_fixed_t x,
+                                   wl_fixed_t y)
+{
+}
+
+static void dataDeviceHandleDrop(void* userData,
+                                 struct wl_data_device* device)
+{
+    if (!_glfw.wl.dragOffer)
+        return;
+
+    char* string = readDataOfferAsString(_glfw.wl.dragOffer, "text/uri-list");
+    if (string)
+    {
+        int count;
+        char** paths = _glfwParseUriList(string, &count);
+        if (paths)
+            _glfwInputDrop(_glfw.wl.dragFocus, count, (const char**) paths);
+
+        for (int i = 0; i < count; i++)
+            free(paths[i]);
+
+        free(paths);
+    }
+
+    free(string);
+}
+
+static void dataDeviceHandleSelection(void* userData,
+                                      struct wl_data_device* device,
+                                      struct wl_data_offer* offer)
+{
+    if (_glfw.wl.selectionOffer)
+    {
+        wl_data_offer_destroy(_glfw.wl.selectionOffer);
+        _glfw.wl.selectionOffer = NULL;
+    }
+
+    for (unsigned int i = 0; i < _glfw.wl.offerCount; i++)
+    {
+        if (_glfw.wl.offers[i].offer == offer)
+        {
+            if (_glfw.wl.offers[i].text_plain_utf8)
+                _glfw.wl.selectionOffer = offer;
+            else
+                wl_data_offer_destroy(offer);
+
+            _glfw.wl.offers[i] = _glfw.wl.offers[_glfw.wl.offerCount - 1];
+            _glfw.wl.offerCount--;
+            break;
+        }
+    }
+}
+
+const struct wl_data_device_listener dataDeviceListener =
+{
+    dataDeviceHandleDataOffer,
+    dataDeviceHandleEnter,
+    dataDeviceHandleLeave,
+    dataDeviceHandleMotion,
+    dataDeviceHandleDrop,
+    dataDeviceHandleSelection,
+};
+
+void _glfwAddSeatListenerWayland(struct wl_seat* seat)
+{
+    wl_seat_add_listener(seat, &seatListener, NULL);
+}
+
+void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device)
+{
+    wl_data_device_add_listener(device, &dataDeviceListener, NULL);
+}
+
+
 //////////////////////////////////////////////////////////////////////////
 //////                       GLFW platform API                      //////
 //////////////////////////////////////////////////////////////////////////
@@ -987,7 +2047,7 @@
                               const _GLFWctxconfig* ctxconfig,
                               const _GLFWfbconfig* fbconfig)
 {
-    if (!createSurface(window, wndconfig, fbconfig))
+    if (!createNativeSurface(window, wndconfig, fbconfig))
         return GLFW_FALSE;
 
     if (ctxconfig->client != GLFW_NO_API)
@@ -995,6 +2055,16 @@
         if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
             ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
         {
+            window->wl.egl.window = wl_egl_window_create(window->wl.surface,
+                                                         wndconfig->width,
+                                                         wndconfig->height);
+            if (!window->wl.egl.window)
+            {
+                _glfwInputError(GLFW_PLATFORM_ERROR,
+                                "Wayland: Failed to create EGL window");
+                return GLFW_FALSE;
+            }
+
             if (!_glfwInitEGL())
                 return GLFW_FALSE;
             if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
@@ -1007,6 +2077,15 @@
             if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
                 return GLFW_FALSE;
         }
+
+        if (!_glfwRefreshContextAttribs(window, ctxconfig))
+            return GLFW_FALSE;
+    }
+
+    if (window->monitor || wndconfig->visible)
+    {
+        if (!createShellObjects(window))
+            return GLFW_FALSE;
     }
 
     return GLFW_TRUE;
@@ -1015,46 +2094,36 @@
 void _glfwPlatformDestroyWindow(_GLFWwindow* window)
 {
     if (window == _glfw.wl.pointerFocus)
-    {
         _glfw.wl.pointerFocus = NULL;
-        _glfwInputCursorEnter(window, GLFW_FALSE);
-    }
+
     if (window == _glfw.wl.keyboardFocus)
-    {
         _glfw.wl.keyboardFocus = NULL;
-        _glfwInputWindowFocus(window, GLFW_FALSE);
-    }
 
     if (window->wl.idleInhibitor)
         zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
 
+    if (window->wl.relativePointer)
+        zwp_relative_pointer_v1_destroy(window->wl.relativePointer);
+
+    if (window->wl.lockedPointer)
+        zwp_locked_pointer_v1_destroy(window->wl.lockedPointer);
+
     if (window->context.destroy)
         window->context.destroy(window);
 
-    destroyDecorations(window);
-    if (window->wl.xdg.decoration)
-        zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
+    destroyShellObjects(window);
 
     if (window->wl.decorations.buffer)
         wl_buffer_destroy(window->wl.decorations.buffer);
 
-    if (window->wl.native)
-        wl_egl_window_destroy(window->wl.native);
-
-    if (window->wl.shellSurface)
-        wl_shell_surface_destroy(window->wl.shellSurface);
-
-    if (window->wl.xdg.toplevel)
-        xdg_toplevel_destroy(window->wl.xdg.toplevel);
-
-    if (window->wl.xdg.surface)
-        xdg_surface_destroy(window->wl.xdg.surface);
+    if (window->wl.egl.window)
+        wl_egl_window_destroy(window->wl.egl.window);
 
     if (window->wl.surface)
         wl_surface_destroy(window->wl.surface);
 
     free(window->wl.title);
-    free(window->wl.monitors);
+    free(window->wl.scales);
 }
 
 void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
@@ -1062,10 +2131,11 @@
     if (window->wl.title)
         free(window->wl.title);
     window->wl.title = _glfw_strdup(title);
-    if (window->wl.xdg.toplevel)
+
+    if (window->wl.libdecor.frame)
+        libdecor_frame_set_title(window->wl.libdecor.frame, title);
+    else if (window->wl.xdg.toplevel)
         xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
-    else if (window->wl.shellSurface)
-        wl_shell_surface_set_title(window->wl.shellSurface, title);
 }
 
 void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
@@ -1102,40 +2172,111 @@
 
 void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
 {
-    window->wl.width = width;
-    window->wl.height = height;
-    resizeWindow(window);
+    if (window->monitor)
+    {
+        // Video mode setting is not available on Wayland
+    }
+    else
+    {
+        window->wl.width = width;
+        window->wl.height = height;
+        resizeWindow(window);
+
+        if (window->wl.libdecor.frame)
+        {
+            struct libdecor_state* frameState = libdecor_state_new(width, height);
+            libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
+            libdecor_state_free(frameState);
+        }
+
+        if (window->wl.visible)
+            _glfwInputWindowDamage(window);
+    }
 }
 
 void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
                                       int minwidth, int minheight,
                                       int maxwidth, int maxheight)
 {
-    if (_glfw.wl.wmBase)
+    if (window->wl.libdecor.frame)
     {
-        if (window->wl.xdg.toplevel)
-        {
-            if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
-                minwidth = minheight = 0;
-            if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
-                maxwidth = maxheight = 0;
-            xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);
-            xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);
-            wl_surface_commit(window->wl.surface);
-        }
+        if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
+            minwidth = minheight = 0;
+
+        if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
+            maxwidth = maxheight = 0;
+
+        libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
+                                            minwidth, minheight);
+        libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
+                                            maxwidth, maxheight);
     }
-    else
+    else if (window->wl.xdg.toplevel)
     {
-        // TODO: find out how to trigger a resize.
-        // The actual limits are checked in the wl_shell_surface::configure handler.
+        if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
+            minwidth = minheight = 0;
+        else
+        {
+            if (window->wl.decorations.top.surface)
+            {
+                minwidth  += GLFW_BORDER_SIZE * 2;
+                minheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE;
+            }
+        }
+
+        if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
+            maxwidth = maxheight = 0;
+        else
+        {
+            if (window->wl.decorations.top.surface)
+            {
+                maxwidth  += GLFW_BORDER_SIZE * 2;
+                maxheight += GLFW_CAPTION_HEIGHT + GLFW_BORDER_SIZE;
+            }
+        }
+
+        xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);
+        xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);
+        wl_surface_commit(window->wl.surface);
     }
 }
 
 void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window,
                                        int numer, int denom)
 {
-    // TODO: find out how to trigger a resize.
-    // The actual limits are checked in the wl_shell_surface::configure handler.
+    if (window->wl.maximized || window->wl.fullscreen)
+        return;
+
+    int width = window->wl.width, height = window->wl.height;
+
+    if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)
+    {
+        const float aspectRatio = (float) width / (float) height;
+        const float targetRatio = (float) numer / (float) denom;
+        if (aspectRatio < targetRatio)
+            height /= targetRatio;
+        else if (aspectRatio > targetRatio)
+            width *= targetRatio;
+    }
+
+    if (width != window->wl.width || height != window->wl.height)
+    {
+        window->wl.width = width;
+        window->wl.height = height;
+        resizeWindow(window);
+
+        if (window->wl.libdecor.frame)
+        {
+            struct libdecor_state* frameState = libdecor_state_new(width, height);
+            libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
+            libdecor_state_free(frameState);
+        }
+
+        _glfwInputWindowSize(window, width, height);
+
+        if (window->wl.visible)
+            _glfwInputWindowDamage(window);
+    }
 }
 
 void _glfwPlatformGetFramebufferSize(_GLFWwindow* window,
@@ -1143,25 +2284,25 @@
 {
     _glfwPlatformGetWindowSize(window, width, height);
     if (width)
-        *width *= window->wl.scale;
+        *width *= window->wl.contentScale;
     if (height)
-        *height *= window->wl.scale;
+        *height *= window->wl.contentScale;
 }
 
 void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
                                      int* left, int* top,
                                      int* right, int* bottom)
 {
-    if (window->decorated && !window->monitor && !window->wl.decorations.serverSide)
+    if (window->wl.decorations.top.surface)
     {
         if (top)
-            *top = _GLFW_DECORATION_TOP;
+            *top = GLFW_CAPTION_HEIGHT;
         if (left)
-            *left = _GLFW_DECORATION_WIDTH;
+            *left = GLFW_BORDER_SIZE;
         if (right)
-            *right = _GLFW_DECORATION_WIDTH;
+            *right = GLFW_BORDER_SIZE;
         if (bottom)
-            *bottom = _GLFW_DECORATION_WIDTH;
+            *bottom = GLFW_BORDER_SIZE;
     }
 }
 
@@ -1169,75 +2310,59 @@
                                         float* xscale, float* yscale)
 {
     if (xscale)
-        *xscale = (float) window->wl.scale;
+        *xscale = (float) window->wl.contentScale;
     if (yscale)
-        *yscale = (float) window->wl.scale;
+        *yscale = (float) window->wl.contentScale;
 }
 
 void _glfwPlatformIconifyWindow(_GLFWwindow* window)
 {
-    if (_glfw.wl.wmBase)
-    {
-        if (window->wl.xdg.toplevel)
-            xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
-    }
-    else
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Iconify window not supported on wl_shell");
-    }
+    if (window->wl.libdecor.frame)
+        libdecor_frame_set_minimized(window->wl.libdecor.frame);
+    else if (window->wl.xdg.toplevel)
+        xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
 }
 
 void _glfwPlatformRestoreWindow(_GLFWwindow* window)
 {
-    if (window->wl.xdg.toplevel)
+    if (window->monitor)
     {
-        if (window->monitor)
-            xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
-        if (window->wl.maximized)
-            xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
         // There is no way to unset minimized, or even to know if we are
         // minimized, so there is nothing to do here.
     }
-    else if (window->wl.shellSurface)
+    else
     {
-        if (window->monitor || window->wl.maximized)
-            wl_shell_surface_set_toplevel(window->wl.shellSurface);
+        // We assume we are not minimized and act only on maximization
+
+        if (window->wl.maximized)
+        {
+            if (window->wl.libdecor.frame)
+                libdecor_frame_unset_maximized(window->wl.libdecor.frame);
+            else if (window->wl.xdg.toplevel)
+                xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
+            else
+                window->wl.maximized = GLFW_FALSE;
+        }
     }
-    _glfwInputWindowMonitor(window, NULL);
-    window->wl.maximized = GLFW_FALSE;
 }
 
 void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
 {
-    if (window->wl.xdg.toplevel)
-    {
+    if (window->wl.libdecor.frame)
+        libdecor_frame_set_maximized(window->wl.libdecor.frame);
+    else if (window->wl.xdg.toplevel)
         xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
-    }
-    else if (window->wl.shellSurface)
-    {
-        // Let the compositor select the best output.
-        wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
-    }
-    window->wl.maximized = GLFW_TRUE;
+    else
+        window->wl.maximized = GLFW_TRUE;
 }
 
 void _glfwPlatformShowWindow(_GLFWwindow* window)
 {
-    if (!window->wl.visible)
+    if (!window->wl.libdecor.frame && !window->wl.xdg.toplevel)
     {
         // NOTE: The XDG/shell surface is created here so command-line applications
         //       with off-screen windows do not appear in for example the Unity dock
-        if (_glfw.wl.wmBase)
-        {
-            if (!window->wl.xdg.toplevel)
-                createXdgSurface(window);
-        }
-        else if (!window->wl.shellSurface)
-            createShellSurface(window);
-
-        window->wl.visible = GLFW_TRUE;
-        _glfwInputWindowDamage(window);
+        createShellObjects(window);
     }
 }
 
@@ -1246,6 +2371,8 @@
     if (window->wl.visible)
     {
         window->wl.visible = GLFW_FALSE;
+        destroyShellObjects(window);
+
         wl_surface_attach(window->wl.surface, NULL, 0, 0);
         wl_surface_commit(window->wl.surface);
     }
@@ -1270,21 +2397,23 @@
                                    int width, int height,
                                    int refreshRate)
 {
-    if (monitor)
+    if (window->monitor == monitor)
     {
-        setFullscreen(window, monitor, refreshRate);
+        if (!monitor)
+            _glfwPlatformSetWindowSize(window, width, height);
+
+        return;
     }
-    else
-    {
-        if (window->wl.xdg.toplevel)
-            xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
-        else if (window->wl.shellSurface)
-            wl_shell_surface_set_toplevel(window->wl.shellSurface);
-        setIdleInhibitor(window, GLFW_FALSE);
-        if (!_glfw.wl.decorationManager)
-            createDecorations(window);
-    }
+
+    if (window->monitor)
+        releaseMonitor(window);
+
     _glfwInputWindowMonitor(window, monitor);
+
+    if (window->monitor)
+        acquireMonitor(window);
+    else
+        _glfwPlatformSetWindowSize(window, width, height);
 }
 
 int _glfwPlatformWindowFocused(_GLFWwindow* window)
@@ -1294,8 +2423,7 @@
 
 int _glfwPlatformWindowIconified(_GLFWwindow* window)
 {
-    // wl_shell doesn't have any iconified concept, and xdg-shell doesn’t give
-    // any way to request whether a surface is iconified.
+    // xdg-shell doesn’t give any way to request whether a surface is iconified
     return GLFW_FALSE;
 }
 
@@ -1321,19 +2449,50 @@
 
 void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
 {
-    // TODO
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Wayland: Window attribute setting not implemented yet");
+    if (window->wl.libdecor.frame)
+    {
+        if (enabled)
+        {
+            libdecor_frame_set_capabilities(window->wl.libdecor.frame,
+                                            LIBDECOR_ACTION_RESIZE);
+        }
+        else
+        {
+            libdecor_frame_unset_capabilities(window->wl.libdecor.frame,
+                                              LIBDECOR_ACTION_RESIZE);
+        }
+    }
+    else
+    {
+        // TODO
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Window attribute setting not implemented yet");
+    }
 }
 
 void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
 {
-    if (!window->monitor)
+    if (window->wl.libdecor.frame)
+    {
+        libdecor_frame_set_visibility(window->wl.libdecor.frame, enabled);
+    }
+    else if (window->wl.xdg.decoration)
+    {
+        uint32_t mode;
+
+        if (enabled)
+            mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE;
+        else
+            mode = ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
+
+        zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode);
+    }
+    else if (window->wl.xdg.toplevel)
     {
         if (enabled)
-            createDecorations(window);
+            createFallbackDecorations(window);
         else
-            destroyDecorations(window);
+            destroyFallbackDecorations(window);
     }
 }
 
@@ -1353,7 +2512,7 @@
 {
 }
 
-void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
+void _glfwPlatformSetRawMouseMotion(_GLFWwindow* window, GLFWbool enabled)
 {
     // This is handled in relativePointerHandleRelativeMotion
 }
@@ -1393,17 +2552,8 @@
         *ypos = window->wl.cursorPosY;
 }
 
-static GLFWbool isPointerLocked(_GLFWwindow* window);
-
 void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
 {
-    if (isPointerLocked(window))
-    {
-        zwp_locked_pointer_v1_set_cursor_position_hint(
-            window->wl.pointerLock.lockedPointer,
-            wl_fixed_from_double(x), wl_fixed_from_double(y));
-        wl_surface_commit(window->wl.surface);
-    }
 }
 
 void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
@@ -1576,7 +2726,7 @@
         wl_buffer_destroy(cursor->wl.buffer);
 }
 
-static void relativePointerHandleRelativeMotion(void* data,
+static void relativePointerHandleRelativeMotion(void* userData,
                                                 struct zwp_relative_pointer_v1* pointer,
                                                 uint32_t timeHi,
                                                 uint32_t timeLo,
@@ -1585,7 +2735,7 @@
                                                 wl_fixed_t dxUnaccel,
                                                 wl_fixed_t dyUnaccel)
 {
-    _GLFWwindow* window = data;
+    _GLFWwindow* window = userData;
     double xpos = window->virtualCursorPosX;
     double ypos = window->virtualCursorPosY;
 
@@ -1606,46 +2756,29 @@
     _glfwInputCursorPos(window, xpos, ypos);
 }
 
-static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
+static const struct zwp_relative_pointer_v1_listener relativePointerListener =
+{
     relativePointerHandleRelativeMotion
 };
 
-static void lockedPointerHandleLocked(void* data,
+static void lockedPointerHandleLocked(void* userData,
                                       struct zwp_locked_pointer_v1* lockedPointer)
 {
 }
 
-static void unlockPointer(_GLFWwindow* window)
-{
-    struct zwp_relative_pointer_v1* relativePointer =
-        window->wl.pointerLock.relativePointer;
-    struct zwp_locked_pointer_v1* lockedPointer =
-        window->wl.pointerLock.lockedPointer;
-
-    zwp_relative_pointer_v1_destroy(relativePointer);
-    zwp_locked_pointer_v1_destroy(lockedPointer);
-
-    window->wl.pointerLock.relativePointer = NULL;
-    window->wl.pointerLock.lockedPointer = NULL;
-}
-
-static void lockPointer(_GLFWwindow* window);
-
-static void lockedPointerHandleUnlocked(void* data,
+static void lockedPointerHandleUnlocked(void* userData,
                                         struct zwp_locked_pointer_v1* lockedPointer)
 {
 }
 
-static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {
+static const struct zwp_locked_pointer_v1_listener lockedPointerListener =
+{
     lockedPointerHandleLocked,
     lockedPointerHandleUnlocked
 };
 
 static void lockPointer(_GLFWwindow* window)
 {
-    struct zwp_relative_pointer_v1* relativePointer;
-    struct zwp_locked_pointer_v1* lockedPointer;
-
     if (!_glfw.wl.relativePointerManager)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR,
@@ -1653,42 +2786,37 @@
         return;
     }
 
-    relativePointer =
+    window->wl.relativePointer =
         zwp_relative_pointer_manager_v1_get_relative_pointer(
             _glfw.wl.relativePointerManager,
             _glfw.wl.pointer);
-    zwp_relative_pointer_v1_add_listener(relativePointer,
+    zwp_relative_pointer_v1_add_listener(window->wl.relativePointer,
                                          &relativePointerListener,
                                          window);
 
-    lockedPointer =
+    window->wl.lockedPointer =
         zwp_pointer_constraints_v1_lock_pointer(
             _glfw.wl.pointerConstraints,
             window->wl.surface,
             _glfw.wl.pointer,
             NULL,
             ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
-    zwp_locked_pointer_v1_add_listener(lockedPointer,
+    zwp_locked_pointer_v1_add_listener(window->wl.lockedPointer,
                                        &lockedPointerListener,
                                        window);
-
-    window->wl.pointerLock.relativePointer = relativePointer;
-    window->wl.pointerLock.lockedPointer = lockedPointer;
-
-    wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
-                          NULL, 0, 0);
 }
 
-static GLFWbool isPointerLocked(_GLFWwindow* window)
+static void unlockPointer(_GLFWwindow* window)
 {
-    return window->wl.pointerLock.lockedPointer != NULL;
+    zwp_relative_pointer_v1_destroy(window->wl.relativePointer);
+    window->wl.relativePointer = NULL;
+
+    zwp_locked_pointer_v1_destroy(window->wl.lockedPointer);
+    window->wl.lockedPointer = NULL;
 }
 
 void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
 {
-    struct wl_cursor* defaultCursor;
-    struct wl_cursor* defaultCursorHiDPI = NULL;
-
     if (!_glfw.wl.pointer)
         return;
 
@@ -1696,12 +2824,24 @@
 
     // If we're not in the correct window just save the cursor
     // the next time the pointer enters the window the cursor will change
-    if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow)
+    if (window != _glfw.wl.pointerFocus ||
+        window->wl.decorations.focus != GLFW_MAIN_WINDOW)
+    {
         return;
+    }
 
-    // Unlock possible pointer lock if no longer disabled.
-    if (window->cursorMode != GLFW_CURSOR_DISABLED && isPointerLocked(window))
-        unlockPointer(window);
+    // Update pointer lock to match cursor mode
+    if (window->cursorMode == GLFW_CURSOR_DISABLED)
+    {
+        if (!window->wl.lockedPointer)
+            lockPointer(window);
+    }
+    else if (window->cursorMode == GLFW_CURSOR_NORMAL ||
+             window->cursorMode == GLFW_CURSOR_HIDDEN)
+    {
+        if (window->wl.lockedPointer)
+            unlockPointer(window);
+    }
 
     if (window->cursorMode == GLFW_CURSOR_NORMAL)
     {
@@ -1709,19 +2849,24 @@
             setCursorImage(window, &cursor->wl);
         else
         {
-            defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
-                                                       "left_ptr");
+            struct wl_cursor* defaultCursor =
+                wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, "left_ptr");
             if (!defaultCursor)
             {
                 _glfwInputError(GLFW_PLATFORM_ERROR,
                                 "Wayland: Standard cursor not found");
                 return;
             }
+
+            struct wl_cursor* defaultCursorHiDPI = NULL;
             if (_glfw.wl.cursorThemeHiDPI)
+            {
                 defaultCursorHiDPI =
-                    wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
-                                               "left_ptr");
-            _GLFWcursorWayland cursorWayland = {
+                    wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI, "left_ptr");
+            }
+
+            _GLFWcursorWayland cursorWayland =
+            {
                 defaultCursor,
                 defaultCursorHiDPI,
                 NULL,
@@ -1729,25 +2874,22 @@
                 0, 0,
                 0
             };
+
             setCursorImage(window, &cursorWayland);
         }
     }
-    else if (window->cursorMode == GLFW_CURSOR_DISABLED)
-    {
-        if (!isPointerLocked(window))
-            lockPointer(window);
-    }
-    else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
+    else if (window->cursorMode == GLFW_CURSOR_HIDDEN ||
+             window->cursorMode == GLFW_CURSOR_DISABLED)
     {
         wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial, NULL, 0, 0);
     }
 }
 
-static void dataSourceHandleTarget(void* data,
-                                   struct wl_data_source* dataSource,
+static void dataSourceHandleTarget(void* userData,
+                                   struct wl_data_source* source,
                                    const char* mimeType)
 {
-    if (_glfw.wl.dataSource != dataSource)
+    if (_glfw.wl.selectionSource != source)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR,
                         "Wayland: Unknown clipboard data source");
@@ -1755,71 +2897,56 @@
     }
 }
 
-static void dataSourceHandleSend(void* data,
-                                 struct wl_data_source* dataSource,
+static void dataSourceHandleSend(void* userData,
+                                 struct wl_data_source* source,
                                  const char* mimeType,
                                  int fd)
 {
-    const char* string = _glfw.wl.clipboardSendString;
-    size_t len = _glfw.wl.clipboardSendSize;
-    int ret;
-
-    if (_glfw.wl.dataSource != dataSource)
+    // Ignore it if this is an outdated or invalid request
+    if (_glfw.wl.selectionSource != source ||
+        strcmp(mimeType, "text/plain;charset=utf-8") != 0)
     {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Unknown clipboard data source");
-        return;
-    }
-
-    if (!string)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Copy requested from an invalid string");
-        return;
-    }
-
-    if (strcmp(mimeType, "text/plain;charset=utf-8") != 0)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Wrong MIME type asked from clipboard");
         close(fd);
         return;
     }
 
-    while (len > 0)
+    char* string = _glfw.wl.clipboardString;
+    size_t length = strlen(string);
+
+    while (length > 0)
     {
-        ret = write(fd, string, len);
-        if (ret == -1 && errno == EINTR)
-            continue;
-        if (ret == -1)
+        const ssize_t result = write(fd, string, length);
+        if (result == -1)
         {
-            // TODO: also report errno maybe.
+            if (errno == EINTR)
+                continue;
+
             _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Error while writing the clipboard");
-            close(fd);
-            return;
+                            "Wayland: Error while writing the clipboard: %s",
+                            strerror(errno));
+            break;
         }
-        len -= ret;
+
+        length -= result;
+        string += result;
     }
+
     close(fd);
 }
 
-static void dataSourceHandleCancelled(void* data,
-                                      struct wl_data_source* dataSource)
+static void dataSourceHandleCancelled(void* userData,
+                                      struct wl_data_source* source)
 {
-    wl_data_source_destroy(dataSource);
+    wl_data_source_destroy(source);
 
-    if (_glfw.wl.dataSource != dataSource)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Unknown clipboard data source");
+    if (_glfw.wl.selectionSource != source)
         return;
-    }
 
-    _glfw.wl.dataSource = NULL;
+    _glfw.wl.selectionSource = NULL;
 }
 
-static const struct wl_data_source_listener dataSourceListener = {
+static const struct wl_data_source_listener dataSourceListener =
+{
     dataSourceHandleTarget,
     dataSourceHandleSend,
     dataSourceHandleCancelled,
@@ -1827,124 +2954,54 @@
 
 void _glfwPlatformSetClipboardString(const char* string)
 {
-    if (_glfw.wl.dataSource)
+    if (_glfw.wl.selectionSource)
     {
-        wl_data_source_destroy(_glfw.wl.dataSource);
-        _glfw.wl.dataSource = NULL;
+        wl_data_source_destroy(_glfw.wl.selectionSource);
+        _glfw.wl.selectionSource = NULL;
     }
 
-    if (_glfw.wl.clipboardSendString)
+    char* copy = _glfw_strdup(string);
+    if (!copy)
     {
-        free(_glfw.wl.clipboardSendString);
-        _glfw.wl.clipboardSendString = NULL;
-    }
-
-    _glfw.wl.clipboardSendString = strdup(string);
-    if (!_glfw.wl.clipboardSendString)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Impossible to allocate clipboard string");
+        _glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
         return;
     }
-    _glfw.wl.clipboardSendSize = strlen(string);
-    _glfw.wl.dataSource =
+
+    free(_glfw.wl.clipboardString);
+    _glfw.wl.clipboardString = copy;
+
+    _glfw.wl.selectionSource =
         wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
-    if (!_glfw.wl.dataSource)
+    if (!_glfw.wl.selectionSource)
     {
         _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Impossible to create clipboard source");
-        free(_glfw.wl.clipboardSendString);
+                        "Wayland: Failed to create clipboard data source");
         return;
     }
-    wl_data_source_add_listener(_glfw.wl.dataSource,
+    wl_data_source_add_listener(_glfw.wl.selectionSource,
                                 &dataSourceListener,
                                 NULL);
-    wl_data_source_offer(_glfw.wl.dataSource, "text/plain;charset=utf-8");
+    wl_data_source_offer(_glfw.wl.selectionSource, "text/plain;charset=utf-8");
     wl_data_device_set_selection(_glfw.wl.dataDevice,
-                                 _glfw.wl.dataSource,
+                                 _glfw.wl.selectionSource,
                                  _glfw.wl.serial);
 }
 
-static GLFWbool growClipboardString(void)
-{
-    char* clipboard = _glfw.wl.clipboardString;
-
-    clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);
-    if (!clipboard)
-    {
-        _glfwInputError(GLFW_OUT_OF_MEMORY,
-                        "Wayland: Impossible to grow clipboard string");
-        return GLFW_FALSE;
-    }
-    _glfw.wl.clipboardString = clipboard;
-    _glfw.wl.clipboardSize = _glfw.wl.clipboardSize * 2;
-    return GLFW_TRUE;
-}
-
 const char* _glfwPlatformGetClipboardString(void)
 {
-    int fds[2];
-    int ret;
-    size_t len = 0;
-
-    if (!_glfw.wl.dataOffer)
+    if (!_glfw.wl.selectionOffer)
     {
         _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "No clipboard data has been sent yet");
+                        "Wayland: No clipboard data available");
         return NULL;
     }
 
-    ret = pipe2(fds, O_CLOEXEC);
-    if (ret < 0)
-    {
-        // TODO: also report errno maybe?
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Impossible to create clipboard pipe fds");
-        return NULL;
-    }
+    if (_glfw.wl.selectionSource)
+        return _glfw.wl.clipboardString;
 
-    wl_data_offer_receive(_glfw.wl.dataOffer, "text/plain;charset=utf-8", fds[1]);
-    close(fds[1]);
-
-    // XXX: this is a huge hack, this function shouldn’t be synchronous!
-    handleEvents(NULL);
-
-    for (;;)
-    {
-        // Grow the clipboard if we need to paste something bigger, there is no
-        // shrink operation yet.
-        if (len + 4096 > _glfw.wl.clipboardSize)
-        {
-            if (!growClipboardString())
-            {
-                close(fds[0]);
-                return NULL;
-            }
-        }
-
-        // Then read from the fd to the clipboard, handling all known errors.
-        ret = read(fds[0], _glfw.wl.clipboardString + len, 4096);
-        if (ret == 0)
-            break;
-        if (ret == -1 && errno == EINTR)
-            continue;
-        if (ret == -1)
-        {
-            // TODO: also report errno maybe.
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Impossible to read from clipboard fd");
-            close(fds[0]);
-            return NULL;
-        }
-        len += ret;
-    }
-    close(fds[0]);
-    if (len + 1 > _glfw.wl.clipboardSize)
-    {
-        if (!growClipboardString())
-            return NULL;
-    }
-    _glfw.wl.clipboardString[len] = '\0';
+    free(_glfw.wl.clipboardString);
+    _glfw.wl.clipboardString =
+        readDataOfferAsString(_glfw.wl.selectionOffer, "text/plain;charset=utf-8");
     return _glfw.wl.clipboardString;
 }
 
diff --git a/src/x11_init.c b/src/x11_init.c
index 2bf8cd5..ca8ffcd 100644
--- a/src/x11_init.c
+++ b/src/x11_init.c
@@ -39,6 +39,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <assert.h>
 
 
 // Translate the X11 KeySyms for a key to a GLFW key code
@@ -1028,8 +1029,9 @@
 //
 void _glfwGrabErrorHandlerX11(void)
 {
+    assert(_glfw.x11.errorHandler == NULL);
     _glfw.x11.errorCode = Success;
-    XSetErrorHandler(errorHandler);
+    _glfw.x11.errorHandler = XSetErrorHandler(errorHandler);
 }
 
 // Clears the X error handler callback
@@ -1038,7 +1040,8 @@
 {
     // Synchronize to make sure all commands are processed
     XSync(_glfw.x11.display, False);
-    XSetErrorHandler(NULL);
+    XSetErrorHandler(_glfw.x11.errorHandler);
+    _glfw.x11.errorHandler = NULL;
 }
 
 // Reports the specified error, appending information about the last X error
@@ -1241,6 +1244,7 @@
         _glfw.x11.xi.handle = NULL;
     }
 
+    _glfwTerminateOSMesa();
     // NOTE: These need to be unloaded after XCloseDisplay, as they register
     //       cleanup callbacks that get called by that function
     _glfwTerminateEGL();
diff --git a/src/x11_platform.h b/src/x11_platform.h
index 8c58df2..01808a7 100644
--- a/src/x11_platform.h
+++ b/src/x11_platform.h
@@ -228,6 +228,8 @@
     XContext        context;
     // XIM input method
     XIM             im;
+    // The previous X error handler, to be restored later
+    XErrorHandler   errorHandler;
     // Most recent error code received by X error handler
     int             errorCode;
     // Primary selection string (while the primary selection is owned)
diff --git a/src/x11_window.c b/src/x11_window.c
index 497954e..3dd152b 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -164,7 +164,7 @@
     for (;;)
     {
         const char byte = 0;
-        const int result = write(_glfw.x11.emptyEventPipe[1], &byte, 1);
+        const ssize_t result = write(_glfw.x11.emptyEventPipe[1], &byte, 1);
         if (result == 1 || (result == -1 && errno != EINTR))
             break;
     }
@@ -177,7 +177,7 @@
     for (;;)
     {
         char dummy[64];
-        const int result = read(_glfw.x11.emptyEventPipe[0], dummy, sizeof(dummy));
+        const ssize_t result = read(_glfw.x11.emptyEventPipe[0], dummy, sizeof(dummy));
         if (result == -1 && errno != EINTR)
             break;
     }
@@ -321,6 +321,11 @@
 {
     XSizeHints* hints = XAllocSizeHints();
 
+    long supplied;
+    XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied);
+
+    hints->flags &= ~(PMinSize | PMaxSize | PAspect);
+
     if (!window->monitor)
     {
         if (window->resizable)
@@ -357,9 +362,6 @@
         }
     }
 
-    hints->flags |= PWinGravity;
-    hints->win_gravity = StaticGravity;
-
     XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
     XFree(hints);
 }
@@ -458,57 +460,6 @@
     }
 }
 
-// Splits and translates a text/uri-list into separate file paths
-// NOTE: This function destroys the provided string
-//
-static char** parseUriList(char* text, int* count)
-{
-    const char* prefix = "file://";
-    char** paths = NULL;
-    char* line;
-
-    *count = 0;
-
-    while ((line = strtok(text, "\r\n")))
-    {
-        text = NULL;
-
-        if (line[0] == '#')
-            continue;
-
-        if (strncmp(line, prefix, strlen(prefix)) == 0)
-        {
-            line += strlen(prefix);
-            // TODO: Validate hostname
-            while (*line != '/')
-                line++;
-        }
-
-        (*count)++;
-
-        char* path = calloc(strlen(line) + 1, 1);
-        paths = realloc(paths, *count * sizeof(char*));
-        paths[*count - 1] = path;
-
-        while (*line)
-        {
-            if (line[0] == '%' && line[1] && line[2])
-            {
-                const char digits[3] = { line[1], line[2], '\0' };
-                *path = strtol(digits, NULL, 16);
-                line += 2;
-            }
-            else
-                *path = *line;
-
-            path++;
-            line++;
-        }
-    }
-
-    return paths;
-}
-
 // Decode a Unicode code point from a UTF-8 stream
 // Based on cutef8 by Jeff Bezanson (Public Domain)
 //
@@ -574,6 +525,25 @@
     }
 }
 
+// Grabs the cursor and confines it to the window
+//
+static void captureCursor(_GLFWwindow* window)
+{
+    XGrabPointer(_glfw.x11.display, window->x11.handle, True,
+                 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
+                 GrabModeAsync, GrabModeAsync,
+                 window->x11.handle,
+                 None,
+                 CurrentTime);
+}
+
+// Ungrabs the cursor
+//
+static void releaseCursor(void)
+{
+    XUngrabPointer(_glfw.x11.display, CurrentTime);
+}
+
 // Enable XI2 raw mouse motion events
 //
 static void enableRawMouseMotion(_GLFWwindow* window)
@@ -616,12 +586,7 @@
                               &_glfw.x11.restoreCursorPosY);
     updateCursorImage(window);
     _glfwCenterCursorInContentArea(window);
-    XGrabPointer(_glfw.x11.display, window->x11.handle, True,
-                 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
-                 GrabModeAsync, GrabModeAsync,
-                 window->x11.handle,
-                 _glfw.x11.hiddenCursorHandle,
-                 CurrentTime);
+    captureCursor(window);
 }
 
 // Exit disabled cursor mode for the specified window
@@ -632,7 +597,7 @@
         disableRawMouseMotion(window);
 
     _glfw.x11.disabledCursorWindow = NULL;
-    XUngrabPointer(_glfw.x11.display, CurrentTime);
+    releaseCursor();
     _glfwPlatformSetCursorPos(window,
                               _glfw.x11.restoreCursorPosX,
                               _glfw.x11.restoreCursorPosY);
@@ -777,7 +742,28 @@
         XFree(hints);
     }
 
-    updateNormalHints(window, width, height);
+    // Set ICCCM WM_NORMAL_HINTS property
+    {
+        XSizeHints* hints = XAllocSizeHints();
+        if (!hints)
+        {
+            _glfwInputError(GLFW_OUT_OF_MEMORY, "X11: Failed to allocate size hints");
+            return GLFW_FALSE;
+        }
+
+        if (!wndconfig->resizable)
+        {
+            hints->flags |= (PMinSize | PMaxSize);
+            hints->min_width  = hints->max_width  = width;
+            hints->min_height = hints->max_height = height;
+        }
+
+        hints->flags |= PWinGravity;
+        hints->win_gravity = StaticGravity;
+
+        XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
+        XFree(hints);
+    }
 
     // Set ICCCM WM_CLASS property
     {
@@ -980,20 +966,6 @@
     return None;
 }
 
-static void handleSelectionClear(XEvent* event)
-{
-    if (event->xselectionclear.selection == _glfw.x11.PRIMARY)
-    {
-        free(_glfw.x11.primarySelectionString);
-        _glfw.x11.primarySelectionString = NULL;
-    }
-    else
-    {
-        free(_glfw.x11.clipboardString);
-        _glfw.x11.clipboardString = NULL;
-    }
-}
-
 static void handleSelectionRequest(XEvent* event)
 {
     const XSelectionRequestEvent* request = &event->xselectionrequest;
@@ -1114,13 +1086,16 @@
 
                 if (!itemCount)
                 {
-                    if (targets[i] == XA_STRING)
+                    if (string)
                     {
-                        *selectionString = convertLatin1toUTF8(string);
-                        free(string);
+                        if (targets[i] == XA_STRING)
+                        {
+                            *selectionString = convertLatin1toUTF8(string);
+                            free(string);
+                        }
+                        else
+                            *selectionString = string;
                     }
-                    else
-                        *selectionString = string;
 
                     break;
                 }
@@ -1287,12 +1262,7 @@
         return;
     }
 
-    if (event->type == SelectionClear)
-    {
-        handleSelectionClear(event);
-        return;
-    }
-    else if (event->type == SelectionRequest)
+    if (event->type == SelectionRequest)
     {
         handleSelectionRequest(event);
         return;
@@ -1808,7 +1778,7 @@
                 if (result)
                 {
                     int i, count;
-                    char** paths = parseUriList(data, &count);
+                    char** paths = _glfwParseUriList(data, &count);
 
                     _glfwInputDrop(window, count, (const char**) paths);
 
@@ -1997,10 +1967,6 @@
                     handleSelectionRequest(&event);
                     break;
 
-                case SelectionClear:
-                    handleSelectionClear(&event);
-                    break;
-
                 case SelectionNotify:
                 {
                     if (event.xselection.target == _glfw.x11.SAVE_TARGETS)
@@ -2084,6 +2050,9 @@
             if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
                 return GLFW_FALSE;
         }
+
+        if (!_glfwRefreshContextAttribs(window, ctxconfig))
+            return GLFW_FALSE;
     }
 
     if (window->monitor)
@@ -2091,6 +2060,18 @@
         _glfwPlatformShowWindow(window);
         updateWindowMode(window);
         acquireMonitor(window);
+
+        if (wndconfig->centerCursor)
+            _glfwCenterCursorInContentArea(window);
+    }
+    else
+    {
+        if (wndconfig->visible)
+        {
+            _glfwPlatformShowWindow(window);
+            if (wndconfig->focused)
+                _glfwPlatformFocusWindow(window);
+        }
     }
 
     XFlush(_glfw.x11.display);
@@ -2100,7 +2081,7 @@
 void _glfwPlatformDestroyWindow(_GLFWwindow* window)
 {
     if (_glfw.x11.disabledCursorWindow == window)
-        _glfw.x11.disabledCursorWindow = NULL;
+        enableCursor(window);
 
     if (window->monitor)
         releaseMonitor(window);
@@ -2907,16 +2888,40 @@
 
 void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
 {
-    if (mode == GLFW_CURSOR_DISABLED)
+    if (_glfwPlatformWindowFocused(window))
     {
-        if (_glfwPlatformWindowFocused(window))
-            disableCursor(window);
-    }
-    else if (_glfw.x11.disabledCursorWindow == window)
-        enableCursor(window);
-    else
-        updateCursorImage(window);
+        if (mode == GLFW_CURSOR_DISABLED)
+        {
+            _glfwPlatformGetCursorPos(window,
+                                      &_glfw.x11.restoreCursorPosX,
+                                      &_glfw.x11.restoreCursorPosY);
+            _glfwCenterCursorInContentArea(window);
+            if (window->rawMouseMotion)
+                enableRawMouseMotion(window);
+        }
+        else if (_glfw.x11.disabledCursorWindow == window)
+        {
+            if (window->rawMouseMotion)
+                disableRawMouseMotion(window);
+        }
 
+        if (mode == GLFW_CURSOR_DISABLED)
+            captureCursor(window);
+        else
+            releaseCursor();
+
+        if (mode == GLFW_CURSOR_DISABLED)
+            _glfw.x11.disabledCursorWindow = window;
+        else if (_glfw.x11.disabledCursorWindow == window)
+        {
+            _glfw.x11.disabledCursorWindow = NULL;
+            _glfwPlatformSetCursorPos(window,
+                                      _glfw.x11.restoreCursorPosX,
+                                      _glfw.x11.restoreCursorPosY);
+        }
+    }
+
+    updateCursorImage(window);
     XFlush(_glfw.x11.display);
 }
 
diff --git a/tests/events.c b/tests/events.c
index f29dfbb..9f698f2 100644
--- a/tests/events.c
+++ b/tests/events.c
@@ -621,7 +621,7 @@
 
         glfwMakeContextCurrent(slots[i].window);
         gladLoadGL(glfwGetProcAddress);
-        glfwSwapInterval(1);
+        glfwSwapBuffers(slots[i].window);
     }
 
     printf("Main loop starting\n");
diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c
index 074bcbd..1f3b24b 100644
--- a/tests/glfwinfo.c
+++ b/tests/glfwinfo.c
@@ -210,30 +210,6 @@
     }
 }
 
-static void list_vulkan_instance_extensions(void)
-{
-    uint32_t i, ep_count = 0;
-    VkExtensionProperties* ep;
-
-    printf("Vulkan instance extensions:\n");
-
-    if (vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL) != VK_SUCCESS)
-        return;
-
-    ep = calloc(ep_count, sizeof(VkExtensionProperties));
-
-    if (vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep) != VK_SUCCESS)
-    {
-        free(ep);
-        return;
-    }
-
-    for (i = 0;  i < ep_count;  i++)
-        printf(" %s (v%u)\n", ep[i].extensionName, ep[i].specVersion);
-
-    free(ep);
-}
-
 static void list_vulkan_instance_layers(void)
 {
     uint32_t i, lp_count = 0;
@@ -254,39 +230,16 @@
 
     for (i = 0;  i < lp_count;  i++)
     {
-        printf(" %s (v%u) \"%s\"\n",
+        printf(" %s (spec version %u.%u) \"%s\"\n",
                lp[i].layerName,
-               lp[i].specVersion >> 22,
+               VK_VERSION_MAJOR(lp[i].specVersion),
+               VK_VERSION_MINOR(lp[i].specVersion),
                lp[i].description);
     }
 
     free(lp);
 }
 
-static void list_vulkan_device_extensions(VkInstance instance, VkPhysicalDevice device)
-{
-    uint32_t i, ep_count;
-    VkExtensionProperties* ep;
-
-    printf("Vulkan device extensions:\n");
-
-    if (vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, NULL) != VK_SUCCESS)
-        return;
-
-    ep = calloc(ep_count, sizeof(VkExtensionProperties));
-
-    if (vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, ep) != VK_SUCCESS)
-    {
-        free(ep);
-        return;
-    }
-
-    for (i = 0;  i < ep_count;  i++)
-        printf(" %s (v%u)\n", ep[i].extensionName, ep[i].specVersion);
-
-    free(ep);
-}
-
 static void list_vulkan_device_layers(VkInstance instance, VkPhysicalDevice device)
 {
     uint32_t i, lp_count;
@@ -307,9 +260,10 @@
 
     for (i = 0;  i < lp_count;  i++)
     {
-        printf(" %s (v%u) \"%s\"\n",
+        printf(" %s (spec version %u.%u) \"%s\"\n",
                lp[i].layerName,
-               lp[i].specVersion >> 22,
+               VK_VERSION_MAJOR(lp[i].specVersion),
+               VK_VERSION_MINOR(lp[i].specVersion),
                lp[i].description);
     }
 
@@ -346,11 +300,6 @@
     printf("GLFW library version string: \"%s\"\n", glfwGetVersionString());
 }
 
-static GLADapiproc glad_vulkan_callback(const char* name, void* user)
-{
-    return glfwGetInstanceProcAddress((VkInstance) user, name);
-}
-
 int main(int argc, char** argv)
 {
     int ch, client, major, minor, revision, profile;
@@ -806,20 +755,33 @@
     if (list_extensions)
         list_context_extensions(client, major, minor);
 
+    glfwDestroyWindow(window);
+
+    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+
+    window = glfwCreateWindow(200, 200, "Version", NULL, NULL);
+    if (!window)
+    {
+        glfwTerminate();
+        exit(EXIT_FAILURE);
+    }
+
     printf("Vulkan loader: %s\n",
            glfwVulkanSupported() ? "available" : "missing");
 
     if (glfwVulkanSupported())
     {
         uint32_t loader_version = VK_API_VERSION_1_0;
-        uint32_t i, re_count, pd_count;
+        int portability_enumeration = GLFW_FALSE;
+        uint32_t i, j, glfw_re_count, re_count, pd_count, ep_count;
+        const char** glfw_re;
         const char** re;
         VkApplicationInfo ai = {0};
         VkInstanceCreateInfo ici = {0};
         VkInstance instance;
         VkPhysicalDevice* pd;
 
-        gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, NULL);
+        gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, NULL);
 
         if (vkEnumerateInstanceVersion)
         {
@@ -832,20 +794,47 @@
                VK_VERSION_MAJOR(loader_version),
                VK_VERSION_MINOR(loader_version));
 
-        re = glfwGetRequiredInstanceExtensions(&re_count);
+        glfw_re = glfwGetRequiredInstanceExtensions(&glfw_re_count);
 
-        printf("Vulkan required instance extensions:");
-        if (re)
+        re_count = glfw_re_count;
+        re = calloc(glfw_re_count, sizeof(char*));
+
+        printf("Vulkan window surface required instance extensions:\n");
+        if (glfw_re)
         {
-            for (i = 0;  i < re_count;  i++)
-                printf(" %s", re[i]);
-            putchar('\n');
+            for (i = 0;  i < glfw_re_count;  i++)
+            {
+                printf(" %s\n", glfw_re[i]);
+                re[i] = glfw_re[i];
+            }
         }
         else
             printf(" missing\n");
 
+        vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL);
+        VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
+        vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep);
+
         if (list_extensions)
-            list_vulkan_instance_extensions();
+        {
+            printf("Vulkan instance extensions:\n");
+
+            for (i = 0;  i < ep_count;  i++)
+                printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion);
+        }
+
+        for (i = 0;  i < ep_count;  i++)
+        {
+            if (strcmp(ep[i].extensionName, "VK_KHR_portability_enumeration") != 0)
+                continue;
+
+            re_count++;
+            re = realloc((void*) re, sizeof(char*) * re_count);
+            re[re_count - 1] = "VK_KHR_portability_enumeration";
+            portability_enumeration = GLFW_TRUE;
+        }
+
+        free(ep);
 
         if (list_layers)
             list_vulkan_instance_layers();
@@ -866,34 +855,40 @@
         ici.enabledExtensionCount = re_count;
         ici.ppEnabledExtensionNames = re;
 
+        if (portability_enumeration)
+            ici.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
+
         if (vkCreateInstance(&ici, NULL, &instance) != VK_SUCCESS)
         {
             glfwTerminate();
             exit(EXIT_FAILURE);
         }
 
-        gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, instance);
-
-        if (vkEnumeratePhysicalDevices(instance, &pd_count, NULL) != VK_SUCCESS)
+        if (re)
         {
-            vkDestroyInstance(instance, NULL);
-            glfwTerminate();
-            exit(EXIT_FAILURE);
+            VkSurfaceKHR surface = VK_NULL_HANDLE;
+
+            if (glfwCreateWindowSurface(instance, window, NULL, &surface) == VK_SUCCESS)
+            {
+                printf("Vulkan window surface created successfully\n");
+                vkDestroySurfaceKHR(instance, surface, NULL);
+            }
+            else
+                printf("Failed to create Vulkan window surface\n");
         }
 
+        free((void*) re);
+
+        gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, instance);
+
+        vkEnumeratePhysicalDevices(instance, &pd_count, NULL);
         pd = calloc(pd_count, sizeof(VkPhysicalDevice));
-
-        if (vkEnumeratePhysicalDevices(instance, &pd_count, pd) != VK_SUCCESS)
-        {
-            free(pd);
-            vkDestroyInstance(instance, NULL);
-            glfwTerminate();
-            exit(EXIT_FAILURE);
-        }
+        vkEnumeratePhysicalDevices(instance, &pd_count, pd);
 
         for (i = 0;  i < pd_count;  i++)
         {
             VkPhysicalDeviceProperties pdp;
+            uint32_t qfp_count, ep_count;
 
             vkGetPhysicalDeviceProperties(pd[i], &pdp);
 
@@ -903,8 +898,62 @@
                    VK_VERSION_MAJOR(pdp.apiVersion),
                    VK_VERSION_MINOR(pdp.apiVersion));
 
+            vkGetPhysicalDeviceQueueFamilyProperties(pd[i], &qfp_count, NULL);
+
+            vkEnumerateDeviceExtensionProperties(pd[i], NULL, &ep_count, NULL);
+            VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
+            vkEnumerateDeviceExtensionProperties(pd[i], NULL, &ep_count, ep);
+
+            if (portability_enumeration)
+            {
+                int conformant = GLFW_TRUE;
+
+                for (j = 0; j < ep_count; j++)
+                {
+                    if (strcmp(ep[j].extensionName, "VK_KHR_portability_subset") == 0)
+                    {
+                        conformant = GLFW_FALSE;
+                        break;
+                    }
+                }
+
+                printf("Vulkan %s %s device: \"%s\" (API version %i.%i)\n",
+                       conformant ? "conformant" : "non-conformant",
+                       get_device_type_name(pdp.deviceType),
+                       pdp.deviceName,
+                       VK_VERSION_MAJOR(pdp.apiVersion),
+                       VK_VERSION_MINOR(pdp.apiVersion));
+            }
+            else
+            {
+                printf("Vulkan %s device: \"%s\" (API version %i.%i)\n",
+                       get_device_type_name(pdp.deviceType),
+                       pdp.deviceName,
+                       VK_VERSION_MAJOR(pdp.apiVersion),
+                       VK_VERSION_MINOR(pdp.apiVersion));
+            }
+
+            if (glfw_re_count)
+            {
+                printf("Vulkan device queue family presentation support:\n");
+                for (j = 0;  j < qfp_count;  j++)
+                {
+                    printf(" %u: ", j);
+                    if (glfwGetPhysicalDevicePresentationSupport(instance, pd[i], j))
+                        printf("supported\n");
+                    else
+                        printf("no\n");
+                }
+            }
+
             if (list_extensions)
-                list_vulkan_device_extensions(instance, pd[i]);
+            {
+                printf("Vulkan device extensions:\n");
+                for (j = 0;  j < ep_count;  j++)
+                    printf(" %s (spec version %u)\n", ep[j].extensionName, ep[j].specVersion);
+            }
+
+            free(ep);
 
             if (list_layers)
                 list_vulkan_device_layers(instance, pd[i]);
@@ -914,6 +963,8 @@
         vkDestroyInstance(instance, NULL);
     }
 
+    glfwDestroyWindow(window);
+
     glfwTerminate();
     exit(EXIT_SUCCESS);
 }
diff --git a/tests/triangle-vulkan.c b/tests/triangle-vulkan.c
index 7f78369..3a4bfb1 100644
--- a/tests/triangle-vulkan.c
+++ b/tests/triangle-vulkan.c
@@ -65,11 +65,6 @@
         exit(1);                                                               \
     } while (0)
 
-static GLADapiproc glad_vulkan_callback(const char* name, void* user)
-{
-    return glfwGetInstanceProcAddress((VkInstance) user, name);
-}
-
 static const uint32_t fragShaderCode[] = {
     0x07230203,0x00010000,0x00080007,0x00000014,0x00000000,0x00020011,0x00000001,0x0006000b,
     0x00000001,0x4c534c47,0x6474732e,0x3035342e,0x00000000,0x0003000e,0x00000000,0x00000001,
@@ -1251,7 +1246,7 @@
     VkPipelineDepthStencilStateCreateInfo ds;
     VkPipelineViewportStateCreateInfo vp;
     VkPipelineMultisampleStateCreateInfo ms;
-    VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE];
+    VkDynamicState dynamicStateEnables[2];
     VkPipelineDynamicStateCreateInfo dynamicState;
 
     VkResult U_ASSERT_ONLY err;
@@ -1565,6 +1560,7 @@
 
 static void demo_init_vk(struct demo *demo) {
     VkResult err;
+    VkBool32 portability_enumeration = VK_FALSE;
     uint32_t i = 0;
     uint32_t required_extension_count = 0;
     uint32_t instance_extension_count = 0;
@@ -1672,6 +1668,13 @@
                 }
             }
             assert(demo->enabled_extension_count < 64);
+            if (!strcmp(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
+                        instance_extensions[i].extensionName)) {
+                demo->extension_names[demo->enabled_extension_count++] =
+                    VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME;
+                portability_enumeration = VK_TRUE;
+            }
+            assert(demo->enabled_extension_count < 64);
         }
 
         free(instance_extensions);
@@ -1696,6 +1699,9 @@
         .ppEnabledExtensionNames = (const char *const *)demo->extension_names,
     };
 
+    if (portability_enumeration)
+        inst_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
+
     uint32_t gpu_count;
 
     err = vkCreateInstance(&inst_info, NULL, &demo->inst);
@@ -1715,7 +1721,7 @@
                  "vkCreateInstance Failure");
     }
 
-    gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, demo->inst);
+    gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, demo->inst);
 
     /* Make initial call to query gpu_count, then second call for gpu info*/
     err = vkEnumeratePhysicalDevices(demo->inst, &gpu_count, NULL);
@@ -1738,7 +1744,7 @@
                  "vkEnumeratePhysicalDevices Failure");
     }
 
-    gladLoadVulkanUserPtr(demo->gpu, glad_vulkan_callback, demo->inst);
+    gladLoadVulkanUserPtr(demo->gpu, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, demo->inst);
 
     /* Look for device extensions */
     uint32_t device_extension_count = 0;
@@ -1966,7 +1972,7 @@
         exit(1);
     }
 
-    gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, NULL);
+    gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, NULL);
 }
 
 static void demo_init(struct demo *demo, const int argc, const char *argv[])