Quellcode durchsuchen

Add the SDL_GPU API

Project Lead: Evan Hemsley <evan@moonside.games>

Co-designer, Metal Port, Console Ports:

Co-authored-by: Caleb Cornett <caleb.cornett@outlook.com>

Production, QA, Debug:

Co-authored-by: Ethan Lee <flibitijibibo@gmail.com>

SDL_Render Driver, Bugfixes:

Co-authored-by: Andrei Alexeyev <akari@taisei-project.org>

Additional D3D12 Programming, Bugfixes:

Co-authored-by: Bart van der Werf <bluelive@gmail.com>

Bugfixes and Feedback:

Co-authored-by: Zakary Strange <zakarystrange@gmail.com>
Co-authored-by: meyraud705 <meyraud705@gmail.com>
Co-authored-by: Joshua T. Fisher <playmer@gmail.com>
Co-authored-by: Topi Ritala <ritalat@fastmail.com>
Co-authored-by: David Gow <david@ingeniumdigital.com>

Original API Proposal:

Co-authored-by: Ryan C. Gordon <icculus@icculus.org>
cosmonaut vor 1 Jahr
Ursprung
Commit
2e7d5bb429
96 geänderte Dateien mit 60218 neuen und 66 gelöschten Zeilen
  1. 2 0
      .gitignore
  2. 2 0
      Android.mk
  3. 39 0
      CMakeLists.txt
  4. 15 0
      VisualC-GDK/SDL/SDL.vcxproj
  5. 6 0
      VisualC-GDK/SDL/SDL.vcxproj.filters
  6. 4 0
      VisualC-WinRT/SDL-UWP.vcxproj
  7. 7 0
      VisualC/SDL/SDL.vcxproj
  8. 22 0
      VisualC/SDL/SDL.vcxproj.filters
  9. 1 0
      include/SDL3/SDL.h
  10. 2512 0
      include/SDL3/SDL_gpu.h
  11. 102 61
      include/SDL3/SDL_hints.h
  12. 4 3
      include/SDL3/SDL_log.h
  13. 7 0
      include/build_config/SDL_build_config.h.cmake
  14. 2 0
      include/build_config/SDL_build_config_android.h
  15. 4 0
      include/build_config/SDL_build_config_macos.h
  16. 6 0
      include/build_config/SDL_build_config_windows.h
  17. 6 0
      include/build_config/SDL_build_config_wingdk.h
  18. 4 0
      include/build_config/SDL_build_config_xbox.h
  19. 2 0
      src/SDL_log.c
  20. 10 0
      src/core/SDL_core_unsupported.c
  21. 81 0
      src/dynapi/SDL_dynapi.sym
  22. 81 0
      src/dynapi/SDL_dynapi_overrides.h
  23. 81 0
      src/dynapi/SDL_dynapi_procs.h
  24. 2400 0
      src/gpu/SDL_gpu.c
  25. 779 0
      src/gpu/SDL_sysgpu.h
  26. 1328 0
      src/gpu/d3d11/D3D11_Blit.h
  27. 6135 0
      src/gpu/d3d11/SDL_gpu_d3d11.c
  28. 7 0
      src/gpu/d3d11/compile_shaders.bat
  29. 2665 0
      src/gpu/d3d12/D3D12_Blit.h
  30. 8255 0
      src/gpu/d3d12/SDL_gpu_d3d12.c
  31. 17 0
      src/gpu/d3d12/compile_shaders.bat
  32. 13 0
      src/gpu/d3d12/compile_shaders_xbox.bat
  33. 91 0
      src/gpu/d3dcommon/D3D_Blit.hlsl
  34. 7969 0
      src/gpu/metal/Metal_Blit.h
  35. 85 0
      src/gpu/metal/Metal_Blit.metal
  36. 3984 0
      src/gpu/metal/SDL_gpu_metal.m
  37. 68 0
      src/gpu/metal/compile_shaders.sh
  38. 11797 0
      src/gpu/vulkan/SDL_gpu_vulkan.c
  39. 176 0
      src/gpu/vulkan/SDL_gpu_vulkan_vkfuncs.h
  40. 1 1
      src/render/SDL_d3dmath.h
  41. 4 1
      src/render/SDL_render.c
  42. 1 0
      src/render/SDL_sysrender.h
  43. 74 0
      src/render/sdlgpu/SDL_gpu_util.h
  44. 223 0
      src/render/sdlgpu/SDL_pipeline_gpu.c
  45. 49 0
      src/render/sdlgpu/SDL_pipeline_gpu.h
  46. 1303 0
      src/render/sdlgpu/SDL_render_gpu.c
  47. 241 0
      src/render/sdlgpu/SDL_shaders_gpu.c
  48. 63 0
      src/render/sdlgpu/SDL_shaders_gpu.h
  49. 1 0
      src/render/sdlgpu/shaders/.gitattributes
  50. 3 0
      src/render/sdlgpu/shaders/.gitignore
  51. 85 0
      src/render/sdlgpu/shaders/build-shaders.sh
  52. 9 0
      src/render/sdlgpu/shaders/color.frag
  53. 28 0
      src/render/sdlgpu/shaders/color.frag.metal.h
  54. 85 0
      src/render/sdlgpu/shaders/color.frag.sm50.dxbc.h
  55. 340 0
      src/render/sdlgpu/shaders/color.frag.sm60.dxil.h
  56. 29 0
      src/render/sdlgpu/shaders/color.frag.spv.h
  57. 6 0
      src/render/sdlgpu/shaders/dxbc50.h
  58. 6 0
      src/render/sdlgpu/shaders/dxil60.h
  59. 17 0
      src/render/sdlgpu/shaders/linepoint.vert
  60. 51 0
      src/render/sdlgpu/shaders/linepoint.vert.metal.h
  61. 172 0
      src/render/sdlgpu/shaders/linepoint.vert.sm50.dxbc.h
  62. 496 0
      src/render/sdlgpu/shaders/linepoint.vert.sm60.dxil.h
  63. 93 0
      src/render/sdlgpu/shaders/linepoint.vert.spv.h
  64. 6 0
      src/render/sdlgpu/shaders/metal.h
  65. 6 0
      src/render/sdlgpu/shaders/spir-v.h
  66. 12 0
      src/render/sdlgpu/shaders/texture_rgb.frag
  67. 41 0
      src/render/sdlgpu/shaders/texture_rgb.frag.metal.h
  68. 123 0
      src/render/sdlgpu/shaders/texture_rgb.frag.sm50.dxbc.h
  69. 465 0
      src/render/sdlgpu/shaders/texture_rgb.frag.sm60.dxil.h
  70. 59 0
      src/render/sdlgpu/shaders/texture_rgb.frag.spv.h
  71. 12 0
      src/render/sdlgpu/shaders/texture_rgba.frag
  72. 40 0
      src/render/sdlgpu/shaders/texture_rgba.frag.metal.h
  73. 120 0
      src/render/sdlgpu/shaders/texture_rgba.frag.sm50.dxbc.h
  74. 467 0
      src/render/sdlgpu/shaders/texture_rgba.frag.sm60.dxil.h
  75. 50 0
      src/render/sdlgpu/shaders/texture_rgba.frag.spv.h
  76. 17 0
      src/render/sdlgpu/shaders/tri_color.vert
  77. 48 0
      src/render/sdlgpu/shaders/tri_color.vert.metal.h
  78. 178 0
      src/render/sdlgpu/shaders/tri_color.vert.sm50.dxbc.h
  79. 515 0
      src/render/sdlgpu/shaders/tri_color.vert.sm60.dxil.h
  80. 89 0
      src/render/sdlgpu/shaders/tri_color.vert.spv.h
  81. 20 0
      src/render/sdlgpu/shaders/tri_texture.vert
  82. 56 0
      src/render/sdlgpu/shaders/tri_texture.vert.metal.h
  83. 195 0
      src/render/sdlgpu/shaders/tri_texture.vert.sm50.dxbc.h
  84. 558 0
      src/render/sdlgpu/shaders/tri_texture.vert.sm60.dxil.h
  85. 106 0
      src/render/sdlgpu/shaders/tri_texture.vert.spv.h
  86. 11 0
      src/video/directx/SDL_d3d12.h
  87. 1 0
      test/CMakeLists.txt
  88. 103 0
      test/testgpu/build-shaders.sh
  89. 31 0
      test/testgpu/cube.glsl
  90. 35 0
      test/testgpu/cube.hlsl
  91. 38 0
      test/testgpu/cube.metal
  92. 333 0
      test/testgpu/testgpu_dxbc.h
  93. 876 0
      test/testgpu/testgpu_dxil.h
  94. 2584 0
      test/testgpu/testgpu_metallib.h
  95. 150 0
      test/testgpu/testgpu_spirv.h
  96. 724 0
      test/testgpu_spinning_cube.c

+ 2 - 0
.gitignore

@@ -83,6 +83,8 @@ VisualC/tests/testyuv/testyuv.bmp
 VisualC-GDK/**/Layout
 src/render/direct3d12/D3D12_*_One.h
 src/render/direct3d12/D3D12_*_Series.h
+src/gpu/d3d12/D3D12_*_One.h
+src/gpu/d3d12/D3D12_*_Series.h
 Directory.Build.props
 
 # for Android

+ 2 - 0
Android.mk

@@ -35,6 +35,8 @@ LOCAL_SRC_FILES := \
 	$(wildcard $(LOCAL_PATH)/src/dynapi/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/events/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/file/*.c) \
+	$(wildcard $(LOCAL_PATH)/src/gpu/*.c) \
+	$(wildcard $(LOCAL_PATH)/src/gpu/vulkan/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/haptic/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/haptic/android/*.c) \
 	$(wildcard $(LOCAL_PATH)/src/haptic/dummy/*.c) \

+ 39 - 0
CMakeLists.txt

@@ -233,6 +233,7 @@ endmacro()
 
 define_sdl_subsystem(Audio)
 define_sdl_subsystem(Video)
+define_sdl_subsystem(Gpu DEPS SDL_VIDEO)
 define_sdl_subsystem(Render DEPS SDL_VIDEO)
 define_sdl_subsystem(Camera DEPS SDL_VIDEO)
 define_sdl_subsystem(Joystick)
@@ -331,6 +332,7 @@ dep_option(SDL_RENDER_D3D          "Enable the Direct3D 9 render driver" ON "SDL
 dep_option(SDL_RENDER_D3D11        "Enable the Direct3D 11 render driver" ON "SDL_RENDER;SDL_DIRECTX" OFF)
 dep_option(SDL_RENDER_D3D12        "Enable the Direct3D 12 render driver" ON "SDL_RENDER;SDL_DIRECTX" OFF)
 dep_option(SDL_RENDER_METAL        "Enable the Metal render driver" ON "SDL_RENDER;${APPLE}" OFF)
+set_option(SDL_RENDER_GPU          "Enable the SDL_Gpu render driver" ON)
 dep_option(SDL_VIVANTE             "Use Vivante EGL video driver" ON "${UNIX_SYS};SDL_CPU_ARM32" OFF)
 dep_option(SDL_VULKAN              "Enable Vulkan support" ON "SDL_VIDEO;ANDROID OR APPLE OR LINUX OR FREEBSD OR WINDOWS" OFF)
 dep_option(SDL_RENDER_VULKAN       "Enable the Vulkan render driver" ON "SDL_RENDER;SDL_VULKAN" OFF)
@@ -350,6 +352,7 @@ set_option(SDL_LIBUDEV             "Enable libudev support" ON)
 set_option(SDL_ASAN                "Use AddressSanitizer to detect memory errors" OFF)
 set_option(SDL_CCACHE              "Use Ccache to speed up build" OFF)
 set_option(SDL_CLANG_TIDY          "Run clang-tidy static analysis" OFF)
+set_option(SDL_GPU_DXVK            "Build SDL_Gpu with DXVK support" OFF)
 
 set(SDL_VENDOR_INFO "" CACHE STRING "Vendor name and/or version to add to SDL_REVISION")
 
@@ -1123,6 +1126,7 @@ sdl_glob_sources(
   "${SDL3_SOURCE_DIR}/src/events/*.c"
   "${SDL3_SOURCE_DIR}/src/file/*.c"
   "${SDL3_SOURCE_DIR}/src/filesystem/*.c"
+  "${SDL3_SOURCE_DIR}/src/gpu/*.c"
   "${SDL3_SOURCE_DIR}/src/joystick/*.c"
   "${SDL3_SOURCE_DIR}/src/haptic/*.c"
   "${SDL3_SOURCE_DIR}/src/hidapi/*.c"
@@ -1704,6 +1708,16 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
       )
     endif()
 
+    if(SDL_GPU AND SDL_GPU_DXVK)
+      if(PKG_CONFIG_FOUND)
+        pkg_search_module(DXVK_NATIVE dxvk-dxgi)
+        if(DXVK_NATIVE_FOUND)
+          set(HAVE_D3D11_H TRUE)
+          sdl_include_directories(PRIVATE SYSTEM ${DXVK_NATIVE_INCLUDE_DIRS})
+        endif()
+      endif()
+    endif()
+
     # Always compiled for Linux, unconditionally:
     sdl_sources(
       "${SDL3_SOURCE_DIR}/src/core/linux/SDL_evdev_capabilities.c"
@@ -2363,6 +2377,10 @@ elseif(APPLE)
           set(SDL_VIDEO_RENDER_METAL 1)
           set(HAVE_RENDER_METAL TRUE)
         endif()
+        if (SDL_GPU)
+          set(SDL_GPU_METAL 1)
+          sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/metal/*.m")
+        endif()
       endif()
     endif()
   endif()
@@ -2925,6 +2943,27 @@ if(SDL_VIDEO)
   endif()
 endif()
 
+if(SDL_GPU)
+  if(HAVE_D3D11_H)
+    sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/d3d11/*.c")
+    set(SDL_GPU_D3D11 1)
+    set(HAVE_SDL_GPU TRUE)
+  endif()
+  if(SDL_RENDER_D3D12)
+    sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/d3d12/*.c")
+    set(SDL_GPU_D3D12 1)
+    set(HAVE_SDL_GPU TRUE)
+  endif()
+  if(SDL_VIDEO_VULKAN)
+    sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/vulkan/*.c")
+    set(SDL_GPU_VULKAN 1)
+    set(HAVE_SDL_GPU TRUE)
+  endif()
+  if(SDL_RENDER_GPU)
+    set(SDL_VIDEO_RENDER_GPU 1)
+  endif()
+endif()
+
 # Dummies
 # configure.ac does it differently:
 # if not have X

+ 15 - 0
VisualC-GDK/SDL/SDL.vcxproj

@@ -166,6 +166,7 @@
     </Link>
     <PreBuildEvent>
       <Command>$(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir)</Command>
+      <Command>$(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir)</Command>
     </PreBuildEvent>
     <PreBuildEvent>
       <Message>Building shader blobs (Xbox Series)</Message>
@@ -200,6 +201,7 @@
     </Link>
     <PreBuildEvent>
       <Command>$(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) one</Command>
+      <Command>$(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir) one</Command>
     </PreBuildEvent>
     <PreBuildEvent>
       <Message>Building shader blobs (Xbox One)</Message>
@@ -266,6 +268,7 @@
     </Link>
     <PreBuildEvent>
       <Command>$(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir)</Command>
+      <Command>$(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir)</Command>
     </PreBuildEvent>
     <PreBuildEvent>
       <Message>Building shader blobs (Xbox Series)</Message>
@@ -301,6 +304,7 @@
     </Link>
     <PreBuildEvent>
       <Command>$(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) one</Command>
+      <Command>$(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir) one</Command>
     </PreBuildEvent>
     <PreBuildEvent>
       <Message>Building shader blobs (Xbox One)</Message>
@@ -330,6 +334,7 @@
     <ClInclude Include="..\..\include\SDL3\SDL_events.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_filesystem.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_gamepad.h" />
+    <ClInclude Include="..\..\include\SDL3\SDL_gpu.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_guid.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_haptic.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_hints.h" />
@@ -424,6 +429,7 @@
     <ClInclude Include="..\..\src\events\SDL_touch_c.h" />
     <ClInclude Include="..\..\src\events\SDL_windowevents_c.h" />
     <ClInclude Include="..\..\src\filesystem\SDL_sysfilesystem.h" />
+    <ClInclude Include="..\..\src\gpu\SDL_sysgpu.h" />
     <ClInclude Include="..\..\src\haptic\SDL_haptic_c.h" />
     <ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
@@ -865,6 +871,15 @@
     <ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb_lsx.c" />
     <ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb_sse.c" />
     <ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb_std.c" />
+    <ClCompile Include="..\..\src\gpu\SDL_gpu.c" />
+    <ClCompile Include="..\..\src\gpu\d3d11\SDL_gpu_d3d11.c" />
+    <ClCompile Include="..\..\src\gpu\d3d12\SDL_gpu_d3d12.c">
+      <CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|Gaming.Xbox.Scarlett.x64'">CompileAsCpp</CompileAs>
+      <CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|Gaming.Xbox.XboxOne.x64'">CompileAsCpp</CompileAs>
+      <CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Xbox.Scarlett.x64'">CompileAsCpp</CompileAs>
+      <CompileAs Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Xbox.XboxOne.x64'">CompileAsCpp</CompileAs>
+    </ClCompile>
+    <ClCompile Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan.c" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\src\core\windows\version.rc" />

+ 6 - 0
VisualC-GDK/SDL/SDL.vcxproj.filters

@@ -57,6 +57,10 @@
     <ClCompile Include="..\..\src\events\SDL_windowevents.c" />
     <ClCompile Include="..\..\src\file\SDL_iostream.c" />
     <ClCompile Include="..\..\src\filesystem\gdk\SDL_sysfilesystem.cpp" />
+    <ClCompile Include="..\..\src\gpu\SDL_gpu.c" />
+    <ClCompile Include="..\..\src\gpu\d3d11\SDL_gpu_d3d11.c" />
+    <ClCompile Include="..\..\src\gpu\d3d12\SDL_gpu_d3d12.c" />
+    <ClCompile Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan.c" />
     <ClCompile Include="..\..\src\haptic\dummy\SDL_syshaptic.c" />
     <ClCompile Include="..\..\src\haptic\SDL_haptic.c" />
     <ClCompile Include="..\..\src\haptic\windows\SDL_dinputhaptic.c" />
@@ -249,6 +253,7 @@
     <ClInclude Include="..\..\include\SDL3\SDL_events.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_filesystem.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_gamepad.h" />
+    <ClInclude Include="..\..\include\SDL3\SDL_gpu.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_guid.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_haptic.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_hints.h" />
@@ -341,6 +346,7 @@
     <ClInclude Include="..\..\src\filesystem\SDL_sysfilesystem.h">
       <Filter>filesystem</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\gpu\SDL_sysgpu.h" />
     <ClInclude Include="..\..\src\haptic\SDL_haptic_c.h" />
     <ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />

+ 4 - 0
VisualC-WinRT/SDL-UWP.vcxproj

@@ -125,6 +125,7 @@
     <ClInclude Include="..\src\events\SDL_touch_c.h" />
     <ClInclude Include="..\src\events\SDL_windowevents_c.h" />
     <ClInclude Include="..\src\filesystem\SDL_sysfilesystem.h" />
+    <ClInclude Include="..\src\gpu\SDL_sysgpu.h" />
     <ClInclude Include="..\src\haptic\SDL_haptic_c.h" />
     <ClInclude Include="..\src\haptic\SDL_syshaptic.h" />
     <ClInclude Include="..\src\haptic\windows\SDL_dinputhaptic_c.h" />
@@ -343,6 +344,9 @@
     <ClCompile Include="..\src\file\SDL_iostream.c" />
     <ClCompile Include="..\src\filesystem\SDL_filesystem.c" />
     <ClCompile Include="..\src\filesystem\windows\SDL_sysfsops.c" />
+    <ClCompile Include="..\src\gpu\SDL_gpu.c "/>
+    <ClCompile Include="..\src\gpu\d3d11\SDL_gpu_d3d11.c "/>
+    <ClCompile Include="..\src\gpu\d3d12\SDL_gpu_d3d12.c "/>
     <ClCompile Include="..\src\haptic\dummy\SDL_syshaptic.c" />
     <ClCompile Include="..\src\haptic\SDL_haptic.c" />
     <ClCompile Include="..\src\haptic\windows\SDL_dinputhaptic.c" />

+ 7 - 0
VisualC/SDL/SDL.vcxproj

@@ -254,6 +254,7 @@
     <ClInclude Include="..\..\include\SDL3\SDL_events.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_filesystem.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_gamepad.h" />
+    <ClInclude Include="..\..\include\SDL3\SDL_gpu.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_guid.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_haptic.h" />
     <ClInclude Include="..\..\include\SDL3\SDL_hints.h" />
@@ -348,6 +349,8 @@
     <ClInclude Include="..\..\src\events\SDL_touch_c.h" />
     <ClInclude Include="..\..\src\events\SDL_windowevents_c.h" />
     <ClInclude Include="..\..\src\filesystem\SDL_sysfilesystem.h" />
+    <ClInclude Include="..\..\src\gpu\SDL_sysgpu.h" />
+    <ClInclude Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan_vkfuncs.h" />
     <ClInclude Include="..\..\src\haptic\SDL_haptic_c.h" />
     <ClInclude Include="..\..\src\haptic\SDL_syshaptic.h" />
     <ClInclude Include="..\..\src\haptic\windows\SDL_dinputhaptic_c.h" />
@@ -408,6 +411,10 @@
     <ClCompile Include="..\..\src\dialog\SDL_dialog_utils.c" />
     <ClCompile Include="..\..\src\filesystem\SDL_filesystem.c" />
     <ClCompile Include="..\..\src\filesystem\windows\SDL_sysfsops.c" />
+    <ClCompile Include="..\..\src\gpu\SDL_gpu.c" />
+    <ClCompile Include="..\..\src\gpu\d3d11\SDL_gpu_d3d11.c" />
+    <ClCompile Include="..\..\src\gpu\d3d12\SDL_gpu_d3d12.c" />
+    <ClCompile Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan.c" />
     <ClCompile Include="..\..\src\main\generic\SDL_sysmain_callbacks.c" />
     <ClCompile Include="..\..\src\main\SDL_main_callbacks.c" />
     <ClCompile Include="..\..\src\main\SDL_runapp.c" />

+ 22 - 0
VisualC/SDL/SDL.vcxproj.filters

@@ -198,6 +198,8 @@
     </Filter>
     <Filter Include="time\windows">
       <UniqueIdentifier>{0000d7fda065b13b0ca4ab262c380000}</UniqueIdentifier>
+    <Filter Include="gpu">
+      <UniqueIdentifier>{098fbef9-d8a0-4b3b-b57b-d157d395335d}</UniqueIdentifier>
     </Filter>
     <Filter Include="dialog">
       <UniqueIdentifier>{00008dfdfa0190856fbf3c7db52d0000}</UniqueIdentifier>
@@ -907,6 +909,14 @@
     </ClInclude>
     <ClInclude Include="..\..\src\video\offscreen\SDL_offscreenwindow.h">
       <Filter>video\offscreen</Filter>
+    <ClInclude Include="..\..\include\SDL3\SDL_gpu.h">
+      <Filter>API Headers</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\gpu\SDL_sysgpu.h">
+      <Filter>gpu</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan_vkfuncs.h">
+      <Filter>gpu</Filter>
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
@@ -1562,6 +1572,18 @@
     <ClCompile Include="..\..\src\video\offscreen\SDL_offscreenwindow.c">
       <Filter>video\offscreen</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\gpu\SDL_gpu.c">
+      <Filter>gpu</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\gpu\d3d11\SDL_gpu_d3d11.c">
+      <Filter>gpu</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\gpu\d3d12\SDL_gpu_d3d12.c">
+      <Filter>gpu</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan.c">
+      <Filter>gpu</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\..\src\core\windows\version.rc" />

+ 1 - 0
include/SDL3/SDL.h

@@ -43,6 +43,7 @@
 #include <SDL3/SDL_events.h>
 #include <SDL3/SDL_filesystem.h>
 #include <SDL3/SDL_gamepad.h>
+#include <SDL3/SDL_gpu.h>
 #include <SDL3/SDL_guid.h>
 #include <SDL3/SDL_haptic.h>
 #include <SDL3/SDL_hidapi.h>

+ 2512 - 0
include/SDL3/SDL_gpu.h

@@ -0,0 +1,2512 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_gpu.h
+ *
+ * Include file for SDL GPU API functions
+ */
+
+#ifndef SDL_GPU_H
+#define SDL_GPU_H
+
+#include <SDL3/SDL_stdinc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Type Declarations */
+
+typedef struct SDL_GpuDevice SDL_GpuDevice;
+typedef struct SDL_GpuBuffer SDL_GpuBuffer;
+typedef struct SDL_GpuTransferBuffer SDL_GpuTransferBuffer;
+typedef struct SDL_GpuTexture SDL_GpuTexture;
+typedef struct SDL_GpuSampler SDL_GpuSampler;
+typedef struct SDL_GpuShader SDL_GpuShader;
+typedef struct SDL_GpuComputePipeline SDL_GpuComputePipeline;
+typedef struct SDL_GpuGraphicsPipeline SDL_GpuGraphicsPipeline;
+typedef struct SDL_GpuCommandBuffer SDL_GpuCommandBuffer;
+typedef struct SDL_GpuRenderPass SDL_GpuRenderPass;
+typedef struct SDL_GpuComputePass SDL_GpuComputePass;
+typedef struct SDL_GpuCopyPass SDL_GpuCopyPass;
+typedef struct SDL_GpuFence SDL_GpuFence;
+
+typedef enum SDL_GpuPrimitiveType
+{
+    SDL_GPU_PRIMITIVETYPE_POINTLIST,
+    SDL_GPU_PRIMITIVETYPE_LINELIST,
+    SDL_GPU_PRIMITIVETYPE_LINESTRIP,
+    SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
+    SDL_GPU_PRIMITIVETYPE_TRIANGLESTRIP
+} SDL_GpuPrimitiveType;
+
+typedef enum SDL_GpuLoadOp
+{
+    SDL_GPU_LOADOP_LOAD,
+    SDL_GPU_LOADOP_CLEAR,
+    SDL_GPU_LOADOP_DONT_CARE
+} SDL_GpuLoadOp;
+
+typedef enum SDL_GpuStoreOp
+{
+    SDL_GPU_STOREOP_STORE,
+    SDL_GPU_STOREOP_DONT_CARE
+} SDL_GpuStoreOp;
+
+typedef enum SDL_GpuIndexElementSize
+{
+    SDL_GPU_INDEXELEMENTSIZE_16BIT,
+    SDL_GPU_INDEXELEMENTSIZE_32BIT
+} SDL_GpuIndexElementSize;
+
+/* Texture format support varies depending on driver, hardware, and usage flags.
+ * In general, you should use SDL_SupportsGpuTextureFormat to query if a format
+ * is supported before using it. However, there are a few guaranteed formats.
+ *
+ * For SAMPLER usage, the following formats are universally supported:
+ *  - R8G8B8A8_UNORM
+ *  - B8G8R8A8_UNORM
+ *  - R8_UNORM
+ *  - R8G8_SNORM
+ *  - R8G8B8A8_SNORM
+ *  - R16_FLOAT
+ *  - R16G16_FLOAT
+ *  - R16G16B16A16_FLOAT
+ *  - R32_FLOAT
+ *  - R32G32_FLOAT
+ *  - R32G32B32A32_FLOAT
+ *  - R8G8B8A8_UNORM_SRGB
+ *  - B8G8R8A8_UNORM_SRGB
+ *  - D16_UNORM
+ *
+ * For COLOR_TARGET usage, the following formats are universally supported:
+ *  - R8G8B8A8_UNORM
+ *  - B8G8R8A8_UNORM
+ *  - R8_UNORM
+ *  - R16_FLOAT
+ *  - R16G16_FLOAT
+ *  - R16G16B16A16_FLOAT
+ *  - R32_FLOAT
+ *  - R32G32_FLOAT
+ *  - R32G32B32A32_FLOAT
+ *  - R8_UINT
+ *  - R8G8_UINT
+ *  - R8G8B8A8_UINT
+ *  - R16_UINT
+ *  - R16G16_UINT
+ *  - R16G16B16A16_UINT
+ *  - R8G8B8A8_UNORM_SRGB
+ *  - B8G8R8A8_UNORM_SRGB
+ *
+ * For STORAGE usages, the following formats are universally supported:
+ *  - R8G8B8A8_UNORM
+ *  - R8G8B8A8_SNORM
+ *  - R16G16B16A16_FLOAT
+ *  - R32_FLOAT
+ *  - R32G32_FLOAT
+ *  - R32G32B32A32_FLOAT
+ *  - R8_UINT
+ *  - R8G8_UINT
+ *  - R8G8B8A8_UINT
+ *  - R16_UINT
+ *  - R16G16_UINT
+ *  - R16G16B16A16_UINT
+ *
+ * For DEPTH_STENCIL_TARGET usage, the following formats are universally supported:
+ *  - D16_UNORM
+ *  - Either (but not necessarily both!) D24_UNORM or D32_SFLOAT
+ *  - Either (but not necessarily both!) D24_UNORM_S8_UINT or D32_SFLOAT_S8_UINT
+ *
+ * Unless D16_UNORM is sufficient for your purposes, always check which
+ * of D24/D32 is supported before creating a depth-stencil texture!
+ */
+typedef enum SDL_GpuTextureFormat
+{
+    SDL_GPU_TEXTUREFORMAT_INVALID = -1,
+
+    /* Unsigned Normalized Float Color Formats */
+    SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM,
+    SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM,
+    SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM,
+    SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM,
+    SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM,
+    SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM,
+    SDL_GPU_TEXTUREFORMAT_R16G16_UNORM,
+    SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM,
+    SDL_GPU_TEXTUREFORMAT_R8_UNORM,
+    SDL_GPU_TEXTUREFORMAT_A8_UNORM,
+    /* Compressed Unsigned Normalized Float Color Formats */
+    SDL_GPU_TEXTUREFORMAT_BC1_UNORM,
+    SDL_GPU_TEXTUREFORMAT_BC2_UNORM,
+    SDL_GPU_TEXTUREFORMAT_BC3_UNORM,
+    SDL_GPU_TEXTUREFORMAT_BC7_UNORM,
+    /* Signed Normalized Float Color Formats  */
+    SDL_GPU_TEXTUREFORMAT_R8G8_SNORM,
+    SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM,
+    /* Signed Float Color Formats */
+    SDL_GPU_TEXTUREFORMAT_R16_FLOAT,
+    SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT,
+    SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT,
+    SDL_GPU_TEXTUREFORMAT_R32_FLOAT,
+    SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT,
+    SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT,
+    /* Unsigned Integer Color Formats */
+    SDL_GPU_TEXTUREFORMAT_R8_UINT,
+    SDL_GPU_TEXTUREFORMAT_R8G8_UINT,
+    SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT,
+    SDL_GPU_TEXTUREFORMAT_R16_UINT,
+    SDL_GPU_TEXTUREFORMAT_R16G16_UINT,
+    SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT,
+    /* SRGB Unsigned Normalized Color Formats */
+    SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB,
+    SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB,
+    /* Compressed SRGB Unsigned Normalized Color Formats */
+    SDL_GPU_TEXTUREFORMAT_BC3_UNORM_SRGB,
+    SDL_GPU_TEXTUREFORMAT_BC7_UNORM_SRGB,
+    /* Depth Formats */
+    SDL_GPU_TEXTUREFORMAT_D16_UNORM,
+    SDL_GPU_TEXTUREFORMAT_D24_UNORM,
+    SDL_GPU_TEXTUREFORMAT_D32_FLOAT,
+    SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT,
+    SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT
+} SDL_GpuTextureFormat;
+
+typedef enum SDL_GpuTextureUsageFlagBits
+{
+    SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT = 0x00000001,
+    SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT = 0x00000002,
+    SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT = 0x00000004,
+    SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT = 0x00000008,
+    SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT = 0x00000020,
+    SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT = 0x00000040
+} SDL_GpuTextureUsageFlagBits;
+
+typedef Uint32 SDL_GpuTextureUsageFlags;
+
+typedef enum SDL_GpuTextureType
+{
+    SDL_GPU_TEXTURETYPE_2D,
+    SDL_GPU_TEXTURETYPE_2D_ARRAY,
+    SDL_GPU_TEXTURETYPE_3D,
+    SDL_GPU_TEXTURETYPE_CUBE
+} SDL_GpuTextureType;
+
+typedef enum SDL_GpuSampleCount
+{
+    SDL_GPU_SAMPLECOUNT_1,
+    SDL_GPU_SAMPLECOUNT_2,
+    SDL_GPU_SAMPLECOUNT_4,
+    SDL_GPU_SAMPLECOUNT_8
+} SDL_GpuSampleCount;
+
+typedef enum SDL_GpuCubeMapFace
+{
+    SDL_GPU_CUBEMAPFACE_POSITIVEX,
+    SDL_GPU_CUBEMAPFACE_NEGATIVEX,
+    SDL_GPU_CUBEMAPFACE_POSITIVEY,
+    SDL_GPU_CUBEMAPFACE_NEGATIVEY,
+    SDL_GPU_CUBEMAPFACE_POSITIVEZ,
+    SDL_GPU_CUBEMAPFACE_NEGATIVEZ
+} SDL_GpuCubeMapFace;
+
+typedef enum SDL_GpuBufferUsageFlagBits
+{
+    SDL_GPU_BUFFERUSAGE_VERTEX_BIT = 0x00000001,
+    SDL_GPU_BUFFERUSAGE_INDEX_BIT = 0x00000002,
+    SDL_GPU_BUFFERUSAGE_INDIRECT_BIT = 0x00000004,
+    SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT = 0x00000008,
+    SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ_BIT = 0x00000020,
+    SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT = 0x00000040
+} SDL_GpuBufferUsageFlagBits;
+
+typedef Uint32 SDL_GpuBufferUsageFlags;
+
+typedef enum SDL_GpuTransferBufferUsage
+{
+    SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
+    SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD
+} SDL_GpuTransferBufferUsage;
+
+typedef enum SDL_GpuShaderStage
+{
+    SDL_GPU_SHADERSTAGE_VERTEX,
+    SDL_GPU_SHADERSTAGE_FRAGMENT
+} SDL_GpuShaderStage;
+
+typedef enum SDL_GpuShaderFormatFlagBits
+{
+    SDL_GPU_SHADERFORMAT_INVALID = 0x00000000,
+    SDL_GPU_SHADERFORMAT_SECRET = 0x00000001,   /* NDA'd platforms */
+    SDL_GPU_SHADERFORMAT_SPIRV = 0x00000002,    /* Vulkan */
+    SDL_GPU_SHADERFORMAT_DXBC = 0x00000004,     /* D3D11 (Shader Model 5_0) */
+    SDL_GPU_SHADERFORMAT_DXIL = 0x00000008,     /* D3D12 */
+    SDL_GPU_SHADERFORMAT_MSL = 0x00000010,      /* Metal */
+    SDL_GPU_SHADERFORMAT_METALLIB = 0x00000020, /* Metal */
+} SDL_GpuShaderFormatFlagBits;
+
+typedef Uint32 SDL_GpuShaderFormat;
+
+typedef enum SDL_GpuVertexElementFormat
+{
+    /* 32-bit Signed Integers */
+    SDL_GPU_VERTEXELEMENTFORMAT_INT,
+    SDL_GPU_VERTEXELEMENTFORMAT_INT2,
+    SDL_GPU_VERTEXELEMENTFORMAT_INT3,
+    SDL_GPU_VERTEXELEMENTFORMAT_INT4,
+
+    /* 32-bit Unsigned Integers */
+    SDL_GPU_VERTEXELEMENTFORMAT_UINT,
+    SDL_GPU_VERTEXELEMENTFORMAT_UINT2,
+    SDL_GPU_VERTEXELEMENTFORMAT_UINT3,
+    SDL_GPU_VERTEXELEMENTFORMAT_UINT4,
+
+    /* 32-bit Floats */
+    SDL_GPU_VERTEXELEMENTFORMAT_FLOAT,
+    SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2,
+    SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3,
+    SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4,
+
+    /* 8-bit Signed Integers */
+    SDL_GPU_VERTEXELEMENTFORMAT_BYTE2,
+    SDL_GPU_VERTEXELEMENTFORMAT_BYTE4,
+
+    /* 8-bit Unsigned Integers */
+    SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2,
+    SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4,
+
+    /* 8-bit Signed Normalized */
+    SDL_GPU_VERTEXELEMENTFORMAT_BYTE2_NORM,
+    SDL_GPU_VERTEXELEMENTFORMAT_BYTE4_NORM,
+
+    /* 8-bit Unsigned Normalized */
+    SDL_GPU_VERTEXELEMENTFORMAT_UBYTE2_NORM,
+    SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM,
+
+    /* 16-bit Signed Integers */
+    SDL_GPU_VERTEXELEMENTFORMAT_SHORT2,
+    SDL_GPU_VERTEXELEMENTFORMAT_SHORT4,
+
+    /* 16-bit Unsigned Integers */
+    SDL_GPU_VERTEXELEMENTFORMAT_USHORT2,
+    SDL_GPU_VERTEXELEMENTFORMAT_USHORT4,
+
+    /* 16-bit Signed Normalized */
+    SDL_GPU_VERTEXELEMENTFORMAT_SHORT2_NORM,
+    SDL_GPU_VERTEXELEMENTFORMAT_SHORT4_NORM,
+
+    /* 16-bit Unsigned Normalized */
+    SDL_GPU_VERTEXELEMENTFORMAT_USHORT2_NORM,
+    SDL_GPU_VERTEXELEMENTFORMAT_USHORT4_NORM,
+
+    /* 16-bit Floats */
+    SDL_GPU_VERTEXELEMENTFORMAT_HALF2,
+    SDL_GPU_VERTEXELEMENTFORMAT_HALF4
+} SDL_GpuVertexElementFormat;
+
+typedef enum SDL_GpuVertexInputRate
+{
+    SDL_GPU_VERTEXINPUTRATE_VERTEX = 0,
+    SDL_GPU_VERTEXINPUTRATE_INSTANCE = 1
+} SDL_GpuVertexInputRate;
+
+typedef enum SDL_GpuFillMode
+{
+    SDL_GPU_FILLMODE_FILL,
+    SDL_GPU_FILLMODE_LINE
+} SDL_GpuFillMode;
+
+typedef enum SDL_GpuCullMode
+{
+    SDL_GPU_CULLMODE_NONE,
+    SDL_GPU_CULLMODE_FRONT,
+    SDL_GPU_CULLMODE_BACK
+} SDL_GpuCullMode;
+
+typedef enum SDL_GpuFrontFace
+{
+    SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE,
+    SDL_GPU_FRONTFACE_CLOCKWISE
+} SDL_GpuFrontFace;
+
+typedef enum SDL_GpuCompareOp
+{
+    SDL_GPU_COMPAREOP_NEVER,
+    SDL_GPU_COMPAREOP_LESS,
+    SDL_GPU_COMPAREOP_EQUAL,
+    SDL_GPU_COMPAREOP_LESS_OR_EQUAL,
+    SDL_GPU_COMPAREOP_GREATER,
+    SDL_GPU_COMPAREOP_NOT_EQUAL,
+    SDL_GPU_COMPAREOP_GREATER_OR_EQUAL,
+    SDL_GPU_COMPAREOP_ALWAYS
+} SDL_GpuCompareOp;
+
+typedef enum SDL_GpuStencilOp
+{
+    SDL_GPU_STENCILOP_KEEP,
+    SDL_GPU_STENCILOP_ZERO,
+    SDL_GPU_STENCILOP_REPLACE,
+    SDL_GPU_STENCILOP_INCREMENT_AND_CLAMP,
+    SDL_GPU_STENCILOP_DECREMENT_AND_CLAMP,
+    SDL_GPU_STENCILOP_INVERT,
+    SDL_GPU_STENCILOP_INCREMENT_AND_WRAP,
+    SDL_GPU_STENCILOP_DECREMENT_AND_WRAP
+} SDL_GpuStencilOp;
+
+typedef enum SDL_GpuBlendOp
+{
+    SDL_GPU_BLENDOP_ADD,
+    SDL_GPU_BLENDOP_SUBTRACT,
+    SDL_GPU_BLENDOP_REVERSE_SUBTRACT,
+    SDL_GPU_BLENDOP_MIN,
+    SDL_GPU_BLENDOP_MAX
+} SDL_GpuBlendOp;
+
+typedef enum SDL_GpuBlendFactor
+{
+    SDL_GPU_BLENDFACTOR_ZERO,
+    SDL_GPU_BLENDFACTOR_ONE,
+    SDL_GPU_BLENDFACTOR_SRC_COLOR,
+    SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_COLOR,
+    SDL_GPU_BLENDFACTOR_DST_COLOR,
+    SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_COLOR,
+    SDL_GPU_BLENDFACTOR_SRC_ALPHA,
+    SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
+    SDL_GPU_BLENDFACTOR_DST_ALPHA,
+    SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_ALPHA,
+    SDL_GPU_BLENDFACTOR_CONSTANT_COLOR,
+    SDL_GPU_BLENDFACTOR_ONE_MINUS_CONSTANT_COLOR,
+    SDL_GPU_BLENDFACTOR_SRC_ALPHA_SATURATE
+} SDL_GpuBlendFactor;
+
+typedef enum SDL_GpuColorComponentFlagBits
+{
+    SDL_GPU_COLORCOMPONENT_R_BIT = 0x00000001,
+    SDL_GPU_COLORCOMPONENT_G_BIT = 0x00000002,
+    SDL_GPU_COLORCOMPONENT_B_BIT = 0x00000004,
+    SDL_GPU_COLORCOMPONENT_A_BIT = 0x00000008
+} SDL_GpuColorComponentFlagBits;
+
+typedef Uint8 SDL_GpuColorComponentFlags;
+
+typedef enum SDL_GpuFilter
+{
+    SDL_GPU_FILTER_NEAREST,
+    SDL_GPU_FILTER_LINEAR
+} SDL_GpuFilter;
+
+typedef enum SDL_GpuSamplerMipmapMode
+{
+    SDL_GPU_SAMPLERMIPMAPMODE_NEAREST,
+    SDL_GPU_SAMPLERMIPMAPMODE_LINEAR
+} SDL_GpuSamplerMipmapMode;
+
+typedef enum SDL_GpuSamplerAddressMode
+{
+    SDL_GPU_SAMPLERADDRESSMODE_REPEAT,
+    SDL_GPU_SAMPLERADDRESSMODE_MIRRORED_REPEAT,
+    SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE
+} SDL_GpuSamplerAddressMode;
+
+/*
+ * VSYNC:
+ *   Waits for vblank before presenting.
+ *   If there is a pending image to present, the new image is enqueued for presentation.
+ *   Disallows tearing at the cost of visual latency.
+ *   When using this present mode, AcquireSwapchainTexture will block if too many frames are in flight.
+ * IMMEDIATE:
+ *   Immediately presents.
+ *   Lowest latency option, but tearing may occur.
+ *   When using this mode, AcquireSwapchainTexture will return NULL if too many frames are in flight.
+ * MAILBOX:
+ *   Waits for vblank before presenting. No tearing is possible.
+ *   If there is a pending image to present, the pending image is replaced by the new image.
+ *   Similar to VSYNC, but with reduced visual latency.
+ *   When using this mode, AcquireSwapchainTexture will return NULL if too many frames are in flight.
+ */
+typedef enum SDL_GpuPresentMode
+{
+    SDL_GPU_PRESENTMODE_VSYNC,
+    SDL_GPU_PRESENTMODE_IMMEDIATE,
+    SDL_GPU_PRESENTMODE_MAILBOX
+} SDL_GpuPresentMode;
+
+/*
+ * SDR:
+ *   B8G8R8A8 or R8G8B8A8 swapchain. Pixel values are in nonlinear sRGB encoding. Blends raw pixel values.
+ * SDR_LINEAR:
+ *   B8G8R8A8_SRGB or R8G8B8A8_SRGB swapchain. Pixel values are in nonlinear sRGB encoding. Blends in linear space.
+ * HDR_EXTENDED_LINEAR:
+ *   R16G16B16A16_SFLOAT swapchain. Pixel values are in extended linear encoding. Blends in linear space.
+ * HDR10_ST2048:
+ *   A2R10G10B10 or A2B10G10R10 swapchain. Pixel values are in PQ ST2048 encoding. Blends raw pixel values. (TODO: verify this)
+ */
+typedef enum SDL_GpuSwapchainComposition
+{
+    SDL_GPU_SWAPCHAINCOMPOSITION_SDR,
+    SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR,
+    SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR,
+    SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2048
+} SDL_GpuSwapchainComposition;
+
+typedef enum SDL_GpuDriver
+{
+    SDL_GPU_DRIVER_INVALID = -1,
+    SDL_GPU_DRIVER_SECRET, /* NDA'd platforms */
+    SDL_GPU_DRIVER_VULKAN,
+    SDL_GPU_DRIVER_D3D11,
+    SDL_GPU_DRIVER_D3D12,
+    SDL_GPU_DRIVER_METAL
+} SDL_GpuDriver;
+
+/* Structures */
+
+typedef struct SDL_GpuDepthStencilValue
+{
+    float depth;
+    Uint8 stencil;
+} SDL_GpuDepthStencilValue;
+
+typedef struct SDL_GpuViewport
+{
+    float x;
+    float y;
+    float w;
+    float h;
+    float minDepth;
+    float maxDepth;
+} SDL_GpuViewport;
+
+typedef struct SDL_GpuTextureTransferInfo
+{
+    SDL_GpuTransferBuffer *transferBuffer;
+    Uint32 offset;      /* starting location of the image data */
+    Uint32 imagePitch;  /* number of pixels from one row to the next */
+    Uint32 imageHeight; /* number of rows from one layer/depth-slice to the next */
+} SDL_GpuTextureTransferInfo;
+
+typedef struct SDL_GpuTransferBufferLocation
+{
+    SDL_GpuTransferBuffer *transferBuffer;
+    Uint32 offset;
+} SDL_GpuTransferBufferLocation;
+
+typedef struct SDL_GpuTextureLocation
+{
+    SDL_GpuTexture *texture;
+    Uint32 mipLevel;
+    Uint32 layer;
+    Uint32 x;
+    Uint32 y;
+    Uint32 z;
+} SDL_GpuTextureLocation;
+
+typedef struct SDL_GpuTextureRegion
+{
+    SDL_GpuTexture *texture;
+    Uint32 mipLevel;
+    Uint32 layer;
+    Uint32 x;
+    Uint32 y;
+    Uint32 z;
+    Uint32 w;
+    Uint32 h;
+    Uint32 d;
+} SDL_GpuTextureRegion;
+
+typedef struct SDL_GpuBlitRegion
+{
+    SDL_GpuTexture *texture;
+    Uint32 mipLevel;
+    Uint32 layerOrDepthPlane;
+    Uint32 x;
+    Uint32 y;
+    Uint32 w;
+    Uint32 h;
+} SDL_GpuBlitRegion;
+
+typedef struct SDL_GpuBufferLocation
+{
+    SDL_GpuBuffer *buffer;
+    Uint32 offset;
+} SDL_GpuBufferLocation;
+
+typedef struct SDL_GpuBufferRegion
+{
+    SDL_GpuBuffer *buffer;
+    Uint32 offset;
+    Uint32 size;
+} SDL_GpuBufferRegion;
+
+/* Note that the `firstVertex` and `firstInstance` parameters are NOT compatible with
+ * built-in vertex/instance ID variables in shaders (for example, SV_VertexID). If
+ * your shader depends on these variables, the correlating draw call parameter MUST
+ * be 0.
+ */
+typedef struct SDL_GpuIndirectDrawCommand
+{
+    Uint32 vertexCount;   /* number of vertices to draw */
+    Uint32 instanceCount; /* number of instances to draw */
+    Uint32 firstVertex;   /* index of the first vertex to draw */
+    Uint32 firstInstance; /* ID of the first instance to draw */
+} SDL_GpuIndirectDrawCommand;
+
+typedef struct SDL_GpuIndexedIndirectDrawCommand
+{
+    Uint32 indexCount;    /* number of vertices to draw per instance */
+    Uint32 instanceCount; /* number of instances to draw */
+    Uint32 firstIndex;    /* base index within the index buffer */
+    Sint32 vertexOffset;  /* value added to vertex index before indexing into the vertex buffer */
+    Uint32 firstInstance; /* ID of the first instance to draw */
+} SDL_GpuIndexedIndirectDrawCommand;
+
+typedef struct SDL_GpuIndirectDispatchCommand
+{
+    Uint32 groupCountX;
+    Uint32 groupCountY;
+    Uint32 groupCountZ;
+} SDL_GpuIndirectDispatchCommand;
+
+/* State structures */
+
+typedef struct SDL_GpuSamplerCreateInfo
+{
+    SDL_GpuFilter minFilter;
+    SDL_GpuFilter magFilter;
+    SDL_GpuSamplerMipmapMode mipmapMode;
+    SDL_GpuSamplerAddressMode addressModeU;
+    SDL_GpuSamplerAddressMode addressModeV;
+    SDL_GpuSamplerAddressMode addressModeW;
+    float mipLodBias;
+    SDL_bool anisotropyEnable;
+    float maxAnisotropy;
+    SDL_bool compareEnable;
+    SDL_GpuCompareOp compareOp;
+    float minLod;
+    float maxLod;
+
+    SDL_PropertiesID props;
+} SDL_GpuSamplerCreateInfo;
+
+typedef struct SDL_GpuVertexBinding
+{
+    Uint32 binding;
+    Uint32 stride;
+    SDL_GpuVertexInputRate inputRate;
+    Uint32 instanceStepRate; /* ignored unless inputRate is INSTANCE */
+} SDL_GpuVertexBinding;
+
+typedef struct SDL_GpuVertexAttribute
+{
+    Uint32 location;
+    Uint32 binding;
+    SDL_GpuVertexElementFormat format;
+    Uint32 offset;
+} SDL_GpuVertexAttribute;
+
+typedef struct SDL_GpuVertexInputState
+{
+    const SDL_GpuVertexBinding *vertexBindings;
+    Uint32 vertexBindingCount;
+    const SDL_GpuVertexAttribute *vertexAttributes;
+    Uint32 vertexAttributeCount;
+} SDL_GpuVertexInputState;
+
+typedef struct SDL_GpuStencilOpState
+{
+    SDL_GpuStencilOp failOp;
+    SDL_GpuStencilOp passOp;
+    SDL_GpuStencilOp depthFailOp;
+    SDL_GpuCompareOp compareOp;
+} SDL_GpuStencilOpState;
+
+typedef struct SDL_GpuColorAttachmentBlendState
+{
+    SDL_bool blendEnable;
+    SDL_GpuBlendFactor srcColorBlendFactor;
+    SDL_GpuBlendFactor dstColorBlendFactor;
+    SDL_GpuBlendOp colorBlendOp;
+    SDL_GpuBlendFactor srcAlphaBlendFactor;
+    SDL_GpuBlendFactor dstAlphaBlendFactor;
+    SDL_GpuBlendOp alphaBlendOp;
+    SDL_GpuColorComponentFlags colorWriteMask;
+} SDL_GpuColorAttachmentBlendState;
+
+typedef struct SDL_GpuShaderCreateInfo
+{
+    size_t codeSize;
+    const Uint8 *code;
+    const char *entryPointName;
+    SDL_GpuShaderFormat format;
+    SDL_GpuShaderStage stage;
+    Uint32 samplerCount;
+    Uint32 storageTextureCount;
+    Uint32 storageBufferCount;
+    Uint32 uniformBufferCount;
+
+    SDL_PropertiesID props;
+} SDL_GpuShaderCreateInfo;
+
+typedef struct SDL_GpuTextureCreateInfo
+{
+    SDL_GpuTextureType type;
+    SDL_GpuTextureFormat format;
+    SDL_GpuTextureUsageFlags usageFlags;
+    Uint32 width;
+    Uint32 height;
+    Uint32 layerCountOrDepth;
+    Uint32 levelCount;
+    SDL_GpuSampleCount sampleCount;
+
+    SDL_PropertiesID props;
+} SDL_GpuTextureCreateInfo;
+
+#define SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_R_FLOAT       "SDL.gpu.createtexture.d3d12.clear.r"
+#define SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_G_FLOAT       "SDL.gpu.createtexture.d3d12.clear.g"
+#define SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_B_FLOAT       "SDL.gpu.createtexture.d3d12.clear.b"
+#define SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_A_FLOAT       "SDL.gpu.createtexture.d3d12.clear.a"
+#define SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_DEPTH_FLOAT   "SDL.gpu.createtexture.d3d12.clear.depth"
+#define SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_STENCIL_UINT8 "SDL.gpu.createtexture.d3d12.clear.stencil"
+
+typedef struct SDL_GpuBufferCreateInfo
+{
+    SDL_GpuBufferUsageFlags usageFlags;
+    Uint32 sizeInBytes;
+
+    SDL_PropertiesID props;
+} SDL_GpuBufferCreateInfo;
+
+typedef struct SDL_GpuTransferBufferCreateInfo
+{
+    SDL_GpuTransferBufferUsage usage;
+    Uint32 sizeInBytes;
+
+    SDL_PropertiesID props;
+} SDL_GpuTransferBufferCreateInfo;
+
+/* Pipeline state structures */
+
+typedef struct SDL_GpuRasterizerState
+{
+    SDL_GpuFillMode fillMode;
+    SDL_GpuCullMode cullMode;
+    SDL_GpuFrontFace frontFace;
+    SDL_bool depthBiasEnable;
+    float depthBiasConstantFactor;
+    float depthBiasClamp;
+    float depthBiasSlopeFactor;
+} SDL_GpuRasterizerState;
+
+typedef struct SDL_GpuMultisampleState
+{
+    SDL_GpuSampleCount sampleCount;
+    Uint32 sampleMask;
+} SDL_GpuMultisampleState;
+
+typedef struct SDL_GpuDepthStencilState
+{
+    SDL_bool depthTestEnable;
+    SDL_bool depthWriteEnable;
+    SDL_GpuCompareOp compareOp;
+    SDL_bool stencilTestEnable;
+    SDL_GpuStencilOpState backStencilState;
+    SDL_GpuStencilOpState frontStencilState;
+    Uint8 compareMask;
+    Uint8 writeMask;
+    Uint8 reference;
+} SDL_GpuDepthStencilState;
+
+typedef struct SDL_GpuColorAttachmentDescription
+{
+    SDL_GpuTextureFormat format;
+    SDL_GpuColorAttachmentBlendState blendState;
+} SDL_GpuColorAttachmentDescription;
+
+typedef struct SDL_GpuGraphicsPipelineAttachmentInfo
+{
+    SDL_GpuColorAttachmentDescription *colorAttachmentDescriptions;
+    Uint32 colorAttachmentCount;
+    SDL_bool hasDepthStencilAttachment;
+    SDL_GpuTextureFormat depthStencilFormat;
+} SDL_GpuGraphicsPipelineAttachmentInfo;
+
+typedef struct SDL_GpuGraphicsPipelineCreateInfo
+{
+    SDL_GpuShader *vertexShader;
+    SDL_GpuShader *fragmentShader;
+    SDL_GpuVertexInputState vertexInputState;
+    SDL_GpuPrimitiveType primitiveType;
+    SDL_GpuRasterizerState rasterizerState;
+    SDL_GpuMultisampleState multisampleState;
+    SDL_GpuDepthStencilState depthStencilState;
+    SDL_GpuGraphicsPipelineAttachmentInfo attachmentInfo;
+    float blendConstants[4];
+
+    SDL_PropertiesID props;
+} SDL_GpuGraphicsPipelineCreateInfo;
+
+typedef struct SDL_GpuComputePipelineCreateInfo
+{
+    size_t codeSize;
+    const Uint8 *code;
+    const char *entryPointName;
+    SDL_GpuShaderFormat format;
+    Uint32 readOnlyStorageTextureCount;
+    Uint32 readOnlyStorageBufferCount;
+    Uint32 writeOnlyStorageTextureCount;
+    Uint32 writeOnlyStorageBufferCount;
+    Uint32 uniformBufferCount;
+    Uint32 threadCountX;
+    Uint32 threadCountY;
+    Uint32 threadCountZ;
+
+    SDL_PropertiesID props;
+} SDL_GpuComputePipelineCreateInfo;
+
+typedef struct SDL_GpuColorAttachmentInfo
+{
+    /* The texture that will be used as a color attachment by a render pass. */
+    SDL_GpuTexture *texture;
+    Uint32 mipLevel;
+    Uint32 layerOrDepthPlane; /* For 3D textures, you can bind an individual depth plane as an attachment. */
+
+    /* Can be ignored by RenderPass if CLEAR is not used */
+    SDL_FColor clearColor;
+
+    /* Determines what is done with the texture at the beginning of the render pass.
+     *
+     *   LOAD:
+     *     Loads the data currently in the texture.
+     *
+     *   CLEAR:
+     *     Clears the texture to a single color.
+     *
+     *   DONT_CARE:
+     *     The driver will do whatever it wants with the texture memory.
+     *     This is a good option if you know that every single pixel will be touched in the render pass.
+     */
+    SDL_GpuLoadOp loadOp;
+
+    /* Determines what is done with the texture at the end of the render pass.
+     *
+     *   STORE:
+     *     Stores the results of the render pass in the texture.
+     *
+     *   DONT_CARE:
+     *     The driver will do whatever it wants with the texture memory.
+     *     This is often a good option for depth/stencil textures.
+     */
+    SDL_GpuStoreOp storeOp;
+
+    /* if SDL_TRUE, cycles the texture if the texture is bound and loadOp is not LOAD */
+    SDL_bool cycle;
+} SDL_GpuColorAttachmentInfo;
+
+typedef struct SDL_GpuDepthStencilAttachmentInfo
+{
+    /* The texture that will be used as the depth stencil attachment by a render pass. */
+    SDL_GpuTexture *texture;
+
+    /* Can be ignored by the render pass if CLEAR is not used */
+    SDL_GpuDepthStencilValue depthStencilClearValue;
+
+    /* Determines what is done with the depth values at the beginning of the render pass.
+     *
+     *   LOAD:
+     *     Loads the depth values currently in the texture.
+     *
+     *   CLEAR:
+     *     Clears the texture to a single depth.
+     *
+     *   DONT_CARE:
+     *     The driver will do whatever it wants with the memory.
+     *     This is a good option if you know that every single pixel will be touched in the render pass.
+     */
+    SDL_GpuLoadOp loadOp;
+
+    /* Determines what is done with the depth values at the end of the render pass.
+     *
+     *   STORE:
+     *     Stores the depth results in the texture.
+     *
+     *   DONT_CARE:
+     *     The driver will do whatever it wants with the texture memory.
+     *     This is often a good option for depth/stencil textures.
+     */
+    SDL_GpuStoreOp storeOp;
+
+    /* Determines what is done with the stencil values at the beginning of the render pass.
+     *
+     *   LOAD:
+     *     Loads the stencil values currently in the texture.
+     *
+     *   CLEAR:
+     *     Clears the texture to a single stencil value.
+     *
+     *   DONT_CARE:
+     *     The driver will do whatever it wants with the memory.
+     *     This is a good option if you know that every single pixel will be touched in the render pass.
+     */
+    SDL_GpuLoadOp stencilLoadOp;
+
+    /* Determines what is done with the stencil values at the end of the render pass.
+     *
+     *   STORE:
+     *     Stores the stencil results in the texture.
+     *
+     *   DONT_CARE:
+     *     The driver will do whatever it wants with the texture memory.
+     *     This is often a good option for depth/stencil textures.
+     */
+    SDL_GpuStoreOp stencilStoreOp;
+
+    /* if SDL_TRUE, cycles the texture if the texture is bound and any load ops are not LOAD */
+    SDL_bool cycle;
+} SDL_GpuDepthStencilAttachmentInfo;
+
+/* Binding structs */
+
+typedef struct SDL_GpuBufferBinding
+{
+    SDL_GpuBuffer *buffer;
+    Uint32 offset;
+} SDL_GpuBufferBinding;
+
+typedef struct SDL_GpuTextureSamplerBinding
+{
+    SDL_GpuTexture *texture;
+    SDL_GpuSampler *sampler;
+} SDL_GpuTextureSamplerBinding;
+
+typedef struct SDL_GpuStorageBufferWriteOnlyBinding
+{
+    SDL_GpuBuffer *buffer;
+
+    /* if SDL_TRUE, cycles the buffer if it is bound. */
+    SDL_bool cycle;
+} SDL_GpuStorageBufferWriteOnlyBinding;
+
+typedef struct SDL_GpuStorageTextureWriteOnlyBinding
+{
+    SDL_GpuTexture *texture;
+    Uint32 mipLevel;
+    Uint32 layer;
+
+    /* if SDL_TRUE, cycles the texture if the texture is bound. */
+    SDL_bool cycle;
+} SDL_GpuStorageTextureWriteOnlyBinding;
+
+/* Functions */
+
+/* Device */
+
+/**
+ * Creates a GPU context.
+ *
+ * \param formatFlags a bitflag indicating which shader formats the app is able to provide
+ * \param debugMode enable debug mode properties and validations
+ * \param preferLowPower set this to SDL_TRUE if your app prefers energy efficiency over maximum GPU performance
+ * \param name the preferred GPU driver, or NULL to let SDL pick the optimal driver
+ * \returns a GPU context on success or NULL on failure
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_GetGpuDriver
+ * \sa SDL_DestroyGpuDevice
+ */
+extern SDL_DECLSPEC SDL_GpuDevice *SDLCALL SDL_CreateGpuDevice(
+    SDL_GpuShaderFormat formatFlags,
+    SDL_bool debugMode,
+    SDL_bool preferLowPower,
+    const char *name);
+
+/**
+ * Creates a GPU context.
+ *
+ * These are the supported properties:
+ *
+ * - `SDL_PROP_GPU_CREATEDEVICE_DEBUGMODE_BOOL`: enable debug mode properties and validations, default is true
+ * - `SDL_PROP_GPU_CREATEDEVICE_PREFERLOWPOWER_BOOL`: enable to prefer energy efficiency over maximum GPU performance
+ * - `SDL_PROP_GPU_CREATEDEVICE_NAME_STRING`: the name of the GPU driver to use, if a specific one is desired
+ *
+ * These are the current shader format properties:
+ *
+ * `SDL_PROP_GPU_CREATEDEVICE_SHADERS_SECRET_BOOL`: The app is able to provide shaders for an NDA platform
+ * `SDL_PROP_GPU_CREATEDEVICE_SHADERS_SPIRV_BOOL`: The app is able to provide SPIR-V shaders if applicable
+ * `SDL_PROP_GPU_CREATEDEVICE_SHADERS_DXBC_BOOL`: The app is able to provide DXBC shaders if applicable
+ * `SDL_PROP_GPU_CREATEDEVICE_SHADERS_DXIL_BOOL`: The app is able to provide DXIL shaders if applicable
+ * `SDL_PROP_GPU_CREATEDEVICE_SHADERS_MSL_BOOL`: The app is able to provide MSL shaders if applicable
+ * `SDL_PROP_GPU_CREATEDEVICE_SHADERS_METALLIB_BOOL`: The app is able to provide Metal shader libraries if applicable
+ *
+ * With the D3D12 renderer:
+ * - `SDL_PROP_GPU_CREATEDEVICE_D3D12_SEMANTIC_NAME_STRING`: the prefix to use for all vertex semantics, default is "TEXCOORD"
+ *
+ * \param props the properties to use.
+ * \returns a GPU context on success or NULL on failure
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_GetGpuDriver
+ * \sa SDL_DestroyGpuDevice
+ */
+extern SDL_DECLSPEC SDL_GpuDevice *SDLCALL SDL_CreateGpuDeviceWithProperties(
+    SDL_PropertiesID props);
+
+#define SDL_PROP_GPU_CREATEDEVICE_DEBUGMODE_BOOL             "SDL.gpu.createdevice.debugmode"
+#define SDL_PROP_GPU_CREATEDEVICE_PREFERLOWPOWER_BOOL        "SDL.gpu.createdevice.preferlowpower"
+#define SDL_PROP_GPU_CREATEDEVICE_NAME_STRING                "SDL.gpu.createdevice.name"
+#define SDL_PROP_GPU_CREATEDEVICE_SHADERS_SECRET_BOOL        "SDL.gpu.createdevice.shaders.secret"
+#define SDL_PROP_GPU_CREATEDEVICE_SHADERS_SPIRV_BOOL         "SDL.gpu.createdevice.shaders.spirv"
+#define SDL_PROP_GPU_CREATEDEVICE_SHADERS_DXBC_BOOL          "SDL.gpu.createdevice.shaders.dxbc"
+#define SDL_PROP_GPU_CREATEDEVICE_SHADERS_DXIL_BOOL          "SDL.gpu.createdevice.shaders.dxil"
+#define SDL_PROP_GPU_CREATEDEVICE_SHADERS_MSL_BOOL           "SDL.gpu.createdevice.shaders.msl"
+#define SDL_PROP_GPU_CREATEDEVICE_SHADERS_METALLIB_BOOL      "SDL.gpu.createdevice.shaders.metallib"
+#define SDL_PROP_GPU_CREATEDEVICE_D3D12_SEMANTIC_NAME_STRING "SDL.gpu.createdevice.d3d12.semantic"
+
+/**
+ * Destroys a GPU context previously returned by SDL_CreateGpuDevice.
+ *
+ * \param device a GPU Context to destroy
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_CreateGpuDevice
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_DestroyGpuDevice(SDL_GpuDevice *device);
+
+/**
+ * Returns the backend used to create this GPU context.
+ *
+ * \param device a GPU context to query
+ * \returns an SDL_GpuDriver value, or SDL_GPU_DRIVER_INVALID on error
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC SDL_GpuDriver SDLCALL SDL_GetGpuDriver(SDL_GpuDevice *device);
+
+/* State Creation */
+
+/**
+ * Creates a pipeline object to be used in a compute workflow.
+ *
+ * Shader resource bindings must be authored to follow a particular order.
+ * For SPIR-V shaders, use the following resource sets:
+ *  0: Read-only storage textures, followed by read-only storage buffers
+ *  1: Write-only storage textures, followed by write-only storage buffers
+ *  2: Uniform buffers
+ *
+ * For DXBC Shader Model 5_0 shaders, use the following register order:
+ *  For t registers:
+ *   Read-only storage textures, followed by read-only storage buffers
+ *  For u registers:
+ *   Write-only storage textures, followed by write-only storage buffers
+ *  For b registers:
+ *   Uniform buffers
+ *
+ * For DXIL shaders, use the following register order:
+ *  (t[n], space0): Read-only storage textures, followed by read-only storage buffers
+ *  (u[n], space1): Write-only storage textures, followed by write-only storage buffers
+ *  (b[n], space2): Uniform buffers
+ *
+ * For MSL/metallib, use the following order:
+ *  For [[buffer]]:
+ *   Uniform buffers, followed by write-only storage buffers, followed by write-only storage buffers
+ *  For [[texture]]:
+ *   Read-only storage textures, followed by write-only storage textures
+ *
+ * \param device a GPU Context
+ * \param computePipelineCreateInfo a struct describing the state of the requested compute pipeline
+ * \returns a compute pipeline object on success, or NULL on failure
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_BindGpuComputePipeline
+ * \sa SDL_ReleaseGpuComputePipeline
+ */
+extern SDL_DECLSPEC SDL_GpuComputePipeline *SDLCALL SDL_CreateGpuComputePipeline(
+    SDL_GpuDevice *device,
+    SDL_GpuComputePipelineCreateInfo *computePipelineCreateInfo);
+
+/**
+ * Creates a pipeline object to be used in a graphics workflow.
+ *
+ * \param device a GPU Context
+ * \param pipelineCreateInfo a struct describing the state of the desired graphics pipeline
+ * \returns a graphics pipeline object on success, or NULL on failure
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_CreateGpuShader
+ * \sa SDL_BindGpuGraphicsPipeline
+ * \sa SDL_ReleaseGpuGraphicsPipeline
+ */
+extern SDL_DECLSPEC SDL_GpuGraphicsPipeline *SDLCALL SDL_CreateGpuGraphicsPipeline(
+    SDL_GpuDevice *device,
+    SDL_GpuGraphicsPipelineCreateInfo *pipelineCreateInfo);
+
+/**
+ * Creates a sampler object to be used when binding textures in a graphics workflow.
+ *
+ * \param device a GPU Context
+ * \param samplerCreateInfo a struct describing the state of the desired sampler
+ * \returns a sampler object on success, or NULL on failure
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_BindGpuVertexSamplers
+ * \sa SDL_BindGpuFragmentSamplers
+ * \sa SDL_ReleaseSampler
+ */
+extern SDL_DECLSPEC SDL_GpuSampler *SDLCALL SDL_CreateGpuSampler(
+    SDL_GpuDevice *device,
+    SDL_GpuSamplerCreateInfo *samplerCreateInfo);
+
+/**
+ * Creates a shader to be used when creating a graphics pipeline.
+ *
+ * Shader resource bindings must be authored to follow a particular order
+ * depending on the shader format.
+ *
+ * For SPIR-V shaders, use the following resource sets:
+ *  For vertex shaders:
+ *   0: Sampled textures, followed by storage textures, followed by storage buffers
+ *   1: Uniform buffers
+ *  For fragment shaders:
+ *   2: Sampled textures, followed by storage textures, followed by storage buffers
+ *   3: Uniform buffers
+ *
+ * For DXBC Shader Model 5_0 shaders, use the following register order:
+ *  For t registers:
+ *   Sampled textures, followed by storage textures, followed by storage buffers
+ *  For s registers:
+ *   Samplers with indices corresponding to the sampled textures
+ *  For b registers:
+ *   Uniform buffers
+ *
+ * For DXIL shaders, use the following register order:
+ *  For vertex shaders:
+ *   (t[n], space0): Sampled textures, followed by storage textures, followed by storage buffers
+ *   (s[n], space0): Samplers with indices corresponding to the sampled textures
+ *   (b[n], space1): Uniform buffers
+ *  For pixel shaders:
+ *   (t[n], space2): Sampled textures, followed by storage textures, followed by storage buffers
+ *   (s[n], space2): Samplers with indices corresponding to the sampled textures
+ *   (b[n], space3): Uniform buffers
+ *
+ * For MSL/metallib, use the following order:
+ *  For [[texture]]:
+ *   Sampled textures, followed by storage textures
+ *  For [[sampler]]:
+ *   Samplers with indices corresponding to the sampled textures
+ *  For [[buffer]]:
+ *   Uniform buffers, followed by storage buffers.
+ *   Vertex buffer 0 is bound at [[buffer(30)]], vertex buffer 1 at [[buffer(29)]], and so on.
+ *    Rather than manually authoring vertex buffer indices, use the [[stage_in]] attribute
+ *    which will automatically use the vertex input information from the SDL_GpuPipeline.
+ *
+ * \param device a GPU Context
+ * \param shaderCreateInfo a struct describing the state of the desired shader
+ * \returns a shader object on success, or NULL on failure
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_CreateGpuGraphicsPipeline
+ * \sa SDL_ReleaseGpuShader
+ */
+extern SDL_DECLSPEC SDL_GpuShader *SDLCALL SDL_CreateGpuShader(
+    SDL_GpuDevice *device,
+    SDL_GpuShaderCreateInfo *shaderCreateInfo);
+
+/**
+ * Creates a texture object to be used in graphics or compute workflows.
+ * The contents of this texture are undefined until data is written to the texture.
+ *
+ * Note that certain combinations of usage flags are invalid.
+ * For example, a texture cannot have both the SAMPLER and GRAPHICS_STORAGE_READ flags.
+ *
+ * If you request a sample count higher than the hardware supports,
+ * the implementation will automatically fall back to the highest available sample count.
+ *
+ * \param device a GPU Context
+ * \param textureCreateInfo a struct describing the state of the texture to create
+ * \returns a texture object on success, or NULL on failure
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_UploadToGpuTexture
+ * \sa SDL_DownloadFromGpuTexture
+ * \sa SDL_BindGpuVertexSamplers
+ * \sa SDL_BindGpuVertexStorageTextures
+ * \sa SDL_BindGpuFragmentSamplers
+ * \sa SDL_BindGpuFragmentStorageTextures
+ * \sa SDL_BindGpuComputeStorageTextures
+ * \sa SDL_BlitGpu
+ * \sa SDL_ReleaseGpuTexture
+ * \sa SDL_SupportsGpuTextureFormat
+ */
+extern SDL_DECLSPEC SDL_GpuTexture *SDLCALL SDL_CreateGpuTexture(
+    SDL_GpuDevice *device,
+    SDL_GpuTextureCreateInfo *textureCreateInfo);
+
+/**
+ * Creates a buffer object to be used in graphics or compute workflows.
+ * The contents of this buffer are undefined until data is written to the buffer.
+ *
+ * Note that certain combinations of usage flags are invalid.
+ * For example, a buffer cannot have both the VERTEX and INDEX flags.
+ *
+ * \param device a GPU Context
+ * \param bufferCreateInfo a struct describing the state of the buffer to create
+ * \returns a buffer object on success, or NULL on failure
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_UploadToGpuBuffer
+ * \sa SDL_BindGpuVertexBuffers
+ * \sa SDL_BindGpuIndexBuffer
+ * \sa SDL_BindGpuVertexStorageBuffers
+ * \sa SDL_BindGpuFragmentStorageBuffers
+ * \sa SDL_BindGpuComputeStorageBuffers
+ * \sa SDL_ReleaseGpuBuffer
+ */
+extern SDL_DECLSPEC SDL_GpuBuffer *SDLCALL SDL_CreateGpuBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuBufferCreateInfo *bufferCreateInfo);
+
+/**
+ * Creates a transfer buffer to be used when uploading to or downloading from graphics resources.
+ *
+ * \param device a GPU Context
+ * \param transferBufferCreateInfo a struct describing the state of the transfer buffer to create
+ * \returns a transfer buffer on success, or NULL on failure
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_UploadToGpuBuffer
+ * \sa SDL_DownloadFromGpuBuffer
+ * \sa SDL_UploadToGpuTexture
+ * \sa SDL_DownloadFromGpuTexture
+ * \sa SDL_ReleaseGpuTransferBuffer
+ */
+extern SDL_DECLSPEC SDL_GpuTransferBuffer *SDLCALL SDL_CreateGpuTransferBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuTransferBufferCreateInfo *transferBufferCreateInfo);
+
+/* Debug Naming */
+
+/**
+ * Sets an arbitrary string constant to label a buffer. Useful for debugging.
+ *
+ * \param device a GPU Context
+ * \param buffer a buffer to attach the name to
+ * \param text a UTF-8 string constant to mark as the name of the buffer
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_SetGpuBufferName(
+    SDL_GpuDevice *device,
+    SDL_GpuBuffer *buffer,
+    const char *text);
+
+/**
+ * Sets an arbitrary string constant to label a texture. Useful for debugging.
+ *
+ * \param device a GPU Context
+ * \param texture a texture to attach the name to
+ * \param text a UTF-8 string constant to mark as the name of the texture
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_SetGpuTextureName(
+    SDL_GpuDevice *device,
+    SDL_GpuTexture *texture,
+    const char *text);
+
+/**
+ * Inserts an arbitrary string label into the command buffer callstream.
+ * Useful for debugging.
+ *
+ * \param commandBuffer a command buffer
+ * \param text a UTF-8 string constant to insert as the label
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_InsertGpuDebugLabel(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *text);
+
+/**
+ * Begins a debug group with an arbitary name.
+ * Used for denoting groups of calls when viewing the command buffer callstream
+ * in a graphics debugging tool.
+ *
+ * Each call to SDL_PushGpuDebugGroup must have a corresponding call to SDL_PopGpuDebugGroup.
+ *
+ * On some backends (e.g. Metal), pushing a debug group during a render/blit/compute pass
+ * will create a group that is scoped to the native pass rather than the command buffer.
+ * For best results, if you push a debug group during a pass, always pop it in the same pass.
+ *
+ * \param commandBuffer a command buffer
+ * \param name a UTF-8 string constant that names the group
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_PopGpuDebugGroup
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_PushGpuDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *name);
+
+/**
+ * Ends the most-recently pushed debug group.
+ *
+ * \param commandBuffer a command buffer
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_PushGpuDebugGroup
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_PopGpuDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer);
+
+/* Disposal */
+
+/**
+ * Frees the given texture as soon as it is safe to do so.
+ * You must not reference the texture after calling this function.
+ *
+ * \param device a GPU context
+ * \param texture a texture to be destroyed
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGpuTexture(
+    SDL_GpuDevice *device,
+    SDL_GpuTexture *texture);
+
+/**
+ * Frees the given sampler as soon as it is safe to do so.
+ * You must not reference the texture after calling this function.
+ *
+ * \param device a GPU context
+ * \param sampler a sampler to be destroyed
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGpuSampler(
+    SDL_GpuDevice *device,
+    SDL_GpuSampler *sampler);
+
+/**
+ * Frees the given buffer as soon as it is safe to do so.
+ * You must not reference the buffer after calling this function.
+ *
+ * \param device a GPU context
+ * \param buffer a buffer to be destroyed
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGpuBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuBuffer *buffer);
+
+/**
+ * Frees the given transfer buffer as soon as it is safe to do so.
+ * You must not reference the transfer buffer after calling this function.
+ *
+ * \param device a GPU context
+ * \param transferBuffer a transfer buffer to be destroyed
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGpuTransferBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuTransferBuffer *transferBuffer);
+
+/**
+ * Frees the given compute pipeline as soon as it is safe to do so.
+ * You must not reference the compute pipeline after calling this function.
+ *
+ * \param device a GPU context
+ * \param computePipeline a compute pipeline to be destroyed
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGpuComputePipeline(
+    SDL_GpuDevice *device,
+    SDL_GpuComputePipeline *computePipeline);
+
+/**
+ * Frees the given shader as soon as it is safe to do so.
+ * You must not reference the shader after calling this function.
+ *
+ * \param device a GPU context
+ * \param shader a shader to be destroyed
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGpuShader(
+    SDL_GpuDevice *device,
+    SDL_GpuShader *shader);
+
+/**
+ * Frees the given graphics pipeline as soon as it is safe to do so.
+ * You must not reference the graphics pipeline after calling this function.
+ *
+ * \param device a GPU context
+ * \param graphicsPipeline a graphics pipeline to be destroyed
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGpuGraphicsPipeline(
+    SDL_GpuDevice *device,
+    SDL_GpuGraphicsPipeline *graphicsPipeline);
+
+/*
+ * COMMAND BUFFERS
+ *
+ * Render state is managed via command buffers.
+ * When setting render state, that state is always local to the command buffer.
+ *
+ * Commands only begin execution on the GPU once Submit is called.
+ * Once the command buffer is submitted, it is no longer valid to use it.
+ *
+ * Command buffers are executed in submission order. If you submit command buffer A and then command buffer B
+ * all commands in A will begin executing before any command in B begins executing.
+ *
+ * In multi-threading scenarios, you should acquire and submit a command buffer on the same thread.
+ * As long as you satisfy this requirement, all functionality related to command buffers is thread-safe.
+ */
+
+/**
+ * Acquire a command buffer.
+ * This command buffer is managed by the implementation and should not be freed by the user.
+ * The command buffer may only be used on the thread it was acquired on.
+ * The command buffer should be submitted on the thread it was acquired on.
+ *
+ * \param device a GPU context
+ * \returns a command buffer
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_SubmitGpu
+ * \sa SDL_SubmitGpuAndAcquireFence
+ */
+extern SDL_DECLSPEC SDL_GpuCommandBuffer *SDLCALL SDL_AcquireGpuCommandBuffer(
+    SDL_GpuDevice *device);
+
+/*
+ * UNIFORM DATA
+ *
+ * Uniforms are for passing data to shaders.
+ * The uniform data will be constant across all executions of the shader.
+ *
+ * There are 4 available uniform slots per shader stage (vertex, fragment, compute).
+ * Uniform data pushed to a slot on a stage keeps its value throughout the command buffer
+ * until you call the relevant Push function on that slot again.
+ *
+ * For example, you could write your vertex shaders to read a camera matrix from uniform binding slot 0,
+ * push the camera matrix at the start of the command buffer, and that data will be used for every
+ * subsequent draw call.
+ *
+ * It is valid to push uniform data during a render or compute pass.
+ *
+ * Uniforms are best for pushing small amounts of data.
+ * If you are pushing more than a matrix or two per call you should consider using a storage buffer instead.
+ */
+
+/**
+ * Pushes data to a vertex uniform slot on the command buffer.
+ * Subsequent draw calls will use this uniform data.
+ *
+ * \param commandBuffer a command buffer
+ * \param slotIndex the vertex uniform slot to push data to
+ * \param data client data to write
+ * \param dataLengthInBytes the length of the data to write
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_PushGpuVertexUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes);
+
+/**
+ * Pushes data to a fragment uniform slot on the command buffer.
+ * Subsequent draw calls will use this uniform data.
+ *
+ * \param commandBuffer a command buffer
+ * \param slotIndex the fragment uniform slot to push data to
+ * \param data client data to write
+ * \param dataLengthInBytes the length of the data to write
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_PushGpuFragmentUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes);
+
+/**
+ * Pushes data to a uniform slot on the command buffer.
+ * Subsequent draw calls will use this uniform data.
+ *
+ * \param commandBuffer a command buffer
+ * \param slotIndex the uniform slot to push data to
+ * \param data client data to write
+ * \param dataLengthInBytes the length of the data to write
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_PushGpuComputeUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes);
+
+/*
+ * A NOTE ON CYCLING
+ *
+ * When using a command buffer, operations do not occur immediately -
+ * they occur some time after the command buffer is submitted.
+ *
+ * When a resource is used in a pending or active command buffer, it is considered to be "bound".
+ * When a resource is no longer used in any pending or active command buffers, it is considered to be "unbound".
+ *
+ * If data resources are bound, it is unspecified when that data will be unbound
+ * unless you acquire a fence when submitting the command buffer and wait on it.
+ * However, this doesn't mean you need to track resource usage manually.
+ *
+ * All of the functions and structs that involve writing to a resource have a "cycle" bool.
+ * GpuTransferBuffer, GpuBuffer, and GpuTexture all effectively function as ring buffers on internal resources.
+ * When cycle is SDL_TRUE, if the resource is bound, the cycle rotates to the next unbound internal resource,
+ * or if none are available, a new one is created.
+ * This means you don't have to worry about complex state tracking and synchronization as long as cycling is correctly employed.
+ *
+ * For example: you can call MapTransferBuffer, write texture data, UnmapTransferBuffer, and then UploadToTexture.
+ * The next time you write texture data to the transfer buffer, if you set the cycle param to SDL_TRUE, you don't have
+ * to worry about overwriting any data that is not yet uploaded.
+ *
+ * Another example: If you are using a texture in a render pass every frame, this can cause a data dependency between frames.
+ * If you set cycle to SDL_TRUE in the ColorAttachmentInfo struct, you can prevent this data dependency.
+ *
+ * Cycling will never undefine already bound data.
+ * When cycling, all data in the resource is considered to be undefined for subsequent commands until that data is written again.
+ * You must take care not to read undefined data.
+ *
+ * Note that when cycling a texture, the entire texture will be cycled,
+ * even if only part of the texture is used in the call,
+ * so you must consider the entire texture to contain undefined data after cycling.
+ *
+ * You must also take care not to overwrite a section of data that has been referenced in a command without cycling first.
+ * It is OK to overwrite unreferenced data in a bound resource without cycling,
+ * but overwriting a section of data that has already been referenced will produce unexpected results.
+ */
+
+/* Graphics State */
+
+/**
+ * Begins a render pass on a command buffer.
+ * A render pass consists of a set of texture subresources (or depth slices in the 3D texture case)
+ * which will be rendered to during the render pass,
+ * along with corresponding clear values and load/store operations.
+ * All operations related to graphics pipelines must take place inside of a render pass.
+ * A default viewport and scissor state are automatically set when this is called.
+ * You cannot begin another render pass, or begin a compute pass or copy pass
+ * until you have ended the render pass.
+ *
+ * \param commandBuffer a command buffer
+ * \param colorAttachmentInfos an array of texture subresources with corresponding clear values and load/store ops
+ * \param colorAttachmentCount the number of color attachments in the colorAttachmentInfos array
+ * \param depthStencilAttachmentInfo a texture subresource with corresponding clear value and load/store ops, may be NULL
+ * \returns a render pass handle
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_EndGpuRenderPass
+ */
+extern SDL_DECLSPEC SDL_GpuRenderPass *SDLCALL SDL_BeginGpuRenderPass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuColorAttachmentInfo *colorAttachmentInfos,
+    Uint32 colorAttachmentCount,
+    SDL_GpuDepthStencilAttachmentInfo *depthStencilAttachmentInfo);
+
+/**
+ * Binds a graphics pipeline on a render pass to be used in rendering.
+ * A graphics pipeline must be bound before making any draw calls.
+ *
+ * \param renderPass a render pass handle
+ * \param graphicsPipeline the graphics pipeline to bind
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuGraphicsPipeline(
+    SDL_GpuRenderPass *renderPass,
+    SDL_GpuGraphicsPipeline *graphicsPipeline);
+
+/**
+ * Sets the current viewport state on a command buffer.
+ *
+ * \param renderPass a render pass handle
+ * \param viewport the viewport to set
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_SetGpuViewport(
+    SDL_GpuRenderPass *renderPass,
+    SDL_GpuViewport *viewport);
+
+/**
+ * Sets the current scissor state on a command buffer.
+ *
+ * \param renderPass a render pass handle
+ * \param scissor the scissor area to set
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_SetGpuScissor(
+    SDL_GpuRenderPass *renderPass,
+    SDL_Rect *scissor);
+
+/**
+ * Binds vertex buffers on a command buffer for use with subsequent draw calls.
+ *
+ * \param renderPass a render pass handle
+ * \param firstBinding the starting bind point for the vertex buffers
+ * \param pBindings an array of SDL_GpuBufferBinding structs containing vertex buffers and offset values
+ * \param bindingCount the number of bindings in the pBindings array
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuVertexBuffers(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstBinding,
+    SDL_GpuBufferBinding *pBindings,
+    Uint32 bindingCount);
+
+/**
+ * Binds an index buffer on a command buffer for use with subsequent draw calls.
+ *
+ * \param renderPass a render pass handle
+ * \param pBinding a pointer to a struct containing an index buffer and offset
+ * \param indexElementSize whether the index values in the buffer are 16- or 32-bit
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuIndexBuffer(
+    SDL_GpuRenderPass *renderPass,
+    SDL_GpuBufferBinding *pBinding,
+    SDL_GpuIndexElementSize indexElementSize);
+
+/**
+ * Binds texture-sampler pairs for use on the vertex shader.
+ * The textures must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT.
+ *
+ * \param renderPass a render pass handle
+ * \param firstSlot the vertex sampler slot to begin binding from
+ * \param textureSamplerBindings an array of texture-sampler binding structs
+ * \param bindingCount the number of texture-sampler pairs to bind from the array
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuVertexSamplers(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount);
+
+/**
+ * Binds storage textures for use on the vertex shader.
+ * These textures must have been created with SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT.
+ *
+ * \param renderPass a render pass handle
+ * \param firstSlot the vertex storage texture slot to begin binding from
+ * \param storageTextures an array of storage textures
+ * \param bindingCount the number of storage texture to bind from the array
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuVertexStorageTextures(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount);
+
+/**
+ * Binds storage buffers for use on the vertex shader.
+ * These buffers must have been created with SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT.
+ *
+ * \param renderPass a render pass handle
+ * \param firstSlot the vertex storage buffer slot to begin binding from
+ * \param storageBuffers an array of buffers
+ * \param bindingCount the number of buffers to bind from the array
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuVertexStorageBuffers(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount);
+
+/**
+ * Binds texture-sampler pairs for use on the fragment shader.
+ * The textures must have been created with SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT.
+ *
+ * \param renderPass a render pass handle
+ * \param firstSlot the fragment sampler slot to begin binding from
+ * \param textureSamplerBindings an array of texture-sampler binding structs
+ * \param bindingCount the number of texture-sampler pairs to bind from the array
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuFragmentSamplers(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount);
+
+/**
+ * Binds storage textures for use on the fragment shader.
+ * These textures must have been created with SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT.
+ *
+ * \param renderPass a render pass handle
+ * \param firstSlot the fragment storage texture slot to begin binding from
+ * \param storageTextures an array of storage textures
+ * \param bindingCount the number of storage textures to bind from the array
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuFragmentStorageTextures(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount);
+
+/**
+ * Binds storage buffers for use on the fragment shader.
+ * These buffers must have been created with SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT.
+ *
+ * \param renderPass a render pass handle
+ * \param firstSlot the fragment storage buffer slot to begin binding from
+ * \param storageBuffers an array of storage buffers
+ * \param bindingCount the number of storage buffers to bind from the array
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuFragmentStorageBuffers(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount);
+
+/* Drawing */
+
+/**
+ * Draws data using bound graphics state with an index buffer and instancing enabled.
+ * You must not call this function before binding a graphics pipeline.
+ *
+ * Note that the `firstVertex` and `firstInstance` parameters are NOT compatible with
+ * built-in vertex/instance ID variables in shaders (for example, SV_VertexID). If
+ * your shader depends on these variables, the correlating draw call parameter MUST
+ * be 0.
+ *
+ * \param renderPass a render pass handle
+ * \param indexCount the number of vertices to draw per instance
+ * \param instanceCount the number of instances to draw
+ * \param firstIndex the starting index within the index buffer
+ * \param vertexOffset value added to vertex index before indexing into the vertex buffer
+ * \param firstInstance the ID of the first instance to draw
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_DrawGpuIndexedPrimitives(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 indexCount,
+    Uint32 instanceCount,
+    Uint32 firstIndex,
+    Sint32 vertexOffset,
+    Uint32 firstInstance);
+
+/**
+ * Draws data using bound graphics state.
+ * You must not call this function before binding a graphics pipeline.
+ *
+ * Note that the `firstVertex` and `firstInstance` parameters are NOT compatible with
+ * built-in vertex/instance ID variables in shaders (for example, SV_VertexID). If
+ * your shader depends on these variables, the correlating draw call parameter MUST
+ * be 0.
+ *
+ * \param renderPass a render pass handle
+ * \param vertexCount the number of vertices to draw
+ * \param instanceCount the number of instances that will be drawn
+ * \param firstVertex the index of the first vertex to draw
+ * \param firstInstance the ID of the first instance to draw
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_DrawGpuPrimitives(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 vertexCount,
+    Uint32 instanceCount,
+    Uint32 firstVertex,
+    Uint32 firstInstance);
+
+/**
+ * Draws data using bound graphics state and with draw parameters set from a buffer.
+ * The buffer layout should match the layout of SDL_GpuIndirectDrawCommand.
+ * You must not call this function before binding a graphics pipeline.
+ *
+ * \param renderPass a render pass handle
+ * \param buffer a buffer containing draw parameters
+ * \param offsetInBytes the offset to start reading from the draw buffer
+ * \param drawCount the number of draw parameter sets that should be read from the draw buffer
+ * \param stride the byte stride between sets of draw parameters
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_DrawGpuPrimitivesIndirect(
+    SDL_GpuRenderPass *renderPass,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride);
+
+/**
+ * Draws data using bound graphics state with an index buffer enabled
+ * and with draw parameters set from a buffer.
+ * The buffer layout should match the layout of SDL_GpuIndexedIndirectDrawCommand.
+ * You must not call this function before binding a graphics pipeline.
+ *
+ * \param renderPass a render pass handle
+ * \param buffer a buffer containing draw parameters
+ * \param offsetInBytes the offset to start reading from the draw buffer
+ * \param drawCount the number of draw parameter sets that should be read from the draw buffer
+ * \param stride the byte stride between sets of draw parameters
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_DrawGpuIndexedPrimitivesIndirect(
+    SDL_GpuRenderPass *renderPass,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride);
+
+/**
+ * Ends the given render pass.
+ * All bound graphics state on the render pass command buffer is unset.
+ * The render pass handle is now invalid.
+ *
+ * \param renderPass a render pass handle
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_EndGpuRenderPass(
+    SDL_GpuRenderPass *renderPass);
+
+/* Compute Pass */
+
+/**
+ * Begins a compute pass on a command buffer.
+ * A compute pass is defined by a set of texture subresources and buffers that
+ * will be written to by compute pipelines.
+ * These textures and buffers must have been created with the COMPUTE_STORAGE_WRITE bit.
+ * All operations related to compute pipelines must take place inside of a compute pass.
+ * You must not begin another compute pass, or a render pass or copy pass
+ * before ending the compute pass.
+ *
+ * A VERY IMPORTANT NOTE
+ * Textures and buffers bound as write-only MUST NOT be read from during
+ * the compute pass. Doing so will result in undefined behavior.
+ * If your compute work requires reading the output from a previous dispatch,
+ * you MUST end the current compute pass and begin a new one before you can
+ * safely access the data.
+ *
+ * \param commandBuffer a command buffer
+ * \param storageTextureBindings an array of writeable storage texture binding structs
+ * \param storageTextureBindingCount the number of storage textures to bind from the array
+ * \param storageBufferBindings an array of writeable storage buffer binding structs
+ * \param storageBufferBindingCount the number of storage buffers to bind from the array
+ *
+ * \returns a compute pass handle
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_EndGpuComputePass
+ */
+extern SDL_DECLSPEC SDL_GpuComputePass *SDLCALL SDL_BeginGpuComputePass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuStorageTextureWriteOnlyBinding *storageTextureBindings,
+    Uint32 storageTextureBindingCount,
+    SDL_GpuStorageBufferWriteOnlyBinding *storageBufferBindings,
+    Uint32 storageBufferBindingCount);
+
+/**
+ * Binds a compute pipeline on a command buffer for use in compute dispatch.
+ *
+ * \param computePass a compute pass handle
+ * \param computePipeline a compute pipeline to bind
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuComputePipeline(
+    SDL_GpuComputePass *computePass,
+    SDL_GpuComputePipeline *computePipeline);
+
+/**
+ * Binds storage textures as readonly for use on the compute pipeline.
+ * These textures must have been created with SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT.
+ *
+ * \param computePass a compute pass handle
+ * \param firstSlot the compute storage texture slot to begin binding from
+ * \param storageTextures an array of storage textures
+ * \param bindingCount the number of storage textures to bind from the array
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuComputeStorageTextures(
+    SDL_GpuComputePass *computePass,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount);
+
+/**
+ * Binds storage buffers as readonly for use on the compute pipeline.
+ * These buffers must have been created with SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ_BIT.
+ *
+ * \param computePass a compute pass handle
+ * \param firstSlot the compute storage buffer slot to begin binding from
+ * \param storageBuffers an array of storage buffer binding structs
+ * \param bindingCount the number of storage buffers to bind from the array
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BindGpuComputeStorageBuffers(
+    SDL_GpuComputePass *computePass,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount);
+
+/**
+ * Dispatches compute work.
+ * You must not call this function before binding a compute pipeline.
+ *
+ * A VERY IMPORTANT NOTE
+ * If you dispatch multiple times in a compute pass,
+ * and the dispatches write to the same resource region as each other,
+ * there is no guarantee of which order the writes will occur.
+ * If the write order matters, you MUST end the compute pass and begin another one.
+ *
+ * \param computePass a compute pass handle
+ * \param groupCountX number of local workgroups to dispatch in the X dimension
+ * \param groupCountY number of local workgroups to dispatch in the Y dimension
+ * \param groupCountZ number of local workgroups to dispatch in the Z dimension
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_DispatchGpuCompute(
+    SDL_GpuComputePass *computePass,
+    Uint32 groupCountX,
+    Uint32 groupCountY,
+    Uint32 groupCountZ);
+
+/**
+ * Dispatches compute work with parameters set from a buffer.
+ * The buffer layout should match the layout of SDL_GpuIndirectDispatchCommand.
+ * You must not call this function before binding a compute pipeline.
+ *
+ * A VERY IMPORTANT NOTE
+ * If you dispatch multiple times in a compute pass,
+ * and the dispatches write to the same resource region as each other,
+ * there is no guarantee of which order the writes will occur.
+ * If the write order matters, you MUST end the compute pass and begin another one.
+ *
+ * \param computePass a compute pass handle
+ * \param buffer a buffer containing dispatch parameters
+ * \param offsetInBytes the offset to start reading from the dispatch buffer
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_DispatchGpuComputeIndirect(
+    SDL_GpuComputePass *computePass,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes);
+
+/**
+ * Ends the current compute pass.
+ * All bound compute state on the command buffer is unset.
+ * The compute pass handle is now invalid.
+ *
+ * \param computePass a compute pass handle
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_EndGpuComputePass(
+    SDL_GpuComputePass *computePass);
+
+/* TransferBuffer Data */
+
+/**
+ * Maps a transfer buffer into application address space.
+ * You must unmap the transfer buffer before encoding upload commands.
+ *
+ * \param device a GPU context
+ * \param transferBuffer a transfer buffer
+ * \param cycle if SDL_TRUE, cycles the transfer buffer if it is bound
+ * \returns the address of the mapped transfer buffer memory
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void *SDLCALL SDL_MapGpuTransferBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuTransferBuffer *transferBuffer,
+    SDL_bool cycle);
+
+/**
+ * Unmaps a previously mapped transfer buffer.
+ *
+ * \param device a GPU context
+ * \param transferBuffer a previously mapped transfer buffer
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_UnmapGpuTransferBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuTransferBuffer *transferBuffer);
+
+/* Copy Pass */
+
+/**
+ * Begins a copy pass on a command buffer.
+ * All operations related to copying to or from buffers or textures take place inside a copy pass.
+ * You must not begin another copy pass, or a render pass or compute pass
+ * before ending the copy pass.
+ *
+ * \param commandBuffer a command buffer
+ * \returns a copy pass handle
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC SDL_GpuCopyPass *SDLCALL SDL_BeginGpuCopyPass(
+    SDL_GpuCommandBuffer *commandBuffer);
+
+/**
+ * Uploads data from a transfer buffer to a texture.
+ * The upload occurs on the GPU timeline.
+ * You may assume that the upload has finished in subsequent commands.
+ *
+ * You must align the data in the transfer buffer to a multiple of
+ * the texel size of the texture format.
+ *
+ * \param copyPass a copy pass handle
+ * \param source the source transfer buffer with image layout information
+ * \param destination the destination texture region
+ * \param cycle if SDL_TRUE, cycles the texture if the texture is bound, otherwise overwrites the data.
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_UploadToGpuTexture(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuTextureTransferInfo *source,
+    SDL_GpuTextureRegion *destination,
+    SDL_bool cycle);
+
+/* Uploads data from a TransferBuffer to a Buffer. */
+
+/**
+ * Uploads data from a transfer buffer to a buffer.
+ * The upload occurs on the GPU timeline.
+ * You may assume that the upload has finished in subsequent commands.
+ *
+ * \param copyPass a copy pass handle
+ * \param source the source transfer buffer with offset
+ * \param destination the destination buffer with offset and size
+ * \param cycle if SDL_TRUE, cycles the buffer if it is bound, otherwise overwrites the data.
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_UploadToGpuBuffer(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuTransferBufferLocation *source,
+    SDL_GpuBufferRegion *destination,
+    SDL_bool cycle);
+
+/**
+ * Performs a texture-to-texture copy.
+ * This copy occurs on the GPU timeline.
+ * You may assume the copy has finished in subsequent commands.
+ *
+ * \param copyPass a copy pass handle
+ * \param source a source texture region
+ * \param destination a destination texture region
+ * \param w the width of the region to copy
+ * \param h the height of the region to copy
+ * \param d the depth of the region to copy
+ * \param cycle if SDL_TRUE, cycles the destination texture if the destination texture is bound, otherwise overwrites the data.
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_CopyGpuTextureToTexture(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuTextureLocation *source,
+    SDL_GpuTextureLocation *destination,
+    Uint32 w,
+    Uint32 h,
+    Uint32 d,
+    SDL_bool cycle);
+
+/* Copies data from a buffer to a buffer. */
+
+/**
+ * Performs a buffer-to-buffer copy.
+ * This copy occurs on the GPU timeline.
+ * You may assume the copy has finished in subsequent commands.
+ *
+ * \param copyPass a copy pass handle
+ * \param source the buffer and offset to copy from
+ * \param destination the buffer and offset to copy to
+ * \param size the length of the buffer to copy
+ * \param cycle if SDL_TRUE, cycles the destination buffer if it is bound, otherwise overwrites the data.
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_CopyGpuBufferToBuffer(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuBufferLocation *source,
+    SDL_GpuBufferLocation *destination,
+    Uint32 size,
+    SDL_bool cycle);
+
+/**
+ * Copies data from a texture to a transfer buffer on the GPU timeline.
+ * This data is not guaranteed to be copied until the command buffer fence is signaled.
+ *
+ * \param copyPass a copy pass handle
+ * \param source the source texture region
+ * \param destination the destination transfer buffer with image layout information
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_DownloadFromGpuTexture(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuTextureRegion *source,
+    SDL_GpuTextureTransferInfo *destination);
+
+/**
+ * Copies data from a buffer to a transfer buffer on the GPU timeline.
+ * This data is not guaranteed to be copied until the command buffer fence is signaled.
+ *
+ * \param copyPass a copy pass handle
+ * \param source the source buffer with offset and size
+ * \param destination the destination transfer buffer with offset
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_DownloadFromGpuBuffer(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuBufferRegion *source,
+    SDL_GpuTransferBufferLocation *destination);
+
+/**
+ * Ends the current copy pass.
+ *
+ * \param copyPass a copy pass handle
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_EndGpuCopyPass(
+    SDL_GpuCopyPass *copyPass);
+
+/**
+ * Generates mipmaps for the given texture.
+ * This function must not be called inside of any pass.
+ *
+ * \param commandBuffer a commandBuffer
+ * \param texture a texture with more than 1 mip level
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_GenerateGpuMipmaps(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTexture *texture);
+
+/**
+ * Blits from a source texture region to a destination texture region.
+ * This function must not be called inside of any pass.
+ *
+ * \param commandBuffer a command buffer
+ * \param source the texture region to copy from
+ * \param destination the texture region to copy to
+ * \param flipMode the flip mode for the source texture region
+ * \param filterMode the filter mode that will be used when blitting
+ * \param cycle if SDL_TRUE, cycles the destination texture if the destination texture is bound, otherwise overwrites the data.
+ *
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_BlitGpu(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBlitRegion *source,
+    SDL_GpuBlitRegion *destination,
+    SDL_FlipMode flipMode,
+    SDL_GpuFilter filterMode,
+    SDL_bool cycle);
+
+/* Submission/Presentation */
+
+/**
+ * Determines whether a swapchain composition is supported by the window.
+ * The window must be claimed before calling this function.
+ *
+ * \param device a GPU context
+ * \param window an SDL_Window
+ * \param swapchainComposition the swapchain composition to check
+ *
+ * \returns SDL_TRUE if supported, SDL_FALSE if unsupported (or on error)
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_ClaimGpuWindow
+ */
+extern SDL_DECLSPEC SDL_bool SDLCALL SDL_SupportsGpuSwapchainComposition(
+    SDL_GpuDevice *device,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition);
+
+/**
+ * Determines whether a presentation mode is supported by the window.
+ * The window must be claimed before calling this function.
+ *
+ * \param device a GPU context
+ * \param window an SDL_Window
+ * \param presentMode the presentation mode to check
+ *
+ * \returns SDL_TRUE if supported, SDL_FALSE if unsupported (or on error)
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_ClaimGpuWindow
+ */
+extern SDL_DECLSPEC SDL_bool SDLCALL SDL_SupportsGpuPresentMode(
+    SDL_GpuDevice *device,
+    SDL_Window *window,
+    SDL_GpuPresentMode presentMode);
+
+/**
+ * Claims a window, creating a swapchain structure for it.
+ * This must be called before SDL_AcquireGpuSwapchainTexture is called using the window.
+ *
+ * The swapchain will be created with SDL_GPU_SWAPCHAINCOMPOSITION_SDR and SDL_GPU_PRESENTMODE_VSYNC.
+ * If you want to have different swapchain parameters, you must call
+ * SetSwapchainParameters after claiming the window.
+ *
+ * \param device a GPU context
+ * \param window an SDL_Window
+ *
+ * \returns SDL_TRUE on success, otherwise SDL_FALSE.
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_AcquireGpuSwapchainTexture
+ * \sa SDL_UnclaimGpuWindow
+ * \sa SDL_SupportsGpuPresentMode
+ * \sa SDL_SupportsGpuSwapchainComposition
+ */
+extern SDL_DECLSPEC SDL_bool SDLCALL SDL_ClaimGpuWindow(
+    SDL_GpuDevice *device,
+    SDL_Window *window);
+
+/**
+ * Unclaims a window, destroying its swapchain structure.
+ *
+ * \param device a GPU context
+ * \param window an SDL_Window that has been claimed
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_ClaimGpuWindow
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_UnclaimGpuWindow(
+    SDL_GpuDevice *device,
+    SDL_Window *window);
+
+/**
+ * Changes the swapchain parameters for the given claimed window.
+ *
+ * This function will fail if the requested present mode or swapchain composition
+ * are unsupported by the device. Check if the parameters are supported via
+ * SDL_SupportsGpuPresentMode / SDL_SupportsGpuSwapchainComposition prior to
+ * calling this function.
+ *
+ * SDL_GPU_PRESENTMODE_VSYNC and SDL_GPU_SWAPCHAINCOMPOSITION_SDR are
+ * always supported.
+ *
+ * \param device a GPU context
+ * \param window an SDL_Window that has been claimed
+ * \param swapchainComposition the desired composition of the swapchain
+ * \param presentMode the desired present mode for the swapchain
+ * \returns SDL_TRUE if successful, SDL_FALSE on error
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_SupportsGpuPresentMode
+ * \sa SDL_SupportsGpuSwapchainComposition
+ */
+extern SDL_DECLSPEC SDL_bool SDLCALL SDL_SetGpuSwapchainParameters(
+    SDL_GpuDevice *device,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition,
+    SDL_GpuPresentMode presentMode);
+
+/**
+ * Obtains the texture format of the swapchain for the given window.
+ *
+ * \param device a GPU context
+ * \param window an SDL_Window that has been claimed
+ *
+ * \returns the texture format of the swapchain
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC SDL_GpuTextureFormat SDLCALL SDL_GetGpuSwapchainTextureFormat(
+    SDL_GpuDevice *device,
+    SDL_Window *window);
+
+/**
+ * Acquire a texture to use in presentation.
+ * When a swapchain texture is acquired on a command buffer,
+ * it will automatically be submitted for presentation when the command buffer is submitted.
+ * The swapchain texture should only be referenced by the command buffer used to acquire it.
+ * May return NULL under certain conditions. This is not necessarily an error.
+ * This texture is managed by the implementation and must not be freed by the user.
+ * You MUST NOT call this function from any thread other than the one that created the window.
+ *
+ * \param commandBuffer a command buffer
+ * \param window a window that has been claimed
+ * \param pWidth a pointer filled in with the swapchain width
+ * \param pHeight a pointer filled in with the swapchain height
+ * \returns a swapchain texture
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_ClaimGpuWindow
+ * \sa SDL_SubmitGpu
+ * \sa SDL_SubmitGpuAndAcquireFence
+ */
+extern SDL_DECLSPEC SDL_GpuTexture *SDLCALL SDL_AcquireGpuSwapchainTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_Window *window,
+    Uint32 *pWidth,
+    Uint32 *pHeight);
+
+/**
+ * Submits a command buffer so its commands can be processed on the GPU.
+ * It is invalid to use the command buffer after this is called.
+ *
+ * This must be called from the thread the command buffer was acquired on.
+ *
+ * All commands in the submission are guaranteed to begin executing before
+ * any command in a subsequent submission begins executing.
+ *
+ * \param commandBuffer a command buffer
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_AcquireGpuCommandBuffer
+ * \sa SDL_AcquireGpuSwapchainTexture
+ * \sa SDL_SubmitGpuAndAcquireFence
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_SubmitGpu(
+    SDL_GpuCommandBuffer *commandBuffer);
+
+/**
+ * Submits a command buffer so its commands can be processed on the GPU,
+ * and acquires a fence associated with the command buffer.
+ * You must release this fence when it is no longer needed or it will cause a leak.
+ * It is invalid to use the command buffer after this is called.
+ *
+ * This must be called from the thread the command buffer was acquired on.
+ *
+ * All commands in the submission are guaranteed to begin executing before
+ * any command in a subsequent submission begins executing.
+ *
+ * \param commandBuffer a command buffer
+ * \returns a fence associated with the command buffer
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_AcquireGpuCommandBuffer
+ * \sa SDL_AcquireGpuSwapchainTexture
+ * \sa SDL_SubmitGpu
+ * \sa SDL_ReleaseGpuFence
+ */
+extern SDL_DECLSPEC SDL_GpuFence *SDLCALL SDL_SubmitGpuAndAcquireFence(
+    SDL_GpuCommandBuffer *commandBuffer);
+
+/**
+ * Blocks the thread until the GPU is completely idle.
+ *
+ * \param device a GPU context
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_WaitGpuForFences
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_WaitGpu(
+    SDL_GpuDevice *device);
+
+/**
+ * Blocks the thread until the given fences are signaled.
+ *
+ * \param device a GPU context
+ * \param waitAll if 0, wait for any fence to be signaled, if 1, wait for all fences to be signaled
+ * \param pFences an array of fences to wait on
+ * \param fenceCount the number of fences in the pFences array
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_SubmitGpuAndAcquireFence
+ * \sa SDL_WaitGpu
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_WaitGpuForFences(
+    SDL_GpuDevice *device,
+    SDL_bool waitAll,
+    SDL_GpuFence **pFences,
+    Uint32 fenceCount);
+
+/**
+ * Checks the status of a fence.
+ *
+ * \param device a GPU context
+ * \param fence a fence
+ * \returns SDL_TRUE if the fence is signaled, SDL_FALSE if it is not
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_SubmitGpuAndAcquireFence
+ */
+extern SDL_DECLSPEC SDL_bool SDLCALL SDL_QueryGpuFence(
+    SDL_GpuDevice *device,
+    SDL_GpuFence *fence);
+
+/**
+ * Releases a fence obtained from SDL_SubmitGpuAndAcquireFence.
+ *
+ * \param device a GPU context
+ * \param fence a fence
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_SubmitGpuAndAcquireFence
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_ReleaseGpuFence(
+    SDL_GpuDevice *device,
+    SDL_GpuFence *fence);
+
+/* Format Info */
+
+/**
+ * Obtains the texel block size for a texture format.
+ *
+ * \param textureFormat the texture format you want to know the texel size of
+ * \returns the texel block size of the texture format
+ *
+ * \since This function is available since SDL 3.x.x
+ *
+ * \sa SDL_UploadToGpuTexture
+ */
+extern SDL_DECLSPEC Uint32 SDLCALL SDL_GpuTextureFormatTexelBlockSize(
+    SDL_GpuTextureFormat textureFormat);
+
+/**
+ * Determines whether a texture format is supported for a given type and usage.
+ *
+ * \param device a GPU context
+ * \param format the texture format to check
+ * \param type the type of texture (2D, 3D, Cube)
+ * \param usage a bitmask of all usage scenarios to check
+ * \returns whether the texture format is supported for this type and usage
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC SDL_bool SDLCALL SDL_SupportsGpuTextureFormat(
+    SDL_GpuDevice *device,
+    SDL_GpuTextureFormat format,
+    SDL_GpuTextureType type,
+    SDL_GpuTextureUsageFlags usage);
+
+/**
+ * Determines if a sample count for a texture format is supported.
+ *
+ * \param device a GPU context
+ * \param format the texture format to check
+ * \param sampleCount the sample count to check
+ * \returns a hardware-specific version of min(preferred, possible)
+ *
+ * \since This function is available since SDL 3.x.x
+ */
+extern SDL_DECLSPEC SDL_bool SDLCALL SDL_SupportsGpuSampleCount(
+    SDL_GpuDevice *device,
+    SDL_GpuTextureFormat format,
+    SDL_GpuSampleCount sampleCount);
+
+#ifdef SDL_PLATFORM_GDK
+
+/**
+ * Call this to suspend GPU operation on Xbox when you receive
+ * the SDL_EVENT_DID_ENTER_BACKGROUND event.
+ *
+ * Do NOT call any SDL_Gpu functions after calling this function!
+ * This must also be called before calling SDL_GDKSuspendComplete.
+ *
+ * \param device a GPU context
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_AddEventWatch
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_GDKSuspendGpu(SDL_GpuDevice *device);
+
+/**
+ * Call this to resume GPU operation on Xbox when you receive
+ * the SDL_EVENT_WILL_ENTER_FOREGROUND event.
+ *
+ * When resuming, this function MUST be called before calling
+ * any other SDL_Gpu functions.
+ *
+ * \param device a GPU context
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_AddEventWatch
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_GDKResumeGpu(SDL_GpuDevice *device);
+
+#endif /* SDL_PLATFORM_GDK */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SDL_GPU_H */

+ 102 - 61
include/SDL3/SDL_hints.h

@@ -39,8 +39,8 @@
 #ifndef SDL_hints_h_
 #define SDL_hints_h_
 
-#include <SDL3/SDL_stdinc.h>
 #include <SDL3/SDL_error.h>
+#include <SDL3/SDL_stdinc.h>
 
 #include <SDL3/SDL_begin_code.h>
 /* Set up for C function definitions, even when using C++ */
@@ -139,7 +139,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_APP_ID      "SDL_APP_ID"
+#define SDL_HINT_APP_ID "SDL_APP_ID"
 
 /**
  * A variable setting the application name.
@@ -227,7 +227,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_AUDIO_CATEGORY   "SDL_AUDIO_CATEGORY"
+#define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY"
 
 /**
  * A variable controlling the default audio channel count.
@@ -473,7 +473,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_AUTO_UPDATE_JOYSTICKS  "SDL_AUTO_UPDATE_JOYSTICKS"
+#define SDL_HINT_AUTO_UPDATE_JOYSTICKS "SDL_AUTO_UPDATE_JOYSTICKS"
 
 /**
  * A variable controlling whether SDL updates sensor state when getting input
@@ -488,7 +488,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_AUTO_UPDATE_SENSORS    "SDL_AUTO_UPDATE_SENSORS"
+#define SDL_HINT_AUTO_UPDATE_SENSORS "SDL_AUTO_UPDATE_SENSORS"
 
 /**
  * Prevent SDL from using version 4 of the bitmap header when saving BMPs.
@@ -642,7 +642,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_EMSCRIPTEN_ASYNCIFY   "SDL_EMSCRIPTEN_ASYNCIFY"
+#define SDL_HINT_EMSCRIPTEN_ASYNCIFY "SDL_EMSCRIPTEN_ASYNCIFY"
 
 /**
  * Specify the CSS selector used for the "default" window/canvas.
@@ -675,7 +675,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT   "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"
+#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"
 
 /**
  * A variable that controls whether the on-screen keyboard should be shown
@@ -733,7 +733,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_EVENT_LOGGING   "SDL_EVENT_LOGGING"
+#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING"
 
 /**
  * A variable controlling whether raising the window should be done more
@@ -753,7 +753,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_FORCE_RAISEWINDOW    "SDL_FORCE_RAISEWINDOW"
+#define SDL_HINT_FORCE_RAISEWINDOW "SDL_FORCE_RAISEWINDOW"
 
 /**
  * A variable controlling how 3D acceleration is used to accelerate the SDL
@@ -774,7 +774,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_FRAMEBUFFER_ACCELERATION   "SDL_FRAMEBUFFER_ACCELERATION"
+#define SDL_HINT_FRAMEBUFFER_ACCELERATION "SDL_FRAMEBUFFER_ACCELERATION"
 
 /**
  * A variable that lets you manually hint extra gamecontroller db entries.
@@ -900,7 +900,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT  "SDL_GDK_TEXTINPUT_DEFAULT_TEXT"
+#define SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT "SDL_GDK_TEXTINPUT_DEFAULT_TEXT"
 
 /**
  * This variable sets the description of the TextInput window on GDK
@@ -1006,6 +1006,20 @@ extern "C" {
  */
 #define SDL_HINT_HIDAPI_UDEV "SDL_HIDAPI_UDEV"
 
+/**
+ * A variable that specifies a GPU backend to use.
+ *
+ * By default, SDL will try all available GPU backends in a reasonable order
+ * until it finds one that can work, but this hint allows the app or user to
+ * force a specific target, such as "d3d11" if, say, your hardware supports
+ * D3D12 but want to try using D3D11 instead.
+ *
+ * This hint should be set before SDL_GpuSelectBackend() is called.
+ *
+ * \since This hint is available since SDL 3.0.0.
+ */
+#define SDL_HINT_GPU_DRIVER "SDL_GPU_DRIVER"
+
 /**
  * A variable to control whether SDL_hid_enumerate() enumerates all HID
  * devices or only controllers.
@@ -1756,7 +1770,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_JOYSTICK_HIDAPI_XBOX   "SDL_JOYSTICK_HIDAPI_XBOX"
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX"
 
 /**
  * A variable controlling whether the HIDAPI driver for XBox 360 controllers
@@ -1773,7 +1787,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360   "SDL_JOYSTICK_HIDAPI_XBOX_360"
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360 "SDL_JOYSTICK_HIDAPI_XBOX_360"
 
 /**
  * A variable controlling whether the player LEDs should be lit to indicate
@@ -1805,7 +1819,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_WIRELESS   "SDL_JOYSTICK_HIDAPI_XBOX_360_WIRELESS"
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_WIRELESS "SDL_JOYSTICK_HIDAPI_XBOX_360_WIRELESS"
 
 /**
  * A variable controlling whether the HIDAPI driver for XBox One controllers
@@ -1822,7 +1836,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE   "SDL_JOYSTICK_HIDAPI_XBOX_ONE"
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE "SDL_JOYSTICK_HIDAPI_XBOX_ONE"
 
 /**
  * A variable controlling whether the Home button LED should be turned on when
@@ -1967,7 +1981,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT   "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT"
+#define SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT"
 
 /**
  * A variable controlling whether the ROG Chakram mice should show up as
@@ -2182,7 +2196,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER      "SDL_KMSDRM_REQUIRE_DRM_MASTER"
+#define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER "SDL_KMSDRM_REQUIRE_DRM_MASTER"
 
 /**
  * A variable controlling the default SDL log levels.
@@ -2208,7 +2222,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_LOGGING   "SDL_LOGGING"
+#define SDL_HINT_LOGGING "SDL_LOGGING"
 
 /**
  * A variable controlling whether to force the application to become the
@@ -2224,7 +2238,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MAC_BACKGROUND_APP    "SDL_MAC_BACKGROUND_APP"
+#define SDL_HINT_MAC_BACKGROUND_APP "SDL_MAC_BACKGROUND_APP"
 
 /**
  * A variable that determines whether Ctrl+Click should generate a right-click
@@ -2300,7 +2314,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_AUTO_CAPTURE    "SDL_MOUSE_AUTO_CAPTURE"
+#define SDL_HINT_MOUSE_AUTO_CAPTURE "SDL_MOUSE_AUTO_CAPTURE"
 
 /**
  * A variable setting the double click radius, in pixels.
@@ -2309,7 +2323,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS    "SDL_MOUSE_DOUBLE_CLICK_RADIUS"
+#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS "SDL_MOUSE_DOUBLE_CLICK_RADIUS"
 
 /**
  * A variable setting the double click time, in milliseconds.
@@ -2318,7 +2332,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME    "SDL_MOUSE_DOUBLE_CLICK_TIME"
+#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME"
 
 /**
  * A variable controlling whether warping a hidden mouse cursor will activate
@@ -2374,7 +2388,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE    "SDL_MOUSE_NORMAL_SPEED_SCALE"
+#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE"
 
 /**
  * A variable controlling whether relative mouse mode constrains the mouse to
@@ -2395,7 +2409,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER    "SDL_MOUSE_RELATIVE_MODE_CENTER"
+#define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER "SDL_MOUSE_RELATIVE_MODE_CENTER"
 
 /**
  * A variable controlling whether relative mouse mode is implemented using
@@ -2410,7 +2424,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP    "SDL_MOUSE_RELATIVE_MODE_WARP"
+#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP"
 
 /**
  * A variable setting the scale for mouse motion, in floating point, when the
@@ -2420,7 +2434,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE    "SDL_MOUSE_RELATIVE_SPEED_SCALE"
+#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE"
 
 /**
  * A variable controlling whether the system mouse acceleration curve is used
@@ -2439,7 +2453,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE    "SDL_MOUSE_RELATIVE_SYSTEM_SCALE"
+#define SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE "SDL_MOUSE_RELATIVE_SYSTEM_SCALE"
 
 /**
  * A variable controlling whether a motion event should be generated for mouse
@@ -2458,7 +2472,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_RELATIVE_WARP_MOTION  "SDL_MOUSE_RELATIVE_WARP_MOTION"
+#define SDL_HINT_MOUSE_RELATIVE_WARP_MOTION "SDL_MOUSE_RELATIVE_WARP_MOTION"
 
 /**
  * A variable controlling whether the hardware cursor stays visible when
@@ -2476,7 +2490,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE  "SDL_MOUSE_RELATIVE_CURSOR_VISIBLE"
+#define SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE "SDL_MOUSE_RELATIVE_CURSOR_VISIBLE"
 
 /**
  * Controls how often SDL issues cursor confinement commands to the operating
@@ -2493,7 +2507,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL  "SDL_MOUSE_RELATIVE_CLIP_INTERVAL"
+#define SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL "SDL_MOUSE_RELATIVE_CLIP_INTERVAL"
 
 /**
  * A variable controlling whether mouse events should generate synthetic touch
@@ -2510,7 +2524,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_MOUSE_TOUCH_EVENTS    "SDL_MOUSE_TOUCH_EVENTS"
+#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS"
 
 /**
  * A variable controlling whether the keyboard should be muted on the console.
@@ -2543,7 +2557,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_NO_SIGNAL_HANDLERS   "SDL_NO_SIGNAL_HANDLERS"
+#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS"
 
 /**
  * Specify the OpenGL library to load.
@@ -2587,7 +2601,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_OPENGL_ES_DRIVER   "SDL_OPENGL_ES_DRIVER"
+#define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER"
 
 /**
  * A variable controlling which orientations are allowed on iOS/Android.
@@ -2694,7 +2708,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_RENDER_DIRECT3D11_DEBUG    "SDL_RENDER_DIRECT3D11_DEBUG"
+#define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG"
 
 /**
  * A variable controlling whether to enable Vulkan Validation Layers.
@@ -2708,7 +2722,35 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_RENDER_VULKAN_DEBUG    "SDL_RENDER_VULKAN_DEBUG"
+#define SDL_HINT_RENDER_VULKAN_DEBUG "SDL_RENDER_VULKAN_DEBUG"
+
+/**
+ * A variable controlling whether to create the GPU device in debug mode.
+ *
+ * This variable can be set to the following values:
+ *
+ * - "0": Disable debug mode use (default)
+ * - "1": Enable debug mode use
+ *
+ * This hint should be set before creating a renderer.
+ *
+ * \since This hint is available since SDL 3.0.0.
+ */
+#define SDL_HINT_RENDER_GPU_DEBUG "SDL_RENDER_GPU_DEBUG"
+
+/**
+ * A variable controlling whether to prefer a low-power GPU on multi-GPU systems.
+ *
+ * This variable can be set to the following values:
+ *
+ * - "0": Prefer high-performance GPU (default)
+ * - "1": Prefer low-power GPU
+ *
+ * This hint should be set before creating a renderer.
+ *
+ * \since This hint is available since SDL 3.0.0.
+ */
+#define SDL_HINT_RENDER_GPU_LOW_POWER "SDL_RENDER_GPU_LOW_POWER"
 
 /**
  * A variable specifying which render driver to use.
@@ -2736,7 +2778,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_RENDER_DRIVER              "SDL_RENDER_DRIVER"
+#define SDL_HINT_RENDER_DRIVER "SDL_RENDER_DRIVER"
 
 /**
  * A variable controlling how the 2D render API renders lines.
@@ -2786,7 +2828,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_RENDER_VSYNC               "SDL_RENDER_VSYNC"
+#define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC"
 
 /**
  * A variable to control whether the return key on the soft keyboard should
@@ -2854,7 +2896,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_RPI_VIDEO_LAYER           "SDL_RPI_VIDEO_LAYER"
+#define SDL_HINT_RPI_VIDEO_LAYER "SDL_RPI_VIDEO_LAYER"
 
 /**
  * Specify an "activity name" for screensaver inhibition.
@@ -2975,7 +3017,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_THREAD_PRIORITY_POLICY         "SDL_THREAD_PRIORITY_POLICY"
+#define SDL_HINT_THREAD_PRIORITY_POLICY "SDL_THREAD_PRIORITY_POLICY"
 
 /**
  * A variable that controls the timer resolution, in milliseconds.
@@ -3010,7 +3052,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_TOUCH_MOUSE_EVENTS    "SDL_TOUCH_MOUSE_EVENTS"
+#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS"
 
 /**
  * A variable controlling whether trackpads should be treated as touch
@@ -3060,7 +3102,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_VIDEO_ALLOW_SCREENSAVER    "SDL_VIDEO_ALLOW_SCREENSAVER"
+#define SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER"
 
 /**
  * Tell the video driver that we only want a double buffer.
@@ -3083,7 +3125,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_VIDEO_DOUBLE_BUFFER      "SDL_VIDEO_DOUBLE_BUFFER"
+#define SDL_HINT_VIDEO_DOUBLE_BUFFER "SDL_VIDEO_DOUBLE_BUFFER"
 
 /**
  * A variable that specifies a video backend to use.
@@ -3158,7 +3200,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES    "SDL_VIDEO_MAC_FULLSCREEN_SPACES"
+#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES"
 
 /**
  * A variable controlling whether fullscreen windows are minimized when they
@@ -3174,7 +3216,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS   "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"
+#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"
 
 /**
  * A variable controlling whether the offscreen video driver saves output
@@ -3356,7 +3398,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_VIDEO_WIN_D3DCOMPILER              "SDL_VIDEO_WIN_D3DCOMPILER"
+#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER"
 
 /**
  * A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint
@@ -3390,7 +3432,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_VIDEO_X11_NET_WM_PING      "SDL_VIDEO_X11_NET_WM_PING"
+#define SDL_HINT_VIDEO_X11_NET_WM_PING "SDL_VIDEO_X11_NET_WM_PING"
 
 /**
  * A variable controlling whether SDL uses DirectColor visuals.
@@ -3415,7 +3457,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_VIDEO_X11_SCALING_FACTOR      "SDL_VIDEO_X11_SCALING_FACTOR"
+#define SDL_HINT_VIDEO_X11_SCALING_FACTOR "SDL_VIDEO_X11_SCALING_FACTOR"
 
 /**
  * A variable forcing the visual ID used for X11 display modes.
@@ -3433,7 +3475,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_VIDEO_X11_WINDOW_VISUALID      "SDL_VIDEO_X11_WINDOW_VISUALID"
+#define SDL_HINT_VIDEO_X11_WINDOW_VISUALID "SDL_VIDEO_X11_WINDOW_VISUALID"
 
 /**
  * A variable controlling whether the X11 XRandR extension should be used.
@@ -3447,7 +3489,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_VIDEO_X11_XRANDR           "SDL_VIDEO_X11_XRANDR"
+#define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR"
 
 /**
  * A variable controlling whether touch should be enabled on the back panel of
@@ -3547,7 +3589,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_VITA_TOUCH_MOUSE_DEVICE    "SDL_VITA_TOUCH_MOUSE_DEVICE"
+#define SDL_HINT_VITA_TOUCH_MOUSE_DEVICE "SDL_VITA_TOUCH_MOUSE_DEVICE"
 
 /**
  * A variable overriding the display index used in SDL_Vulkan_CreateSurface()
@@ -3600,7 +3642,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_WAVE_FACT_CHUNK   "SDL_WAVE_FACT_CHUNK"
+#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK"
 
 /**
  * A variable controlling the maximum number of chunks in a WAVE file.
@@ -3612,7 +3654,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_WAVE_CHUNK_LIMIT   "SDL_WAVE_CHUNK_LIMIT"
+#define SDL_HINT_WAVE_CHUNK_LIMIT "SDL_WAVE_CHUNK_LIMIT"
 
 /**
  * A variable controlling how the size of the RIFF chunk affects the loading
@@ -3640,7 +3682,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE   "SDL_WAVE_RIFF_CHUNK_SIZE"
+#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE"
 
 /**
  * A variable controlling how a truncated WAVE file is handled.
@@ -3660,7 +3702,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_WAVE_TRUNCATION   "SDL_WAVE_TRUNCATION"
+#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION"
 
 /**
  * A variable controlling whether the window is activated when the
@@ -3677,7 +3719,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED    "SDL_WINDOW_ACTIVATE_WHEN_RAISED"
+#define SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED "SDL_WINDOW_ACTIVATE_WHEN_RAISED"
 
 /**
  * A variable controlling whether the window is activated when the
@@ -3694,7 +3736,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN    "SDL_WINDOW_ACTIVATE_WHEN_SHOWN"
+#define SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN "SDL_WINDOW_ACTIVATE_WHEN_SHOWN"
 
 /**
  * If set to "0" then never set the top-most flag on an SDL Window even if the
@@ -3728,7 +3770,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN    "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN"
+#define SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN"
 
 /**
  * A variable controlling whether SDL generates window-close events for Alt+F4
@@ -3818,7 +3860,7 @@ extern "C" {
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_WINDOWS_RAW_KEYBOARD   "SDL_WINDOWS_RAW_KEYBOARD"
+#define SDL_HINT_WINDOWS_RAW_KEYBOARD "SDL_WINDOWS_RAW_KEYBOARD"
 
 /**
  * A variable controlling whether SDL uses Kernel Semaphores on Windows.
@@ -4109,7 +4151,6 @@ typedef enum SDL_HintPriority
     SDL_HINT_OVERRIDE
 } SDL_HintPriority;
 
-
 /**
  * Set a hint with a specific priority.
  *
@@ -4208,7 +4249,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ResetHints(void);
  * \sa SDL_SetHint
  * \sa SDL_SetHintWithPriority
  */
-extern SDL_DECLSPEC const char * SDLCALL SDL_GetHint(const char *name);
+extern SDL_DECLSPEC const char *SDLCALL SDL_GetHint(const char *name);
 
 /**
  * Get the boolean value of a hint variable.
@@ -4246,7 +4287,7 @@ extern SDL_DECLSPEC SDL_bool SDLCALL SDL_GetHintBoolean(const char *name, SDL_bo
  *
  * \sa SDL_AddHintCallback
  */
-typedef void (SDLCALL *SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue);
+typedef void(SDLCALL *SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue);
 
 /**
  * Add a function to watch a particular hint.

+ 4 - 3
include/SDL3/SDL_log.h

@@ -72,9 +72,9 @@ extern "C" {
 /**
  * The predefined log categories
  *
- * By default the application category is enabled at the INFO level, the
- * assert category is enabled at the WARN level, test is enabled at the
- * VERBOSE level and all other categories are enabled at the ERROR level.
+ * By default the application and gpu categories are enabled at the INFO
+ * level, the assert category is enabled at the WARN level, test is enabled at
+ * the VERBOSE level and all other categories are enabled at the ERROR level.
  *
  * \since This enum is available since SDL 3.0.0.
  */
@@ -87,6 +87,7 @@ typedef enum SDL_LogCategory
     SDL_LOG_CATEGORY_AUDIO,
     SDL_LOG_CATEGORY_VIDEO,
     SDL_LOG_CATEGORY_RENDER,
+    SDL_LOG_CATEGORY_GPU,
     SDL_LOG_CATEGORY_INPUT,
     SDL_LOG_CATEGORY_TEST,
 

+ 7 - 0
include/build_config/SDL_build_config.h.cmake

@@ -426,6 +426,7 @@
 #cmakedefine SDL_VIDEO_RENDER_PS2 @SDL_VIDEO_RENDER_PS2@
 #cmakedefine SDL_VIDEO_RENDER_PSP @SDL_VIDEO_RENDER_PSP@
 #cmakedefine SDL_VIDEO_RENDER_VITA_GXM @SDL_VIDEO_RENDER_VITA_GXM@
+#cmakedefine SDL_VIDEO_RENDER_GPU @SDL_VIDEO_RENDER_GPU@
 
 /* Enable OpenGL support */
 #cmakedefine SDL_VIDEO_OPENGL @SDL_VIDEO_OPENGL@
@@ -445,6 +446,12 @@
 /* Enable Metal support */
 #cmakedefine SDL_VIDEO_METAL @SDL_VIDEO_METAL@
 
+/* Enable GPU support */
+#cmakedefine SDL_GPU_D3D11 @SDL_GPU_D3D11@
+#cmakedefine SDL_GPU_D3D12 @SDL_GPU_D3D12@
+#cmakedefine SDL_GPU_VULKAN @SDL_GPU_VULKAN@
+#cmakedefine SDL_GPU_METAL @SDL_GPU_METAL@
+
 /* Enable system power support */
 #cmakedefine SDL_POWER_ANDROID @SDL_POWER_ANDROID@
 #cmakedefine SDL_POWER_LINUX @SDL_POWER_LINUX@

+ 2 - 0
include/build_config/SDL_build_config_android.h

@@ -197,6 +197,8 @@
 #endif
 #endif
 
+#define SDL_GPU_VULKAN SDL_VIDEO_VULKAN
+
 /* Enable system power support */
 #define SDL_POWER_ANDROID 1
 

+ 4 - 0
include/build_config/SDL_build_config_macos.h

@@ -260,6 +260,8 @@
 #endif
 #endif
 
+#define SDL_GPU_VULKAN SDL_VIDEO_VULKAN
+
 #ifndef SDL_VIDEO_METAL
 #if SDL_PLATFORM_SUPPORTS_METAL
 #define SDL_VIDEO_METAL 1
@@ -268,6 +270,8 @@
 #endif
 #endif
 
+#define SDL_GPU_METAL SDL_VIDEO_METAL
+
 /* Enable system power support */
 #define SDL_POWER_MACOSX 1
 

+ 6 - 0
include/build_config/SDL_build_config_windows.h

@@ -310,6 +310,12 @@ typedef unsigned int uintptr_t;
 /* Enable Vulkan support */
 #define SDL_VIDEO_VULKAN 1
 
+#define SDL_GPU_D3D11 HAVE_D3D11_H
+#if !defined(SDL_GPU_D3D12)
+#define SDL_GPU_D3D12 1
+#endif
+#define SDL_GPU_VULKAN SDL_VIDEO_VULKAN
+
 #ifndef SDL_VIDEO_RENDER_VULKAN
 #define SDL_VIDEO_RENDER_VULKAN    1
 #endif

+ 6 - 0
include/build_config/SDL_build_config_wingdk.h

@@ -232,6 +232,12 @@
 /* Enable Vulkan support */
 #define SDL_VIDEO_VULKAN 1
 
+#define SDL_GPU_D3D11 HAVE_D3D11_H
+#if !defined(SDL_GPU_D3D12)
+#define SDL_GPU_D3D12 1
+#endif
+#define SDL_GPU_VULKAN SDL_VIDEO_VULKAN
+
 /* Enable system power support */
 #define SDL_POWER_WINDOWS 1
 

+ 4 - 0
include/build_config/SDL_build_config_xbox.h

@@ -200,6 +200,10 @@
 #define SDL_VIDEO_RENDER_D3D12  1
 #endif
 
+#if !defined(SDL_GPU_D3D12)
+#define SDL_GPU_D3D12 1
+#endif
+
 /* Enable OpenGL support */
 #ifndef SDL_VIDEO_OPENGL
 #define SDL_VIDEO_OPENGL    1

+ 2 - 0
src/SDL_log.c

@@ -91,6 +91,7 @@ static const char * const SDL_category_names[] = {
     "AUDIO",
     "VIDEO",
     "RENDER",
+    "GPU",
     "INPUT",
     "TEST"
 };
@@ -270,6 +271,7 @@ static SDL_LogPriority SDL_GetDefaultLogPriority(int category)
 
     switch (category) {
     case SDL_LOG_CATEGORY_APPLICATION:
+    case SDL_LOG_CATEGORY_GPU:
         return SDL_LOG_PRIORITY_INFO;
     case SDL_LOG_CATEGORY_ASSERT:
         return SDL_LOG_PRIORITY_WARN;

+ 10 - 0
src/core/SDL_core_unsupported.c

@@ -64,6 +64,16 @@ SDL_bool SDL_GetGDKDefaultUser(void *outUserHandle)
     return SDL_Unsupported();
 }
 
+SDL_DECLSPEC void SDLCALL SDL_GDKSuspendGpu(SDL_GpuDevice *device);
+void SDL_GDKSuspendGpu(SDL_GpuDevice *device)
+{
+}
+
+SDL_DECLSPEC void SDLCALL SDL_GDKResumeGpu(SDL_GpuDevice *device);
+void SDL_GDKResumeGpu(SDL_GpuDevice *device)
+{
+}
+
 #endif
 
 #if !(defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK))

+ 81 - 0
src/dynapi/SDL_dynapi.sym

@@ -1060,6 +1060,87 @@ SDL3_0.0.0 {
     SDL_wcsnstr;
     SDL_wcsstr;
     SDL_wcstol;
+    SDL_CreateGpuDevice;
+    SDL_CreateGpuDeviceWithProperties;
+    SDL_DestroyGpuDevice;
+    SDL_GetGpuDriver;
+    SDL_CreateGpuComputePipeline;
+    SDL_CreateGpuGraphicsPipeline;
+    SDL_CreateGpuSampler;
+    SDL_CreateGpuShader;
+    SDL_CreateGpuTexture;
+    SDL_CreateGpuBuffer;
+    SDL_CreateGpuTransferBuffer;
+    SDL_SetGpuBufferName;
+    SDL_SetGpuTextureName;
+    SDL_InsertGpuDebugLabel;
+    SDL_PushGpuDebugGroup;
+    SDL_PopGpuDebugGroup;
+    SDL_ReleaseGpuTexture;
+    SDL_ReleaseGpuSampler;
+    SDL_ReleaseGpuBuffer;
+    SDL_ReleaseGpuTransferBuffer;
+    SDL_ReleaseGpuComputePipeline;
+    SDL_ReleaseGpuShader;
+    SDL_ReleaseGpuGraphicsPipeline;
+    SDL_BeginGpuRenderPass;
+    SDL_BindGpuGraphicsPipeline;
+    SDL_SetGpuViewport;
+    SDL_SetGpuScissor;
+    SDL_BindGpuVertexBuffers;
+    SDL_BindGpuIndexBuffer;
+    SDL_BindGpuVertexSamplers;
+    SDL_BindGpuVertexStorageTextures;
+    SDL_BindGpuVertexStorageBuffers;
+    SDL_BindGpuFragmentSamplers;
+    SDL_BindGpuFragmentStorageTextures;
+    SDL_BindGpuFragmentStorageBuffers;
+    SDL_PushGpuVertexUniformData;
+    SDL_PushGpuFragmentUniformData;
+    SDL_DrawGpuIndexedPrimitives;
+    SDL_DrawGpuPrimitives;
+    SDL_DrawGpuPrimitivesIndirect;
+    SDL_DrawGpuIndexedPrimitivesIndirect;
+    SDL_EndGpuRenderPass;
+    SDL_BeginGpuComputePass;
+    SDL_BindGpuComputePipeline;
+    SDL_BindGpuComputeStorageTextures;
+    SDL_BindGpuComputeStorageBuffers;
+    SDL_PushGpuComputeUniformData;
+    SDL_DispatchGpuCompute;
+    SDL_DispatchGpuComputeIndirect;
+    SDL_EndGpuComputePass;
+    SDL_MapGpuTransferBuffer;
+    SDL_UnmapGpuTransferBuffer;
+    SDL_BeginGpuCopyPass;
+    SDL_UploadToGpuTexture;
+    SDL_UploadToGpuBuffer;
+    SDL_CopyGpuTextureToTexture;
+    SDL_CopyGpuBufferToBuffer;
+    SDL_GenerateGpuMipmaps;
+    SDL_DownloadFromGpuTexture;
+    SDL_DownloadFromGpuBuffer;
+    SDL_EndGpuCopyPass;
+    SDL_BlitGpu;
+    SDL_SupportsGpuSwapchainComposition;
+    SDL_SupportsGpuPresentMode;
+    SDL_ClaimGpuWindow;
+    SDL_UnclaimGpuWindow;
+    SDL_SetGpuSwapchainParameters;
+    SDL_GetGpuSwapchainTextureFormat;
+    SDL_AcquireGpuCommandBuffer;
+    SDL_AcquireGpuSwapchainTexture;
+    SDL_SubmitGpu;
+    SDL_SubmitGpuAndAcquireFence;
+    SDL_WaitGpu;
+    SDL_WaitGpuForFences;
+    SDL_QueryGpuFence;
+    SDL_ReleaseGpuFence;
+    SDL_GpuTextureFormatTexelBlockSize;
+    SDL_SupportsGpuTextureFormat;
+    SDL_SupportsGpuSampleCount;
+    SDL_GDKSuspendGpu;
+    SDL_GDKResumeGpu;
     # extra symbols go here (don't modify this line)
   local: *;
 };

+ 81 - 0
src/dynapi/SDL_dynapi_overrides.h

@@ -1085,3 +1085,84 @@
 #define SDL_wcsnstr SDL_wcsnstr_REAL
 #define SDL_wcsstr SDL_wcsstr_REAL
 #define SDL_wcstol SDL_wcstol_REAL
+#define SDL_CreateGpuDevice SDL_CreateGpuDevice_REAL
+#define SDL_CreateGpuDeviceWithProperties SDL_CreateGpuDeviceWithProperties_REAL
+#define SDL_DestroyGpuDevice SDL_DestroyGpuDevice_REAL
+#define SDL_GetGpuDriver SDL_GetGpuDriver_REAL
+#define SDL_CreateGpuComputePipeline SDL_CreateGpuComputePipeline_REAL
+#define SDL_CreateGpuGraphicsPipeline SDL_CreateGpuGraphicsPipeline_REAL
+#define SDL_CreateGpuSampler SDL_CreateGpuSampler_REAL
+#define SDL_CreateGpuShader SDL_CreateGpuShader_REAL
+#define SDL_CreateGpuTexture SDL_CreateGpuTexture_REAL
+#define SDL_CreateGpuBuffer SDL_CreateGpuBuffer_REAL
+#define SDL_CreateGpuTransferBuffer SDL_CreateGpuTransferBuffer_REAL
+#define SDL_SetGpuBufferName SDL_SetGpuBufferName_REAL
+#define SDL_SetGpuTextureName SDL_SetGpuTextureName_REAL
+#define SDL_InsertGpuDebugLabel SDL_InsertGpuDebugLabel_REAL
+#define SDL_PushGpuDebugGroup SDL_PushGpuDebugGroup_REAL
+#define SDL_PopGpuDebugGroup SDL_PopGpuDebugGroup_REAL
+#define SDL_ReleaseGpuTexture SDL_ReleaseGpuTexture_REAL
+#define SDL_ReleaseGpuSampler SDL_ReleaseGpuSampler_REAL
+#define SDL_ReleaseGpuBuffer SDL_ReleaseGpuBuffer_REAL
+#define SDL_ReleaseGpuTransferBuffer SDL_ReleaseGpuTransferBuffer_REAL
+#define SDL_ReleaseGpuComputePipeline SDL_ReleaseGpuComputePipeline_REAL
+#define SDL_ReleaseGpuShader SDL_ReleaseGpuShader_REAL
+#define SDL_ReleaseGpuGraphicsPipeline SDL_ReleaseGpuGraphicsPipeline_REAL
+#define SDL_BeginGpuRenderPass SDL_BeginGpuRenderPass_REAL
+#define SDL_BindGpuGraphicsPipeline SDL_BindGpuGraphicsPipeline_REAL
+#define SDL_SetGpuViewport SDL_SetGpuViewport_REAL
+#define SDL_SetGpuScissor SDL_SetGpuScissor_REAL
+#define SDL_BindGpuVertexBuffers SDL_BindGpuVertexBuffers_REAL
+#define SDL_BindGpuIndexBuffer SDL_BindGpuIndexBuffer_REAL
+#define SDL_BindGpuVertexSamplers SDL_BindGpuVertexSamplers_REAL
+#define SDL_BindGpuVertexStorageTextures SDL_BindGpuVertexStorageTextures_REAL
+#define SDL_BindGpuVertexStorageBuffers SDL_BindGpuVertexStorageBuffers_REAL
+#define SDL_BindGpuFragmentSamplers SDL_BindGpuFragmentSamplers_REAL
+#define SDL_BindGpuFragmentStorageTextures SDL_BindGpuFragmentStorageTextures_REAL
+#define SDL_BindGpuFragmentStorageBuffers SDL_BindGpuFragmentStorageBuffers_REAL
+#define SDL_PushGpuVertexUniformData SDL_PushGpuVertexUniformData_REAL
+#define SDL_PushGpuFragmentUniformData SDL_PushGpuFragmentUniformData_REAL
+#define SDL_DrawGpuIndexedPrimitives SDL_DrawGpuIndexedPrimitives_REAL
+#define SDL_DrawGpuPrimitives SDL_DrawGpuPrimitives_REAL
+#define SDL_DrawGpuPrimitivesIndirect SDL_DrawGpuPrimitivesIndirect_REAL
+#define SDL_DrawGpuIndexedPrimitivesIndirect SDL_DrawGpuIndexedPrimitivesIndirect_REAL
+#define SDL_EndGpuRenderPass SDL_EndGpuRenderPass_REAL
+#define SDL_BeginGpuComputePass SDL_BeginGpuComputePass_REAL
+#define SDL_BindGpuComputePipeline SDL_BindGpuComputePipeline_REAL
+#define SDL_BindGpuComputeStorageTextures SDL_BindGpuComputeStorageTextures_REAL
+#define SDL_BindGpuComputeStorageBuffers SDL_BindGpuComputeStorageBuffers_REAL
+#define SDL_PushGpuComputeUniformData SDL_PushGpuComputeUniformData_REAL
+#define SDL_DispatchGpuCompute SDL_DispatchGpuCompute_REAL
+#define SDL_DispatchGpuComputeIndirect SDL_DispatchGpuComputeIndirect_REAL
+#define SDL_EndGpuComputePass SDL_EndGpuComputePass_REAL
+#define SDL_MapGpuTransferBuffer SDL_MapGpuTransferBuffer_REAL
+#define SDL_UnmapGpuTransferBuffer SDL_UnmapGpuTransferBuffer_REAL
+#define SDL_BeginGpuCopyPass SDL_BeginGpuCopyPass_REAL
+#define SDL_UploadToGpuTexture SDL_UploadToGpuTexture_REAL
+#define SDL_UploadToGpuBuffer SDL_UploadToGpuBuffer_REAL
+#define SDL_CopyGpuTextureToTexture SDL_CopyGpuTextureToTexture_REAL
+#define SDL_CopyGpuBufferToBuffer SDL_CopyGpuBufferToBuffer_REAL
+#define SDL_GenerateGpuMipmaps SDL_GenerateGpuMipmaps_REAL
+#define SDL_DownloadFromGpuTexture SDL_DownloadFromGpuTexture_REAL
+#define SDL_DownloadFromGpuBuffer SDL_DownloadFromGpuBuffer_REAL
+#define SDL_EndGpuCopyPass SDL_EndGpuCopyPass_REAL
+#define SDL_BlitGpu SDL_BlitGpu_REAL
+#define SDL_SupportsGpuSwapchainComposition SDL_SupportsGpuSwapchainComposition_REAL
+#define SDL_SupportsGpuPresentMode SDL_SupportsGpuPresentMode_REAL
+#define SDL_ClaimGpuWindow SDL_ClaimGpuWindow_REAL
+#define SDL_UnclaimGpuWindow SDL_UnclaimGpuWindow_REAL
+#define SDL_SetGpuSwapchainParameters SDL_SetGpuSwapchainParameters_REAL
+#define SDL_GetGpuSwapchainTextureFormat SDL_GetGpuSwapchainTextureFormat_REAL
+#define SDL_AcquireGpuCommandBuffer SDL_AcquireGpuCommandBuffer_REAL
+#define SDL_AcquireGpuSwapchainTexture SDL_AcquireGpuSwapchainTexture_REAL
+#define SDL_SubmitGpu SDL_SubmitGpu_REAL
+#define SDL_SubmitGpuAndAcquireFence SDL_SubmitGpuAndAcquireFence_REAL
+#define SDL_WaitGpu SDL_WaitGpu_REAL
+#define SDL_WaitGpuForFences SDL_WaitGpuForFences_REAL
+#define SDL_QueryGpuFence SDL_QueryGpuFence_REAL
+#define SDL_ReleaseGpuFence SDL_ReleaseGpuFence_REAL
+#define SDL_GpuTextureFormatTexelBlockSize SDL_GpuTextureFormatTexelBlockSize_REAL
+#define SDL_SupportsGpuTextureFormat SDL_SupportsGpuTextureFormat_REAL
+#define SDL_SupportsGpuSampleCount SDL_SupportsGpuSampleCount_REAL
+#define SDL_GDKSuspendGpu SDL_GDKSuspendGpu_REAL
+#define SDL_GDKResumeGpu SDL_GDKResumeGpu_REAL

+ 81 - 0
src/dynapi/SDL_dynapi_procs.h

@@ -1091,3 +1091,84 @@ SDL_DYNAPI_PROC(size_t,SDL_wcsnlen,(const wchar_t *a, size_t b),(a,b),return)
 SDL_DYNAPI_PROC(wchar_t*,SDL_wcsnstr,(const wchar_t *a, const wchar_t *b, size_t c),(a,b,c),return)
 SDL_DYNAPI_PROC(wchar_t*,SDL_wcsstr,(const wchar_t *a, const wchar_t *b),(a,b),return)
 SDL_DYNAPI_PROC(long,SDL_wcstol,(const wchar_t *a, wchar_t **b, int c),(a,b,c),return)
+SDL_DYNAPI_PROC(SDL_GpuDevice*,SDL_CreateGpuDevice,(SDL_GpuShaderFormat a, SDL_bool b, SDL_bool c, const char *d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(SDL_GpuDevice*,SDL_CreateGpuDeviceWithProperties,(SDL_PropertiesID a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_DestroyGpuDevice,(SDL_GpuDevice *a),(a),)
+SDL_DYNAPI_PROC(SDL_GpuDriver,SDL_GetGpuDriver,(SDL_GpuDevice *a),(a),return)
+SDL_DYNAPI_PROC(SDL_GpuComputePipeline*,SDL_CreateGpuComputePipeline,(SDL_GpuDevice *a, SDL_GpuComputePipelineCreateInfo *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_GpuGraphicsPipeline*,SDL_CreateGpuGraphicsPipeline,(SDL_GpuDevice *a, SDL_GpuGraphicsPipelineCreateInfo *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_GpuSampler*,SDL_CreateGpuSampler,(SDL_GpuDevice *a, SDL_GpuSamplerCreateInfo *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_GpuShader*,SDL_CreateGpuShader,(SDL_GpuDevice *a, SDL_GpuShaderCreateInfo *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_GpuTexture*,SDL_CreateGpuTexture,(SDL_GpuDevice *a, SDL_GpuTextureCreateInfo *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_GpuBuffer*,SDL_CreateGpuBuffer,(SDL_GpuDevice *a, SDL_GpuBufferCreateInfo* b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_GpuTransferBuffer*,SDL_CreateGpuTransferBuffer,(SDL_GpuDevice *a, SDL_GpuTransferBufferCreateInfo *b),(a,b),return)
+SDL_DYNAPI_PROC(void,SDL_SetGpuBufferName,(SDL_GpuDevice *a, SDL_GpuBuffer *b, const char *c),(a,b,c),)
+SDL_DYNAPI_PROC(void,SDL_SetGpuTextureName,(SDL_GpuDevice *a, SDL_GpuTexture *b, const char *c),(a,b,c),)
+SDL_DYNAPI_PROC(void,SDL_InsertGpuDebugLabel,(SDL_GpuCommandBuffer *a, const char *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_PushGpuDebugGroup,(SDL_GpuCommandBuffer *a, const char *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_PopGpuDebugGroup,(SDL_GpuCommandBuffer *a),(a),)
+SDL_DYNAPI_PROC(void,SDL_ReleaseGpuTexture,(SDL_GpuDevice *a, SDL_GpuTexture *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_ReleaseGpuSampler,(SDL_GpuDevice *a, SDL_GpuSampler *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_ReleaseGpuBuffer,(SDL_GpuDevice *a, SDL_GpuBuffer *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_ReleaseGpuTransferBuffer,(SDL_GpuDevice *a, SDL_GpuTransferBuffer *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_ReleaseGpuComputePipeline,(SDL_GpuDevice *a, SDL_GpuComputePipeline *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_ReleaseGpuShader,(SDL_GpuDevice *a, SDL_GpuShader *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_ReleaseGpuGraphicsPipeline,(SDL_GpuDevice *a, SDL_GpuGraphicsPipeline *b),(a,b),)
+SDL_DYNAPI_PROC(SDL_GpuCommandBuffer*,SDL_AcquireGpuCommandBuffer,(SDL_GpuDevice *a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_PushGpuVertexUniformData,(SDL_GpuCommandBuffer *a, Uint32 b, const void *c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_PushGpuFragmentUniformData,(SDL_GpuCommandBuffer *a, Uint32 b, const void *c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_PushGpuComputeUniformData,(SDL_GpuCommandBuffer *a, Uint32 b, const void *c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(SDL_GpuRenderPass*,SDL_BeginGpuRenderPass,(SDL_GpuCommandBuffer *a, SDL_GpuColorAttachmentInfo *b, Uint32 c, SDL_GpuDepthStencilAttachmentInfo *d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(void,SDL_BindGpuGraphicsPipeline,(SDL_GpuRenderPass *a, SDL_GpuGraphicsPipeline *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_SetGpuViewport,(SDL_GpuRenderPass *a, SDL_GpuViewport *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_SetGpuScissor,(SDL_GpuRenderPass *a, SDL_Rect *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_BindGpuVertexBuffers,(SDL_GpuRenderPass *a, Uint32 b, SDL_GpuBufferBinding *c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_BindGpuIndexBuffer,(SDL_GpuRenderPass *a, SDL_GpuBufferBinding *b, SDL_GpuIndexElementSize c),(a,b,c),)
+SDL_DYNAPI_PROC(void,SDL_BindGpuVertexSamplers,(SDL_GpuRenderPass *a, Uint32 b, SDL_GpuTextureSamplerBinding *c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_BindGpuVertexStorageTextures,(SDL_GpuRenderPass *a, Uint32 b, SDL_GpuTexture **c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_BindGpuVertexStorageBuffers,(SDL_GpuRenderPass *a, Uint32 b, SDL_GpuBuffer **c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_BindGpuFragmentSamplers,(SDL_GpuRenderPass *a, Uint32 b, SDL_GpuTextureSamplerBinding *c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_BindGpuFragmentStorageTextures,(SDL_GpuRenderPass *a, Uint32 b, SDL_GpuTexture **c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_BindGpuFragmentStorageBuffers,(SDL_GpuRenderPass *a, Uint32 b, SDL_GpuBuffer **c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_DrawGpuIndexedPrimitives,(SDL_GpuRenderPass *a, Uint32 b, Uint32 c, Uint32 d, Sint32 e, Uint32 f),(a,b,c,d,e,f),)
+SDL_DYNAPI_PROC(void,SDL_DrawGpuPrimitives,(SDL_GpuRenderPass *a, Uint32 b, Uint32 c, Uint32 d, Uint32 e),(a,b,c,d,e),)
+SDL_DYNAPI_PROC(void,SDL_DrawGpuPrimitivesIndirect,(SDL_GpuRenderPass *a, SDL_GpuBuffer *b, Uint32 c, Uint32 d, Uint32 e),(a,b,c,d,e),)
+SDL_DYNAPI_PROC(void,SDL_DrawGpuIndexedPrimitivesIndirect,(SDL_GpuRenderPass *a, SDL_GpuBuffer *b, Uint32 c, Uint32 d, Uint32 e),(a,b,c,d,e),)
+SDL_DYNAPI_PROC(void,SDL_EndGpuRenderPass,(SDL_GpuRenderPass *a),(a),)
+SDL_DYNAPI_PROC(SDL_GpuComputePass*,SDL_BeginGpuComputePass,(SDL_GpuCommandBuffer *a, SDL_GpuStorageTextureWriteOnlyBinding *b, Uint32 c, SDL_GpuStorageBufferWriteOnlyBinding *d, Uint32 e),(a,b,c,d,e),return)
+SDL_DYNAPI_PROC(void,SDL_BindGpuComputePipeline,(SDL_GpuComputePass *a, SDL_GpuComputePipeline *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_BindGpuComputeStorageTextures,(SDL_GpuComputePass *a, Uint32 b, SDL_GpuTexture **c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_BindGpuComputeStorageBuffers,(SDL_GpuComputePass *a, Uint32 b, SDL_GpuBuffer **c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_DispatchGpuCompute,(SDL_GpuComputePass *a, Uint32 b, Uint32 c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_DispatchGpuComputeIndirect,(SDL_GpuComputePass *a, SDL_GpuBuffer *b, Uint32 c),(a,b,c),)
+SDL_DYNAPI_PROC(void,SDL_EndGpuComputePass,(SDL_GpuComputePass *a),(a),)
+SDL_DYNAPI_PROC(void*,SDL_MapGpuTransferBuffer,(SDL_GpuDevice *a, SDL_GpuTransferBuffer *b, SDL_bool c),(a,b,c),return)
+SDL_DYNAPI_PROC(void,SDL_UnmapGpuTransferBuffer,(SDL_GpuDevice *a, SDL_GpuTransferBuffer *b),(a,b),)
+SDL_DYNAPI_PROC(SDL_GpuCopyPass*,SDL_BeginGpuCopyPass,(SDL_GpuCommandBuffer *a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_UploadToGpuTexture,(SDL_GpuCopyPass *a, SDL_GpuTextureTransferInfo *b, SDL_GpuTextureRegion *c, SDL_bool d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_UploadToGpuBuffer,(SDL_GpuCopyPass *a, SDL_GpuTransferBufferLocation *b, SDL_GpuBufferRegion *c, SDL_bool d),(a,b,c,d),)
+SDL_DYNAPI_PROC(void,SDL_CopyGpuTextureToTexture,(SDL_GpuCopyPass *a, SDL_GpuTextureLocation *b, SDL_GpuTextureLocation *c, Uint32 d, Uint32 e, Uint32 f, SDL_bool g),(a,b,c,d,e,f,g),)
+SDL_DYNAPI_PROC(void,SDL_CopyGpuBufferToBuffer,(SDL_GpuCopyPass *a, SDL_GpuBufferLocation *b, SDL_GpuBufferLocation *c, Uint32 d, SDL_bool e),(a,b,c,d,e),)
+SDL_DYNAPI_PROC(void,SDL_GenerateGpuMipmaps,(SDL_GpuCommandBuffer *a, SDL_GpuTexture *b),(a,b),)
+SDL_DYNAPI_PROC(void,SDL_DownloadFromGpuTexture,(SDL_GpuCopyPass *a, SDL_GpuTextureRegion *b, SDL_GpuTextureTransferInfo *c),(a,b,c),)
+SDL_DYNAPI_PROC(void,SDL_DownloadFromGpuBuffer,(SDL_GpuCopyPass *a, SDL_GpuBufferRegion *b, SDL_GpuTransferBufferLocation *c),(a,b,c),)
+SDL_DYNAPI_PROC(void,SDL_EndGpuCopyPass,(SDL_GpuCopyPass *a),(a),)
+SDL_DYNAPI_PROC(void,SDL_BlitGpu,(SDL_GpuCommandBuffer *a, SDL_GpuBlitRegion *b, SDL_GpuBlitRegion *c, SDL_FlipMode d, SDL_GpuFilter e, SDL_bool f),(a,b,c,d,e,f),)
+SDL_DYNAPI_PROC(SDL_bool,SDL_SupportsGpuSwapchainComposition,(SDL_GpuDevice *a, SDL_Window *b, SDL_GpuSwapchainComposition c),(a,b,c),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_SupportsGpuPresentMode,(SDL_GpuDevice *a, SDL_Window *b, SDL_GpuPresentMode c),(a,b,c),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_ClaimGpuWindow,(SDL_GpuDevice *a, SDL_Window *b),(a,b),return)
+SDL_DYNAPI_PROC(void,SDL_UnclaimGpuWindow,(SDL_GpuDevice *a, SDL_Window *b),(a,b),)
+SDL_DYNAPI_PROC(SDL_bool,SDL_SetGpuSwapchainParameters,(SDL_GpuDevice *a, SDL_Window *b, SDL_GpuSwapchainComposition c, SDL_GpuPresentMode d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(SDL_GpuTextureFormat,SDL_GetGpuSwapchainTextureFormat,(SDL_GpuDevice *a, SDL_Window *b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_GpuTexture*,SDL_AcquireGpuSwapchainTexture,(SDL_GpuCommandBuffer *a, SDL_Window *b, Uint32 *c, Uint32 *d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(void,SDL_SubmitGpu,(SDL_GpuCommandBuffer *a),(a),)
+SDL_DYNAPI_PROC(SDL_GpuFence*,SDL_SubmitGpuAndAcquireFence,(SDL_GpuCommandBuffer *a),(a),return)
+SDL_DYNAPI_PROC(void,SDL_WaitGpu,(SDL_GpuDevice *a),(a),)
+SDL_DYNAPI_PROC(void,SDL_WaitGpuForFences,(SDL_GpuDevice *a, SDL_bool b, SDL_GpuFence **c, Uint32 d),(a,b,c,d),)
+SDL_DYNAPI_PROC(SDL_bool,SDL_QueryGpuFence,(SDL_GpuDevice *a, SDL_GpuFence *b),(a,b),return)
+SDL_DYNAPI_PROC(void,SDL_ReleaseGpuFence,(SDL_GpuDevice *a, SDL_GpuFence *b),(a,b),)
+SDL_DYNAPI_PROC(Uint32,SDL_GpuTextureFormatTexelBlockSize,(SDL_GpuTextureFormat a),(a),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_SupportsGpuTextureFormat,(SDL_GpuDevice *a, SDL_GpuTextureFormat b, SDL_GpuTextureType c, SDL_GpuTextureUsageFlags d),(a,b,c,d),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_SupportsGpuSampleCount,(SDL_GpuDevice *a, SDL_GpuTextureFormat b, SDL_GpuSampleCount c),(a,b,c),return)
+SDL_DYNAPI_PROC(void,SDL_GDKSuspendGpu,(SDL_GpuDevice *a),(a),)
+SDL_DYNAPI_PROC(void,SDL_GDKResumeGpu,(SDL_GpuDevice *a),(a),)

+ 2400 - 0
src/gpu/SDL_gpu.c

@@ -0,0 +1,2400 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_internal.h"
+#include "SDL_sysgpu.h"
+
+// FIXME: This could probably use SDL_ObjectValid
+#define CHECK_DEVICE_MAGIC(device, retval)  \
+    if (device == NULL) {                   \
+        SDL_SetError("Invalid GPU device"); \
+        return retval;                      \
+    }
+
+#define CHECK_COMMAND_BUFFER                                       \
+    if (((CommandBufferCommonHeader *)commandBuffer)->submitted) { \
+        SDL_assert_release(!"Command buffer already submitted!");  \
+        return;                                                    \
+    }
+
+#define CHECK_COMMAND_BUFFER_RETURN_NULL                           \
+    if (((CommandBufferCommonHeader *)commandBuffer)->submitted) { \
+        SDL_assert_release(!"Command buffer already submitted!");  \
+        return NULL;                                               \
+    }
+
+#define CHECK_ANY_PASS_IN_PROGRESS(msg, retval)                                 \
+    if (                                                                        \
+        ((CommandBufferCommonHeader *)commandBuffer)->renderPass.inProgress ||  \
+        ((CommandBufferCommonHeader *)commandBuffer)->computePass.inProgress || \
+        ((CommandBufferCommonHeader *)commandBuffer)->copyPass.inProgress) {    \
+        SDL_assert_release(!msg);                                               \
+        return retval;                                                          \
+    }
+
+#define CHECK_RENDERPASS                                     \
+    if (!((Pass *)renderPass)->inProgress) {                 \
+        SDL_assert_release(!"Render pass not in progress!"); \
+        return;                                              \
+    }
+
+#define CHECK_GRAPHICS_PIPELINE_BOUND                                                       \
+    if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->graphicsPipelineBound) { \
+        SDL_assert_release(!"Graphics pipeline not bound!");                                \
+        return;                                                                             \
+    }
+
+#define CHECK_COMPUTEPASS                                     \
+    if (!((Pass *)computePass)->inProgress) {                 \
+        SDL_assert_release(!"Compute pass not in progress!"); \
+        return;                                               \
+    }
+
+#define CHECK_COMPUTE_PIPELINE_BOUND                                                        \
+    if (!((CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER)->computePipelineBound) { \
+        SDL_assert_release(!"Compute pipeline not bound!");                                 \
+        return;                                                                             \
+    }
+
+#define CHECK_COPYPASS                                     \
+    if (!((Pass *)copyPass)->inProgress) {                 \
+        SDL_assert_release(!"Copy pass not in progress!"); \
+        return;                                            \
+    }
+
+#define CHECK_TEXTUREFORMAT_ENUM_INVALID(format, retval)     \
+    if (format >= SDL_GPU_TEXTUREFORMAT_MAX) {               \
+        SDL_assert_release(!"Invalid texture format enum!"); \
+        return retval;                                       \
+    }
+
+#define CHECK_SWAPCHAINCOMPOSITION_ENUM_INVALID(enumval, retval)    \
+    if (enumval >= SDL_GPU_SWAPCHAINCOMPOSITION_MAX) {              \
+        SDL_assert_release(!"Invalid swapchain composition enum!"); \
+        return retval;                                              \
+    }
+
+#define CHECK_PRESENTMODE_ENUM_INVALID(enumval, retval)    \
+    if (enumval >= SDL_GPU_PRESENTMODE_MAX) {              \
+        SDL_assert_release(!"Invalid present mode enum!"); \
+        return retval;                                     \
+    }
+
+#define COMMAND_BUFFER_DEVICE \
+    ((CommandBufferCommonHeader *)commandBuffer)->device
+
+#define RENDERPASS_COMMAND_BUFFER \
+    ((Pass *)renderPass)->commandBuffer
+
+#define RENDERPASS_DEVICE \
+    ((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->device
+
+#define COMPUTEPASS_COMMAND_BUFFER \
+    ((Pass *)computePass)->commandBuffer
+
+#define COMPUTEPASS_DEVICE \
+    ((CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER)->device
+
+#define COPYPASS_COMMAND_BUFFER \
+    ((Pass *)copyPass)->commandBuffer
+
+#define COPYPASS_DEVICE \
+    ((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->device
+
+// Drivers
+
+static const SDL_GpuBootstrap *backends[] = {
+#ifdef SDL_GPU_METAL
+    &MetalDriver,
+#endif
+#ifdef SDL_GPU_D3D12
+    &D3D12Driver,
+#endif
+#ifdef SDL_GPU_VULKAN
+    &VulkanDriver,
+#endif
+#ifdef SDL_GPU_D3D11
+    &D3D11Driver,
+#endif
+    NULL
+};
+
+// Internal Utility Functions
+
+SDL_GpuGraphicsPipeline *SDL_Gpu_FetchBlitPipeline(
+    SDL_GpuDevice *device,
+    SDL_GpuTextureType sourceTextureType,
+    SDL_GpuTextureFormat destinationFormat,
+    SDL_GpuShader *blitVertexShader,
+    SDL_GpuShader *blitFrom2DShader,
+    SDL_GpuShader *blitFrom2DArrayShader,
+    SDL_GpuShader *blitFrom3DShader,
+    SDL_GpuShader *blitFromCubeShader,
+    BlitPipelineCacheEntry **blitPipelines,
+    Uint32 *blitPipelineCount,
+    Uint32 *blitPipelineCapacity)
+{
+    SDL_GpuGraphicsPipelineCreateInfo blitPipelineCreateInfo;
+    SDL_GpuColorAttachmentDescription colorAttachmentDesc;
+    SDL_GpuGraphicsPipeline *pipeline;
+
+    if (blitPipelineCount == NULL) {
+        // use pre-created, format-agnostic pipelines
+        return (*blitPipelines)[sourceTextureType].pipeline;
+    }
+
+    for (Uint32 i = 0; i < *blitPipelineCount; i += 1) {
+        if ((*blitPipelines)[i].type == sourceTextureType && (*blitPipelines)[i].format == destinationFormat) {
+            return (*blitPipelines)[i].pipeline;
+        }
+    }
+
+    // No pipeline found, we'll need to make one!
+    SDL_zero(blitPipelineCreateInfo);
+
+    SDL_zero(colorAttachmentDesc);
+    colorAttachmentDesc.blendState.colorWriteMask = 0xF;
+    colorAttachmentDesc.format = destinationFormat;
+
+    blitPipelineCreateInfo.attachmentInfo.colorAttachmentDescriptions = &colorAttachmentDesc;
+    blitPipelineCreateInfo.attachmentInfo.colorAttachmentCount = 1;
+    blitPipelineCreateInfo.attachmentInfo.depthStencilFormat = SDL_GPU_TEXTUREFORMAT_D16_UNORM; // arbitrary
+    blitPipelineCreateInfo.attachmentInfo.hasDepthStencilAttachment = SDL_FALSE;
+
+    blitPipelineCreateInfo.vertexShader = blitVertexShader;
+    if (sourceTextureType == SDL_GPU_TEXTURETYPE_CUBE) {
+        blitPipelineCreateInfo.fragmentShader = blitFromCubeShader;
+    } else if (sourceTextureType == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
+        blitPipelineCreateInfo.fragmentShader = blitFrom2DArrayShader;
+    } else if (sourceTextureType == SDL_GPU_TEXTURETYPE_3D) {
+        blitPipelineCreateInfo.fragmentShader = blitFrom3DShader;
+    } else {
+        blitPipelineCreateInfo.fragmentShader = blitFrom2DShader;
+    }
+
+    blitPipelineCreateInfo.multisampleState.sampleCount = SDL_GPU_SAMPLECOUNT_1;
+    blitPipelineCreateInfo.multisampleState.sampleMask = 0xFFFFFFFF;
+
+    blitPipelineCreateInfo.primitiveType = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST;
+
+    blitPipelineCreateInfo.blendConstants[0] = 1.0f;
+    blitPipelineCreateInfo.blendConstants[1] = 1.0f;
+    blitPipelineCreateInfo.blendConstants[2] = 1.0f;
+    blitPipelineCreateInfo.blendConstants[3] = 1.0f;
+
+    pipeline = SDL_CreateGpuGraphicsPipeline(
+        device,
+        &blitPipelineCreateInfo);
+
+    if (pipeline == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create graphics pipeline for blit");
+        return NULL;
+    }
+
+    // Cache the new pipeline
+    EXPAND_ARRAY_IF_NEEDED(
+        (*blitPipelines),
+        BlitPipelineCacheEntry,
+        *blitPipelineCount + 1,
+        *blitPipelineCapacity,
+        *blitPipelineCapacity * 2)
+
+    (*blitPipelines)[*blitPipelineCount].pipeline = pipeline;
+    (*blitPipelines)[*blitPipelineCount].type = sourceTextureType;
+    (*blitPipelines)[*blitPipelineCount].format = destinationFormat;
+    *blitPipelineCount += 1;
+
+    return pipeline;
+}
+
+void SDL_Gpu_BlitCommon(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBlitRegion *source,
+    SDL_GpuBlitRegion *destination,
+    SDL_FlipMode flipMode,
+    SDL_GpuFilter filterMode,
+    SDL_bool cycle,
+    SDL_GpuSampler *blitLinearSampler,
+    SDL_GpuSampler *blitNearestSampler,
+    SDL_GpuShader *blitVertexShader,
+    SDL_GpuShader *blitFrom2DShader,
+    SDL_GpuShader *blitFrom2DArrayShader,
+    SDL_GpuShader *blitFrom3DShader,
+    SDL_GpuShader *blitFromCubeShader,
+    BlitPipelineCacheEntry **blitPipelines,
+    Uint32 *blitPipelineCount,
+    Uint32 *blitPipelineCapacity)
+{
+    CommandBufferCommonHeader *cmdbufHeader = (CommandBufferCommonHeader *)commandBuffer;
+    SDL_GpuRenderPass *renderPass;
+    TextureCommonHeader *srcHeader = (TextureCommonHeader *)source->texture;
+    TextureCommonHeader *dstHeader = (TextureCommonHeader *)destination->texture;
+    SDL_GpuGraphicsPipeline *blitPipeline;
+    SDL_GpuColorAttachmentInfo colorAttachmentInfo;
+    SDL_GpuViewport viewport;
+    SDL_GpuTextureSamplerBinding textureSamplerBinding;
+    BlitFragmentUniforms blitFragmentUniforms;
+    Uint32 layerDivisor;
+
+    blitPipeline = SDL_Gpu_FetchBlitPipeline(
+        cmdbufHeader->device,
+        srcHeader->info.type,
+        dstHeader->info.format,
+        blitVertexShader,
+        blitFrom2DShader,
+        blitFrom2DArrayShader,
+        blitFrom3DShader,
+        blitFromCubeShader,
+        blitPipelines,
+        blitPipelineCount,
+        blitPipelineCapacity);
+
+    if (blitPipeline == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not fetch blit pipeline");
+        return;
+    }
+
+    // If the entire destination is blitted, we don't have to load
+    if (
+        dstHeader->info.layerCountOrDepth == 1 &&
+        dstHeader->info.levelCount == 1 &&
+        dstHeader->info.type != SDL_GPU_TEXTURETYPE_3D &&
+        destination->w == dstHeader->info.width &&
+        destination->h == dstHeader->info.height) {
+        colorAttachmentInfo.loadOp = SDL_GPU_LOADOP_DONT_CARE;
+    } else {
+        colorAttachmentInfo.loadOp = SDL_GPU_LOADOP_LOAD;
+    }
+
+    colorAttachmentInfo.storeOp = SDL_GPU_STOREOP_STORE;
+
+    colorAttachmentInfo.texture = destination->texture;
+    colorAttachmentInfo.mipLevel = destination->mipLevel;
+    colorAttachmentInfo.layerOrDepthPlane = destination->layerOrDepthPlane;
+    colorAttachmentInfo.cycle = cycle;
+
+    renderPass = SDL_BeginGpuRenderPass(
+        commandBuffer,
+        &colorAttachmentInfo,
+        1,
+        NULL);
+
+    viewport.x = (float)destination->x;
+    viewport.y = (float)destination->y;
+    viewport.w = (float)destination->w;
+    viewport.h = (float)destination->h;
+    viewport.minDepth = 0;
+    viewport.maxDepth = 1;
+
+    SDL_SetGpuViewport(
+        renderPass,
+        &viewport);
+
+    SDL_BindGpuGraphicsPipeline(
+        renderPass,
+        blitPipeline);
+
+    textureSamplerBinding.texture = source->texture;
+    textureSamplerBinding.sampler =
+        filterMode == SDL_GPU_FILTER_NEAREST ? blitNearestSampler : blitLinearSampler;
+
+    SDL_BindGpuFragmentSamplers(
+        renderPass,
+        0,
+        &textureSamplerBinding,
+        1);
+
+    blitFragmentUniforms.left = (float)source->x / (srcHeader->info.width >> source->mipLevel);
+    blitFragmentUniforms.top = (float)source->y / (srcHeader->info.height >> source->mipLevel);
+    blitFragmentUniforms.width = (float)source->w / (srcHeader->info.width >> source->mipLevel);
+    blitFragmentUniforms.height = (float)source->h / (srcHeader->info.height >> source->mipLevel);
+    blitFragmentUniforms.mipLevel = source->mipLevel;
+
+    layerDivisor = (srcHeader->info.type == SDL_GPU_TEXTURETYPE_3D) ? srcHeader->info.layerCountOrDepth : 1;
+    blitFragmentUniforms.layerOrDepth = (float)source->layerOrDepthPlane / layerDivisor;
+
+    if (flipMode & SDL_FLIP_HORIZONTAL) {
+        blitFragmentUniforms.left += blitFragmentUniforms.width;
+        blitFragmentUniforms.width *= -1;
+    }
+
+    if (flipMode & SDL_FLIP_VERTICAL) {
+        blitFragmentUniforms.top += blitFragmentUniforms.height;
+        blitFragmentUniforms.height *= -1;
+    }
+
+    SDL_PushGpuFragmentUniformData(
+        commandBuffer,
+        0,
+        &blitFragmentUniforms,
+        sizeof(blitFragmentUniforms));
+
+    SDL_DrawGpuPrimitives(renderPass, 3, 1, 0, 0);
+    SDL_EndGpuRenderPass(renderPass);
+}
+
+// Driver Functions
+
+static SDL_GpuDriver SDL_GpuSelectBackend(
+    SDL_VideoDevice *_this,
+    const char *gpudriver,
+    SDL_GpuShaderFormat formatFlags)
+{
+    Uint32 i;
+
+    // Environment/Properties override...
+    if (gpudriver != NULL) {
+        for (i = 0; backends[i]; i += 1) {
+            if (SDL_strcasecmp(gpudriver, backends[i]->Name) == 0) {
+                if (!(backends[i]->shaderFormats & formatFlags)) {
+                    SDL_LogError(SDL_LOG_CATEGORY_GPU, "Required shader format for backend %s not provided!", gpudriver);
+                    return SDL_GPU_DRIVER_INVALID;
+                }
+                if (backends[i]->PrepareDriver(_this)) {
+                    return backends[i]->backendflag;
+                }
+            }
+        }
+
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "SDL_HINT_GPU_DRIVER %s unsupported!", gpudriver);
+        return SDL_GPU_DRIVER_INVALID;
+    }
+
+    for (i = 0; backends[i]; i += 1) {
+        if ((backends[i]->shaderFormats & formatFlags) == 0) {
+            // Don't select a backend which doesn't support the app's shaders.
+            continue;
+        }
+        if (backends[i]->PrepareDriver(_this)) {
+            return backends[i]->backendflag;
+        }
+    }
+
+    SDL_LogError(SDL_LOG_CATEGORY_GPU, "No supported SDL_Gpu backend found!");
+    return SDL_GPU_DRIVER_INVALID;
+}
+
+SDL_GpuDevice *SDL_CreateGpuDevice(
+    SDL_GpuShaderFormat formatFlags,
+    SDL_bool debugMode,
+    SDL_bool preferLowPower,
+    const char *name)
+{
+    SDL_GpuDevice *result;
+    SDL_PropertiesID props = SDL_CreateProperties();
+    if (formatFlags & SDL_GPU_SHADERFORMAT_SECRET) {
+        SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_SECRET_BOOL, SDL_TRUE);
+    }
+    if (formatFlags & SDL_GPU_SHADERFORMAT_SPIRV) {
+        SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_SPIRV_BOOL, SDL_TRUE);
+    }
+    if (formatFlags & SDL_GPU_SHADERFORMAT_DXBC) {
+        SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_DXBC_BOOL, SDL_TRUE);
+    }
+    if (formatFlags & SDL_GPU_SHADERFORMAT_DXIL) {
+        SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_DXIL_BOOL, SDL_TRUE);
+    }
+    if (formatFlags & SDL_GPU_SHADERFORMAT_MSL) {
+        SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_MSL_BOOL, SDL_TRUE);
+    }
+    if (formatFlags & SDL_GPU_SHADERFORMAT_METALLIB) {
+        SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_METALLIB_BOOL, SDL_TRUE);
+    }
+    SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_DEBUGMODE_BOOL, debugMode);
+    SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_PREFERLOWPOWER_BOOL, preferLowPower);
+    SDL_SetStringProperty(props, SDL_PROP_GPU_CREATEDEVICE_NAME_STRING, name);
+    result = SDL_CreateGpuDeviceWithProperties(props);
+    SDL_DestroyProperties(props);
+    return result;
+}
+
+SDL_GpuDevice *SDL_CreateGpuDeviceWithProperties(SDL_PropertiesID props)
+{
+    SDL_GpuShaderFormat formatFlags = 0;
+    SDL_bool debugMode;
+    SDL_bool preferLowPower;
+
+    int i;
+    const char *gpudriver;
+    SDL_GpuDevice *result = NULL;
+    SDL_GpuDriver selectedBackend;
+    SDL_VideoDevice *_this = SDL_GetVideoDevice();
+
+    if (_this == NULL) {
+        SDL_SetError("Video subsystem not initialized");
+        return NULL;
+    }
+
+    if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_SECRET_BOOL, SDL_FALSE)) {
+        formatFlags |= SDL_GPU_SHADERFORMAT_SECRET;
+    }
+    if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_SPIRV_BOOL, SDL_FALSE)) {
+        formatFlags |= SDL_GPU_SHADERFORMAT_SPIRV;
+    }
+    if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_DXBC_BOOL, SDL_FALSE)) {
+        formatFlags |= SDL_GPU_SHADERFORMAT_DXBC;
+    }
+    if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_DXIL_BOOL, SDL_FALSE)) {
+        formatFlags |= SDL_GPU_SHADERFORMAT_DXIL;
+    }
+    if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_MSL_BOOL, SDL_FALSE)) {
+        formatFlags |= SDL_GPU_SHADERFORMAT_MSL;
+    }
+    if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_METALLIB_BOOL, SDL_FALSE)) {
+        formatFlags |= SDL_GPU_SHADERFORMAT_METALLIB;
+    }
+
+    debugMode = SDL_GetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_DEBUGMODE_BOOL, SDL_TRUE);
+    preferLowPower = SDL_GetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_PREFERLOWPOWER_BOOL, SDL_TRUE);
+
+    gpudriver = SDL_GetHint(SDL_HINT_GPU_DRIVER);
+    if (gpudriver == NULL) {
+        gpudriver = SDL_GetStringProperty(props, SDL_PROP_GPU_CREATEDEVICE_NAME_STRING, NULL);
+    }
+
+    selectedBackend = SDL_GpuSelectBackend(_this, gpudriver, formatFlags);
+    if (selectedBackend != SDL_GPU_DRIVER_INVALID) {
+        for (i = 0; backends[i]; i += 1) {
+            if (backends[i]->backendflag == selectedBackend) {
+                result = backends[i]->CreateDevice(debugMode, preferLowPower, props);
+                if (result != NULL) {
+                    result->backend = backends[i]->backendflag;
+                    result->shaderFormats = backends[i]->shaderFormats;
+                    result->debugMode = debugMode;
+                    break;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+void SDL_DestroyGpuDevice(SDL_GpuDevice *device)
+{
+    CHECK_DEVICE_MAGIC(device, );
+
+    device->DestroyDevice(device);
+}
+
+SDL_GpuDriver SDL_GetGpuDriver(SDL_GpuDevice *device)
+{
+    CHECK_DEVICE_MAGIC(device, SDL_GPU_DRIVER_INVALID);
+
+    return device->backend;
+}
+
+Uint32 SDL_GpuTextureFormatTexelBlockSize(
+    SDL_GpuTextureFormat textureFormat)
+{
+    switch (textureFormat) {
+    case SDL_GPU_TEXTUREFORMAT_BC1_UNORM:
+        return 8;
+    case SDL_GPU_TEXTUREFORMAT_BC2_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_BC3_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_BC7_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_BC3_UNORM_SRGB:
+    case SDL_GPU_TEXTUREFORMAT_BC7_UNORM_SRGB:
+        return 16;
+    case SDL_GPU_TEXTUREFORMAT_R8_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_A8_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_R8_UINT:
+        return 1;
+    case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_R16_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R8G8_SNORM:
+    case SDL_GPU_TEXTUREFORMAT_R8G8_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R16_UINT:
+        return 2;
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB:
+    case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB:
+    case SDL_GPU_TEXTUREFORMAT_R32_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM:
+    case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R16G16_UINT:
+        return 4;
+    case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT:
+        return 8;
+    case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT:
+        return 16;
+    default:
+        SDL_assert_release(!"Unrecognized TextureFormat!");
+        return 0;
+    }
+}
+
+SDL_bool SDL_SupportsGpuTextureFormat(
+    SDL_GpuDevice *device,
+    SDL_GpuTextureFormat format,
+    SDL_GpuTextureType type,
+    SDL_GpuTextureUsageFlags usage)
+{
+    CHECK_DEVICE_MAGIC(device, SDL_FALSE);
+
+    if (device->debugMode) {
+        CHECK_TEXTUREFORMAT_ENUM_INVALID(format, SDL_FALSE)
+    }
+
+    return device->SupportsTextureFormat(
+        device->driverData,
+        format,
+        type,
+        usage);
+}
+
+SDL_bool SDL_SupportsGpuSampleCount(
+    SDL_GpuDevice *device,
+    SDL_GpuTextureFormat format,
+    SDL_GpuSampleCount sampleCount)
+{
+    CHECK_DEVICE_MAGIC(device, 0);
+
+    if (device->debugMode) {
+        CHECK_TEXTUREFORMAT_ENUM_INVALID(format, 0)
+    }
+
+    return device->SupportsSampleCount(
+        device->driverData,
+        format,
+        sampleCount);
+}
+
+// State Creation
+
+SDL_GpuComputePipeline *SDL_CreateGpuComputePipeline(
+    SDL_GpuDevice *device,
+    SDL_GpuComputePipelineCreateInfo *computePipelineCreateInfo)
+{
+    CHECK_DEVICE_MAGIC(device, NULL);
+    if (computePipelineCreateInfo == NULL) {
+        SDL_InvalidParamError("computePipelineCreateInfo");
+        return NULL;
+    }
+
+    if (device->debugMode) {
+        if (!(computePipelineCreateInfo->format & device->shaderFormats)) {
+            SDL_assert_release(!"Incompatible shader format for GPU backend");
+            return NULL;
+        }
+
+        if (computePipelineCreateInfo->writeOnlyStorageTextureCount > MAX_COMPUTE_WRITE_TEXTURES) {
+            SDL_assert_release(!"Compute pipeline write-only texture count cannot be higher than 8!");
+            return NULL;
+        }
+        if (computePipelineCreateInfo->writeOnlyStorageBufferCount > MAX_COMPUTE_WRITE_BUFFERS) {
+            SDL_assert_release(!"Compute pipeline write-only buffer count cannot be higher than 8!");
+            return NULL;
+        }
+        if (computePipelineCreateInfo->threadCountX == 0 ||
+            computePipelineCreateInfo->threadCountY == 0 ||
+            computePipelineCreateInfo->threadCountZ == 0) {
+            SDL_assert_release(!"Compute pipeline threadCount dimensions must be at least 1!");
+            return NULL;
+        }
+    }
+
+    return device->CreateComputePipeline(
+        device->driverData,
+        computePipelineCreateInfo);
+}
+
+SDL_GpuGraphicsPipeline *SDL_CreateGpuGraphicsPipeline(
+    SDL_GpuDevice *device,
+    SDL_GpuGraphicsPipelineCreateInfo *graphicsPipelineCreateInfo)
+{
+    CHECK_DEVICE_MAGIC(device, NULL);
+    if (graphicsPipelineCreateInfo == NULL) {
+        SDL_InvalidParamError("graphicsPipelineCreateInfo");
+        return NULL;
+    }
+
+    if (device->debugMode) {
+        for (Uint32 i = 0; i < graphicsPipelineCreateInfo->attachmentInfo.colorAttachmentCount; i += 1) {
+            CHECK_TEXTUREFORMAT_ENUM_INVALID(graphicsPipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].format, NULL);
+            if (IsDepthFormat(graphicsPipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].format)) {
+                SDL_assert_release(!"Color attachment formats cannot be a depth format!");
+                return NULL;
+            }
+        }
+        if (graphicsPipelineCreateInfo->attachmentInfo.hasDepthStencilAttachment) {
+            CHECK_TEXTUREFORMAT_ENUM_INVALID(graphicsPipelineCreateInfo->attachmentInfo.depthStencilFormat, NULL);
+            if (!IsDepthFormat(graphicsPipelineCreateInfo->attachmentInfo.depthStencilFormat)) {
+                SDL_assert_release(!"Depth-stencil attachment format must be a depth format!");
+                return NULL;
+            }
+        }
+    }
+
+    return device->CreateGraphicsPipeline(
+        device->driverData,
+        graphicsPipelineCreateInfo);
+}
+
+SDL_GpuSampler *SDL_CreateGpuSampler(
+    SDL_GpuDevice *device,
+    SDL_GpuSamplerCreateInfo *samplerCreateInfo)
+{
+    CHECK_DEVICE_MAGIC(device, NULL);
+    if (samplerCreateInfo == NULL) {
+        SDL_InvalidParamError("samplerCreateInfo");
+        return NULL;
+    }
+
+    return device->CreateSampler(
+        device->driverData,
+        samplerCreateInfo);
+}
+
+SDL_GpuShader *SDL_CreateGpuShader(
+    SDL_GpuDevice *device,
+    SDL_GpuShaderCreateInfo *shaderCreateInfo)
+{
+    CHECK_DEVICE_MAGIC(device, NULL);
+    if (shaderCreateInfo == NULL) {
+        SDL_InvalidParamError("shaderCreateInfo");
+        return NULL;
+    }
+
+    if (device->debugMode) {
+        if (!(shaderCreateInfo->format & device->shaderFormats)) {
+            SDL_assert_release(!"Incompatible shader format for GPU backend");
+            return NULL;
+        }
+    }
+
+    return device->CreateShader(
+        device->driverData,
+        shaderCreateInfo);
+}
+
+SDL_GpuTexture *SDL_CreateGpuTexture(
+    SDL_GpuDevice *device,
+    SDL_GpuTextureCreateInfo *textureCreateInfo)
+{
+    CHECK_DEVICE_MAGIC(device, NULL);
+    if (textureCreateInfo == NULL) {
+        SDL_InvalidParamError("textureCreateInfo");
+        return NULL;
+    }
+
+    if (device->debugMode) {
+        SDL_bool failed = SDL_FALSE;
+
+        const Uint32 MAX_2D_DIMENSION = 16384;
+        const Uint32 MAX_3D_DIMENSION = 2048;
+
+        // Common checks for all texture types
+        CHECK_TEXTUREFORMAT_ENUM_INVALID(textureCreateInfo->format, NULL)
+
+        if (textureCreateInfo->width <= 0 || textureCreateInfo->height <= 0 || textureCreateInfo->layerCountOrDepth <= 0) {
+            SDL_assert_release(!"For any texture: width, height, and layerCountOrDepth must be >= 1");
+            failed = SDL_TRUE;
+        }
+        if (textureCreateInfo->levelCount <= 0) {
+            SDL_assert_release(!"For any texture: levelCount must be >= 1");
+            failed = SDL_TRUE;
+        }
+        if ((textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT) && (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT)) {
+            SDL_assert_release(!"For any texture: usageFlags cannot contain both GRAPHICS_STORAGE_READ_BIT and SAMPLER_BIT");
+            failed = SDL_TRUE;
+        }
+        if (IsDepthFormat(textureCreateInfo->format) && (textureCreateInfo->usageFlags & ~(SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT | SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT))) {
+            SDL_assert_release(!"For depth textures: usageFlags cannot contain any flags except for DEPTH_STENCIL_TARGET_BIT and SAMPLER_BIT");
+            failed = SDL_TRUE;
+        }
+        if (IsIntegerFormat(textureCreateInfo->format) && (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT)) {
+            SDL_assert_release(!"For any texture: usageFlags cannot contain SAMPLER_BIT for textures with an integer format");
+            failed = SDL_TRUE;
+        }
+
+        if (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+            // Cubemap validation
+            if (textureCreateInfo->width != textureCreateInfo->height) {
+                SDL_assert_release(!"For cube textures: width and height must be identical");
+                failed = SDL_TRUE;
+            }
+            if (textureCreateInfo->width > MAX_2D_DIMENSION || textureCreateInfo->height > MAX_2D_DIMENSION) {
+                SDL_assert_release(!"For cube textures: width and height must be <= 16384");
+                failed = SDL_TRUE;
+            }
+            if (textureCreateInfo->layerCountOrDepth != 6) {
+                SDL_assert_release(!"For cube textures: layerCountOrDepth must be 6");
+                failed = SDL_TRUE;
+            }
+            if (textureCreateInfo->sampleCount > SDL_GPU_SAMPLECOUNT_1) {
+                SDL_assert_release(!"For cube textures: sampleCount must be SDL_GPU_SAMPLECOUNT_1");
+                failed = SDL_TRUE;
+            }
+            if (!SDL_SupportsGpuTextureFormat(device, textureCreateInfo->format, SDL_GPU_TEXTURETYPE_CUBE, textureCreateInfo->usageFlags)) {
+                SDL_assert_release(!"For cube textures: the format is unsupported for the given usageFlags");
+                failed = SDL_TRUE;
+            }
+        } else if (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_3D) {
+            // 3D Texture Validation
+            if (textureCreateInfo->width > MAX_3D_DIMENSION || textureCreateInfo->height > MAX_3D_DIMENSION || textureCreateInfo->layerCountOrDepth > MAX_3D_DIMENSION) {
+                SDL_assert_release(!"For 3D textures: width, height, and layerCountOrDepth must be <= 2048");
+                failed = SDL_TRUE;
+            }
+            if (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) {
+                SDL_assert_release(!"For 3D textures: usageFlags must not contain DEPTH_STENCIL_TARGET_BIT");
+                failed = SDL_TRUE;
+            }
+            if (textureCreateInfo->sampleCount > SDL_GPU_SAMPLECOUNT_1) {
+                SDL_assert_release(!"For 3D textures: sampleCount must be SDL_GPU_SAMPLECOUNT_1");
+                failed = SDL_TRUE;
+            }
+            if (!SDL_SupportsGpuTextureFormat(device, textureCreateInfo->format, SDL_GPU_TEXTURETYPE_3D, textureCreateInfo->usageFlags)) {
+                SDL_assert_release(!"For 3D textures: the format is unsupported for the given usageFlags");
+                failed = SDL_TRUE;
+            }
+        } else {
+            if (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
+                // Array Texture Validation
+                if (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) {
+                    SDL_assert_release(!"For array textures: usageFlags must not contain DEPTH_STENCIL_TARGET_BIT");
+                    failed = SDL_TRUE;
+                }
+                if (textureCreateInfo->sampleCount > SDL_GPU_SAMPLECOUNT_1) {
+                    SDL_assert_release(!"For array textures: sampleCount must be SDL_GPU_SAMPLECOUNT_1");
+                    failed = SDL_TRUE;
+                }
+            } else {
+                // 2D Texture Validation
+                if (textureCreateInfo->sampleCount > SDL_GPU_SAMPLECOUNT_1 && textureCreateInfo->levelCount > 1) {
+                    SDL_assert_release(!"For 2D textures: if sampleCount is >= SDL_GPU_SAMPLECOUNT_1, then levelCount must be 1");
+                    failed = SDL_TRUE;
+                }
+            }
+            if (!SDL_SupportsGpuTextureFormat(device, textureCreateInfo->format, SDL_GPU_TEXTURETYPE_2D, textureCreateInfo->usageFlags)) {
+                SDL_assert_release(!"For 2D textures: the format is unsupported for the given usageFlags");
+                failed = SDL_TRUE;
+            }
+        }
+
+        if (failed) {
+            return NULL;
+        }
+    }
+
+    return device->CreateTexture(
+        device->driverData,
+        textureCreateInfo);
+}
+
+SDL_GpuBuffer *SDL_CreateGpuBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuBufferCreateInfo *bufferCreateInfo)
+{
+    CHECK_DEVICE_MAGIC(device, NULL);
+    if (bufferCreateInfo == NULL) {
+        SDL_InvalidParamError("bufferCreateInfo");
+        return NULL;
+    }
+
+    return device->CreateBuffer(
+        device->driverData,
+        bufferCreateInfo->usageFlags,
+        bufferCreateInfo->sizeInBytes);
+}
+
+SDL_GpuTransferBuffer *SDL_CreateGpuTransferBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuTransferBufferCreateInfo *transferBufferCreateInfo)
+{
+    CHECK_DEVICE_MAGIC(device, NULL);
+    if (transferBufferCreateInfo == NULL) {
+        SDL_InvalidParamError("transferBufferCreateInfo");
+        return NULL;
+    }
+
+    return device->CreateTransferBuffer(
+        device->driverData,
+        transferBufferCreateInfo->usage,
+        transferBufferCreateInfo->sizeInBytes);
+}
+
+// Debug Naming
+
+void SDL_SetGpuBufferName(
+    SDL_GpuDevice *device,
+    SDL_GpuBuffer *buffer,
+    const char *text)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (buffer == NULL) {
+        SDL_InvalidParamError("buffer");
+        return;
+    }
+    if (text == NULL) {
+        SDL_InvalidParamError("text");
+    }
+
+    device->SetBufferName(
+        device->driverData,
+        buffer,
+        text);
+}
+
+void SDL_SetGpuTextureName(
+    SDL_GpuDevice *device,
+    SDL_GpuTexture *texture,
+    const char *text)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (texture == NULL) {
+        SDL_InvalidParamError("texture");
+        return;
+    }
+    if (text == NULL) {
+        SDL_InvalidParamError("text");
+    }
+
+    device->SetTextureName(
+        device->driverData,
+        texture,
+        text);
+}
+
+void SDL_InsertGpuDebugLabel(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *text)
+{
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return;
+    }
+    if (text == NULL) {
+        SDL_InvalidParamError("text");
+        return;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER
+    }
+
+    COMMAND_BUFFER_DEVICE->InsertDebugLabel(
+        commandBuffer,
+        text);
+}
+
+void SDL_PushGpuDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *name)
+{
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return;
+    }
+    if (name == NULL) {
+        SDL_InvalidParamError("name");
+        return;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER
+    }
+
+    COMMAND_BUFFER_DEVICE->PushDebugGroup(
+        commandBuffer,
+        name);
+}
+
+void SDL_PopGpuDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER
+    }
+
+    COMMAND_BUFFER_DEVICE->PopDebugGroup(
+        commandBuffer);
+}
+
+// Disposal
+
+void SDL_ReleaseGpuTexture(
+    SDL_GpuDevice *device,
+    SDL_GpuTexture *texture)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (texture == NULL) {
+        return;
+    }
+
+    device->ReleaseTexture(
+        device->driverData,
+        texture);
+}
+
+void SDL_ReleaseGpuSampler(
+    SDL_GpuDevice *device,
+    SDL_GpuSampler *sampler)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (sampler == NULL) {
+        return;
+    }
+
+    device->ReleaseSampler(
+        device->driverData,
+        sampler);
+}
+
+void SDL_ReleaseGpuBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuBuffer *buffer)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (buffer == NULL) {
+        return;
+    }
+
+    device->ReleaseBuffer(
+        device->driverData,
+        buffer);
+}
+
+void SDL_ReleaseGpuTransferBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuTransferBuffer *transferBuffer)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (transferBuffer == NULL) {
+        return;
+    }
+
+    device->ReleaseTransferBuffer(
+        device->driverData,
+        transferBuffer);
+}
+
+void SDL_ReleaseGpuShader(
+    SDL_GpuDevice *device,
+    SDL_GpuShader *shader)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (shader == NULL) {
+        return;
+    }
+
+    device->ReleaseShader(
+        device->driverData,
+        shader);
+}
+
+void SDL_ReleaseGpuComputePipeline(
+    SDL_GpuDevice *device,
+    SDL_GpuComputePipeline *computePipeline)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (computePipeline == NULL) {
+        return;
+    }
+
+    device->ReleaseComputePipeline(
+        device->driverData,
+        computePipeline);
+}
+
+void SDL_ReleaseGpuGraphicsPipeline(
+    SDL_GpuDevice *device,
+    SDL_GpuGraphicsPipeline *graphicsPipeline)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (graphicsPipeline == NULL) {
+        return;
+    }
+
+    device->ReleaseGraphicsPipeline(
+        device->driverData,
+        graphicsPipeline);
+}
+
+// Command Buffer
+
+SDL_GpuCommandBuffer *SDL_AcquireGpuCommandBuffer(
+    SDL_GpuDevice *device)
+{
+    SDL_GpuCommandBuffer *commandBuffer;
+    CommandBufferCommonHeader *commandBufferHeader;
+
+    CHECK_DEVICE_MAGIC(device, NULL);
+
+    commandBuffer = device->AcquireCommandBuffer(
+        device->driverData);
+
+    if (commandBuffer == NULL) {
+        return NULL;
+    }
+
+    commandBufferHeader = (CommandBufferCommonHeader *)commandBuffer;
+    commandBufferHeader->device = device;
+    commandBufferHeader->renderPass.commandBuffer = commandBuffer;
+    commandBufferHeader->renderPass.inProgress = SDL_FALSE;
+    commandBufferHeader->graphicsPipelineBound = SDL_FALSE;
+    commandBufferHeader->computePass.commandBuffer = commandBuffer;
+    commandBufferHeader->computePass.inProgress = SDL_FALSE;
+    commandBufferHeader->computePipelineBound = SDL_FALSE;
+    commandBufferHeader->copyPass.commandBuffer = commandBuffer;
+    commandBufferHeader->copyPass.inProgress = SDL_FALSE;
+    commandBufferHeader->submitted = SDL_FALSE;
+
+    return commandBuffer;
+}
+
+// Uniforms
+
+void SDL_PushGpuVertexUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return;
+    }
+    if (data == NULL) {
+        SDL_InvalidParamError("data");
+        return;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER
+    }
+
+    COMMAND_BUFFER_DEVICE->PushVertexUniformData(
+        commandBuffer,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+void SDL_PushGpuFragmentUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return;
+    }
+    if (data == NULL) {
+        SDL_InvalidParamError("data");
+        return;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER
+    }
+
+    COMMAND_BUFFER_DEVICE->PushFragmentUniformData(
+        commandBuffer,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+void SDL_PushGpuComputeUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return;
+    }
+    if (data == NULL) {
+        SDL_InvalidParamError("data");
+        return;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER
+    }
+
+    COMMAND_BUFFER_DEVICE->PushComputeUniformData(
+        commandBuffer,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+// Render Pass
+
+SDL_GpuRenderPass *SDL_BeginGpuRenderPass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuColorAttachmentInfo *colorAttachmentInfos,
+    Uint32 colorAttachmentCount,
+    SDL_GpuDepthStencilAttachmentInfo *depthStencilAttachmentInfo)
+{
+    CommandBufferCommonHeader *commandBufferHeader;
+
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return NULL;
+    }
+    if (colorAttachmentInfos == NULL && colorAttachmentCount > 0) {
+        SDL_InvalidParamError("colorAttachmentInfos");
+        return NULL;
+    }
+
+    if (colorAttachmentCount > MAX_COLOR_TARGET_BINDINGS) {
+        SDL_SetError("colorAttachmentCount exceeds MAX_COLOR_TARGET_BINDINGS");
+        return NULL;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER_RETURN_NULL
+        CHECK_ANY_PASS_IN_PROGRESS("Cannot begin render pass during another pass!", NULL)
+
+        for (Uint32 i = 0; i < colorAttachmentCount; i += 1) {
+            if (colorAttachmentInfos[i].cycle && colorAttachmentInfos[i].loadOp == SDL_GPU_LOADOP_LOAD) {
+                SDL_assert_release(!"Cannot cycle color attachment when load op is LOAD!");
+            }
+        }
+
+        if (depthStencilAttachmentInfo != NULL && depthStencilAttachmentInfo->cycle && (depthStencilAttachmentInfo->loadOp == SDL_GPU_LOADOP_LOAD || depthStencilAttachmentInfo->loadOp == SDL_GPU_LOADOP_LOAD)) {
+            SDL_assert_release(!"Cannot cycle depth attachment when load op or stencil load op is LOAD!");
+        }
+    }
+
+    COMMAND_BUFFER_DEVICE->BeginRenderPass(
+        commandBuffer,
+        colorAttachmentInfos,
+        colorAttachmentCount,
+        depthStencilAttachmentInfo);
+
+    commandBufferHeader = (CommandBufferCommonHeader *)commandBuffer;
+    commandBufferHeader->renderPass.inProgress = SDL_TRUE;
+    return (SDL_GpuRenderPass *)&(commandBufferHeader->renderPass);
+}
+
+void SDL_BindGpuGraphicsPipeline(
+    SDL_GpuRenderPass *renderPass,
+    SDL_GpuGraphicsPipeline *graphicsPipeline)
+{
+    CommandBufferCommonHeader *commandBufferHeader;
+
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (graphicsPipeline == NULL) {
+        SDL_InvalidParamError("graphicsPipeline");
+        return;
+    }
+
+    RENDERPASS_DEVICE->BindGraphicsPipeline(
+        RENDERPASS_COMMAND_BUFFER,
+        graphicsPipeline);
+
+    commandBufferHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
+    commandBufferHeader->graphicsPipelineBound = SDL_TRUE;
+}
+
+void SDL_SetGpuViewport(
+    SDL_GpuRenderPass *renderPass,
+    SDL_GpuViewport *viewport)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (viewport == NULL) {
+        SDL_InvalidParamError("viewport");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->SetViewport(
+        RENDERPASS_COMMAND_BUFFER,
+        viewport);
+}
+
+void SDL_SetGpuScissor(
+    SDL_GpuRenderPass *renderPass,
+    SDL_Rect *scissor)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (scissor == NULL) {
+        SDL_InvalidParamError("scissor");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->SetScissor(
+        RENDERPASS_COMMAND_BUFFER,
+        scissor);
+}
+
+void SDL_BindGpuVertexBuffers(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstBinding,
+    SDL_GpuBufferBinding *pBindings,
+    Uint32 bindingCount)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (pBindings == NULL && bindingCount > 0) {
+        SDL_InvalidParamError("pBindings");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->BindVertexBuffers(
+        RENDERPASS_COMMAND_BUFFER,
+        firstBinding,
+        pBindings,
+        bindingCount);
+}
+
+void SDL_BindGpuIndexBuffer(
+    SDL_GpuRenderPass *renderPass,
+    SDL_GpuBufferBinding *pBinding,
+    SDL_GpuIndexElementSize indexElementSize)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (pBinding == NULL) {
+        SDL_InvalidParamError("pBinding");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->BindIndexBuffer(
+        RENDERPASS_COMMAND_BUFFER,
+        pBinding,
+        indexElementSize);
+}
+
+void SDL_BindGpuVertexSamplers(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (textureSamplerBindings == NULL && bindingCount > 0) {
+        SDL_InvalidParamError("textureSamplerBindings");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->BindVertexSamplers(
+        RENDERPASS_COMMAND_BUFFER,
+        firstSlot,
+        textureSamplerBindings,
+        bindingCount);
+}
+
+void SDL_BindGpuVertexStorageTextures(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (storageTextures == NULL && bindingCount > 0) {
+        SDL_InvalidParamError("storageTextures");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->BindVertexStorageTextures(
+        RENDERPASS_COMMAND_BUFFER,
+        firstSlot,
+        storageTextures,
+        bindingCount);
+}
+
+void SDL_BindGpuVertexStorageBuffers(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (storageBuffers == NULL && bindingCount > 0) {
+        SDL_InvalidParamError("storageBuffers");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->BindVertexStorageBuffers(
+        RENDERPASS_COMMAND_BUFFER,
+        firstSlot,
+        storageBuffers,
+        bindingCount);
+}
+
+void SDL_BindGpuFragmentSamplers(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (textureSamplerBindings == NULL && bindingCount > 0) {
+        SDL_InvalidParamError("textureSamplerBindings");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->BindFragmentSamplers(
+        RENDERPASS_COMMAND_BUFFER,
+        firstSlot,
+        textureSamplerBindings,
+        bindingCount);
+}
+
+void SDL_BindGpuFragmentStorageTextures(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (storageTextures == NULL && bindingCount > 0) {
+        SDL_InvalidParamError("storageTextures");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->BindFragmentStorageTextures(
+        RENDERPASS_COMMAND_BUFFER,
+        firstSlot,
+        storageTextures,
+        bindingCount);
+}
+
+void SDL_BindGpuFragmentStorageBuffers(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (storageBuffers == NULL && bindingCount > 0) {
+        SDL_InvalidParamError("storageBuffers");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->BindFragmentStorageBuffers(
+        RENDERPASS_COMMAND_BUFFER,
+        firstSlot,
+        storageBuffers,
+        bindingCount);
+}
+
+void SDL_DrawGpuIndexedPrimitives(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 indexCount,
+    Uint32 instanceCount,
+    Uint32 firstIndex,
+    Sint32 vertexOffset,
+    Uint32 firstInstance)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+        CHECK_GRAPHICS_PIPELINE_BOUND
+    }
+
+    RENDERPASS_DEVICE->DrawIndexedPrimitives(
+        RENDERPASS_COMMAND_BUFFER,
+        indexCount,
+        instanceCount,
+        firstIndex,
+        vertexOffset,
+        firstInstance);
+}
+
+void SDL_DrawGpuPrimitives(
+    SDL_GpuRenderPass *renderPass,
+    Uint32 vertexCount,
+    Uint32 instanceCount,
+    Uint32 firstVertex,
+    Uint32 firstInstance)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+        CHECK_GRAPHICS_PIPELINE_BOUND
+    }
+
+    RENDERPASS_DEVICE->DrawPrimitives(
+        RENDERPASS_COMMAND_BUFFER,
+        vertexCount,
+        instanceCount,
+        firstVertex,
+        firstInstance);
+}
+
+void SDL_DrawGpuPrimitivesIndirect(
+    SDL_GpuRenderPass *renderPass,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (buffer == NULL) {
+        SDL_InvalidParamError("buffer");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+        CHECK_GRAPHICS_PIPELINE_BOUND
+    }
+
+    RENDERPASS_DEVICE->DrawPrimitivesIndirect(
+        RENDERPASS_COMMAND_BUFFER,
+        buffer,
+        offsetInBytes,
+        drawCount,
+        stride);
+}
+
+void SDL_DrawGpuIndexedPrimitivesIndirect(
+    SDL_GpuRenderPass *renderPass,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride)
+{
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+    if (buffer == NULL) {
+        SDL_InvalidParamError("buffer");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+        CHECK_GRAPHICS_PIPELINE_BOUND
+    }
+
+    RENDERPASS_DEVICE->DrawIndexedPrimitivesIndirect(
+        RENDERPASS_COMMAND_BUFFER,
+        buffer,
+        offsetInBytes,
+        drawCount,
+        stride);
+}
+
+void SDL_EndGpuRenderPass(
+    SDL_GpuRenderPass *renderPass)
+{
+    CommandBufferCommonHeader *commandBufferCommonHeader;
+
+    if (renderPass == NULL) {
+        SDL_InvalidParamError("renderPass");
+        return;
+    }
+
+    if (RENDERPASS_DEVICE->debugMode) {
+        CHECK_RENDERPASS
+    }
+
+    RENDERPASS_DEVICE->EndRenderPass(
+        RENDERPASS_COMMAND_BUFFER);
+
+    commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
+    commandBufferCommonHeader->renderPass.inProgress = SDL_FALSE;
+    commandBufferCommonHeader->graphicsPipelineBound = SDL_FALSE;
+}
+
+// Compute Pass
+
+SDL_GpuComputePass *SDL_BeginGpuComputePass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuStorageTextureWriteOnlyBinding *storageTextureBindings,
+    Uint32 storageTextureBindingCount,
+    SDL_GpuStorageBufferWriteOnlyBinding *storageBufferBindings,
+    Uint32 storageBufferBindingCount)
+{
+    CommandBufferCommonHeader *commandBufferHeader;
+
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return NULL;
+    }
+    if (storageTextureBindings == NULL && storageTextureBindingCount > 0) {
+        SDL_InvalidParamError("storageTextureBindings");
+        return NULL;
+    }
+    if (storageBufferBindings == NULL && storageBufferBindingCount > 0) {
+        SDL_InvalidParamError("storageBufferBindings");
+        return NULL;
+    }
+    if (storageTextureBindingCount > MAX_COMPUTE_WRITE_TEXTURES) {
+        SDL_InvalidParamError("storageTextureBindingCount");
+        return NULL;
+    }
+    if (storageBufferBindingCount > MAX_COMPUTE_WRITE_BUFFERS) {
+        SDL_InvalidParamError("storageBufferBindingCount");
+        return NULL;
+    }
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER_RETURN_NULL
+        CHECK_ANY_PASS_IN_PROGRESS("Cannot begin compute pass during another pass!", NULL)
+    }
+
+    COMMAND_BUFFER_DEVICE->BeginComputePass(
+        commandBuffer,
+        storageTextureBindings,
+        storageTextureBindingCount,
+        storageBufferBindings,
+        storageBufferBindingCount);
+
+    commandBufferHeader = (CommandBufferCommonHeader *)commandBuffer;
+    commandBufferHeader->computePass.inProgress = SDL_TRUE;
+    return (SDL_GpuComputePass *)&(commandBufferHeader->computePass);
+}
+
+void SDL_BindGpuComputePipeline(
+    SDL_GpuComputePass *computePass,
+    SDL_GpuComputePipeline *computePipeline)
+{
+    CommandBufferCommonHeader *commandBufferHeader;
+
+    if (computePass == NULL) {
+        SDL_InvalidParamError("computePass");
+        return;
+    }
+    if (computePipeline == NULL) {
+        SDL_InvalidParamError("computePipeline");
+        return;
+    }
+
+    if (COMPUTEPASS_DEVICE->debugMode) {
+        CHECK_COMPUTEPASS
+    }
+
+    COMPUTEPASS_DEVICE->BindComputePipeline(
+        COMPUTEPASS_COMMAND_BUFFER,
+        computePipeline);
+
+    commandBufferHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER;
+    commandBufferHeader->computePipelineBound = SDL_TRUE;
+}
+
+void SDL_BindGpuComputeStorageTextures(
+    SDL_GpuComputePass *computePass,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    if (computePass == NULL) {
+        SDL_InvalidParamError("computePass");
+        return;
+    }
+    if (storageTextures == NULL && bindingCount > 0) {
+        SDL_InvalidParamError("storageTextures");
+        return;
+    }
+
+    if (COMPUTEPASS_DEVICE->debugMode) {
+        CHECK_COMPUTEPASS
+    }
+
+    COMPUTEPASS_DEVICE->BindComputeStorageTextures(
+        COMPUTEPASS_COMMAND_BUFFER,
+        firstSlot,
+        storageTextures,
+        bindingCount);
+}
+
+void SDL_BindGpuComputeStorageBuffers(
+    SDL_GpuComputePass *computePass,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    if (computePass == NULL) {
+        SDL_InvalidParamError("computePass");
+        return;
+    }
+    if (storageBuffers == NULL && bindingCount > 0) {
+        SDL_InvalidParamError("storageBuffers");
+        return;
+    }
+
+    if (COMPUTEPASS_DEVICE->debugMode) {
+        CHECK_COMPUTEPASS
+    }
+
+    COMPUTEPASS_DEVICE->BindComputeStorageBuffers(
+        COMPUTEPASS_COMMAND_BUFFER,
+        firstSlot,
+        storageBuffers,
+        bindingCount);
+}
+
+void SDL_DispatchGpuCompute(
+    SDL_GpuComputePass *computePass,
+    Uint32 groupCountX,
+    Uint32 groupCountY,
+    Uint32 groupCountZ)
+{
+    if (computePass == NULL) {
+        SDL_InvalidParamError("computePass");
+        return;
+    }
+
+    if (COMPUTEPASS_DEVICE->debugMode) {
+        CHECK_COMPUTEPASS
+        CHECK_COMPUTE_PIPELINE_BOUND
+    }
+
+    COMPUTEPASS_DEVICE->DispatchCompute(
+        COMPUTEPASS_COMMAND_BUFFER,
+        groupCountX,
+        groupCountY,
+        groupCountZ);
+}
+
+void SDL_DispatchGpuComputeIndirect(
+    SDL_GpuComputePass *computePass,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes)
+{
+    if (computePass == NULL) {
+        SDL_InvalidParamError("computePass");
+        return;
+    }
+
+    if (COMPUTEPASS_DEVICE->debugMode) {
+        CHECK_COMPUTEPASS
+        CHECK_COMPUTE_PIPELINE_BOUND
+    }
+
+    COMPUTEPASS_DEVICE->DispatchComputeIndirect(
+        COMPUTEPASS_COMMAND_BUFFER,
+        buffer,
+        offsetInBytes);
+}
+
+void SDL_EndGpuComputePass(
+    SDL_GpuComputePass *computePass)
+{
+    CommandBufferCommonHeader *commandBufferCommonHeader;
+
+    if (computePass == NULL) {
+        SDL_InvalidParamError("computePass");
+        return;
+    }
+
+    if (COMPUTEPASS_DEVICE->debugMode) {
+        CHECK_COMPUTEPASS
+    }
+
+    COMPUTEPASS_DEVICE->EndComputePass(
+        COMPUTEPASS_COMMAND_BUFFER);
+
+    commandBufferCommonHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER;
+    commandBufferCommonHeader->computePass.inProgress = SDL_FALSE;
+    commandBufferCommonHeader->computePipelineBound = SDL_FALSE;
+}
+
+// TransferBuffer Data
+
+void *SDL_MapGpuTransferBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuTransferBuffer *transferBuffer,
+    SDL_bool cycle)
+{
+    CHECK_DEVICE_MAGIC(device, NULL);
+    if (transferBuffer == NULL) {
+        SDL_InvalidParamError("transferBuffer");
+        return NULL;
+    }
+
+    return device->MapTransferBuffer(
+        device->driverData,
+        transferBuffer,
+        cycle);
+}
+
+void SDL_UnmapGpuTransferBuffer(
+    SDL_GpuDevice *device,
+    SDL_GpuTransferBuffer *transferBuffer)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (transferBuffer == NULL) {
+        SDL_InvalidParamError("transferBuffer");
+        return;
+    }
+
+    device->UnmapTransferBuffer(
+        device->driverData,
+        transferBuffer);
+}
+
+// Copy Pass
+
+SDL_GpuCopyPass *SDL_BeginGpuCopyPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    CommandBufferCommonHeader *commandBufferHeader;
+
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return NULL;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER_RETURN_NULL
+        CHECK_ANY_PASS_IN_PROGRESS("Cannot begin copy pass during another pass!", NULL)
+    }
+
+    COMMAND_BUFFER_DEVICE->BeginCopyPass(
+        commandBuffer);
+
+    commandBufferHeader = (CommandBufferCommonHeader *)commandBuffer;
+    commandBufferHeader->copyPass.inProgress = SDL_TRUE;
+    return (SDL_GpuCopyPass *)&(commandBufferHeader->copyPass);
+}
+
+void SDL_UploadToGpuTexture(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuTextureTransferInfo *source,
+    SDL_GpuTextureRegion *destination,
+    SDL_bool cycle)
+{
+    if (copyPass == NULL) {
+        SDL_InvalidParamError("copyPass");
+        return;
+    }
+    if (source == NULL) {
+        SDL_InvalidParamError("source");
+        return;
+    }
+    if (destination == NULL) {
+        SDL_InvalidParamError("destination");
+        return;
+    }
+
+    if (COPYPASS_DEVICE->debugMode) {
+        CHECK_COPYPASS
+    }
+
+    COPYPASS_DEVICE->UploadToTexture(
+        COPYPASS_COMMAND_BUFFER,
+        source,
+        destination,
+        cycle);
+}
+
+void SDL_UploadToGpuBuffer(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuTransferBufferLocation *source,
+    SDL_GpuBufferRegion *destination,
+    SDL_bool cycle)
+{
+    if (copyPass == NULL) {
+        SDL_InvalidParamError("copyPass");
+        return;
+    }
+    if (source == NULL) {
+        SDL_InvalidParamError("source");
+        return;
+    }
+    if (destination == NULL) {
+        SDL_InvalidParamError("destination");
+        return;
+    }
+
+    COPYPASS_DEVICE->UploadToBuffer(
+        COPYPASS_COMMAND_BUFFER,
+        source,
+        destination,
+        cycle);
+}
+
+void SDL_CopyGpuTextureToTexture(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuTextureLocation *source,
+    SDL_GpuTextureLocation *destination,
+    Uint32 w,
+    Uint32 h,
+    Uint32 d,
+    SDL_bool cycle)
+{
+    if (copyPass == NULL) {
+        SDL_InvalidParamError("copyPass");
+        return;
+    }
+    if (source == NULL) {
+        SDL_InvalidParamError("source");
+        return;
+    }
+    if (destination == NULL) {
+        SDL_InvalidParamError("destination");
+        return;
+    }
+
+    COPYPASS_DEVICE->CopyTextureToTexture(
+        COPYPASS_COMMAND_BUFFER,
+        source,
+        destination,
+        w,
+        h,
+        d,
+        cycle);
+}
+
+void SDL_CopyGpuBufferToBuffer(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuBufferLocation *source,
+    SDL_GpuBufferLocation *destination,
+    Uint32 size,
+    SDL_bool cycle)
+{
+    if (copyPass == NULL) {
+        SDL_InvalidParamError("copyPass");
+        return;
+    }
+    if (source == NULL) {
+        SDL_InvalidParamError("source");
+        return;
+    }
+    if (destination == NULL) {
+        SDL_InvalidParamError("destination");
+        return;
+    }
+
+    COPYPASS_DEVICE->CopyBufferToBuffer(
+        COPYPASS_COMMAND_BUFFER,
+        source,
+        destination,
+        size,
+        cycle);
+}
+
+void SDL_DownloadFromGpuTexture(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuTextureRegion *source,
+    SDL_GpuTextureTransferInfo *destination)
+{
+    if (copyPass == NULL) {
+        SDL_InvalidParamError("copyPass");
+        return;
+    }
+    if (source == NULL) {
+        SDL_InvalidParamError("source");
+        return;
+    }
+    if (destination == NULL) {
+        SDL_InvalidParamError("destination");
+        return;
+    }
+
+    COPYPASS_DEVICE->DownloadFromTexture(
+        COPYPASS_COMMAND_BUFFER,
+        source,
+        destination);
+}
+
+void SDL_DownloadFromGpuBuffer(
+    SDL_GpuCopyPass *copyPass,
+    SDL_GpuBufferRegion *source,
+    SDL_GpuTransferBufferLocation *destination)
+{
+    if (copyPass == NULL) {
+        SDL_InvalidParamError("copyPass");
+        return;
+    }
+    if (source == NULL) {
+        SDL_InvalidParamError("source");
+        return;
+    }
+    if (destination == NULL) {
+        SDL_InvalidParamError("destination");
+        return;
+    }
+
+    COPYPASS_DEVICE->DownloadFromBuffer(
+        COPYPASS_COMMAND_BUFFER,
+        source,
+        destination);
+}
+
+void SDL_EndGpuCopyPass(
+    SDL_GpuCopyPass *copyPass)
+{
+    if (copyPass == NULL) {
+        SDL_InvalidParamError("copyPass");
+        return;
+    }
+
+    if (COPYPASS_DEVICE->debugMode) {
+        CHECK_COPYPASS
+    }
+
+    COPYPASS_DEVICE->EndCopyPass(
+        COPYPASS_COMMAND_BUFFER);
+
+    ((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->copyPass.inProgress = SDL_FALSE;
+}
+
+void SDL_GenerateGpuMipmaps(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTexture *texture)
+{
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return;
+    }
+    if (texture == NULL) {
+        SDL_InvalidParamError("texture");
+        return;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER
+        CHECK_ANY_PASS_IN_PROGRESS("Cannot generate mipmaps during a pass!", )
+
+        TextureCommonHeader *header = (TextureCommonHeader *)texture;
+        if (header->info.levelCount <= 1) {
+            SDL_assert_release(!"Cannot generate mipmaps for texture with levelCount <= 1!");
+            return;
+        }
+
+        if (!(header->info.usageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) || !(header->info.usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT)) {
+            SDL_assert_release(!"GenerateMipmaps texture must be created with SAMPLER_BIT and COLOR_TARGET_BIT usage flags!");
+            return;
+        }
+    }
+
+    COMMAND_BUFFER_DEVICE->GenerateMipmaps(
+        commandBuffer,
+        texture);
+}
+
+void SDL_BlitGpu(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBlitRegion *source,
+    SDL_GpuBlitRegion *destination,
+    SDL_FlipMode flipMode,
+    SDL_GpuFilter filterMode,
+    SDL_bool cycle)
+{
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return;
+    }
+    if (source == NULL) {
+        SDL_InvalidParamError("source");
+        return;
+    }
+    if (destination == NULL) {
+        SDL_InvalidParamError("destination");
+        return;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER
+        CHECK_ANY_PASS_IN_PROGRESS("Cannot blit during a pass!", )
+
+        // Validation
+        SDL_bool failed = SDL_FALSE;
+        TextureCommonHeader *srcHeader = (TextureCommonHeader *)source->texture;
+        TextureCommonHeader *dstHeader = (TextureCommonHeader *)destination->texture;
+
+        if (srcHeader == NULL || dstHeader == NULL) {
+            SDL_assert_release(!"Blit source and destination textures must be non-NULL");
+            return; // attempting to proceed will crash
+        }
+        if ((srcHeader->info.usageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) == 0) {
+            SDL_assert_release(!"Blit source texture must be created with the SAMPLER_BIT usage flag");
+            failed = SDL_TRUE;
+        }
+        if ((dstHeader->info.usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) == 0) {
+            SDL_assert_release(!"Blit destination texture must be created with the COLOR_TARGET_BIT usage flag");
+            failed = SDL_TRUE;
+        }
+        if (IsDepthFormat(srcHeader->info.format)) {
+            SDL_assert_release(!"Blit source texture cannot have a depth format");
+            failed = SDL_TRUE;
+        }
+        if (source->w == 0 || source->h == 0 || destination->w == 0 || destination->h == 0) {
+            SDL_assert_release(!"Blit source/destination regions must have non-zero width, height, and depth");
+            failed = SDL_TRUE;
+        }
+
+        if (failed) {
+            return;
+        }
+    }
+
+    COMMAND_BUFFER_DEVICE->Blit(
+        commandBuffer,
+        source,
+        destination,
+        flipMode,
+        filterMode,
+        cycle);
+}
+
+// Submission/Presentation
+
+SDL_bool SDL_SupportsGpuSwapchainComposition(
+    SDL_GpuDevice *device,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition)
+{
+    CHECK_DEVICE_MAGIC(device, SDL_FALSE);
+    if (window == NULL) {
+        SDL_InvalidParamError("window");
+        return SDL_FALSE;
+    }
+
+    if (device->debugMode) {
+        CHECK_SWAPCHAINCOMPOSITION_ENUM_INVALID(swapchainComposition, SDL_FALSE)
+    }
+
+    return device->SupportsSwapchainComposition(
+        device->driverData,
+        window,
+        swapchainComposition);
+}
+
+SDL_bool SDL_SupportsGpuPresentMode(
+    SDL_GpuDevice *device,
+    SDL_Window *window,
+    SDL_GpuPresentMode presentMode)
+{
+    CHECK_DEVICE_MAGIC(device, SDL_FALSE);
+    if (window == NULL) {
+        SDL_InvalidParamError("window");
+        return SDL_FALSE;
+    }
+
+    if (device->debugMode) {
+        CHECK_PRESENTMODE_ENUM_INVALID(presentMode, SDL_FALSE)
+    }
+
+    return device->SupportsPresentMode(
+        device->driverData,
+        window,
+        presentMode);
+}
+
+SDL_bool SDL_ClaimGpuWindow(
+    SDL_GpuDevice *device,
+    SDL_Window *window)
+{
+    CHECK_DEVICE_MAGIC(device, SDL_FALSE);
+    if (window == NULL) {
+        SDL_InvalidParamError("window");
+        return SDL_FALSE;
+    }
+
+    return device->ClaimWindow(
+        device->driverData,
+        window);
+}
+
+void SDL_UnclaimGpuWindow(
+    SDL_GpuDevice *device,
+    SDL_Window *window)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (window == NULL) {
+        SDL_InvalidParamError("window");
+        return;
+    }
+
+    device->UnclaimWindow(
+        device->driverData,
+        window);
+}
+
+SDL_bool SDL_SetGpuSwapchainParameters(
+    SDL_GpuDevice *device,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition,
+    SDL_GpuPresentMode presentMode)
+{
+    CHECK_DEVICE_MAGIC(device, SDL_FALSE);
+    if (window == NULL) {
+        SDL_InvalidParamError("window");
+        return SDL_FALSE;
+    }
+
+    if (device->debugMode) {
+        CHECK_SWAPCHAINCOMPOSITION_ENUM_INVALID(swapchainComposition, SDL_FALSE)
+        CHECK_PRESENTMODE_ENUM_INVALID(presentMode, SDL_FALSE)
+    }
+
+    return device->SetSwapchainParameters(
+        device->driverData,
+        window,
+        swapchainComposition,
+        presentMode);
+}
+
+SDL_GpuTextureFormat SDL_GetGpuSwapchainTextureFormat(
+    SDL_GpuDevice *device,
+    SDL_Window *window)
+{
+    CHECK_DEVICE_MAGIC(device, SDL_GPU_TEXTUREFORMAT_INVALID);
+    if (window == NULL) {
+        SDL_InvalidParamError("window");
+        return SDL_GPU_TEXTUREFORMAT_INVALID;
+    }
+
+    return device->GetSwapchainTextureFormat(
+        device->driverData,
+        window);
+}
+
+SDL_GpuTexture *SDL_AcquireGpuSwapchainTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_Window *window,
+    Uint32 *pWidth,
+    Uint32 *pHeight)
+{
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return NULL;
+    }
+    if (window == NULL) {
+        SDL_InvalidParamError("window");
+        return NULL;
+    }
+    if (pWidth == NULL) {
+        SDL_InvalidParamError("pWidth");
+        return NULL;
+    }
+    if (pHeight == NULL) {
+        SDL_InvalidParamError("pHeight");
+        return NULL;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER_RETURN_NULL
+        CHECK_ANY_PASS_IN_PROGRESS("Cannot acquire a swapchain texture during a pass!", NULL)
+    }
+
+    return COMMAND_BUFFER_DEVICE->AcquireSwapchainTexture(
+        commandBuffer,
+        window,
+        pWidth,
+        pHeight);
+}
+
+void SDL_SubmitGpu(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)commandBuffer;
+
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER
+        if (
+            commandBufferHeader->renderPass.inProgress ||
+            commandBufferHeader->computePass.inProgress ||
+            commandBufferHeader->copyPass.inProgress) {
+            SDL_assert_release(!"Cannot submit command buffer while a pass is in progress!");
+            return;
+        }
+    }
+
+    commandBufferHeader->submitted = SDL_TRUE;
+
+    COMMAND_BUFFER_DEVICE->Submit(
+        commandBuffer);
+}
+
+SDL_GpuFence *SDL_SubmitGpuAndAcquireFence(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)commandBuffer;
+
+    if (commandBuffer == NULL) {
+        SDL_InvalidParamError("commandBuffer");
+        return NULL;
+    }
+
+    if (COMMAND_BUFFER_DEVICE->debugMode) {
+        CHECK_COMMAND_BUFFER_RETURN_NULL
+        if (
+            commandBufferHeader->renderPass.inProgress ||
+            commandBufferHeader->computePass.inProgress ||
+            commandBufferHeader->copyPass.inProgress) {
+            SDL_assert_release(!"Cannot submit command buffer while a pass is in progress!");
+            return NULL;
+        }
+    }
+
+    commandBufferHeader->submitted = SDL_TRUE;
+
+    return COMMAND_BUFFER_DEVICE->SubmitAndAcquireFence(
+        commandBuffer);
+}
+
+void SDL_WaitGpu(
+    SDL_GpuDevice *device)
+{
+    CHECK_DEVICE_MAGIC(device, );
+
+    device->Wait(
+        device->driverData);
+}
+
+void SDL_WaitGpuForFences(
+    SDL_GpuDevice *device,
+    SDL_bool waitAll,
+    SDL_GpuFence **pFences,
+    Uint32 fenceCount)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (pFences == NULL && fenceCount > 0) {
+        SDL_InvalidParamError("pFences");
+        return;
+    }
+
+    device->WaitForFences(
+        device->driverData,
+        waitAll,
+        pFences,
+        fenceCount);
+}
+
+SDL_bool SDL_QueryGpuFence(
+    SDL_GpuDevice *device,
+    SDL_GpuFence *fence)
+{
+    CHECK_DEVICE_MAGIC(device, SDL_FALSE);
+    if (fence == NULL) {
+        SDL_InvalidParamError("fence");
+        return SDL_FALSE;
+    }
+
+    return device->QueryFence(
+        device->driverData,
+        fence);
+}
+
+void SDL_ReleaseGpuFence(
+    SDL_GpuDevice *device,
+    SDL_GpuFence *fence)
+{
+    CHECK_DEVICE_MAGIC(device, );
+    if (fence == NULL) {
+        return;
+    }
+
+    device->ReleaseFence(
+        device->driverData,
+        fence);
+}

+ 779 - 0
src/gpu/SDL_sysgpu.h

@@ -0,0 +1,779 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_internal.h"
+#include "../video/SDL_sysvideo.h"
+
+#ifndef SDL_GPU_DRIVER_H
+#define SDL_GPU_DRIVER_H
+
+// Common Structs
+
+typedef struct Pass
+{
+    SDL_GpuCommandBuffer *commandBuffer;
+    SDL_bool inProgress;
+} Pass;
+
+typedef struct CommandBufferCommonHeader
+{
+    SDL_GpuDevice *device;
+    Pass renderPass;
+    SDL_bool graphicsPipelineBound;
+    Pass computePass;
+    SDL_bool computePipelineBound;
+    Pass copyPass;
+    SDL_bool submitted;
+} CommandBufferCommonHeader;
+
+typedef struct TextureCommonHeader
+{
+    SDL_GpuTextureCreateInfo info;
+} TextureCommonHeader;
+
+typedef struct BlitFragmentUniforms
+{
+    // texcoord space
+    float left;
+    float top;
+    float width;
+    float height;
+
+    Uint32 mipLevel;
+    float layerOrDepth;
+} BlitFragmentUniforms;
+
+typedef struct BlitPipelineCacheEntry
+{
+    SDL_GpuTextureType type;
+    SDL_GpuTextureFormat format;
+    SDL_GpuGraphicsPipeline *pipeline;
+} BlitPipelineCacheEntry;
+
+// Internal Helper Utilities
+
+#define SDL_GPU_TEXTUREFORMAT_MAX        (SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT + 1)
+#define SDL_GPU_SWAPCHAINCOMPOSITION_MAX (SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2048 + 1)
+#define SDL_GPU_PRESENTMODE_MAX          (SDL_GPU_PRESENTMODE_MAILBOX + 1)
+
+static inline Sint32 Texture_GetBlockSize(
+    SDL_GpuTextureFormat format)
+{
+    switch (format) {
+    case SDL_GPU_TEXTUREFORMAT_BC1_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_BC2_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_BC3_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_BC7_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_BC3_UNORM_SRGB:
+    case SDL_GPU_TEXTUREFORMAT_BC7_UNORM_SRGB:
+        return 4;
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_R16G16_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_R8_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_A8_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_R8G8_SNORM:
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM:
+    case SDL_GPU_TEXTUREFORMAT_R16_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R32_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_R8_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R8G8_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R16_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R16G16_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB:
+    case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB:
+        return 1;
+    default:
+        SDL_assert_release(!"Unrecognized TextureFormat!");
+        return 0;
+    }
+}
+
+static inline SDL_bool IsDepthFormat(
+    SDL_GpuTextureFormat format)
+{
+    switch (format) {
+    case SDL_GPU_TEXTUREFORMAT_D16_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_D24_UNORM:
+    case SDL_GPU_TEXTUREFORMAT_D32_FLOAT:
+    case SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT:
+    case SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT:
+        return SDL_TRUE;
+
+    default:
+        return SDL_FALSE;
+    }
+}
+
+static inline SDL_bool IsStencilFormat(
+    SDL_GpuTextureFormat format)
+{
+    switch (format) {
+    case SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT:
+    case SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT:
+        return SDL_TRUE;
+
+    default:
+        return SDL_FALSE;
+    }
+}
+
+static inline SDL_bool IsIntegerFormat(
+    SDL_GpuTextureFormat format)
+{
+    switch (format) {
+    case SDL_GPU_TEXTUREFORMAT_R8_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R8G8_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R16_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R16G16_UINT:
+    case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT:
+        return SDL_TRUE;
+
+    default:
+        return SDL_FALSE;
+    }
+}
+
+static inline Uint32 IndexSize(SDL_GpuIndexElementSize size)
+{
+    return (size == SDL_GPU_INDEXELEMENTSIZE_16BIT) ? 2 : 4;
+}
+
+static inline Uint32 BytesPerRow(
+    Sint32 width,
+    SDL_GpuTextureFormat format)
+{
+    Uint32 blocksPerRow = width;
+
+    if (format == SDL_GPU_TEXTUREFORMAT_BC1_UNORM ||
+        format == SDL_GPU_TEXTUREFORMAT_BC2_UNORM ||
+        format == SDL_GPU_TEXTUREFORMAT_BC3_UNORM ||
+        format == SDL_GPU_TEXTUREFORMAT_BC7_UNORM) {
+        blocksPerRow = (width + 3) / 4;
+    }
+
+    return blocksPerRow * SDL_GpuTextureFormatTexelBlockSize(format);
+}
+
+static inline Sint32 BytesPerImage(
+    Uint32 width,
+    Uint32 height,
+    SDL_GpuTextureFormat format)
+{
+    Uint32 blocksPerRow = width;
+    Uint32 blocksPerColumn = height;
+
+    if (format == SDL_GPU_TEXTUREFORMAT_BC1_UNORM ||
+        format == SDL_GPU_TEXTUREFORMAT_BC2_UNORM ||
+        format == SDL_GPU_TEXTUREFORMAT_BC3_UNORM ||
+        format == SDL_GPU_TEXTUREFORMAT_BC7_UNORM) {
+        blocksPerRow = (width + 3) / 4;
+        blocksPerColumn = (height + 3) / 4;
+    }
+
+    return blocksPerRow * blocksPerColumn * SDL_GpuTextureFormatTexelBlockSize(format);
+}
+
+// GraphicsDevice Limits
+
+#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16
+#define MAX_STORAGE_TEXTURES_PER_STAGE 8
+#define MAX_STORAGE_BUFFERS_PER_STAGE  8
+#define MAX_UNIFORM_BUFFERS_PER_STAGE  4
+#define MAX_COMPUTE_WRITE_TEXTURES     8
+#define MAX_COMPUTE_WRITE_BUFFERS      8
+#define UNIFORM_BUFFER_SIZE            32768
+#define MAX_BUFFER_BINDINGS            16
+#define MAX_COLOR_TARGET_BINDINGS      4
+#define MAX_PRESENT_COUNT              16
+#define MAX_FRAMES_IN_FLIGHT           3
+
+// Internal Macros
+
+#define EXPAND_ARRAY_IF_NEEDED(arr, elementType, newCount, capacity, newCapacity) \
+    if (newCount >= capacity) {                                                   \
+        capacity = newCapacity;                                                   \
+        arr = (elementType *)SDL_realloc(                                         \
+            arr,                                                                  \
+            sizeof(elementType) * capacity);                                      \
+    }
+
+// Internal Declarations
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+SDL_GpuGraphicsPipeline *SDL_Gpu_FetchBlitPipeline(
+    SDL_GpuDevice *device,
+    SDL_GpuTextureType sourceTextureType,
+    SDL_GpuTextureFormat destinationFormat,
+    SDL_GpuShader *blitVertexShader,
+    SDL_GpuShader *blitFrom2DShader,
+    SDL_GpuShader *blitFrom2DArrayShader,
+    SDL_GpuShader *blitFrom3DShader,
+    SDL_GpuShader *blitFromCubeShader,
+    BlitPipelineCacheEntry **blitPipelines,
+    Uint32 *blitPipelineCount,
+    Uint32 *blitPipelineCapacity);
+
+void SDL_Gpu_BlitCommon(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBlitRegion *source,
+    SDL_GpuBlitRegion *destination,
+    SDL_FlipMode flipMode,
+    SDL_GpuFilter filterMode,
+    SDL_bool cycle,
+    SDL_GpuSampler *blitLinearSampler,
+    SDL_GpuSampler *blitNearestSampler,
+    SDL_GpuShader *blitVertexShader,
+    SDL_GpuShader *blitFrom2DShader,
+    SDL_GpuShader *blitFrom2DArrayShader,
+    SDL_GpuShader *blitFrom3DShader,
+    SDL_GpuShader *blitFromCubeShader,
+    BlitPipelineCacheEntry **blitPipelines,
+    Uint32 *blitPipelineCount,
+    Uint32 *blitPipelineCapacity);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+// SDL_GpuDevice Definition
+
+typedef struct SDL_GpuRenderer SDL_GpuRenderer;
+
+struct SDL_GpuDevice
+{
+    // Quit
+
+    void (*DestroyDevice)(SDL_GpuDevice *device);
+
+    // State Creation
+
+    SDL_GpuComputePipeline *(*CreateComputePipeline)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuComputePipelineCreateInfo *pipelineCreateInfo);
+
+    SDL_GpuGraphicsPipeline *(*CreateGraphicsPipeline)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuGraphicsPipelineCreateInfo *pipelineCreateInfo);
+
+    SDL_GpuSampler *(*CreateSampler)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuSamplerCreateInfo *samplerCreateInfo);
+
+    SDL_GpuShader *(*CreateShader)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuShaderCreateInfo *shaderCreateInfo);
+
+    SDL_GpuTexture *(*CreateTexture)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuTextureCreateInfo *textureCreateInfo);
+
+    SDL_GpuBuffer *(*CreateBuffer)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuBufferUsageFlags usageFlags,
+        Uint32 sizeInBytes);
+
+    SDL_GpuTransferBuffer *(*CreateTransferBuffer)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuTransferBufferUsage usage,
+        Uint32 sizeInBytes);
+
+    // Debug Naming
+
+    void (*SetBufferName)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuBuffer *buffer,
+        const char *text);
+
+    void (*SetTextureName)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuTexture *texture,
+        const char *text);
+
+    void (*InsertDebugLabel)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        const char *text);
+
+    void (*PushDebugGroup)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        const char *name);
+
+    void (*PopDebugGroup)(
+        SDL_GpuCommandBuffer *commandBuffer);
+
+    // Disposal
+
+    void (*ReleaseTexture)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuTexture *texture);
+
+    void (*ReleaseSampler)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuSampler *sampler);
+
+    void (*ReleaseBuffer)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuBuffer *buffer);
+
+    void (*ReleaseTransferBuffer)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuTransferBuffer *transferBuffer);
+
+    void (*ReleaseShader)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuShader *shader);
+
+    void (*ReleaseComputePipeline)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuComputePipeline *computePipeline);
+
+    void (*ReleaseGraphicsPipeline)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuGraphicsPipeline *graphicsPipeline);
+
+    // Render Pass
+
+    void (*BeginRenderPass)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuColorAttachmentInfo *colorAttachmentInfos,
+        Uint32 colorAttachmentCount,
+        SDL_GpuDepthStencilAttachmentInfo *depthStencilAttachmentInfo);
+
+    void (*BindGraphicsPipeline)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuGraphicsPipeline *graphicsPipeline);
+
+    void (*SetViewport)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuViewport *viewport);
+
+    void (*SetScissor)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_Rect *scissor);
+
+    void (*BindVertexBuffers)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 firstBinding,
+        SDL_GpuBufferBinding *pBindings,
+        Uint32 bindingCount);
+
+    void (*BindIndexBuffer)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuBufferBinding *pBinding,
+        SDL_GpuIndexElementSize indexElementSize);
+
+    void (*BindVertexSamplers)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 firstSlot,
+        SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+        Uint32 bindingCount);
+
+    void (*BindVertexStorageTextures)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 firstSlot,
+        SDL_GpuTexture **storageTextures,
+        Uint32 bindingCount);
+
+    void (*BindVertexStorageBuffers)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 firstSlot,
+        SDL_GpuBuffer **storageBuffers,
+        Uint32 bindingCount);
+
+    void (*BindFragmentSamplers)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 firstSlot,
+        SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+        Uint32 bindingCount);
+
+    void (*BindFragmentStorageTextures)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 firstSlot,
+        SDL_GpuTexture **storageTextures,
+        Uint32 bindingCount);
+
+    void (*BindFragmentStorageBuffers)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 firstSlot,
+        SDL_GpuBuffer **storageBuffers,
+        Uint32 bindingCount);
+
+    void (*PushVertexUniformData)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 slotIndex,
+        const void *data,
+        Uint32 dataLengthInBytes);
+
+    void (*PushFragmentUniformData)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 slotIndex,
+        const void *data,
+        Uint32 dataLengthInBytes);
+
+    void (*DrawIndexedPrimitives)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 indexCount,
+        Uint32 instanceCount,
+        Uint32 firstIndex,
+        Sint32 vertexOffset,
+        Uint32 firstInstance);
+
+    void (*DrawPrimitives)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 vertexCount,
+        Uint32 instanceCount,
+        Uint32 firstVertex,
+        Uint32 firstInstance);
+
+    void (*DrawPrimitivesIndirect)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuBuffer *buffer,
+        Uint32 offsetInBytes,
+        Uint32 drawCount,
+        Uint32 stride);
+
+    void (*DrawIndexedPrimitivesIndirect)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuBuffer *buffer,
+        Uint32 offsetInBytes,
+        Uint32 drawCount,
+        Uint32 stride);
+
+    void (*EndRenderPass)(
+        SDL_GpuCommandBuffer *commandBuffer);
+
+    // Compute Pass
+
+    void (*BeginComputePass)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuStorageTextureWriteOnlyBinding *storageTextureBindings,
+        Uint32 storageTextureBindingCount,
+        SDL_GpuStorageBufferWriteOnlyBinding *storageBufferBindings,
+        Uint32 storageBufferBindingCount);
+
+    void (*BindComputePipeline)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuComputePipeline *computePipeline);
+
+    void (*BindComputeStorageTextures)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 firstSlot,
+        SDL_GpuTexture **storageTextures,
+        Uint32 bindingCount);
+
+    void (*BindComputeStorageBuffers)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 firstSlot,
+        SDL_GpuBuffer **storageBuffers,
+        Uint32 bindingCount);
+
+    void (*PushComputeUniformData)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 slotIndex,
+        const void *data,
+        Uint32 dataLengthInBytes);
+
+    void (*DispatchCompute)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        Uint32 groupCountX,
+        Uint32 groupCountY,
+        Uint32 groupCountZ);
+
+    void (*DispatchComputeIndirect)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuBuffer *buffer,
+        Uint32 offsetInBytes);
+
+    void (*EndComputePass)(
+        SDL_GpuCommandBuffer *commandBuffer);
+
+    // TransferBuffer Data
+
+    void *(*MapTransferBuffer)(
+        SDL_GpuRenderer *device,
+        SDL_GpuTransferBuffer *transferBuffer,
+        SDL_bool cycle);
+
+    void (*UnmapTransferBuffer)(
+        SDL_GpuRenderer *device,
+        SDL_GpuTransferBuffer *transferBuffer);
+
+    // Copy Pass
+
+    void (*BeginCopyPass)(
+        SDL_GpuCommandBuffer *commandBuffer);
+
+    void (*UploadToTexture)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuTextureTransferInfo *source,
+        SDL_GpuTextureRegion *destination,
+        SDL_bool cycle);
+
+    void (*UploadToBuffer)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuTransferBufferLocation *source,
+        SDL_GpuBufferRegion *destination,
+        SDL_bool cycle);
+
+    void (*CopyTextureToTexture)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuTextureLocation *source,
+        SDL_GpuTextureLocation *destination,
+        Uint32 w,
+        Uint32 h,
+        Uint32 d,
+        SDL_bool cycle);
+
+    void (*CopyBufferToBuffer)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuBufferLocation *source,
+        SDL_GpuBufferLocation *destination,
+        Uint32 size,
+        SDL_bool cycle);
+
+    void (*GenerateMipmaps)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuTexture *texture);
+
+    void (*DownloadFromTexture)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuTextureRegion *source,
+        SDL_GpuTextureTransferInfo *destination);
+
+    void (*DownloadFromBuffer)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuBufferRegion *source,
+        SDL_GpuTransferBufferLocation *destination);
+
+    void (*EndCopyPass)(
+        SDL_GpuCommandBuffer *commandBuffer);
+
+    void (*Blit)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_GpuBlitRegion *source,
+        SDL_GpuBlitRegion *destination,
+        SDL_FlipMode flipMode,
+        SDL_GpuFilter filterMode,
+        SDL_bool cycle);
+
+    // Submission/Presentation
+
+    SDL_bool (*SupportsSwapchainComposition)(
+        SDL_GpuRenderer *driverData,
+        SDL_Window *window,
+        SDL_GpuSwapchainComposition swapchainComposition);
+
+    SDL_bool (*SupportsPresentMode)(
+        SDL_GpuRenderer *driverData,
+        SDL_Window *window,
+        SDL_GpuPresentMode presentMode);
+
+    SDL_bool (*ClaimWindow)(
+        SDL_GpuRenderer *driverData,
+        SDL_Window *window);
+
+    void (*UnclaimWindow)(
+        SDL_GpuRenderer *driverData,
+        SDL_Window *window);
+
+    SDL_bool (*SetSwapchainParameters)(
+        SDL_GpuRenderer *driverData,
+        SDL_Window *window,
+        SDL_GpuSwapchainComposition swapchainComposition,
+        SDL_GpuPresentMode presentMode);
+
+    SDL_GpuTextureFormat (*GetSwapchainTextureFormat)(
+        SDL_GpuRenderer *driverData,
+        SDL_Window *window);
+
+    SDL_GpuCommandBuffer *(*AcquireCommandBuffer)(
+        SDL_GpuRenderer *driverData);
+
+    SDL_GpuTexture *(*AcquireSwapchainTexture)(
+        SDL_GpuCommandBuffer *commandBuffer,
+        SDL_Window *window,
+        Uint32 *pWidth,
+        Uint32 *pHeight);
+
+    void (*Submit)(
+        SDL_GpuCommandBuffer *commandBuffer);
+
+    SDL_GpuFence *(*SubmitAndAcquireFence)(
+        SDL_GpuCommandBuffer *commandBuffer);
+
+    void (*Wait)(
+        SDL_GpuRenderer *driverData);
+
+    void (*WaitForFences)(
+        SDL_GpuRenderer *driverData,
+        SDL_bool waitAll,
+        SDL_GpuFence **pFences,
+        Uint32 fenceCount);
+
+    SDL_bool (*QueryFence)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuFence *fence);
+
+    void (*ReleaseFence)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuFence *fence);
+
+    // Feature Queries
+
+    SDL_bool (*SupportsTextureFormat)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuTextureFormat format,
+        SDL_GpuTextureType type,
+        SDL_GpuTextureUsageFlags usage);
+
+    SDL_bool (*SupportsSampleCount)(
+        SDL_GpuRenderer *driverData,
+        SDL_GpuTextureFormat format,
+        SDL_GpuSampleCount desiredSampleCount);
+
+    // Opaque pointer for the Driver
+    SDL_GpuRenderer *driverData;
+
+    // Store this for SDL_GetGpuDriver()
+    SDL_GpuDriver backend;
+
+    // Store this for SDL_gpu.c's debug layer
+    SDL_bool debugMode;
+    SDL_GpuShaderFormat shaderFormats;
+};
+
+#define ASSIGN_DRIVER_FUNC(func, name) \
+    result->func = name##_##func;
+#define ASSIGN_DRIVER(name)                                 \
+    ASSIGN_DRIVER_FUNC(DestroyDevice, name)                 \
+    ASSIGN_DRIVER_FUNC(CreateComputePipeline, name)         \
+    ASSIGN_DRIVER_FUNC(CreateGraphicsPipeline, name)        \
+    ASSIGN_DRIVER_FUNC(CreateSampler, name)                 \
+    ASSIGN_DRIVER_FUNC(CreateShader, name)                  \
+    ASSIGN_DRIVER_FUNC(CreateTexture, name)                 \
+    ASSIGN_DRIVER_FUNC(CreateBuffer, name)                  \
+    ASSIGN_DRIVER_FUNC(CreateTransferBuffer, name)          \
+    ASSIGN_DRIVER_FUNC(SetBufferName, name)                 \
+    ASSIGN_DRIVER_FUNC(SetTextureName, name)                \
+    ASSIGN_DRIVER_FUNC(InsertDebugLabel, name)              \
+    ASSIGN_DRIVER_FUNC(PushDebugGroup, name)                \
+    ASSIGN_DRIVER_FUNC(PopDebugGroup, name)                 \
+    ASSIGN_DRIVER_FUNC(ReleaseTexture, name)                \
+    ASSIGN_DRIVER_FUNC(ReleaseSampler, name)                \
+    ASSIGN_DRIVER_FUNC(ReleaseBuffer, name)                 \
+    ASSIGN_DRIVER_FUNC(ReleaseTransferBuffer, name)         \
+    ASSIGN_DRIVER_FUNC(ReleaseShader, name)                 \
+    ASSIGN_DRIVER_FUNC(ReleaseComputePipeline, name)        \
+    ASSIGN_DRIVER_FUNC(ReleaseGraphicsPipeline, name)       \
+    ASSIGN_DRIVER_FUNC(BeginRenderPass, name)               \
+    ASSIGN_DRIVER_FUNC(BindGraphicsPipeline, name)          \
+    ASSIGN_DRIVER_FUNC(SetViewport, name)                   \
+    ASSIGN_DRIVER_FUNC(SetScissor, name)                    \
+    ASSIGN_DRIVER_FUNC(BindVertexBuffers, name)             \
+    ASSIGN_DRIVER_FUNC(BindIndexBuffer, name)               \
+    ASSIGN_DRIVER_FUNC(BindVertexSamplers, name)            \
+    ASSIGN_DRIVER_FUNC(BindVertexStorageTextures, name)     \
+    ASSIGN_DRIVER_FUNC(BindVertexStorageBuffers, name)      \
+    ASSIGN_DRIVER_FUNC(BindFragmentSamplers, name)          \
+    ASSIGN_DRIVER_FUNC(BindFragmentStorageTextures, name)   \
+    ASSIGN_DRIVER_FUNC(BindFragmentStorageBuffers, name)    \
+    ASSIGN_DRIVER_FUNC(PushVertexUniformData, name)         \
+    ASSIGN_DRIVER_FUNC(PushFragmentUniformData, name)       \
+    ASSIGN_DRIVER_FUNC(DrawIndexedPrimitives, name)         \
+    ASSIGN_DRIVER_FUNC(DrawPrimitives, name)                \
+    ASSIGN_DRIVER_FUNC(DrawPrimitivesIndirect, name)        \
+    ASSIGN_DRIVER_FUNC(DrawIndexedPrimitivesIndirect, name) \
+    ASSIGN_DRIVER_FUNC(EndRenderPass, name)                 \
+    ASSIGN_DRIVER_FUNC(BeginComputePass, name)              \
+    ASSIGN_DRIVER_FUNC(BindComputePipeline, name)           \
+    ASSIGN_DRIVER_FUNC(BindComputeStorageTextures, name)    \
+    ASSIGN_DRIVER_FUNC(BindComputeStorageBuffers, name)     \
+    ASSIGN_DRIVER_FUNC(PushComputeUniformData, name)        \
+    ASSIGN_DRIVER_FUNC(DispatchCompute, name)               \
+    ASSIGN_DRIVER_FUNC(DispatchComputeIndirect, name)       \
+    ASSIGN_DRIVER_FUNC(EndComputePass, name)                \
+    ASSIGN_DRIVER_FUNC(MapTransferBuffer, name)             \
+    ASSIGN_DRIVER_FUNC(UnmapTransferBuffer, name)           \
+    ASSIGN_DRIVER_FUNC(BeginCopyPass, name)                 \
+    ASSIGN_DRIVER_FUNC(UploadToTexture, name)               \
+    ASSIGN_DRIVER_FUNC(UploadToBuffer, name)                \
+    ASSIGN_DRIVER_FUNC(DownloadFromTexture, name)           \
+    ASSIGN_DRIVER_FUNC(DownloadFromBuffer, name)            \
+    ASSIGN_DRIVER_FUNC(CopyTextureToTexture, name)          \
+    ASSIGN_DRIVER_FUNC(CopyBufferToBuffer, name)            \
+    ASSIGN_DRIVER_FUNC(GenerateMipmaps, name)               \
+    ASSIGN_DRIVER_FUNC(EndCopyPass, name)                   \
+    ASSIGN_DRIVER_FUNC(Blit, name)                          \
+    ASSIGN_DRIVER_FUNC(SupportsSwapchainComposition, name)  \
+    ASSIGN_DRIVER_FUNC(SupportsPresentMode, name)           \
+    ASSIGN_DRIVER_FUNC(ClaimWindow, name)                   \
+    ASSIGN_DRIVER_FUNC(UnclaimWindow, name)                 \
+    ASSIGN_DRIVER_FUNC(SetSwapchainParameters, name)        \
+    ASSIGN_DRIVER_FUNC(GetSwapchainTextureFormat, name)     \
+    ASSIGN_DRIVER_FUNC(AcquireCommandBuffer, name)          \
+    ASSIGN_DRIVER_FUNC(AcquireSwapchainTexture, name)       \
+    ASSIGN_DRIVER_FUNC(Submit, name)                        \
+    ASSIGN_DRIVER_FUNC(SubmitAndAcquireFence, name)         \
+    ASSIGN_DRIVER_FUNC(Wait, name)                          \
+    ASSIGN_DRIVER_FUNC(WaitForFences, name)                 \
+    ASSIGN_DRIVER_FUNC(QueryFence, name)                    \
+    ASSIGN_DRIVER_FUNC(ReleaseFence, name)                  \
+    ASSIGN_DRIVER_FUNC(SupportsTextureFormat, name)         \
+    ASSIGN_DRIVER_FUNC(SupportsSampleCount, name)
+
+typedef struct SDL_GpuBootstrap
+{
+    const char *Name;
+    const SDL_GpuDriver backendflag;
+    const SDL_GpuShaderFormat shaderFormats;
+    SDL_bool (*PrepareDriver)(SDL_VideoDevice *_this);
+    SDL_GpuDevice *(*CreateDevice)(SDL_bool debugMode, SDL_bool preferLowPower, SDL_PropertiesID props);
+} SDL_GpuBootstrap;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern SDL_GpuBootstrap VulkanDriver;
+extern SDL_GpuBootstrap D3D11Driver;
+extern SDL_GpuBootstrap D3D12Driver;
+extern SDL_GpuBootstrap MetalDriver;
+extern SDL_GpuBootstrap PS5Driver;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SDL_GPU_DRIVER_H

+ 1328 - 0
src/gpu/d3d11/D3D11_Blit.h

@@ -0,0 +1,1328 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_VERTEXID              0   x           0   VERTID    uint   x   
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// TEXCOORD                 0   xy          0     NONE   float   xy  
+// SV_POSITION              0   xyzw        1      POS   float   xyzw
+//
+vs_5_0
+dcl_globalFlags refactoringAllowed
+dcl_input_sgv v0.x, vertex_id
+dcl_output o0.xy
+dcl_output_siv o1.xyzw, position
+dcl_temps 1
+bfi r0.x, l(1), l(1), v0.x, l(0)
+and r0.z, v0.x, l(2)
+utof r0.xy, r0.xzxx
+mov o0.xy, r0.xyxx
+mad o1.xy, r0.xyxx, l(2.000000, -2.000000, 0.000000, 0.000000), l(-1.000000, 1.000000, 0.000000, 0.000000)
+mov o1.zw, l(0,0,0,1.000000)
+ret 
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_FullscreenVert[] =
+{
+     68,  88,  66,  67,  35, 105, 
+    237, 237, 146, 210, 147,  25, 
+    112,  64, 239,   9, 223, 111, 
+    229, 225,   1,   0,   0,   0, 
+    224,   2,   0,   0,   5,   0, 
+      0,   0,  52,   0,   0,   0, 
+    160,   0,   0,   0, 212,   0, 
+      0,   0,  44,   1,   0,   0, 
+     68,   2,   0,   0,  82,  68, 
+     69,  70, 100,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     60,   0,   0,   0,   0,   5, 
+    254, 255,   0,   1,   0,   0, 
+     60,   0,   0,   0,  82,  68, 
+     49,  49,  60,   0,   0,   0, 
+     24,   0,   0,   0,  32,   0, 
+      0,   0,  40,   0,   0,   0, 
+     36,   0,   0,   0,  12,   0, 
+      0,   0,   0,   0,   0,   0, 
+     77, 105,  99, 114, 111, 115, 
+    111, 102, 116,  32,  40,  82, 
+     41,  32,  72,  76,  83,  76, 
+     32,  83, 104,  97, 100, 101, 
+    114,  32,  67, 111, 109, 112, 
+    105, 108, 101, 114,  32,  49, 
+     48,  46,  49,   0,  73,  83, 
+     71,  78,  44,   0,   0,   0, 
+      1,   0,   0,   0,   8,   0, 
+      0,   0,  32,   0,   0,   0, 
+      0,   0,   0,   0,   6,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   1,   1, 
+      0,   0,  83,  86,  95,  86, 
+     69,  82,  84,  69,  88,  73, 
+     68,   0,  79,  83,  71,  78, 
+     80,   0,   0,   0,   2,   0, 
+      0,   0,   8,   0,   0,   0, 
+     56,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,   3,  12,   0,   0, 
+     65,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      3,   0,   0,   0,   1,   0, 
+      0,   0,  15,   0,   0,   0, 
+     84,  69,  88,  67,  79,  79, 
+     82,  68,   0,  83,  86,  95, 
+     80,  79,  83,  73,  84,  73, 
+     79,  78,   0, 171, 171, 171, 
+     83,  72,  69,  88,  16,   1, 
+      0,   0,  80,   0,   1,   0, 
+     68,   0,   0,   0, 106,   8, 
+      0,   1,  96,   0,   0,   4, 
+     18,  16,  16,   0,   0,   0, 
+      0,   0,   6,   0,   0,   0, 
+    101,   0,   0,   3,  50,  32, 
+     16,   0,   0,   0,   0,   0, 
+    103,   0,   0,   4, 242,  32, 
+     16,   0,   1,   0,   0,   0, 
+      1,   0,   0,   0, 104,   0, 
+      0,   2,   1,   0,   0,   0, 
+    140,   0,   0,  11,  18,   0, 
+     16,   0,   0,   0,   0,   0, 
+      1,  64,   0,   0,   1,   0, 
+      0,   0,   1,  64,   0,   0, 
+      1,   0,   0,   0,  10,  16, 
+     16,   0,   0,   0,   0,   0, 
+      1,  64,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   7, 
+     66,   0,  16,   0,   0,   0, 
+      0,   0,  10,  16,  16,   0, 
+      0,   0,   0,   0,   1,  64, 
+      0,   0,   2,   0,   0,   0, 
+     86,   0,   0,   5,  50,   0, 
+     16,   0,   0,   0,   0,   0, 
+    134,   0,  16,   0,   0,   0, 
+      0,   0,  54,   0,   0,   5, 
+     50,  32,  16,   0,   0,   0, 
+      0,   0,  70,   0,  16,   0, 
+      0,   0,   0,   0,  50,   0, 
+      0,  15,  50,  32,  16,   0, 
+      1,   0,   0,   0,  70,   0, 
+     16,   0,   0,   0,   0,   0, 
+      2,  64,   0,   0,   0,   0, 
+      0,  64,   0,   0,   0, 192, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   2,  64,   0,   0, 
+      0,   0, 128, 191,   0,   0, 
+    128,  63,   0,   0,   0,   0, 
+      0,   0,   0,   0,  54,   0, 
+      0,   8, 194,  32,  16,   0, 
+      1,   0,   0,   0,   2,  64, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 128,  63, 
+     62,   0,   0,   1,  83,  84, 
+     65,  84, 148,   0,   0,   0, 
+      7,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions: 
+//
+// cbuffer SourceRegionBuffer
+// {
+//
+//   float2 UVLeftTop;                  // Offset:    0 Size:     8
+//   float2 UVDimensions;               // Offset:    8 Size:     8
+//   uint MipLevel;                     // Offset:   16 Size:     4
+//   float LayerOrDepth;                // Offset:   20 Size:     4 [unused]
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name                                 Type  Format         Dim      HLSL Bind  Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// SourceSampler                     sampler      NA          NA             s0      1 
+// SourceTexture2D                   texture  float4          2d             t0      1 
+// SourceRegionBuffer                cbuffer      NA          NA            cb0      1 
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// TEXCOORD                 0   xy          0     NONE   float   xy  
+// SV_POSITION              0   xyzw        1      POS   float       
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target                0   xyzw        0   TARGET   float   xyzw
+//
+ps_5_0
+dcl_globalFlags refactoringAllowed
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v0.xy
+dcl_output o0.xyzw
+dcl_temps 1
+mad r0.xy, cb0[0].zwzz, v0.xyxx, cb0[0].xyxx
+utof r0.z, cb0[1].x
+sample_l_indexable(texture2d)(float,float,float,float) o0.xyzw, r0.xyxx, t0.xyzw, s0, r0.z
+ret 
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_BlitFrom2D[] =
+{
+     68,  88,  66,  67, 202, 121, 
+     86, 209, 195,  28,  22, 216, 
+     35, 118,  37,  69, 114, 188, 
+    248, 164,   1,   0,   0,   0, 
+    160,   4,   0,   0,   5,   0, 
+      0,   0,  52,   0,   0,   0, 
+    156,   2,   0,   0, 244,   2, 
+      0,   0,  40,   3,   0,   0, 
+      4,   4,   0,   0,  82,  68, 
+     69,  70,  96,   2,   0,   0, 
+      1,   0,   0,   0, 208,   0, 
+      0,   0,   3,   0,   0,   0, 
+     60,   0,   0,   0,   0,   5, 
+    255, 255,   0,   1,   0,   0, 
+     56,   2,   0,   0,  82,  68, 
+     49,  49,  60,   0,   0,   0, 
+     24,   0,   0,   0,  32,   0, 
+      0,   0,  40,   0,   0,   0, 
+     36,   0,   0,   0,  12,   0, 
+      0,   0,   0,   0,   0,   0, 
+    156,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0, 170,   0,   0,   0, 
+      2,   0,   0,   0,   5,   0, 
+      0,   0,   4,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     13,   0,   0,   0, 186,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   1,   0,   0,   0, 
+     83, 111, 117, 114,  99, 101, 
+     83,  97, 109, 112, 108, 101, 
+    114,   0,  83, 111, 117, 114, 
+     99, 101,  84, 101, 120, 116, 
+    117, 114, 101,  50,  68,   0, 
+     83, 111, 117, 114,  99, 101, 
+     82, 101, 103, 105, 111, 110, 
+     66, 117, 102, 102, 101, 114, 
+      0, 171, 171, 171, 186,   0, 
+      0,   0,   4,   0,   0,   0, 
+    232,   0,   0,   0,  32,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 136,   1, 
+      0,   0,   0,   0,   0,   0, 
+      8,   0,   0,   0,   2,   0, 
+      0,   0, 156,   1,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0, 192,   1,   0,   0, 
+      8,   0,   0,   0,   8,   0, 
+      0,   0,   2,   0,   0,   0, 
+    156,   1,   0,   0,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    205,   1,   0,   0,  16,   0, 
+      0,   0,   4,   0,   0,   0, 
+      2,   0,   0,   0, 220,   1, 
+      0,   0,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0,   0,   2, 
+      0,   0,  20,   0,   0,   0, 
+      4,   0,   0,   0,   0,   0, 
+      0,   0,  20,   2,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,  85,  86,  76, 101, 
+    102, 116,  84, 111, 112,   0, 
+    102, 108, 111,  97, 116,  50, 
+      0, 171, 171, 171,   1,   0, 
+      3,   0,   1,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    146,   1,   0,   0,  85,  86, 
+     68, 105, 109, 101, 110, 115, 
+    105, 111, 110, 115,   0,  77, 
+    105, 112,  76, 101, 118, 101, 
+    108,   0, 100, 119, 111, 114, 
+    100,   0,   0,   0,  19,   0, 
+      1,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 214,   1, 
+      0,   0,  76,  97, 121, 101, 
+    114,  79, 114,  68, 101, 112, 
+    116, 104,   0, 102, 108, 111, 
+     97, 116,   0, 171,   0,   0, 
+      3,   0,   1,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     13,   2,   0,   0,  77, 105, 
+     99, 114, 111, 115, 111, 102, 
+    116,  32,  40,  82,  41,  32, 
+     72,  76,  83,  76,  32,  83, 
+    104,  97, 100, 101, 114,  32, 
+     67, 111, 109, 112, 105, 108, 
+    101, 114,  32,  49,  48,  46, 
+     49,   0,  73,  83,  71,  78, 
+     80,   0,   0,   0,   2,   0, 
+      0,   0,   8,   0,   0,   0, 
+     56,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,   3,   3,   0,   0, 
+     65,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      3,   0,   0,   0,   1,   0, 
+      0,   0,  15,   0,   0,   0, 
+     84,  69,  88,  67,  79,  79, 
+     82,  68,   0,  83,  86,  95, 
+     80,  79,  83,  73,  84,  73, 
+     79,  78,   0, 171, 171, 171, 
+     79,  83,  71,  78,  44,   0, 
+      0,   0,   1,   0,   0,   0, 
+      8,   0,   0,   0,  32,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+     15,   0,   0,   0,  83,  86, 
+     95,  84,  97, 114, 103, 101, 
+    116,   0, 171, 171,  83,  72, 
+     69,  88, 212,   0,   0,   0, 
+     80,   0,   0,   0,  53,   0, 
+      0,   0, 106,   8,   0,   1, 
+     89,   0,   0,   4,  70, 142, 
+     32,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,  90,   0, 
+      0,   3,   0,  96,  16,   0, 
+      0,   0,   0,   0,  88,  24, 
+      0,   4,   0, 112,  16,   0, 
+      0,   0,   0,   0,  85,  85, 
+      0,   0,  98,  16,   0,   3, 
+     50,  16,  16,   0,   0,   0, 
+      0,   0, 101,   0,   0,   3, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0, 104,   0,   0,   2, 
+      1,   0,   0,   0,  50,   0, 
+      0,  11,  50,   0,  16,   0, 
+      0,   0,   0,   0, 230, 138, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  70,  16, 
+     16,   0,   0,   0,   0,   0, 
+     70, 128,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     86,   0,   0,   6,  66,   0, 
+     16,   0,   0,   0,   0,   0, 
+     10, 128,  32,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     72,   0,   0, 141, 194,   0, 
+      0, 128,  67,  85,  21,   0, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0,  70,   0,  16,   0, 
+      0,   0,   0,   0,  70, 126, 
+     16,   0,   0,   0,   0,   0, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  42,   0,  16,   0, 
+      0,   0,   0,   0,  62,   0, 
+      0,   1,  83,  84,  65,  84, 
+    148,   0,   0,   0,   4,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions: 
+//
+// cbuffer SourceRegionBuffer
+// {
+//
+//   float2 UVLeftTop;                  // Offset:    0 Size:     8
+//   float2 UVDimensions;               // Offset:    8 Size:     8
+//   uint MipLevel;                     // Offset:   16 Size:     4
+//   float LayerOrDepth;                // Offset:   20 Size:     4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name                                 Type  Format         Dim      HLSL Bind  Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// SourceSampler                     sampler      NA          NA             s0      1 
+// SourceTexture2DArray              texture  float4     2darray             t0      1 
+// SourceRegionBuffer                cbuffer      NA          NA            cb0      1 
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// TEXCOORD                 0   xy          0     NONE   float   xy  
+// SV_POSITION              0   xyzw        1      POS   float       
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target                0   xyzw        0   TARGET   float   xyzw
+//
+ps_5_0
+dcl_globalFlags refactoringAllowed
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps linear v0.xy
+dcl_output o0.xyzw
+dcl_temps 1
+ftou r0.x, cb0[1].y
+utof r0.z, r0.x
+mad r0.xy, cb0[0].zwzz, v0.xyxx, cb0[0].xyxx
+utof r0.w, cb0[1].x
+sample_l_indexable(texture2darray)(float,float,float,float) o0.xyzw, r0.xyzx, t0.xyzw, s0, r0.w
+ret 
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_BlitFrom2DArray[] =
+{
+     68,  88,  66,  67, 228, 235, 
+     27, 223, 254, 144, 184,  34, 
+     12, 203, 116, 115,  17, 233, 
+    159, 157,   1,   0,   0,   0, 
+    208,   4,   0,   0,   5,   0, 
+      0,   0,  52,   0,   0,   0, 
+    160,   2,   0,   0, 248,   2, 
+      0,   0,  44,   3,   0,   0, 
+     52,   4,   0,   0,  82,  68, 
+     69,  70, 100,   2,   0,   0, 
+      1,   0,   0,   0, 212,   0, 
+      0,   0,   3,   0,   0,   0, 
+     60,   0,   0,   0,   0,   5, 
+    255, 255,   0,   1,   0,   0, 
+     60,   2,   0,   0,  82,  68, 
+     49,  49,  60,   0,   0,   0, 
+     24,   0,   0,   0,  32,   0, 
+      0,   0,  40,   0,   0,   0, 
+     36,   0,   0,   0,  12,   0, 
+      0,   0,   0,   0,   0,   0, 
+    156,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0, 170,   0,   0,   0, 
+      2,   0,   0,   0,   5,   0, 
+      0,   0,   5,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     13,   0,   0,   0, 191,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   1,   0,   0,   0, 
+     83, 111, 117, 114,  99, 101, 
+     83,  97, 109, 112, 108, 101, 
+    114,   0,  83, 111, 117, 114, 
+     99, 101,  84, 101, 120, 116, 
+    117, 114, 101,  50,  68,  65, 
+    114, 114,  97, 121,   0,  83, 
+    111, 117, 114,  99, 101,  82, 
+    101, 103, 105, 111, 110,  66, 
+    117, 102, 102, 101, 114,   0, 
+    171, 171, 191,   0,   0,   0, 
+      4,   0,   0,   0, 236,   0, 
+      0,   0,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0, 140,   1,   0,   0, 
+      0,   0,   0,   0,   8,   0, 
+      0,   0,   2,   0,   0,   0, 
+    160,   1,   0,   0,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    196,   1,   0,   0,   8,   0, 
+      0,   0,   8,   0,   0,   0, 
+      2,   0,   0,   0, 160,   1, 
+      0,   0,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0, 209,   1, 
+      0,   0,  16,   0,   0,   0, 
+      4,   0,   0,   0,   2,   0, 
+      0,   0, 224,   1,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,   4,   2,   0,   0, 
+     20,   0,   0,   0,   4,   0, 
+      0,   0,   2,   0,   0,   0, 
+     24,   2,   0,   0,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+     85,  86,  76, 101, 102, 116, 
+     84, 111, 112,   0, 102, 108, 
+    111,  97, 116,  50,   0, 171, 
+    171, 171,   1,   0,   3,   0, 
+      1,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 150,   1, 
+      0,   0,  85,  86,  68, 105, 
+    109, 101, 110, 115, 105, 111, 
+    110, 115,   0,  77, 105, 112, 
+     76, 101, 118, 101, 108,   0, 
+    100, 119, 111, 114, 100,   0, 
+      0,   0,  19,   0,   1,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0, 218,   1,   0,   0, 
+     76,  97, 121, 101, 114,  79, 
+    114,  68, 101, 112, 116, 104, 
+      0, 102, 108, 111,  97, 116, 
+      0, 171,   0,   0,   3,   0, 
+      1,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  17,   2, 
+      0,   0,  77, 105,  99, 114, 
+    111, 115, 111, 102, 116,  32, 
+     40,  82,  41,  32,  72,  76, 
+     83,  76,  32,  83, 104,  97, 
+    100, 101, 114,  32,  67, 111, 
+    109, 112, 105, 108, 101, 114, 
+     32,  49,  48,  46,  49,   0, 
+     73,  83,  71,  78,  80,   0, 
+      0,   0,   2,   0,   0,   0, 
+      8,   0,   0,   0,  56,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   3,   0,   0,  65,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+     15,   0,   0,   0,  84,  69, 
+     88,  67,  79,  79,  82,  68, 
+      0,  83,  86,  95,  80,  79, 
+     83,  73,  84,  73,  79,  78, 
+      0, 171, 171, 171,  79,  83, 
+     71,  78,  44,   0,   0,   0, 
+      1,   0,   0,   0,   8,   0, 
+      0,   0,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      0,   0,   0,   0,  15,   0, 
+      0,   0,  83,  86,  95,  84, 
+     97, 114, 103, 101, 116,   0, 
+    171, 171,  83,  72,  69,  88, 
+      0,   1,   0,   0,  80,   0, 
+      0,   0,  64,   0,   0,   0, 
+    106,   8,   0,   1,  89,   0, 
+      0,   4,  70, 142,  32,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,  90,   0,   0,   3, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  88,  64,   0,   4, 
+      0, 112,  16,   0,   0,   0, 
+      0,   0,  85,  85,   0,   0, 
+     98,  16,   0,   3,  50,  16, 
+     16,   0,   0,   0,   0,   0, 
+    101,   0,   0,   3, 242,  32, 
+     16,   0,   0,   0,   0,   0, 
+    104,   0,   0,   2,   1,   0, 
+      0,   0,  28,   0,   0,   6, 
+     18,   0,  16,   0,   0,   0, 
+      0,   0,  26, 128,  32,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  86,   0,   0,   5, 
+     66,   0,  16,   0,   0,   0, 
+      0,   0,  10,   0,  16,   0, 
+      0,   0,   0,   0,  50,   0, 
+      0,  11,  50,   0,  16,   0, 
+      0,   0,   0,   0, 230, 138, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  70,  16, 
+     16,   0,   0,   0,   0,   0, 
+     70, 128,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     86,   0,   0,   6, 130,   0, 
+     16,   0,   0,   0,   0,   0, 
+     10, 128,  32,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     72,   0,   0, 141,   2,   2, 
+      0, 128,  67,  85,  21,   0, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0,  70,   2,  16,   0, 
+      0,   0,   0,   0,  70, 126, 
+     16,   0,   0,   0,   0,   0, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  58,   0,  16,   0, 
+      0,   0,   0,   0,  62,   0, 
+      0,   1,  83,  84,  65,  84, 
+    148,   0,   0,   0,   6,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions: 
+//
+// cbuffer SourceRegionBuffer
+// {
+//
+//   float2 UVLeftTop;                  // Offset:    0 Size:     8
+//   float2 UVDimensions;               // Offset:    8 Size:     8
+//   uint MipLevel;                     // Offset:   16 Size:     4
+//   float LayerOrDepth;                // Offset:   20 Size:     4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name                                 Type  Format         Dim      HLSL Bind  Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// SourceSampler                     sampler      NA          NA             s0      1 
+// SourceTexture3D                   texture  float4          3d             t0      1 
+// SourceRegionBuffer                cbuffer      NA          NA            cb0      1 
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// TEXCOORD                 0   xy          0     NONE   float   xy  
+// SV_POSITION              0   xyzw        1      POS   float       
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target                0   xyzw        0   TARGET   float   xyzw
+//
+ps_5_0
+dcl_globalFlags refactoringAllowed
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v0.xy
+dcl_output o0.xyzw
+dcl_temps 1
+mad r0.xy, cb0[0].zwzz, v0.xyxx, cb0[0].xyxx
+utof r0.w, cb0[1].x
+mov r0.z, cb0[1].y
+sample_l_indexable(texture3d)(float,float,float,float) o0.xyzw, r0.xyzx, t0.xyzw, s0, r0.w
+ret 
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_BlitFrom3D[] =
+{
+     68,  88,  66,  67, 147, 168, 
+      4, 231, 209,  46, 121,   4, 
+    107, 179,  12, 172, 196, 130, 
+    224,  85,   1,   0,   0,   0, 
+    184,   4,   0,   0,   5,   0, 
+      0,   0,  52,   0,   0,   0, 
+    156,   2,   0,   0, 244,   2, 
+      0,   0,  40,   3,   0,   0, 
+     28,   4,   0,   0,  82,  68, 
+     69,  70,  96,   2,   0,   0, 
+      1,   0,   0,   0, 208,   0, 
+      0,   0,   3,   0,   0,   0, 
+     60,   0,   0,   0,   0,   5, 
+    255, 255,   0,   1,   0,   0, 
+     56,   2,   0,   0,  82,  68, 
+     49,  49,  60,   0,   0,   0, 
+     24,   0,   0,   0,  32,   0, 
+      0,   0,  40,   0,   0,   0, 
+     36,   0,   0,   0,  12,   0, 
+      0,   0,   0,   0,   0,   0, 
+    156,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0, 170,   0,   0,   0, 
+      2,   0,   0,   0,   5,   0, 
+      0,   0,   8,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     13,   0,   0,   0, 186,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   1,   0,   0,   0, 
+     83, 111, 117, 114,  99, 101, 
+     83,  97, 109, 112, 108, 101, 
+    114,   0,  83, 111, 117, 114, 
+     99, 101,  84, 101, 120, 116, 
+    117, 114, 101,  51,  68,   0, 
+     83, 111, 117, 114,  99, 101, 
+     82, 101, 103, 105, 111, 110, 
+     66, 117, 102, 102, 101, 114, 
+      0, 171, 171, 171, 186,   0, 
+      0,   0,   4,   0,   0,   0, 
+    232,   0,   0,   0,  32,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 136,   1, 
+      0,   0,   0,   0,   0,   0, 
+      8,   0,   0,   0,   2,   0, 
+      0,   0, 156,   1,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0, 192,   1,   0,   0, 
+      8,   0,   0,   0,   8,   0, 
+      0,   0,   2,   0,   0,   0, 
+    156,   1,   0,   0,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    205,   1,   0,   0,  16,   0, 
+      0,   0,   4,   0,   0,   0, 
+      2,   0,   0,   0, 220,   1, 
+      0,   0,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0,   0,   2, 
+      0,   0,  20,   0,   0,   0, 
+      4,   0,   0,   0,   2,   0, 
+      0,   0,  20,   2,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,  85,  86,  76, 101, 
+    102, 116,  84, 111, 112,   0, 
+    102, 108, 111,  97, 116,  50, 
+      0, 171, 171, 171,   1,   0, 
+      3,   0,   1,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    146,   1,   0,   0,  85,  86, 
+     68, 105, 109, 101, 110, 115, 
+    105, 111, 110, 115,   0,  77, 
+    105, 112,  76, 101, 118, 101, 
+    108,   0, 100, 119, 111, 114, 
+    100,   0,   0,   0,  19,   0, 
+      1,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 214,   1, 
+      0,   0,  76,  97, 121, 101, 
+    114,  79, 114,  68, 101, 112, 
+    116, 104,   0, 102, 108, 111, 
+     97, 116,   0, 171,   0,   0, 
+      3,   0,   1,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     13,   2,   0,   0,  77, 105, 
+     99, 114, 111, 115, 111, 102, 
+    116,  32,  40,  82,  41,  32, 
+     72,  76,  83,  76,  32,  83, 
+    104,  97, 100, 101, 114,  32, 
+     67, 111, 109, 112, 105, 108, 
+    101, 114,  32,  49,  48,  46, 
+     49,   0,  73,  83,  71,  78, 
+     80,   0,   0,   0,   2,   0, 
+      0,   0,   8,   0,   0,   0, 
+     56,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,   3,   3,   0,   0, 
+     65,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      3,   0,   0,   0,   1,   0, 
+      0,   0,  15,   0,   0,   0, 
+     84,  69,  88,  67,  79,  79, 
+     82,  68,   0,  83,  86,  95, 
+     80,  79,  83,  73,  84,  73, 
+     79,  78,   0, 171, 171, 171, 
+     79,  83,  71,  78,  44,   0, 
+      0,   0,   1,   0,   0,   0, 
+      8,   0,   0,   0,  32,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+     15,   0,   0,   0,  83,  86, 
+     95,  84,  97, 114, 103, 101, 
+    116,   0, 171, 171,  83,  72, 
+     69,  88, 236,   0,   0,   0, 
+     80,   0,   0,   0,  59,   0, 
+      0,   0, 106,   8,   0,   1, 
+     89,   0,   0,   4,  70, 142, 
+     32,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,  90,   0, 
+      0,   3,   0,  96,  16,   0, 
+      0,   0,   0,   0,  88,  40, 
+      0,   4,   0, 112,  16,   0, 
+      0,   0,   0,   0,  85,  85, 
+      0,   0,  98,  16,   0,   3, 
+     50,  16,  16,   0,   0,   0, 
+      0,   0, 101,   0,   0,   3, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0, 104,   0,   0,   2, 
+      1,   0,   0,   0,  50,   0, 
+      0,  11,  50,   0,  16,   0, 
+      0,   0,   0,   0, 230, 138, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  70,  16, 
+     16,   0,   0,   0,   0,   0, 
+     70, 128,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     86,   0,   0,   6, 130,   0, 
+     16,   0,   0,   0,   0,   0, 
+     10, 128,  32,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     54,   0,   0,   6,  66,   0, 
+     16,   0,   0,   0,   0,   0, 
+     26, 128,  32,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     72,   0,   0, 141,  66,   1, 
+      0, 128,  67,  85,  21,   0, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0,  70,   2,  16,   0, 
+      0,   0,   0,   0,  70, 126, 
+     16,   0,   0,   0,   0,   0, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  58,   0,  16,   0, 
+      0,   0,   0,   0,  62,   0, 
+      0,   1,  83,  84,  65,  84, 
+    148,   0,   0,   0,   5,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions: 
+//
+// cbuffer SourceRegionBuffer
+// {
+//
+//   float2 UVLeftTop;                  // Offset:    0 Size:     8
+//   float2 UVDimensions;               // Offset:    8 Size:     8
+//   uint MipLevel;                     // Offset:   16 Size:     4
+//   float LayerOrDepth;                // Offset:   20 Size:     4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name                                 Type  Format         Dim      HLSL Bind  Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// SourceSampler                     sampler      NA          NA             s0      1 
+// SourceTextureCube                 texture  float4        cube             t0      1 
+// SourceRegionBuffer                cbuffer      NA          NA            cb0      1 
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// TEXCOORD                 0   xy          0     NONE   float   xy  
+// SV_POSITION              0   xyzw        1      POS   float       
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target                0   xyzw        0   TARGET   float   xyzw
+//
+ps_5_0
+dcl_globalFlags refactoringAllowed
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texturecube (float,float,float,float) t0
+dcl_input_ps linear v0.xy
+dcl_output o0.xyzw
+dcl_temps 2
+mad r0.xy, cb0[0].zwzz, v0.xyxx, cb0[0].xyxx
+mad r0.xz, r0.xxyx, l(2.000000, 0.000000, 2.000000, 0.000000), l(-1.000000, 0.000000, -1.000000, 0.000000)
+ftou r1.x, cb0[1].y
+switch r1.x
+  case l(0)
+  mov r0.yz, -r0.zzxz
+  mov r0.x, l(1.000000)
+  break 
+  case l(1)
+  mov r0.y, l(-1.000000)
+  mov r0.w, -r0.z
+  mov r0.xyz, r0.ywxy
+  break 
+  case l(2)
+  mul r0.xz, r0.xxzx, l(1.000000, 0.000000, -1.000000, 0.000000)
+  mov r0.y, l(-1.000000)
+  break 
+  case l(3)
+  mov r0.y, l(1.000000)
+  break 
+  case l(4)
+  mul r0.xy, r0.xzxx, l(1.000000, -1.000000, 0.000000, 0.000000)
+  mov r0.z, l(1.000000)
+  break 
+  case l(5)
+  mov r0.xy, -r0.xzxx
+  mov r0.z, l(-1.000000)
+  break 
+  default 
+  mov r0.xyz, l(0,0,0,0)
+  break 
+endswitch 
+utof r0.w, cb0[1].x
+sample_l_indexable(texturecube)(float,float,float,float) o0.xyzw, r0.xyzx, t0.xyzw, s0, r0.w
+ret 
+// Approximately 35 instruction slots used
+#endif
+
+const BYTE g_BlitFromCube[] =
+{
+     68,  88,  66,  67,  74, 191, 
+     49,  23, 175,  39, 209, 200, 
+     62, 140,  77, 177,  73, 191, 
+     60, 231,   1,   0,   0,   0, 
+    176,   6,   0,   0,   5,   0, 
+      0,   0,  52,   0,   0,   0, 
+    156,   2,   0,   0, 244,   2, 
+      0,   0,  40,   3,   0,   0, 
+     20,   6,   0,   0,  82,  68, 
+     69,  70,  96,   2,   0,   0, 
+      1,   0,   0,   0, 208,   0, 
+      0,   0,   3,   0,   0,   0, 
+     60,   0,   0,   0,   0,   5, 
+    255, 255,   0,   1,   0,   0, 
+     56,   2,   0,   0,  82,  68, 
+     49,  49,  60,   0,   0,   0, 
+     24,   0,   0,   0,  32,   0, 
+      0,   0,  40,   0,   0,   0, 
+     36,   0,   0,   0,  12,   0, 
+      0,   0,   0,   0,   0,   0, 
+    156,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0, 170,   0,   0,   0, 
+      2,   0,   0,   0,   5,   0, 
+      0,   0,   9,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     13,   0,   0,   0, 188,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   1,   0,   0,   0, 
+     83, 111, 117, 114,  99, 101, 
+     83,  97, 109, 112, 108, 101, 
+    114,   0,  83, 111, 117, 114, 
+     99, 101,  84, 101, 120, 116, 
+    117, 114, 101,  67, 117,  98, 
+    101,   0,  83, 111, 117, 114, 
+     99, 101,  82, 101, 103, 105, 
+    111, 110,  66, 117, 102, 102, 
+    101, 114,   0, 171, 188,   0, 
+      0,   0,   4,   0,   0,   0, 
+    232,   0,   0,   0,  32,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 136,   1, 
+      0,   0,   0,   0,   0,   0, 
+      8,   0,   0,   0,   2,   0, 
+      0,   0, 156,   1,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0, 192,   1,   0,   0, 
+      8,   0,   0,   0,   8,   0, 
+      0,   0,   2,   0,   0,   0, 
+    156,   1,   0,   0,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    205,   1,   0,   0,  16,   0, 
+      0,   0,   4,   0,   0,   0, 
+      2,   0,   0,   0, 220,   1, 
+      0,   0,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0,   0,   2, 
+      0,   0,  20,   0,   0,   0, 
+      4,   0,   0,   0,   2,   0, 
+      0,   0,  20,   2,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,  85,  86,  76, 101, 
+    102, 116,  84, 111, 112,   0, 
+    102, 108, 111,  97, 116,  50, 
+      0, 171, 171, 171,   1,   0, 
+      3,   0,   1,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    146,   1,   0,   0,  85,  86, 
+     68, 105, 109, 101, 110, 115, 
+    105, 111, 110, 115,   0,  77, 
+    105, 112,  76, 101, 118, 101, 
+    108,   0, 100, 119, 111, 114, 
+    100,   0,   0,   0,  19,   0, 
+      1,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 214,   1, 
+      0,   0,  76,  97, 121, 101, 
+    114,  79, 114,  68, 101, 112, 
+    116, 104,   0, 102, 108, 111, 
+     97, 116,   0, 171,   0,   0, 
+      3,   0,   1,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     13,   2,   0,   0,  77, 105, 
+     99, 114, 111, 115, 111, 102, 
+    116,  32,  40,  82,  41,  32, 
+     72,  76,  83,  76,  32,  83, 
+    104,  97, 100, 101, 114,  32, 
+     67, 111, 109, 112, 105, 108, 
+    101, 114,  32,  49,  48,  46, 
+     49,   0,  73,  83,  71,  78, 
+     80,   0,   0,   0,   2,   0, 
+      0,   0,   8,   0,   0,   0, 
+     56,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,   3,   3,   0,   0, 
+     65,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      3,   0,   0,   0,   1,   0, 
+      0,   0,  15,   0,   0,   0, 
+     84,  69,  88,  67,  79,  79, 
+     82,  68,   0,  83,  86,  95, 
+     80,  79,  83,  73,  84,  73, 
+     79,  78,   0, 171, 171, 171, 
+     79,  83,  71,  78,  44,   0, 
+      0,   0,   1,   0,   0,   0, 
+      8,   0,   0,   0,  32,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+     15,   0,   0,   0,  83,  86, 
+     95,  84,  97, 114, 103, 101, 
+    116,   0, 171, 171,  83,  72, 
+     69,  88, 228,   2,   0,   0, 
+     80,   0,   0,   0, 185,   0, 
+      0,   0, 106,   8,   0,   1, 
+     89,   0,   0,   4,  70, 142, 
+     32,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,  90,   0, 
+      0,   3,   0,  96,  16,   0, 
+      0,   0,   0,   0,  88,  48, 
+      0,   4,   0, 112,  16,   0, 
+      0,   0,   0,   0,  85,  85, 
+      0,   0,  98,  16,   0,   3, 
+     50,  16,  16,   0,   0,   0, 
+      0,   0, 101,   0,   0,   3, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0, 104,   0,   0,   2, 
+      2,   0,   0,   0,  50,   0, 
+      0,  11,  50,   0,  16,   0, 
+      0,   0,   0,   0, 230, 138, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  70,  16, 
+     16,   0,   0,   0,   0,   0, 
+     70, 128,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     50,   0,   0,  15,  82,   0, 
+     16,   0,   0,   0,   0,   0, 
+      6,   1,  16,   0,   0,   0, 
+      0,   0,   2,  64,   0,   0, 
+      0,   0,   0,  64,   0,   0, 
+      0,   0,   0,   0,   0,  64, 
+      0,   0,   0,   0,   2,  64, 
+      0,   0,   0,   0, 128, 191, 
+      0,   0,   0,   0,   0,   0, 
+    128, 191,   0,   0,   0,   0, 
+     28,   0,   0,   6,  18,   0, 
+     16,   0,   1,   0,   0,   0, 
+     26, 128,  32,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     76,   0,   0,   3,  10,   0, 
+     16,   0,   1,   0,   0,   0, 
+      6,   0,   0,   3,   1,  64, 
+      0,   0,   0,   0,   0,   0, 
+     54,   0,   0,   6,  98,   0, 
+     16,   0,   0,   0,   0,   0, 
+    166,   8,  16, 128,  65,   0, 
+      0,   0,   0,   0,   0,   0, 
+     54,   0,   0,   5,  18,   0, 
+     16,   0,   0,   0,   0,   0, 
+      1,  64,   0,   0,   0,   0, 
+    128,  63,   2,   0,   0,   1, 
+      6,   0,   0,   3,   1,  64, 
+      0,   0,   1,   0,   0,   0, 
+     54,   0,   0,   5,  34,   0, 
+     16,   0,   0,   0,   0,   0, 
+      1,  64,   0,   0,   0,   0, 
+    128, 191,  54,   0,   0,   6, 
+    130,   0,  16,   0,   0,   0, 
+      0,   0,  42,   0,  16, 128, 
+     65,   0,   0,   0,   0,   0, 
+      0,   0,  54,   0,   0,   5, 
+    114,   0,  16,   0,   0,   0, 
+      0,   0, 214,   4,  16,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   1,   6,   0,   0,   3, 
+      1,  64,   0,   0,   2,   0, 
+      0,   0,  56,   0,   0,  10, 
+     82,   0,  16,   0,   0,   0, 
+      0,   0,   6,   2,  16,   0, 
+      0,   0,   0,   0,   2,  64, 
+      0,   0,   0,   0, 128,  63, 
+      0,   0,   0,   0,   0,   0, 
+    128, 191,   0,   0,   0,   0, 
+     54,   0,   0,   5,  34,   0, 
+     16,   0,   0,   0,   0,   0, 
+      1,  64,   0,   0,   0,   0, 
+    128, 191,   2,   0,   0,   1, 
+      6,   0,   0,   3,   1,  64, 
+      0,   0,   3,   0,   0,   0, 
+     54,   0,   0,   5,  34,   0, 
+     16,   0,   0,   0,   0,   0, 
+      1,  64,   0,   0,   0,   0, 
+    128,  63,   2,   0,   0,   1, 
+      6,   0,   0,   3,   1,  64, 
+      0,   0,   4,   0,   0,   0, 
+     56,   0,   0,  10,  50,   0, 
+     16,   0,   0,   0,   0,   0, 
+    134,   0,  16,   0,   0,   0, 
+      0,   0,   2,  64,   0,   0, 
+      0,   0, 128,  63,   0,   0, 
+    128, 191,   0,   0,   0,   0, 
+      0,   0,   0,   0,  54,   0, 
+      0,   5,  66,   0,  16,   0, 
+      0,   0,   0,   0,   1,  64, 
+      0,   0,   0,   0, 128,  63, 
+      2,   0,   0,   1,   6,   0, 
+      0,   3,   1,  64,   0,   0, 
+      5,   0,   0,   0,  54,   0, 
+      0,   6,  50,   0,  16,   0, 
+      0,   0,   0,   0, 134,   0, 
+     16, 128,  65,   0,   0,   0, 
+      0,   0,   0,   0,  54,   0, 
+      0,   5,  66,   0,  16,   0, 
+      0,   0,   0,   0,   1,  64, 
+      0,   0,   0,   0, 128, 191, 
+      2,   0,   0,   1,  10,   0, 
+      0,   1,  54,   0,   0,   8, 
+    114,   0,  16,   0,   0,   0, 
+      0,   0,   2,  64,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   1,  23,   0,   0,   1, 
+     86,   0,   0,   6, 130,   0, 
+     16,   0,   0,   0,   0,   0, 
+     10, 128,  32,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     72,   0,   0, 141, 130,   1, 
+      0, 128,  67,  85,  21,   0, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0,  70,   2,  16,   0, 
+      0,   0,   0,   0,  70, 126, 
+     16,   0,   0,   0,   0,   0, 
+      0,  96,  16,   0,   0,   0, 
+      0,   0,  58,   0,  16,   0, 
+      0,   0,   0,   0,  62,   0, 
+      0,   1,  83,  84,  65,  84, 
+    148,   0,   0,   0,  35,   0, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   7,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   8,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   8,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0
+};

+ 6135 - 0
src/gpu/d3d11/SDL_gpu_d3d11.c

@@ -0,0 +1,6135 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+         claim that you wrote the original software. If you use this software
+         in a product, an acknowledgment in the product documentation would be
+         appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+         misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_internal.h"
+
+#if SDL_GPU_D3D11
+
+#define D3D11_NO_HELPERS
+#define CINTERFACE
+#define COBJMACROS
+
+#include <d3d11.h>
+#include <d3d11_1.h>
+#include <dxgi.h>
+#include <dxgi1_6.h>
+#include <dxgidebug.h>
+
+#include "../SDL_sysgpu.h"
+
+// MinGW doesn't implement this yet
+#ifdef _WIN32
+#define HAVE_IDXGIINFOQUEUE
+#endif
+
+// Function Pointer Signatures
+typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY1)(const GUID *riid, void **ppFactory);
+typedef HRESULT(WINAPI *PFN_DXGI_GET_DEBUG_INTERFACE)(const GUID *riid, void **ppDebug);
+
+// IIDs (from https://www.magnumdb.com/)
+static const IID D3D_IID_IDXGIFactory1 = { 0x770aae78, 0xf26f, 0x4dba, { 0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87 } };
+static const IID D3D_IID_IDXGIFactory4 = { 0x1bc6ea02, 0xef36, 0x464f, { 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a } };
+static const IID D3D_IID_IDXGIFactory5 = { 0x7632e1f5, 0xee65, 0x4dca, { 0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d } };
+static const IID D3D_IID_IDXGIFactory6 = { 0xc1b6694f, 0xff09, 0x44a9, { 0xb0, 0x3c, 0x77, 0x90, 0x0a, 0x0a, 0x1d, 0x17 } };
+static const IID D3D_IID_IDXGIAdapter1 = { 0x29038f61, 0x3839, 0x4626, { 0x91, 0xfd, 0x08, 0x68, 0x79, 0x01, 0x1a, 0x05 } };
+static const IID D3D_IID_IDXGISwapChain3 = { 0x94d99bdb, 0xf1f8, 0x4ab0, { 0xb2, 0x36, 0x7d, 0xa0, 0x17, 0x0e, 0xda, 0xb1 } };
+static const IID D3D_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } };
+static const IID D3D_IID_ID3DUserDefinedAnnotation = { 0xb2daad8b, 0x03d4, 0x4dbf, { 0x95, 0xeb, 0x32, 0xab, 0x4b, 0x63, 0xd0, 0xab } };
+static const IID D3D_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } };
+static const IID D3D_IID_IDXGIDebug = { 0x119e7452, 0xde9e, 0x40fe, { 0x88, 0x06, 0x88, 0xf9, 0x0c, 0x12, 0xb4, 0x41 } };
+#ifdef HAVE_IDXGIINFOQUEUE
+static const IID D3D_IID_IDXGIInfoQueue = { 0xd67441c7, 0x672a, 0x476f, { 0x9e, 0x82, 0xcd, 0x55, 0xb4, 0x49, 0x49, 0xce } };
+#endif
+
+static const GUID D3D_IID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, { 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 } };
+static const GUID D3D_IID_DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x08 } };
+
+// Defines
+
+#if defined(_WIN32)
+#define D3D11_DLL     "d3d11.dll"
+#define DXGI_DLL      "dxgi.dll"
+#define DXGIDEBUG_DLL "dxgidebug.dll"
+#elif defined(__APPLE__)
+#define D3D11_DLL     "libdxvk_d3d11.0.dylib"
+#define DXGI_DLL      "libdxvk_dxgi.0.dylib"
+#define DXGIDEBUG_DLL "libdxvk_dxgidebug.0.dylib"
+#else
+#define D3D11_DLL     "libdxvk_d3d11.so.0"
+#define DXGI_DLL      "libdxvk_dxgi.so.0"
+#define DXGIDEBUG_DLL "libdxvk_dxgidebug.so.0"
+#endif
+
+#define D3D11_CREATE_DEVICE_FUNC      "D3D11CreateDevice"
+#define CREATE_DXGI_FACTORY1_FUNC     "CreateDXGIFactory1"
+#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface"
+#define WINDOW_PROPERTY_DATA          "SDL_GpuD3D11WindowPropertyData"
+
+#define SDL_GPU_SHADERSTAGE_COMPUTE 2
+
+#ifdef _WIN32
+#define HRESULT_FMT "(0x%08lX)"
+#else
+#define HRESULT_FMT "(0x%08X)"
+#endif
+
+// Built-in shaders, compiled with compile_shaders.bat
+
+#define g_FullscreenVert  D3D11_FullscreenVert
+#define g_BlitFrom2D      D3D11_BlitFrom2D
+#define g_BlitFrom2DArray D3D11_BlitFrom2DArray
+#define g_BlitFrom3D      D3D11_BlitFrom3D
+#define g_BlitFromCube    D3D11_BlitFromCube
+#include "D3D11_Blit.h"
+#undef g_FullscreenVert
+#undef g_BlitFrom2D
+#undef g_BlitFrom2DArray
+#undef g_BlitFrom3D
+#undef g_BlitFromCube
+
+// Macros
+
+#define ERROR_CHECK(msg)                                     \
+    if (FAILED(res)) {                                       \
+        D3D11_INTERNAL_LogError(renderer->device, msg, res); \
+    }
+
+#define ERROR_CHECK_RETURN(msg, ret)                         \
+    if (FAILED(res)) {                                       \
+        D3D11_INTERNAL_LogError(renderer->device, msg, res); \
+        return ret;                                          \
+    }
+
+#define TRACK_RESOURCE(resource, type, array, count, capacity) \
+    Uint32 i;                                                  \
+                                                               \
+    for (i = 0; i < commandBuffer->count; i += 1) {            \
+        if (commandBuffer->array[i] == resource) {             \
+            return;                                            \
+        }                                                      \
+    }                                                          \
+                                                               \
+    if (commandBuffer->count == commandBuffer->capacity) {     \
+        commandBuffer->capacity += 1;                          \
+        commandBuffer->array = SDL_realloc(                    \
+            commandBuffer->array,                              \
+            commandBuffer->capacity * sizeof(type));           \
+    }                                                          \
+    commandBuffer->array[commandBuffer->count] = resource;     \
+    commandBuffer->count += 1;                                 \
+    SDL_AtomicIncRef(&resource->referenceCount);
+
+// Forward Declarations
+
+static void D3D11_Wait(SDL_GpuRenderer *driverData);
+static void D3D11_UnclaimWindow(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window);
+static void D3D11_INTERNAL_DestroyBlitPipelines(SDL_GpuRenderer *driverData);
+
+// Conversions
+
+static SDL_GpuTextureFormat SwapchainCompositionToSDLTextureFormat[] = {
+    SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM,      // SDR
+    SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, // SDR_SRGB
+    SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT,  // HDR
+    SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM,   // HDR_ADVANCED
+};
+
+static DXGI_FORMAT SwapchainCompositionToTextureFormat[] = {
+    DXGI_FORMAT_B8G8R8A8_UNORM,                // SDR
+    DXGI_FORMAT_B8G8R8A8_UNORM, /* SDR_SRGB */ // NOTE: The RTV uses the sRGB format
+    DXGI_FORMAT_R16G16B16A16_FLOAT,            // HDR
+    DXGI_FORMAT_R10G10B10A2_UNORM,             // HDR_ADVANCED
+};
+
+static DXGI_COLOR_SPACE_TYPE SwapchainCompositionToColorSpace[] = {
+    DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709,   // SDR
+    DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709,   // SDR_SRGB
+    DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709,   // HDR
+    DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 // HDR_ADVANCED
+};
+
+static DXGI_FORMAT SDLToD3D11_TextureFormat[] = {
+    DXGI_FORMAT_R8G8B8A8_UNORM,       // R8G8B8A8_UNORM
+    DXGI_FORMAT_B8G8R8A8_UNORM,       // B8G8R8A8_UNORM
+    DXGI_FORMAT_B5G6R5_UNORM,         // B5G6R5_UNORM
+    DXGI_FORMAT_B5G5R5A1_UNORM,       // B5G5R5A1_UNORM
+    DXGI_FORMAT_B4G4R4A4_UNORM,       // B4G4R4A4_UNORM
+    DXGI_FORMAT_R10G10B10A2_UNORM,    // R10G10B10A2_UNORM
+    DXGI_FORMAT_R16G16_UNORM,         // R16G16_UNORM
+    DXGI_FORMAT_R16G16B16A16_UNORM,   // R16G16B16A16_UNORM
+    DXGI_FORMAT_R8_UNORM,             // R8_UNORM
+    DXGI_FORMAT_A8_UNORM,             // A8_UNORM
+    DXGI_FORMAT_BC1_UNORM,            // BC1_UNORM
+    DXGI_FORMAT_BC2_UNORM,            // BC2_UNORM
+    DXGI_FORMAT_BC3_UNORM,            // BC3_UNORM
+    DXGI_FORMAT_BC7_UNORM,            // BC7_UNORM
+    DXGI_FORMAT_R8G8_SNORM,           // R8G8_SNORM
+    DXGI_FORMAT_R8G8B8A8_SNORM,       // R8G8B8A8_SNORM
+    DXGI_FORMAT_R16_FLOAT,            // R16_FLOAT
+    DXGI_FORMAT_R16G16_FLOAT,         // R16G16_FLOAT
+    DXGI_FORMAT_R16G16B16A16_FLOAT,   // R16G16B16A16_FLOAT
+    DXGI_FORMAT_R32_FLOAT,            // R32_FLOAT
+    DXGI_FORMAT_R32G32_FLOAT,         // R32G32_FLOAT
+    DXGI_FORMAT_R32G32B32A32_FLOAT,   // R32G32B32A32_FLOAT
+    DXGI_FORMAT_R8_UINT,              // R8_UINT
+    DXGI_FORMAT_R8G8_UINT,            // R8G8_UINT
+    DXGI_FORMAT_R8G8B8A8_UINT,        // R8G8B8A8_UINT
+    DXGI_FORMAT_R16_UINT,             // R16_UINT
+    DXGI_FORMAT_R16G16_UINT,          // R16G16_UINT
+    DXGI_FORMAT_R16G16B16A16_UINT,    // R16G16B16A16_UINT
+    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  // R8G8B8A8_UNORM_SRGB
+    DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,  // B8G8R8A8_UNORM_SRGB
+    DXGI_FORMAT_BC3_UNORM_SRGB,       // BC3_UNORM_SRGB
+    DXGI_FORMAT_BC7_UNORM_SRGB,       // BC7_UNORM_SRGB
+    DXGI_FORMAT_D16_UNORM,            // D16_UNORM
+    DXGI_FORMAT_D24_UNORM_S8_UINT,    // D24_UNORM
+    DXGI_FORMAT_D32_FLOAT,            // D32_FLOAT
+    DXGI_FORMAT_D24_UNORM_S8_UINT,    // D24_UNORM_S8_UINT
+    DXGI_FORMAT_D32_FLOAT_S8X24_UINT, // D32_FLOAT_S8_UINT
+};
+SDL_COMPILE_TIME_ASSERT(SDLToD3D11_TextureFormat, SDL_arraysize(SDLToD3D11_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX);
+
+static DXGI_FORMAT SDLToD3D11_VertexFormat[] = {
+    DXGI_FORMAT_R32_SINT,           // INT
+    DXGI_FORMAT_R32G32_SINT,        // INT2
+    DXGI_FORMAT_R32G32B32_SINT,     // INT3
+    DXGI_FORMAT_R32G32B32A32_SINT,  // INT4
+    DXGI_FORMAT_R32_UINT,           // UINT
+    DXGI_FORMAT_R32G32_UINT,        // UINT2
+    DXGI_FORMAT_R32G32B32_UINT,     // UINT3
+    DXGI_FORMAT_R32G32B32A32_UINT,  // UINT4
+    DXGI_FORMAT_R32_FLOAT,          // FLOAT
+    DXGI_FORMAT_R32G32_FLOAT,       // FLOAT2
+    DXGI_FORMAT_R32G32B32_FLOAT,    // FLOAT3
+    DXGI_FORMAT_R32G32B32A32_FLOAT, // FLOAT4
+    DXGI_FORMAT_R8G8_SINT,          // BYTE2
+    DXGI_FORMAT_R8G8B8A8_SINT,      // BYTE4
+    DXGI_FORMAT_R8G8_UINT,          // UBYTE2
+    DXGI_FORMAT_R8G8B8A8_UINT,      // UBYTE4
+    DXGI_FORMAT_R8G8_SNORM,         // BYTE2_NORM
+    DXGI_FORMAT_R8G8B8A8_SNORM,     // BYTE4_NORM
+    DXGI_FORMAT_R8G8_UNORM,         // UBYTE2_NORM
+    DXGI_FORMAT_R8G8B8A8_UNORM,     // UBYTE4_NORM
+    DXGI_FORMAT_R16G16_SINT,        // SHORT2
+    DXGI_FORMAT_R16G16B16A16_SINT,  // SHORT4
+    DXGI_FORMAT_R16G16_UINT,        // USHORT2
+    DXGI_FORMAT_R16G16B16A16_UINT,  // USHORT4
+    DXGI_FORMAT_R16G16_SNORM,       // SHORT2_NORM
+    DXGI_FORMAT_R16G16B16A16_SNORM, // SHORT4_NORM
+    DXGI_FORMAT_R16G16_UNORM,       // USHORT2_NORM
+    DXGI_FORMAT_R16G16B16A16_UNORM, // USHORT4_NORM
+    DXGI_FORMAT_R16G16_FLOAT,       // HALF2
+    DXGI_FORMAT_R16G16B16A16_FLOAT  // HALF4
+};
+
+static Uint32 SDLToD3D11_SampleCount[] = {
+    1, // SDL_GPU_SAMPLECOUNT_1
+    2, // SDL_GPU_SAMPLECOUNT_2
+    4, // SDL_GPU_SAMPLECOUNT_4
+    8  // SDL_GPU_SAMPLECOUNT_8
+};
+
+static DXGI_FORMAT SDLToD3D11_IndexType[] = {
+    DXGI_FORMAT_R16_UINT, // 16BIT
+    DXGI_FORMAT_R32_UINT  // 32BIT
+};
+
+static D3D11_PRIMITIVE_TOPOLOGY SDLToD3D11_PrimitiveType[] = {
+    D3D_PRIMITIVE_TOPOLOGY_POINTLIST,    // POINTLIST
+    D3D_PRIMITIVE_TOPOLOGY_LINELIST,     // LINELIST
+    D3D_PRIMITIVE_TOPOLOGY_LINESTRIP,    // LINESTRIP
+    D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // TRIANGLELIST
+    D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP // TRIANGLESTRIP
+};
+
+static D3D11_CULL_MODE SDLToD3D11_CullMode[] = {
+    D3D11_CULL_NONE,  // NONE
+    D3D11_CULL_FRONT, // FRONT
+    D3D11_CULL_BACK   // BACK
+};
+
+static D3D11_BLEND SDLToD3D11_BlendFactor[] = {
+    D3D11_BLEND_ZERO,             // ZERO
+    D3D11_BLEND_ONE,              // ONE
+    D3D11_BLEND_SRC_COLOR,        // SRC_COLOR
+    D3D11_BLEND_INV_SRC_COLOR,    // ONE_MINUS_SRC_COLOR
+    D3D11_BLEND_DEST_COLOR,       // DST_COLOR
+    D3D11_BLEND_INV_DEST_COLOR,   // ONE_MINUS_DST_COLOR
+    D3D11_BLEND_SRC_ALPHA,        // SRC_ALPHA
+    D3D11_BLEND_INV_SRC_ALPHA,    // ONE_MINUS_SRC_ALPHA
+    D3D11_BLEND_DEST_ALPHA,       // DST_ALPHA
+    D3D11_BLEND_INV_DEST_ALPHA,   // ONE_MINUS_DST_ALPHA
+    D3D11_BLEND_BLEND_FACTOR,     // CONSTANT_COLOR
+    D3D11_BLEND_INV_BLEND_FACTOR, // ONE_MINUS_CONSTANT_COLOR
+    D3D11_BLEND_SRC_ALPHA_SAT,    // SRC_ALPHA_SATURATE
+};
+
+static D3D11_BLEND SDLToD3D11_BlendFactorAlpha[] = {
+    D3D11_BLEND_ZERO,             // ZERO
+    D3D11_BLEND_ONE,              // ONE
+    D3D11_BLEND_SRC_ALPHA,        // SRC_COLOR
+    D3D11_BLEND_INV_SRC_ALPHA,    // ONE_MINUS_SRC_COLOR
+    D3D11_BLEND_DEST_ALPHA,       // DST_COLOR
+    D3D11_BLEND_INV_DEST_ALPHA,   // ONE_MINUS_DST_COLOR
+    D3D11_BLEND_SRC_ALPHA,        // SRC_ALPHA
+    D3D11_BLEND_INV_SRC_ALPHA,    // ONE_MINUS_SRC_ALPHA
+    D3D11_BLEND_DEST_ALPHA,       // DST_ALPHA
+    D3D11_BLEND_INV_DEST_ALPHA,   // ONE_MINUS_DST_ALPHA
+    D3D11_BLEND_BLEND_FACTOR,     // CONSTANT_COLOR
+    D3D11_BLEND_INV_BLEND_FACTOR, // ONE_MINUS_CONSTANT_COLOR
+    D3D11_BLEND_SRC_ALPHA_SAT,    // SRC_ALPHA_SATURATE
+};
+
+static D3D11_BLEND_OP SDLToD3D11_BlendOp[] = {
+    D3D11_BLEND_OP_ADD,          // ADD
+    D3D11_BLEND_OP_SUBTRACT,     // SUBTRACT
+    D3D11_BLEND_OP_REV_SUBTRACT, // REVERSE_SUBTRACT
+    D3D11_BLEND_OP_MIN,          // MIN
+    D3D11_BLEND_OP_MAX           // MAX
+};
+
+static D3D11_COMPARISON_FUNC SDLToD3D11_CompareOp[] = {
+    D3D11_COMPARISON_NEVER,         // NEVER
+    D3D11_COMPARISON_LESS,          // LESS
+    D3D11_COMPARISON_EQUAL,         // EQUAL
+    D3D11_COMPARISON_LESS_EQUAL,    // LESS_OR_EQUAL
+    D3D11_COMPARISON_GREATER,       // GREATER
+    D3D11_COMPARISON_NOT_EQUAL,     // NOT_EQUAL
+    D3D11_COMPARISON_GREATER_EQUAL, // GREATER_OR_EQUAL
+    D3D11_COMPARISON_ALWAYS         // ALWAYS
+};
+
+static D3D11_STENCIL_OP SDLToD3D11_StencilOp[] = {
+    D3D11_STENCIL_OP_KEEP,     // KEEP
+    D3D11_STENCIL_OP_ZERO,     // ZERO
+    D3D11_STENCIL_OP_REPLACE,  // REPLACE
+    D3D11_STENCIL_OP_INCR_SAT, // INCREMENT_AND_CLAMP
+    D3D11_STENCIL_OP_DECR_SAT, // DECREMENT_AND_CLAMP
+    D3D11_STENCIL_OP_INVERT,   // INVERT
+    D3D11_STENCIL_OP_INCR,     // INCREMENT_AND_WRAP
+    D3D11_STENCIL_OP_DECR      // DECREMENT_AND_WRAP
+};
+
+static D3D11_INPUT_CLASSIFICATION SDLToD3D11_VertexInputRate[] = {
+    D3D11_INPUT_PER_VERTEX_DATA,  // VERTEX
+    D3D11_INPUT_PER_INSTANCE_DATA // INSTANCE
+};
+
+static D3D11_TEXTURE_ADDRESS_MODE SDLToD3D11_SamplerAddressMode[] = {
+    D3D11_TEXTURE_ADDRESS_WRAP,   // REPEAT
+    D3D11_TEXTURE_ADDRESS_MIRROR, // MIRRORED_REPEAT
+    D3D11_TEXTURE_ADDRESS_CLAMP   // CLAMP_TO_EDGE
+};
+
+static D3D11_FILTER SDLToD3D11_Filter(SDL_GpuSamplerCreateInfo *createInfo)
+{
+    if (createInfo->minFilter == SDL_GPU_FILTER_LINEAR) {
+        if (createInfo->magFilter == SDL_GPU_FILTER_LINEAR) {
+            if (createInfo->mipmapMode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) {
+                return D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+            } else {
+                return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
+            }
+        } else {
+            if (createInfo->mipmapMode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) {
+                return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR;
+            } else {
+                return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT;
+            }
+        }
+    } else {
+        if (createInfo->magFilter == SDL_GPU_FILTER_LINEAR) {
+            if (createInfo->mipmapMode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) {
+                return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR;
+            } else {
+                return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT;
+            }
+        } else {
+            if (createInfo->mipmapMode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) {
+                return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
+            } else {
+                return D3D11_FILTER_MIN_MAG_MIP_POINT;
+            }
+        }
+    }
+}
+
+// Structs
+
+typedef struct D3D11Texture D3D11Texture;
+
+typedef struct D3D11TextureContainer
+{
+    TextureCommonHeader header;
+
+    D3D11Texture *activeTexture;
+    SDL_bool canBeCycled;
+
+    Uint32 textureCapacity;
+    Uint32 textureCount;
+    D3D11Texture **textures;
+
+    char *debugName;
+} D3D11TextureContainer;
+
+typedef struct D3D11TextureSubresource
+{
+    D3D11Texture *parent;
+    Uint32 layer;
+    Uint32 level;
+    Uint32 depth; // total depth
+    Uint32 index;
+
+    // One RTV per depth slice
+    ID3D11RenderTargetView **colorTargetViews; // NULL if not a color target
+
+    ID3D11UnorderedAccessView *uav;                 // NULL if not a storage texture
+    ID3D11DepthStencilView *depthStencilTargetView; // NULL if not a depth stencil target
+
+    ID3D11Resource *msaaHandle;             // NULL if not using MSAA
+    ID3D11RenderTargetView *msaaTargetView; // NULL if not an MSAA color target
+} D3D11TextureSubresource;
+
+struct D3D11Texture
+{
+    D3D11TextureContainer *container;
+    Uint32 containerIndex;
+
+    ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */
+    ID3D11ShaderResourceView *shaderView;
+
+    D3D11TextureSubresource *subresources;
+    Uint32 subresourceCount; /* layerCount * levelCount */
+
+    SDL_AtomicInt referenceCount;
+};
+
+typedef struct D3D11Fence
+{
+    ID3D11Query *handle;
+    SDL_AtomicInt referenceCount;
+} D3D11Fence;
+
+typedef struct D3D11WindowData
+{
+    SDL_Window *window;
+    IDXGISwapChain *swapchain;
+    D3D11Texture texture;
+    D3D11TextureContainer textureContainer;
+    SDL_GpuPresentMode presentMode;
+    SDL_GpuSwapchainComposition swapchainComposition;
+    DXGI_FORMAT swapchainFormat;
+    DXGI_COLOR_SPACE_TYPE swapchainColorSpace;
+    D3D11Fence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
+    Uint32 frameCounter;
+} D3D11WindowData;
+
+typedef struct D3D11Shader
+{
+    ID3D11DeviceChild *handle; // ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader
+    void *bytecode;
+    size_t bytecodeSize;
+
+    Uint32 samplerCount;
+    Uint32 uniformBufferCount;
+    Uint32 storageBufferCount;
+    Uint32 storageTextureCount;
+} D3D11Shader;
+
+typedef struct D3D11GraphicsPipeline
+{
+    float blendConstants[4];
+    Sint32 numColorAttachments;
+    DXGI_FORMAT colorAttachmentFormats[MAX_COLOR_TARGET_BINDINGS];
+    ID3D11BlendState *colorAttachmentBlendState;
+
+    SDL_GpuMultisampleState multisampleState;
+
+    Uint8 hasDepthStencilAttachment;
+    DXGI_FORMAT depthStencilAttachmentFormat;
+    ID3D11DepthStencilState *depthStencilState;
+    Uint8 stencilRef;
+
+    SDL_GpuPrimitiveType primitiveType;
+    ID3D11RasterizerState *rasterizerState;
+
+    ID3D11VertexShader *vertexShader;
+    ID3D11PixelShader *fragmentShader;
+
+    ID3D11InputLayout *inputLayout;
+    Uint32 *vertexStrides;
+
+    Uint32 vertexSamplerCount;
+    Uint32 vertexUniformBufferCount;
+    Uint32 vertexStorageBufferCount;
+    Uint32 vertexStorageTextureCount;
+
+    Uint32 fragmentSamplerCount;
+    Uint32 fragmentUniformBufferCount;
+    Uint32 fragmentStorageBufferCount;
+    Uint32 fragmentStorageTextureCount;
+} D3D11GraphicsPipeline;
+
+typedef struct D3D11ComputePipeline
+{
+    ID3D11ComputeShader *computeShader;
+
+    Uint32 readOnlyStorageTextureCount;
+    Uint32 writeOnlyStorageTextureCount;
+    Uint32 readOnlyStorageBufferCount;
+    Uint32 writeOnlyStorageBufferCount;
+    Uint32 uniformBufferCount;
+} D3D11ComputePipeline;
+
+typedef struct D3D11Buffer
+{
+    ID3D11Buffer *handle;
+    ID3D11UnorderedAccessView *uav;
+    ID3D11ShaderResourceView *srv;
+    Uint32 size;
+    SDL_AtomicInt referenceCount;
+} D3D11Buffer;
+
+typedef struct D3D11BufferContainer
+{
+    D3D11Buffer *activeBuffer;
+
+    Uint32 bufferCapacity;
+    Uint32 bufferCount;
+    D3D11Buffer **buffers;
+
+    D3D11_BUFFER_DESC bufferDesc;
+
+    char *debugName;
+} D3D11BufferContainer;
+
+typedef struct D3D11BufferDownload
+{
+    ID3D11Buffer *stagingBuffer;
+    Uint32 dstOffset;
+    Uint32 size;
+} D3D11BufferDownload;
+
+typedef struct D3D11TextureDownload
+{
+    ID3D11Resource *stagingTexture;
+    Uint32 width;
+    Uint32 height;
+    Uint32 depth;
+    Uint32 bufferOffset;
+    Uint32 bytesPerRow;
+    Uint32 bytesPerDepthSlice;
+} D3D11TextureDownload;
+
+typedef struct D3D11TransferBuffer
+{
+    Uint8 *data;
+    Uint32 size;
+    SDL_AtomicInt referenceCount;
+
+    D3D11BufferDownload *bufferDownloads;
+    Uint32 bufferDownloadCount;
+    Uint32 bufferDownloadCapacity;
+
+    D3D11TextureDownload *textureDownloads;
+    Uint32 textureDownloadCount;
+    Uint32 textureDownloadCapacity;
+} D3D11TransferBuffer;
+
+typedef struct D3D11TransferBufferContainer
+{
+    D3D11TransferBuffer *activeBuffer;
+
+    /* These are all the buffers that have been used by this container.
+     * If the resource is bound and then updated with DISCARD, a new resource
+     * will be added to this list.
+     * These can be reused after they are submitted and command processing is complete.
+     */
+    Uint32 bufferCapacity;
+    Uint32 bufferCount;
+    D3D11TransferBuffer **buffers;
+} D3D11TransferBufferContainer;
+
+typedef struct D3D11UniformBuffer
+{
+    ID3D11Buffer *buffer;
+    void *mappedData;
+
+    Uint32 drawOffset;
+    Uint32 writeOffset;
+    Uint32 currentBlockSize;
+} D3D11UniformBuffer;
+
+typedef struct D3D11Renderer D3D11Renderer;
+
+typedef struct D3D11CommandBuffer
+{
+    CommandBufferCommonHeader common;
+    D3D11Renderer *renderer;
+
+    // Deferred Context
+    ID3D11DeviceContext1 *context;
+
+    // Presentation
+    D3D11WindowData **windowDatas;
+    Uint32 windowDataCount;
+    Uint32 windowDataCapacity;
+
+    // Render Pass
+    D3D11GraphicsPipeline *graphicsPipeline;
+
+    // Render Pass MSAA resolve
+    D3D11Texture *colorTargetResolveTexture[MAX_COLOR_TARGET_BINDINGS];
+    Uint32 colorTargetResolveSubresourceIndex[MAX_COLOR_TARGET_BINDINGS];
+    ID3D11Resource *colorTargetMsaaHandle[MAX_COLOR_TARGET_BINDINGS];
+    DXGI_FORMAT colorTargetMsaaFormat[MAX_COLOR_TARGET_BINDINGS];
+
+    // Compute Pass
+    D3D11ComputePipeline *computePipeline;
+
+    // Debug Annotation
+    ID3DUserDefinedAnnotation *annotation;
+
+    // Resource slot state
+
+    SDL_bool needVertexBufferBind;
+
+    SDL_bool needVertexSamplerBind;
+    SDL_bool needVertexResourceBind;
+    SDL_bool needVertexUniformBufferBind;
+
+    SDL_bool needFragmentSamplerBind;
+    SDL_bool needFragmentResourceBind;
+    SDL_bool needFragmentUniformBufferBind;
+
+    SDL_bool needComputeUAVBind;
+    SDL_bool needComputeSRVBind;
+    SDL_bool needComputeUniformBufferBind;
+
+    ID3D11Buffer *vertexBuffers[MAX_BUFFER_BINDINGS];
+    Uint32 vertexBufferOffsets[MAX_BUFFER_BINDINGS];
+    Uint32 vertexBufferCount;
+
+    ID3D11SamplerState *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    ID3D11ShaderResourceView *vertexShaderResourceViews[MAX_TEXTURE_SAMPLERS_PER_STAGE +
+                                                        MAX_STORAGE_BUFFERS_PER_STAGE +
+                                                        MAX_STORAGE_TEXTURES_PER_STAGE];
+
+    ID3D11SamplerState *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    ID3D11ShaderResourceView *fragmentShaderResourceViews[MAX_TEXTURE_SAMPLERS_PER_STAGE +
+                                                          MAX_STORAGE_BUFFERS_PER_STAGE +
+                                                          MAX_STORAGE_TEXTURES_PER_STAGE];
+
+    ID3D11ShaderResourceView *computeShaderResourceViews[MAX_STORAGE_TEXTURES_PER_STAGE +
+                                                         MAX_STORAGE_BUFFERS_PER_STAGE];
+    ID3D11UnorderedAccessView *computeUnorderedAccessViews[MAX_COMPUTE_WRITE_TEXTURES +
+                                                           MAX_COMPUTE_WRITE_BUFFERS];
+
+    // Uniform buffers
+    D3D11UniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+    D3D11UniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+    D3D11UniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+
+    // Fences
+    D3D11Fence *fence;
+    Uint8 autoReleaseFence;
+
+    // Reference Counting
+    D3D11Buffer **usedBuffers;
+    Uint32 usedBufferCount;
+    Uint32 usedBufferCapacity;
+
+    D3D11TransferBuffer **usedTransferBuffers;
+    Uint32 usedTransferBufferCount;
+    Uint32 usedTransferBufferCapacity;
+
+    D3D11Texture **usedTextures;
+    Uint32 usedTextureCount;
+    Uint32 usedTextureCapacity;
+
+    D3D11UniformBuffer **usedUniformBuffers;
+    Uint32 usedUniformBufferCount;
+    Uint32 usedUniformBufferCapacity;
+} D3D11CommandBuffer;
+
+typedef struct D3D11Sampler
+{
+    ID3D11SamplerState *handle;
+} D3D11Sampler;
+
+struct D3D11Renderer
+{
+    ID3D11Device1 *device;
+    ID3D11DeviceContext *immediateContext;
+    IDXGIFactory1 *factory;
+    IDXGIAdapter1 *adapter;
+    IDXGIDebug *dxgiDebug;
+#ifdef HAVE_IDXGIINFOQUEUE
+    IDXGIInfoQueue *dxgiInfoQueue;
+#endif
+
+    void *d3d11_dll;
+    void *dxgi_dll;
+    void *dxgidebug_dll;
+
+    Uint8 debugMode;
+    BOOL supportsTearing;
+    Uint8 supportsFlipDiscard;
+
+    SDL_iconv_t iconv;
+
+    // Blit
+    BlitPipelineCacheEntry blitPipelines[4];
+    SDL_GpuSampler *blitNearestSampler;
+    SDL_GpuSampler *blitLinearSampler;
+
+    // Resource Tracking
+    D3D11WindowData **claimedWindows;
+    Uint32 claimedWindowCount;
+    Uint32 claimedWindowCapacity;
+
+    D3D11CommandBuffer **availableCommandBuffers;
+    Uint32 availableCommandBufferCount;
+    Uint32 availableCommandBufferCapacity;
+
+    D3D11CommandBuffer **submittedCommandBuffers;
+    Uint32 submittedCommandBufferCount;
+    Uint32 submittedCommandBufferCapacity;
+
+    D3D11Fence **availableFences;
+    Uint32 availableFenceCount;
+    Uint32 availableFenceCapacity;
+
+    D3D11UniformBuffer **uniformBufferPool;
+    Uint32 uniformBufferPoolCount;
+    Uint32 uniformBufferPoolCapacity;
+
+    D3D11TransferBufferContainer **transferBufferContainersToDestroy;
+    Uint32 transferBufferContainersToDestroyCount;
+    Uint32 transferBufferContainersToDestroyCapacity;
+
+    D3D11BufferContainer **bufferContainersToDestroy;
+    Uint32 bufferContainersToDestroyCount;
+    Uint32 bufferContainersToDestroyCapacity;
+
+    D3D11TextureContainer **textureContainersToDestroy;
+    Uint32 textureContainersToDestroyCount;
+    Uint32 textureContainersToDestroyCapacity;
+
+    SDL_Mutex *contextLock;
+    SDL_Mutex *acquireCommandBufferLock;
+    SDL_Mutex *acquireUniformBufferLock;
+    SDL_Mutex *fenceLock;
+    SDL_Mutex *windowLock;
+};
+
+// Null arrays for resetting shader resource slots
+
+ID3D11RenderTargetView *nullRTVs[MAX_COLOR_TARGET_BINDINGS];
+
+ID3D11ShaderResourceView *nullSRVs[MAX_TEXTURE_SAMPLERS_PER_STAGE +
+                                   MAX_STORAGE_TEXTURES_PER_STAGE +
+                                   MAX_STORAGE_BUFFERS_PER_STAGE];
+
+ID3D11SamplerState *nullSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+
+ID3D11UnorderedAccessView *nullUAVs[MAX_COMPUTE_WRITE_TEXTURES +
+                                    MAX_COMPUTE_WRITE_BUFFERS];
+
+// Logging
+
+static void D3D11_INTERNAL_LogError(
+    ID3D11Device1 *device,
+    const char *msg,
+    HRESULT res)
+{
+#define MAX_ERROR_LEN 1024 // FIXME: Arbitrary!
+
+    // Buffer for text, ensure space for \0 terminator after buffer
+    char wszMsgBuff[MAX_ERROR_LEN + 1];
+    DWORD dwChars; // Number of chars returned.
+
+    if (res == DXGI_ERROR_DEVICE_REMOVED) {
+        res = ID3D11Device_GetDeviceRemovedReason(device);
+    }
+
+    // Try to get the message from the system errors.
+#ifdef _WIN32
+    dwChars = FormatMessageA(
+        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+        NULL,
+        res,
+        0,
+        wszMsgBuff,
+        MAX_ERROR_LEN,
+        NULL);
+#else
+    // FIXME: Do we have error strings in dxvk-native? -flibit
+    dwChars = 0;
+#endif
+
+    // No message? Screw it, just post the code.
+    if (dwChars == 0) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: " HRESULT_FMT, msg, res);
+        return;
+    }
+
+    // Ensure valid range
+    dwChars = SDL_min(dwChars, MAX_ERROR_LEN);
+
+    // Trim whitespace from tail of message
+    while (dwChars > 0) {
+        if (wszMsgBuff[dwChars - 1] <= ' ') {
+            dwChars--;
+        } else {
+            break;
+        }
+    }
+
+    // Ensure null-terminated string
+    wszMsgBuff[dwChars] = '\0';
+
+    SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res);
+}
+
+// Helper Functions
+
+static inline Uint32 D3D11_INTERNAL_CalcSubresource(
+    Uint32 mipLevel,
+    Uint32 layer,
+    Uint32 numLevels)
+{
+    return mipLevel + (layer * numLevels);
+}
+
+static inline Uint32 D3D11_INTERNAL_NextHighestAlignment(
+    Uint32 n,
+    Uint32 align)
+{
+    return align * ((n + align - 1) / align);
+}
+
+static DXGI_FORMAT D3D11_INTERNAL_GetTypelessFormat(
+    DXGI_FORMAT typedFormat)
+{
+    switch (typedFormat) {
+    case DXGI_FORMAT_D16_UNORM:
+        return DXGI_FORMAT_R16_TYPELESS;
+    case DXGI_FORMAT_D32_FLOAT:
+        return DXGI_FORMAT_R32_TYPELESS;
+    case DXGI_FORMAT_D24_UNORM_S8_UINT:
+        return DXGI_FORMAT_R24G8_TYPELESS;
+    case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+        return DXGI_FORMAT_R32G8X24_TYPELESS;
+    default:
+        return DXGI_FORMAT_UNKNOWN;
+    }
+}
+
+static DXGI_FORMAT D3D11_INTERNAL_GetSampleableFormat(
+    DXGI_FORMAT format)
+{
+    switch (format) {
+    case DXGI_FORMAT_R16_TYPELESS:
+        return DXGI_FORMAT_R16_UNORM;
+    case DXGI_FORMAT_R32_TYPELESS:
+        return DXGI_FORMAT_R32_FLOAT;
+    case DXGI_FORMAT_R24G8_TYPELESS:
+        return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
+    case DXGI_FORMAT_R32G8X24_TYPELESS:
+        return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS;
+    default:
+        return format;
+    }
+}
+
+// Quit
+
+static void D3D11_INTERNAL_DestroyBufferContainer(
+    D3D11BufferContainer *container)
+{
+    for (Uint32 i = 0; i < container->bufferCount; i += 1) {
+        D3D11Buffer *d3d11Buffer = container->buffers[i];
+
+        if (d3d11Buffer->uav != NULL) {
+            ID3D11UnorderedAccessView_Release(d3d11Buffer->uav);
+        }
+
+        if (d3d11Buffer->srv != NULL) {
+            ID3D11ShaderResourceView_Release(d3d11Buffer->srv);
+        }
+
+        ID3D11Buffer_Release(d3d11Buffer->handle);
+
+        SDL_free(d3d11Buffer);
+    }
+
+    SDL_free(container->buffers);
+    SDL_free(container);
+}
+
+static void D3D11_DestroyDevice(
+    SDL_GpuDevice *device)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)device->driverData;
+
+    // Flush any remaining GPU work...
+    D3D11_Wait(device->driverData);
+
+    // Release the window data
+    for (Sint32 i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) {
+        D3D11_UnclaimWindow(device->driverData, renderer->claimedWindows[i]->window);
+    }
+    SDL_free(renderer->claimedWindows);
+
+    // Release the blit resources
+    D3D11_INTERNAL_DestroyBlitPipelines(device->driverData);
+
+    // Release UBOs
+    for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
+        ID3D11Buffer_Release(renderer->uniformBufferPool[i]->buffer);
+        SDL_free(renderer->uniformBufferPool[i]);
+    }
+    SDL_free(renderer->uniformBufferPool);
+
+    // Release command buffer infrastructure
+    for (Uint32 i = 0; i < renderer->availableCommandBufferCount; i += 1) {
+        D3D11CommandBuffer *commandBuffer = renderer->availableCommandBuffers[i];
+        if (commandBuffer->annotation) {
+            ID3DUserDefinedAnnotation_Release(commandBuffer->annotation);
+        }
+        ID3D11DeviceContext_Release(commandBuffer->context);
+        SDL_free(commandBuffer->usedBuffers);
+        SDL_free(commandBuffer->usedTransferBuffers);
+        SDL_free(commandBuffer);
+    }
+    SDL_free(renderer->availableCommandBuffers);
+    SDL_free(renderer->submittedCommandBuffers);
+
+    // Release fence infrastructure
+    for (Uint32 i = 0; i < renderer->availableFenceCount; i += 1) {
+        D3D11Fence *fence = renderer->availableFences[i];
+        ID3D11Query_Release(fence->handle);
+        SDL_free(fence);
+    }
+    SDL_free(renderer->availableFences);
+
+    // Release the iconv, if applicable
+    if (renderer->iconv != NULL) {
+        SDL_iconv_close(renderer->iconv);
+    }
+
+    // Release the mutexes
+    SDL_DestroyMutex(renderer->acquireCommandBufferLock);
+    SDL_DestroyMutex(renderer->acquireUniformBufferLock);
+    SDL_DestroyMutex(renderer->contextLock);
+    SDL_DestroyMutex(renderer->fenceLock);
+    SDL_DestroyMutex(renderer->windowLock);
+
+    // Release the device and associated objects
+    ID3D11DeviceContext_Release(renderer->immediateContext);
+    ID3D11Device_Release(renderer->device);
+    IDXGIAdapter_Release(renderer->adapter);
+    IDXGIFactory_Release(renderer->factory);
+
+    // Report leaks and clean up debug objects
+    if (renderer->dxgiDebug) {
+        IDXGIDebug_ReportLiveObjects(
+            renderer->dxgiDebug,
+            D3D_IID_DXGI_DEBUG_ALL,
+            DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL);
+        IDXGIDebug_Release(renderer->dxgiDebug);
+    }
+
+#ifdef HAVE_IDXGIINFOQUEUE
+    if (renderer->dxgiInfoQueue) {
+        IDXGIInfoQueue_Release(renderer->dxgiInfoQueue);
+    }
+#endif
+
+    // Release the DLLs
+    SDL_UnloadObject(renderer->d3d11_dll);
+    SDL_UnloadObject(renderer->dxgi_dll);
+    if (renderer->dxgidebug_dll) {
+        SDL_UnloadObject(renderer->dxgidebug_dll);
+    }
+
+    // Free the primary structures
+    SDL_free(renderer);
+    SDL_free(device);
+}
+
+// Resource tracking
+
+static void D3D11_INTERNAL_TrackBuffer(
+    D3D11CommandBuffer *commandBuffer,
+    D3D11Buffer *buffer)
+{
+    TRACK_RESOURCE(
+        buffer,
+        D3D11Buffer *,
+        usedBuffers,
+        usedBufferCount,
+        usedBufferCapacity);
+}
+
+static void D3D11_INTERNAL_TrackTransferBuffer(
+    D3D11CommandBuffer *commandBuffer,
+    D3D11TransferBuffer *buffer)
+{
+    TRACK_RESOURCE(
+        buffer,
+        D3D11TransferBuffer *,
+        usedTransferBuffers,
+        usedTransferBufferCount,
+        usedTransferBufferCapacity);
+}
+
+static void D3D11_INTERNAL_TrackTexture(
+    D3D11CommandBuffer *commandBuffer,
+    D3D11Texture *texture)
+{
+    TRACK_RESOURCE(
+        texture,
+        D3D11Texture *,
+        usedTextures,
+        usedTextureCount,
+        usedTextureCapacity);
+}
+
+static void D3D11_INTERNAL_TrackUniformBuffer(
+    D3D11CommandBuffer *commandBuffer,
+    D3D11UniformBuffer *uniformBuffer)
+{
+    Uint32 i;
+    for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
+        if (commandBuffer->usedUniformBuffers[i] == uniformBuffer) {
+            return;
+        }
+    }
+
+    if (commandBuffer->usedUniformBufferCount == commandBuffer->usedUniformBufferCapacity) {
+        commandBuffer->usedUniformBufferCapacity += 1;
+        commandBuffer->usedUniformBuffers = SDL_realloc(
+            commandBuffer->usedUniformBuffers,
+            commandBuffer->usedUniformBufferCapacity * sizeof(D3D11UniformBuffer *));
+    }
+
+    commandBuffer->usedUniformBuffers[commandBuffer->usedUniformBufferCount] = uniformBuffer;
+    commandBuffer->usedUniformBufferCount += 1;
+}
+
+// Disposal
+
+static void D3D11_INTERNAL_DestroyTexture(D3D11Texture *d3d11Texture)
+{
+    if (d3d11Texture->shaderView) {
+        ID3D11ShaderResourceView_Release(d3d11Texture->shaderView);
+    }
+
+    for (Uint32 subresourceIndex = 0; subresourceIndex < d3d11Texture->subresourceCount; subresourceIndex += 1) {
+        if (d3d11Texture->subresources[subresourceIndex].msaaHandle != NULL) {
+            ID3D11Resource_Release(d3d11Texture->subresources[subresourceIndex].msaaHandle);
+        }
+
+        if (d3d11Texture->subresources[subresourceIndex].msaaTargetView != NULL) {
+            ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].msaaTargetView);
+        }
+
+        if (d3d11Texture->subresources[subresourceIndex].colorTargetViews != NULL) {
+            for (Uint32 depthIndex = 0; depthIndex < d3d11Texture->subresources[subresourceIndex].depth; depthIndex += 1) {
+                ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].colorTargetViews[depthIndex]);
+            }
+            SDL_free(d3d11Texture->subresources[subresourceIndex].colorTargetViews);
+        }
+
+        if (d3d11Texture->subresources[subresourceIndex].depthStencilTargetView != NULL) {
+            ID3D11DepthStencilView_Release(d3d11Texture->subresources[subresourceIndex].depthStencilTargetView);
+        }
+
+        if (d3d11Texture->subresources[subresourceIndex].uav != NULL) {
+            ID3D11UnorderedAccessView_Release(d3d11Texture->subresources[subresourceIndex].uav);
+        }
+    }
+    SDL_free(d3d11Texture->subresources);
+
+    ID3D11Resource_Release(d3d11Texture->handle);
+}
+
+static void D3D11_INTERNAL_DestroyTextureContainer(
+    D3D11TextureContainer *container)
+{
+    for (Uint32 i = 0; i < container->textureCount; i += 1) {
+        D3D11_INTERNAL_DestroyTexture(container->textures[i]);
+    }
+
+    SDL_free(container->textures);
+    SDL_free(container);
+}
+
+static void D3D11_ReleaseTexture(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTexture *texture)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11TextureContainer *container = (D3D11TextureContainer *)texture;
+
+    SDL_LockMutex(renderer->contextLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->textureContainersToDestroy,
+        D3D11TextureContainer *,
+        renderer->textureContainersToDestroyCount + 1,
+        renderer->textureContainersToDestroyCapacity,
+        renderer->textureContainersToDestroyCapacity + 1);
+
+    renderer->textureContainersToDestroy[renderer->textureContainersToDestroyCount] = container;
+    renderer->textureContainersToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->contextLock);
+}
+
+static void D3D11_ReleaseSampler(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuSampler *sampler)
+{
+    (void)driverData; // used by other backends
+    D3D11Sampler *d3d11Sampler = (D3D11Sampler *)sampler;
+    ID3D11SamplerState_Release(d3d11Sampler->handle);
+    SDL_free(d3d11Sampler);
+}
+
+static void D3D11_ReleaseBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBuffer *buffer)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11BufferContainer *container = (D3D11BufferContainer *)buffer;
+
+    SDL_LockMutex(renderer->contextLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->bufferContainersToDestroy,
+        D3D11BufferContainer *,
+        renderer->bufferContainersToDestroyCount + 1,
+        renderer->bufferContainersToDestroyCapacity,
+        renderer->bufferContainersToDestroyCapacity + 1);
+
+    renderer->bufferContainersToDestroy[renderer->bufferContainersToDestroyCount] = container;
+    renderer->bufferContainersToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->contextLock);
+}
+
+static void D3D11_ReleaseTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+
+    SDL_LockMutex(renderer->contextLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->transferBufferContainersToDestroy,
+        D3D11TransferBufferContainer *,
+        renderer->transferBufferContainersToDestroyCount + 1,
+        renderer->transferBufferContainersToDestroyCapacity,
+        renderer->transferBufferContainersToDestroyCapacity + 1);
+
+    renderer->transferBufferContainersToDestroy[renderer->transferBufferContainersToDestroyCount] = (D3D11TransferBufferContainer *)transferBuffer;
+    renderer->transferBufferContainersToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->contextLock);
+}
+
+static void D3D11_INTERNAL_DestroyTransferBufferContainer(
+    D3D11TransferBufferContainer *transferBufferContainer)
+{
+    for (Uint32 i = 0; i < transferBufferContainer->bufferCount; i += 1) {
+        if (transferBufferContainer->buffers[i]->bufferDownloadCount > 0) {
+            SDL_free(transferBufferContainer->buffers[i]->bufferDownloads);
+        }
+        if (transferBufferContainer->buffers[i]->textureDownloadCount > 0) {
+            SDL_free(transferBufferContainer->buffers[i]->textureDownloads);
+        }
+        SDL_free(transferBufferContainer->buffers[i]->data);
+        SDL_free(transferBufferContainer->buffers[i]);
+    }
+    SDL_free(transferBufferContainer->buffers);
+}
+
+static void D3D11_ReleaseShader(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuShader *shader)
+{
+    (void)driverData; // used by other backends
+    D3D11Shader *d3dShader = (D3D11Shader *)shader;
+    ID3D11DeviceChild_Release(d3dShader->handle);
+    if (d3dShader->bytecode) {
+        SDL_free(d3dShader->bytecode);
+    }
+    SDL_free(d3dShader);
+}
+
+static void D3D11_ReleaseComputePipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuComputePipeline *computePipeline)
+{
+    D3D11ComputePipeline *d3d11ComputePipeline = (D3D11ComputePipeline *)computePipeline;
+
+    ID3D11ComputeShader_Release(d3d11ComputePipeline->computeShader);
+
+    SDL_free(d3d11ComputePipeline);
+}
+
+static void D3D11_ReleaseGraphicsPipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuGraphicsPipeline *graphicsPipeline)
+{
+    (void)driverData; // used by other backends
+    D3D11GraphicsPipeline *d3d11GraphicsPipeline = (D3D11GraphicsPipeline *)graphicsPipeline;
+
+    ID3D11BlendState_Release(d3d11GraphicsPipeline->colorAttachmentBlendState);
+    ID3D11DepthStencilState_Release(d3d11GraphicsPipeline->depthStencilState);
+    ID3D11RasterizerState_Release(d3d11GraphicsPipeline->rasterizerState);
+
+    if (d3d11GraphicsPipeline->inputLayout) {
+        ID3D11InputLayout_Release(d3d11GraphicsPipeline->inputLayout);
+    }
+    if (d3d11GraphicsPipeline->vertexStrides) {
+        SDL_free(d3d11GraphicsPipeline->vertexStrides);
+    }
+
+    ID3D11VertexShader_Release(d3d11GraphicsPipeline->vertexShader);
+    ID3D11PixelShader_Release(d3d11GraphicsPipeline->fragmentShader);
+
+    SDL_free(d3d11GraphicsPipeline);
+}
+
+// State Creation
+
+static ID3D11BlendState *D3D11_INTERNAL_FetchBlendState(
+    D3D11Renderer *renderer,
+    Uint32 numColorAttachments,
+    SDL_GpuColorAttachmentDescription *colorAttachments)
+{
+    ID3D11BlendState *result;
+    D3D11_BLEND_DESC blendDesc;
+    HRESULT res;
+
+    /* Create a new blend state.
+     * The spec says the driver will not create duplicate states, so there's no need to cache.
+     */
+    SDL_zero(blendDesc); // needed for any unused RT entries
+
+    blendDesc.AlphaToCoverageEnable = FALSE;
+    blendDesc.IndependentBlendEnable = TRUE;
+
+    for (Uint32 i = 0; i < numColorAttachments; i += 1) {
+        blendDesc.RenderTarget[i].BlendEnable = colorAttachments[i].blendState.blendEnable;
+        blendDesc.RenderTarget[i].BlendOp = SDLToD3D11_BlendOp[colorAttachments[i].blendState.colorBlendOp];
+        blendDesc.RenderTarget[i].BlendOpAlpha = SDLToD3D11_BlendOp[colorAttachments[i].blendState.alphaBlendOp];
+        blendDesc.RenderTarget[i].DestBlend = SDLToD3D11_BlendFactor[colorAttachments[i].blendState.dstColorBlendFactor];
+        blendDesc.RenderTarget[i].DestBlendAlpha = SDLToD3D11_BlendFactorAlpha[colorAttachments[i].blendState.dstAlphaBlendFactor];
+        blendDesc.RenderTarget[i].RenderTargetWriteMask = colorAttachments[i].blendState.colorWriteMask;
+        blendDesc.RenderTarget[i].SrcBlend = SDLToD3D11_BlendFactor[colorAttachments[i].blendState.srcColorBlendFactor];
+        blendDesc.RenderTarget[i].SrcBlendAlpha = SDLToD3D11_BlendFactorAlpha[colorAttachments[i].blendState.srcAlphaBlendFactor];
+    }
+
+    res = ID3D11Device_CreateBlendState(
+        renderer->device,
+        &blendDesc,
+        &result);
+    ERROR_CHECK_RETURN("Could not create blend state", NULL);
+
+    return result;
+}
+
+static ID3D11DepthStencilState *D3D11_INTERNAL_FetchDepthStencilState(
+    D3D11Renderer *renderer,
+    SDL_GpuDepthStencilState depthStencilState)
+{
+    ID3D11DepthStencilState *result;
+    D3D11_DEPTH_STENCIL_DESC dsDesc;
+    HRESULT res;
+
+    /* Create a new depth-stencil state.
+     * The spec says the driver will not create duplicate states, so there's no need to cache.
+     */
+    dsDesc.DepthEnable = depthStencilState.depthTestEnable;
+    dsDesc.StencilEnable = depthStencilState.stencilTestEnable;
+    dsDesc.DepthFunc = SDLToD3D11_CompareOp[depthStencilState.compareOp];
+    dsDesc.DepthWriteMask = (depthStencilState.depthWriteEnable ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO);
+
+    dsDesc.BackFace.StencilFunc = SDLToD3D11_CompareOp[depthStencilState.backStencilState.compareOp];
+    dsDesc.BackFace.StencilDepthFailOp = SDLToD3D11_StencilOp[depthStencilState.backStencilState.depthFailOp];
+    dsDesc.BackFace.StencilFailOp = SDLToD3D11_StencilOp[depthStencilState.backStencilState.failOp];
+    dsDesc.BackFace.StencilPassOp = SDLToD3D11_StencilOp[depthStencilState.backStencilState.passOp];
+
+    dsDesc.FrontFace.StencilFunc = SDLToD3D11_CompareOp[depthStencilState.frontStencilState.compareOp];
+    dsDesc.FrontFace.StencilDepthFailOp = SDLToD3D11_StencilOp[depthStencilState.frontStencilState.depthFailOp];
+    dsDesc.FrontFace.StencilFailOp = SDLToD3D11_StencilOp[depthStencilState.frontStencilState.failOp];
+    dsDesc.FrontFace.StencilPassOp = SDLToD3D11_StencilOp[depthStencilState.frontStencilState.passOp];
+
+    dsDesc.StencilReadMask = depthStencilState.compareMask;
+    dsDesc.StencilWriteMask = depthStencilState.writeMask;
+
+    res = ID3D11Device_CreateDepthStencilState(
+        renderer->device,
+        &dsDesc,
+        &result);
+    ERROR_CHECK_RETURN("Could not create depth-stencil state", NULL);
+
+    return result;
+}
+
+static ID3D11RasterizerState *D3D11_INTERNAL_FetchRasterizerState(
+    D3D11Renderer *renderer,
+    SDL_GpuRasterizerState rasterizerState)
+{
+    ID3D11RasterizerState *result;
+    D3D11_RASTERIZER_DESC rasterizerDesc;
+    HRESULT res;
+
+    /* Create a new rasterizer state.
+     * The spec says the driver will not create duplicate states, so there's no need to cache.
+     */
+    rasterizerDesc.AntialiasedLineEnable = FALSE;
+    rasterizerDesc.CullMode = SDLToD3D11_CullMode[rasterizerState.cullMode];
+    rasterizerDesc.DepthBias = SDL_lroundf(rasterizerState.depthBiasConstantFactor);
+    rasterizerDesc.DepthBiasClamp = rasterizerState.depthBiasClamp;
+    rasterizerDesc.DepthClipEnable = TRUE;
+    rasterizerDesc.FillMode = (rasterizerState.fillMode == SDL_GPU_FILLMODE_FILL) ? D3D11_FILL_SOLID : D3D11_FILL_WIREFRAME;
+    rasterizerDesc.FrontCounterClockwise = (rasterizerState.frontFace == SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE);
+    rasterizerDesc.MultisampleEnable = TRUE; // only applies to MSAA render targets
+    rasterizerDesc.ScissorEnable = TRUE;
+    rasterizerDesc.SlopeScaledDepthBias = rasterizerState.depthBiasSlopeFactor;
+
+    res = ID3D11Device_CreateRasterizerState(
+        renderer->device,
+        &rasterizerDesc,
+        &result);
+    ERROR_CHECK_RETURN("Could not create rasterizer state", NULL);
+
+    return result;
+}
+
+static Uint32 D3D11_INTERNAL_FindIndexOfVertexBinding(
+    Uint32 targetBinding,
+    const SDL_GpuVertexBinding *bindings,
+    Uint32 numBindings)
+{
+    for (Uint32 i = 0; i < numBindings; i += 1) {
+        if (bindings[i].binding == targetBinding) {
+            return i;
+        }
+    }
+
+    SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not find vertex binding %u!", targetBinding);
+    return 0;
+}
+
+static ID3D11InputLayout *D3D11_INTERNAL_FetchInputLayout(
+    D3D11Renderer *renderer,
+    SDL_GpuVertexInputState inputState,
+    void *shaderBytes,
+    size_t shaderByteLength)
+{
+    ID3D11InputLayout *result = NULL;
+    D3D11_INPUT_ELEMENT_DESC *elementDescs;
+    Uint32 bindingIndex;
+    HRESULT res;
+
+    // Don't bother creating/fetching an input layout if there are no attributes.
+    if (inputState.vertexAttributeCount == 0) {
+        return NULL;
+    }
+
+    // Allocate an array of vertex elements
+    elementDescs = SDL_stack_alloc(
+        D3D11_INPUT_ELEMENT_DESC,
+        inputState.vertexAttributeCount);
+
+    // Create the array of input elements
+    for (Uint32 i = 0; i < inputState.vertexAttributeCount; i += 1) {
+        elementDescs[i].AlignedByteOffset = inputState.vertexAttributes[i].offset;
+        elementDescs[i].Format = SDLToD3D11_VertexFormat[inputState.vertexAttributes[i].format];
+        elementDescs[i].InputSlot = inputState.vertexAttributes[i].binding;
+
+        bindingIndex = D3D11_INTERNAL_FindIndexOfVertexBinding(
+            elementDescs[i].InputSlot,
+            inputState.vertexBindings,
+            inputState.vertexBindingCount);
+        elementDescs[i].InputSlotClass = SDLToD3D11_VertexInputRate[inputState.vertexBindings[bindingIndex].inputRate];
+        // The spec requires this to be 0 for per-vertex data
+        elementDescs[i].InstanceDataStepRate = (inputState.vertexBindings[bindingIndex].inputRate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) ? inputState.vertexBindings[bindingIndex].instanceStepRate : 0;
+
+        elementDescs[i].SemanticIndex = inputState.vertexAttributes[i].location;
+        elementDescs[i].SemanticName = "TEXCOORD";
+    }
+
+    res = ID3D11Device_CreateInputLayout(
+        renderer->device,
+        elementDescs,
+        inputState.vertexAttributeCount,
+        shaderBytes,
+        shaderByteLength,
+        &result);
+    if (FAILED(res)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not create input layout! Error: " HRESULT_FMT, res);
+        SDL_stack_free(elementDescs);
+        return NULL;
+    }
+
+    /* FIXME:
+     * These are not cached by the driver! Should we cache them, or allow duplicates?
+     * If we have one input layout per graphics pipeline maybe that wouldn't be so bad...?
+     */
+
+    SDL_stack_free(elementDescs);
+    return result;
+}
+
+// Pipeline Creation
+
+static ID3D11DeviceChild *D3D11_INTERNAL_CreateID3D11Shader(
+    D3D11Renderer *renderer,
+    Uint32 stage,
+    const Uint8 *code,
+    size_t codeSize,
+    const char *entryPointName,
+    void **pBytecode,
+    size_t *pBytecodeSize)
+{
+    ID3D11DeviceChild *handle = NULL;
+    HRESULT res;
+
+    // Create the shader from the byte blob
+    if (stage == SDL_GPU_SHADERSTAGE_VERTEX) {
+        res = ID3D11Device_CreateVertexShader(
+            renderer->device,
+            code,
+            codeSize,
+            NULL,
+            (ID3D11VertexShader **)&handle);
+        if (FAILED(res)) {
+            D3D11_INTERNAL_LogError(renderer->device, "Could not create vertex shader", res);
+            return NULL;
+        }
+    } else if (stage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
+        res = ID3D11Device_CreatePixelShader(
+            renderer->device,
+            code,
+            codeSize,
+            NULL,
+            (ID3D11PixelShader **)&handle);
+        if (FAILED(res)) {
+            D3D11_INTERNAL_LogError(renderer->device, "Could not create pixel shader", res);
+            return NULL;
+        }
+    } else if (stage == SDL_GPU_SHADERSTAGE_COMPUTE) {
+        res = ID3D11Device_CreateComputeShader(
+            renderer->device,
+            code,
+            codeSize,
+            NULL,
+            (ID3D11ComputeShader **)&handle);
+        if (FAILED(res)) {
+            D3D11_INTERNAL_LogError(renderer->device, "Could not create compute shader", res);
+            return NULL;
+        }
+    }
+
+    if (pBytecode != NULL) {
+        *pBytecode = SDL_malloc(codeSize);
+        SDL_memcpy(*pBytecode, code, codeSize);
+        *pBytecodeSize = codeSize;
+    }
+
+    return handle;
+}
+
+static SDL_GpuComputePipeline *D3D11_CreateComputePipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuComputePipelineCreateInfo *pipelineCreateInfo)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    ID3D11ComputeShader *shader;
+    D3D11ComputePipeline *pipeline;
+
+    shader = (ID3D11ComputeShader *)D3D11_INTERNAL_CreateID3D11Shader(
+        renderer,
+        SDL_GPU_SHADERSTAGE_COMPUTE,
+        pipelineCreateInfo->code,
+        pipelineCreateInfo->codeSize,
+        pipelineCreateInfo->entryPointName,
+        NULL,
+        NULL);
+    if (shader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create compute pipeline!");
+        return NULL;
+    }
+
+    pipeline = SDL_malloc(sizeof(D3D11ComputePipeline));
+    pipeline->computeShader = shader;
+    pipeline->readOnlyStorageTextureCount = pipelineCreateInfo->readOnlyStorageTextureCount;
+    pipeline->writeOnlyStorageTextureCount = pipelineCreateInfo->writeOnlyStorageTextureCount;
+    pipeline->readOnlyStorageBufferCount = pipelineCreateInfo->readOnlyStorageBufferCount;
+    pipeline->writeOnlyStorageBufferCount = pipelineCreateInfo->writeOnlyStorageBufferCount;
+    pipeline->uniformBufferCount = pipelineCreateInfo->uniformBufferCount;
+    // thread counts are ignored in d3d11
+
+    return (SDL_GpuComputePipeline *)pipeline;
+}
+
+static SDL_GpuGraphicsPipeline *D3D11_CreateGraphicsPipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuGraphicsPipelineCreateInfo *pipelineCreateInfo)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11Shader *vertShader = (D3D11Shader *)pipelineCreateInfo->vertexShader;
+    D3D11Shader *fragShader = (D3D11Shader *)pipelineCreateInfo->fragmentShader;
+    D3D11GraphicsPipeline *pipeline = SDL_malloc(sizeof(D3D11GraphicsPipeline));
+
+    // Blend
+
+    pipeline->colorAttachmentBlendState = D3D11_INTERNAL_FetchBlendState(
+        renderer,
+        pipelineCreateInfo->attachmentInfo.colorAttachmentCount,
+        pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions);
+
+    pipeline->numColorAttachments = pipelineCreateInfo->attachmentInfo.colorAttachmentCount;
+    for (Sint32 i = 0; i < pipeline->numColorAttachments; i += 1) {
+        pipeline->colorAttachmentFormats[i] = SDLToD3D11_TextureFormat[pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].format];
+    }
+
+    pipeline->blendConstants[0] = pipelineCreateInfo->blendConstants[0];
+    pipeline->blendConstants[1] = pipelineCreateInfo->blendConstants[1];
+    pipeline->blendConstants[2] = pipelineCreateInfo->blendConstants[2];
+    pipeline->blendConstants[3] = pipelineCreateInfo->blendConstants[3];
+
+    // Multisample
+
+    pipeline->multisampleState = pipelineCreateInfo->multisampleState;
+
+    // Depth-Stencil
+
+    pipeline->depthStencilState = D3D11_INTERNAL_FetchDepthStencilState(
+        renderer,
+        pipelineCreateInfo->depthStencilState);
+
+    pipeline->hasDepthStencilAttachment = pipelineCreateInfo->attachmentInfo.hasDepthStencilAttachment;
+    pipeline->depthStencilAttachmentFormat = SDLToD3D11_TextureFormat[pipelineCreateInfo->attachmentInfo.depthStencilFormat];
+    pipeline->stencilRef = pipelineCreateInfo->depthStencilState.reference;
+
+    // Rasterizer
+
+    pipeline->primitiveType = pipelineCreateInfo->primitiveType;
+    pipeline->rasterizerState = D3D11_INTERNAL_FetchRasterizerState(
+        renderer,
+        pipelineCreateInfo->rasterizerState);
+
+    // Shaders
+
+    pipeline->vertexShader = (ID3D11VertexShader *)vertShader->handle;
+    ID3D11VertexShader_AddRef(pipeline->vertexShader);
+
+    pipeline->fragmentShader = (ID3D11PixelShader *)fragShader->handle;
+    ID3D11PixelShader_AddRef(pipeline->fragmentShader);
+
+    // Input Layout
+
+    pipeline->inputLayout = D3D11_INTERNAL_FetchInputLayout(
+        renderer,
+        pipelineCreateInfo->vertexInputState,
+        vertShader->bytecode,
+        vertShader->bytecodeSize);
+
+    if (pipelineCreateInfo->vertexInputState.vertexBindingCount > 0) {
+        pipeline->vertexStrides = SDL_malloc(
+            sizeof(Uint32) *
+            pipelineCreateInfo->vertexInputState.vertexBindingCount);
+
+        for (Uint32 i = 0; i < pipelineCreateInfo->vertexInputState.vertexBindingCount; i += 1) {
+            pipeline->vertexStrides[i] = pipelineCreateInfo->vertexInputState.vertexBindings[i].stride;
+        }
+    } else {
+        pipeline->vertexStrides = NULL;
+    }
+
+    // Resource layout
+
+    pipeline->vertexSamplerCount = vertShader->samplerCount;
+    pipeline->vertexStorageTextureCount = vertShader->storageTextureCount;
+    pipeline->vertexStorageBufferCount = vertShader->storageBufferCount;
+    pipeline->vertexUniformBufferCount = vertShader->uniformBufferCount;
+
+    pipeline->fragmentSamplerCount = fragShader->samplerCount;
+    pipeline->fragmentStorageTextureCount = fragShader->storageTextureCount;
+    pipeline->fragmentStorageBufferCount = fragShader->storageBufferCount;
+    pipeline->fragmentUniformBufferCount = fragShader->uniformBufferCount;
+
+    return (SDL_GpuGraphicsPipeline *)pipeline;
+}
+
+// Debug Naming
+
+static void D3D11_INTERNAL_SetBufferName(
+    D3D11Renderer *renderer,
+    D3D11Buffer *buffer,
+    const char *text)
+{
+    if (renderer->debugMode) {
+        ID3D11DeviceChild_SetPrivateData(
+            buffer->handle,
+            &D3D_IID_D3DDebugObjectName,
+            (UINT)SDL_strlen(text),
+            text);
+    }
+}
+
+static void D3D11_SetBufferName(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBuffer *buffer,
+    const char *text)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11BufferContainer *container = (D3D11BufferContainer *)buffer;
+    size_t textLength = SDL_strlen(text) + 1;
+
+    if (renderer->debugMode) {
+        container->debugName = SDL_realloc(
+            container->debugName,
+            textLength);
+
+        SDL_utf8strlcpy(
+            container->debugName,
+            text,
+            textLength);
+
+        for (Uint32 i = 0; i < container->bufferCount; i += 1) {
+            D3D11_INTERNAL_SetBufferName(
+                renderer,
+                container->buffers[i],
+                text);
+        }
+    }
+}
+
+static void D3D11_INTERNAL_SetTextureName(
+    D3D11Renderer *renderer,
+    D3D11Texture *texture,
+    const char *text)
+{
+    if (renderer->debugMode) {
+        ID3D11DeviceChild_SetPrivateData(
+            texture->handle,
+            &D3D_IID_D3DDebugObjectName,
+            (UINT)SDL_strlen(text),
+            text);
+    }
+}
+
+static void D3D11_SetTextureName(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTexture *texture,
+    const char *text)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11TextureContainer *container = (D3D11TextureContainer *)texture;
+    size_t textLength = SDL_strlen(text) + 1;
+
+    if (renderer->debugMode) {
+        container->debugName = SDL_realloc(
+            container->debugName,
+            textLength);
+
+        SDL_utf8strlcpy(
+            container->debugName,
+            text,
+            textLength);
+
+        for (Uint32 i = 0; i < container->textureCount; i += 1) {
+            D3D11_INTERNAL_SetTextureName(
+                renderer,
+                container->textures[i],
+                text);
+        }
+    }
+}
+
+static SDL_bool D3D11_INTERNAL_StrToWStr(
+    D3D11Renderer *renderer,
+    const char *str,
+    wchar_t *wstr,
+    size_t wstr_size)
+{
+    size_t inlen, result;
+    size_t outlen = wstr_size;
+
+    if (renderer->iconv == NULL) {
+        renderer->iconv = SDL_iconv_open("WCHAR_T", "UTF-8");
+        SDL_assert(renderer->iconv);
+    }
+
+    // Convert...
+    inlen = SDL_strlen(str) + 1;
+    result = SDL_iconv(
+        renderer->iconv,
+        &str,
+        &inlen,
+        (char **)&wstr,
+        &outlen);
+
+    // Check...
+    switch (result) {
+    case SDL_ICONV_ERROR:
+    case SDL_ICONV_E2BIG:
+    case SDL_ICONV_EILSEQ:
+    case SDL_ICONV_EINVAL:
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Failed to convert string to wchar_t!");
+        return SDL_FALSE;
+    default:
+        break;
+    }
+
+    return SDL_TRUE;
+}
+
+static void D3D11_InsertDebugLabel(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *text)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+
+    if (d3d11CommandBuffer->annotation == NULL) {
+        return;
+    }
+
+    wchar_t wstr[256];
+    if (!D3D11_INTERNAL_StrToWStr(renderer, text, wstr, sizeof(wstr))) {
+        return;
+    }
+
+    ID3DUserDefinedAnnotation_SetMarker(d3d11CommandBuffer->annotation, wstr);
+}
+
+static void D3D11_PushDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *name)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+
+    if (d3d11CommandBuffer->annotation == NULL) {
+        return;
+    }
+
+    wchar_t wstr[256];
+    if (!D3D11_INTERNAL_StrToWStr(renderer, name, wstr, sizeof(wstr))) {
+        return;
+    }
+
+    ID3DUserDefinedAnnotation_BeginEvent(d3d11CommandBuffer->annotation, wstr);
+}
+
+static void D3D11_PopDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    if (d3d11CommandBuffer->annotation == NULL) {
+        return;
+    }
+    ID3DUserDefinedAnnotation_EndEvent(d3d11CommandBuffer->annotation);
+}
+
+// Resource Creation
+
+static SDL_GpuSampler *D3D11_CreateSampler(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuSamplerCreateInfo *samplerCreateInfo)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11_SAMPLER_DESC samplerDesc;
+    ID3D11SamplerState *samplerStateHandle;
+    D3D11Sampler *d3d11Sampler;
+    HRESULT res;
+
+    samplerDesc.AddressU = SDLToD3D11_SamplerAddressMode[samplerCreateInfo->addressModeU];
+    samplerDesc.AddressV = SDLToD3D11_SamplerAddressMode[samplerCreateInfo->addressModeV];
+    samplerDesc.AddressW = SDLToD3D11_SamplerAddressMode[samplerCreateInfo->addressModeW];
+    samplerDesc.ComparisonFunc = (samplerCreateInfo->compareEnable ? SDLToD3D11_CompareOp[samplerCreateInfo->compareOp] : SDLToD3D11_CompareOp[SDL_GPU_COMPAREOP_ALWAYS]);
+    samplerDesc.MaxAnisotropy = (samplerCreateInfo->anisotropyEnable ? (UINT)samplerCreateInfo->maxAnisotropy : 0);
+    samplerDesc.Filter = SDLToD3D11_Filter(samplerCreateInfo);
+    samplerDesc.MaxLOD = samplerCreateInfo->maxLod;
+    samplerDesc.MinLOD = samplerCreateInfo->minLod;
+    samplerDesc.MipLODBias = samplerCreateInfo->mipLodBias;
+    SDL_zeroa(samplerDesc.BorderColor); // arbitrary, unused
+
+    res = ID3D11Device_CreateSamplerState(
+        renderer->device,
+        &samplerDesc,
+        &samplerStateHandle);
+    ERROR_CHECK_RETURN("Could not create sampler state", NULL);
+
+    d3d11Sampler = (D3D11Sampler *)SDL_malloc(sizeof(D3D11Sampler));
+    d3d11Sampler->handle = samplerStateHandle;
+
+    return (SDL_GpuSampler *)d3d11Sampler;
+}
+
+SDL_GpuShader *D3D11_CreateShader(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuShaderCreateInfo *shaderCreateInfo)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    ID3D11DeviceChild *handle;
+    void *bytecode = NULL;
+    size_t bytecodeSize = 0;
+    D3D11Shader *shader;
+
+    handle = D3D11_INTERNAL_CreateID3D11Shader(
+        renderer,
+        shaderCreateInfo->stage,
+        shaderCreateInfo->code,
+        shaderCreateInfo->codeSize,
+        shaderCreateInfo->entryPointName,
+        shaderCreateInfo->stage == SDL_GPU_SHADERSTAGE_VERTEX ? &bytecode : NULL,
+        shaderCreateInfo->stage == SDL_GPU_SHADERSTAGE_VERTEX ? &bytecodeSize : NULL);
+    if (!handle) {
+        return NULL;
+    }
+
+    shader = (D3D11Shader *)SDL_calloc(1, sizeof(D3D11Shader));
+    shader->handle = handle;
+    shader->samplerCount = shaderCreateInfo->samplerCount;
+    shader->storageBufferCount = shaderCreateInfo->storageBufferCount;
+    shader->storageTextureCount = shaderCreateInfo->storageTextureCount;
+    shader->uniformBufferCount = shaderCreateInfo->uniformBufferCount;
+    if (shaderCreateInfo->stage == SDL_GPU_SHADERSTAGE_VERTEX) {
+        // Store the raw bytecode and its length for creating InputLayouts
+        shader->bytecode = bytecode;
+        shader->bytecodeSize = bytecodeSize;
+    }
+
+    return (SDL_GpuShader *)shader;
+}
+
+static D3D11Texture *D3D11_INTERNAL_CreateTexture(
+    D3D11Renderer *renderer,
+    SDL_GpuTextureCreateInfo *createInfo,
+    D3D11_SUBRESOURCE_DATA *initialData)
+{
+    Uint8 needsSRV, isColorTarget, isDepthStencil, isMultisample, isStaging, needSubresourceUAV, isMippable;
+    DXGI_FORMAT format;
+    ID3D11Resource *textureHandle;
+    ID3D11ShaderResourceView *srv = NULL;
+    D3D11Texture *d3d11Texture;
+    HRESULT res;
+
+    isColorTarget = createInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT;
+    isDepthStencil = createInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT;
+    needsSRV =
+        (createInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) ||
+        (createInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT) ||
+        (createInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT);
+    needSubresourceUAV =
+        (createInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT);
+    isMultisample = createInfo->sampleCount > SDL_GPU_SAMPLECOUNT_1;
+    isStaging = createInfo->usageFlags == 0;
+    isMippable =
+        createInfo->levelCount > 1 &&
+        (createInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) &&
+        (createInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT);
+    format = SDLToD3D11_TextureFormat[createInfo->format];
+    if (isDepthStencil) {
+        format = D3D11_INTERNAL_GetTypelessFormat(format);
+    }
+
+    Uint32 layerCount = createInfo->type == SDL_GPU_TEXTURETYPE_3D ? 1 : createInfo->layerCountOrDepth;
+    Uint32 depth = createInfo->type == SDL_GPU_TEXTURETYPE_3D ? createInfo->layerCountOrDepth : 1;
+
+    if (createInfo->type != SDL_GPU_TEXTURETYPE_3D) {
+        D3D11_TEXTURE2D_DESC desc2D;
+
+        desc2D.BindFlags = 0;
+        if (needsSRV) {
+            desc2D.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+        }
+        if (needSubresourceUAV) {
+            desc2D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+        }
+        if (isColorTarget) {
+            desc2D.BindFlags |= D3D11_BIND_RENDER_TARGET;
+        }
+        if (isDepthStencil) {
+            desc2D.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
+        }
+
+        desc2D.Width = createInfo->width;
+        desc2D.Height = createInfo->height;
+        desc2D.ArraySize = layerCount;
+        desc2D.CPUAccessFlags = isStaging ? D3D11_CPU_ACCESS_WRITE : 0;
+        desc2D.Format = format;
+        desc2D.MipLevels = createInfo->levelCount;
+        desc2D.MiscFlags = 0;
+        desc2D.SampleDesc.Count = 1;
+        desc2D.SampleDesc.Quality = 0;
+        desc2D.Usage = isStaging ? D3D11_USAGE_STAGING : D3D11_USAGE_DEFAULT;
+
+        if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+            desc2D.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
+        }
+        if (isMippable) {
+            desc2D.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
+        }
+
+        res = ID3D11Device_CreateTexture2D(
+            renderer->device,
+            &desc2D,
+            initialData,
+            (ID3D11Texture2D **)&textureHandle);
+        ERROR_CHECK_RETURN("Could not create Texture2D", NULL);
+
+        // Create the SRV, if applicable
+        if (needsSRV) {
+            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+            srvDesc.Format = D3D11_INTERNAL_GetSampleableFormat(format);
+
+            if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+                srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+                srvDesc.TextureCube.MipLevels = desc2D.MipLevels;
+                srvDesc.TextureCube.MostDetailedMip = 0;
+            } else if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
+                srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+                srvDesc.Texture2DArray.MipLevels = desc2D.MipLevels;
+                srvDesc.Texture2DArray.MostDetailedMip = 0;
+                srvDesc.Texture2DArray.FirstArraySlice = 0;
+                srvDesc.Texture2DArray.ArraySize = layerCount;
+            } else {
+                srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+                srvDesc.Texture2D.MipLevels = desc2D.MipLevels;
+                srvDesc.Texture2D.MostDetailedMip = 0;
+            }
+
+            res = ID3D11Device_CreateShaderResourceView(
+                renderer->device,
+                textureHandle,
+                &srvDesc,
+                &srv);
+            if (FAILED(res)) {
+                ID3D11Resource_Release(textureHandle);
+                D3D11_INTERNAL_LogError(renderer->device, "Could not create SRV for 2D texture", res);
+                return NULL;
+            }
+        }
+    } else {
+        D3D11_TEXTURE3D_DESC desc3D;
+
+        desc3D.BindFlags = 0;
+        if (needsSRV) {
+            desc3D.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+        }
+        if (needSubresourceUAV) {
+            desc3D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+        }
+        if (isColorTarget) {
+            desc3D.BindFlags |= D3D11_BIND_RENDER_TARGET;
+        }
+
+        desc3D.Width = createInfo->width;
+        desc3D.Height = createInfo->height;
+        desc3D.Depth = depth;
+        desc3D.CPUAccessFlags = isStaging ? D3D11_CPU_ACCESS_WRITE : 0;
+        desc3D.Format = format;
+        desc3D.MipLevels = createInfo->levelCount;
+        desc3D.MiscFlags = isMippable ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0;
+        desc3D.Usage = isStaging ? D3D11_USAGE_STAGING : D3D11_USAGE_DEFAULT;
+
+        res = ID3D11Device_CreateTexture3D(
+            renderer->device,
+            &desc3D,
+            initialData,
+            (ID3D11Texture3D **)&textureHandle);
+        ERROR_CHECK_RETURN("Could not create Texture3D", NULL);
+
+        // Create the SRV, if applicable
+        if (needsSRV) {
+            D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+            srvDesc.Format = format;
+            srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+            srvDesc.Texture3D.MipLevels = desc3D.MipLevels;
+            srvDesc.Texture3D.MostDetailedMip = 0;
+
+            res = ID3D11Device_CreateShaderResourceView(
+                renderer->device,
+                textureHandle,
+                &srvDesc,
+                &srv);
+            if (FAILED(res)) {
+                ID3D11Resource_Release(textureHandle);
+                D3D11_INTERNAL_LogError(renderer->device, "Could not create SRV for 3D texture", res);
+                return NULL;
+            }
+        }
+    }
+
+    d3d11Texture = (D3D11Texture *)SDL_malloc(sizeof(D3D11Texture));
+    d3d11Texture->handle = textureHandle;
+    d3d11Texture->shaderView = srv;
+    SDL_AtomicSet(&d3d11Texture->referenceCount, 0);
+    d3d11Texture->container = NULL;
+    d3d11Texture->containerIndex = 0;
+
+    d3d11Texture->subresourceCount = createInfo->levelCount * layerCount;
+    d3d11Texture->subresources = SDL_malloc(
+        d3d11Texture->subresourceCount * sizeof(D3D11TextureSubresource));
+
+    for (Uint32 layerIndex = 0; layerIndex < layerCount; layerIndex += 1) {
+        for (Uint32 levelIndex = 0; levelIndex < createInfo->levelCount; levelIndex += 1) {
+            Uint32 subresourceIndex = D3D11_INTERNAL_CalcSubresource(
+                levelIndex,
+                layerIndex,
+                createInfo->levelCount);
+
+            d3d11Texture->subresources[subresourceIndex].parent = d3d11Texture;
+            d3d11Texture->subresources[subresourceIndex].layer = layerIndex;
+            d3d11Texture->subresources[subresourceIndex].level = levelIndex;
+            d3d11Texture->subresources[subresourceIndex].depth = depth;
+            d3d11Texture->subresources[subresourceIndex].index = subresourceIndex;
+
+            d3d11Texture->subresources[subresourceIndex].colorTargetViews = NULL;
+            d3d11Texture->subresources[subresourceIndex].uav = NULL;
+            d3d11Texture->subresources[subresourceIndex].depthStencilTargetView = NULL;
+            d3d11Texture->subresources[subresourceIndex].msaaHandle = NULL;
+            d3d11Texture->subresources[subresourceIndex].msaaTargetView = NULL;
+
+            if (isMultisample) {
+                D3D11_TEXTURE2D_DESC desc2D;
+
+                if (isColorTarget) {
+                    desc2D.BindFlags = D3D11_BIND_RENDER_TARGET;
+                } else if (isDepthStencil) {
+                    desc2D.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+                }
+
+                desc2D.Width = createInfo->width;
+                desc2D.Height = createInfo->height;
+                desc2D.ArraySize = 1;
+                desc2D.CPUAccessFlags = 0;
+                desc2D.Format = format;
+                desc2D.MipLevels = 1;
+                desc2D.MiscFlags = 0;
+                desc2D.SampleDesc.Count = SDLToD3D11_SampleCount[createInfo->sampleCount];
+                desc2D.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
+                desc2D.Usage = D3D11_USAGE_DEFAULT;
+
+                res = ID3D11Device_CreateTexture2D(
+                    renderer->device,
+                    &desc2D,
+                    NULL,
+                    (ID3D11Texture2D **)&d3d11Texture->subresources[subresourceIndex].msaaHandle);
+                ERROR_CHECK_RETURN("Could not create MSAA texture!", NULL);
+
+                if (!isDepthStencil) {
+                    D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+
+                    rtvDesc.Format = format;
+                    rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+
+                    res = ID3D11Device_CreateRenderTargetView(
+                        renderer->device,
+                        d3d11Texture->subresources[subresourceIndex].msaaHandle,
+                        &rtvDesc,
+                        &d3d11Texture->subresources[subresourceIndex].msaaTargetView);
+                    ERROR_CHECK_RETURN("Could not create MSAA RTV!", NULL);
+                }
+            }
+
+            if (isDepthStencil) {
+                D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+
+                dsvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format];
+                dsvDesc.Flags = 0;
+
+                if (isMultisample) {
+                    dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+                } else {
+                    dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+                    dsvDesc.Texture2D.MipSlice = levelIndex;
+                }
+
+                res = ID3D11Device_CreateDepthStencilView(
+                    renderer->device,
+                    isMultisample ? d3d11Texture->subresources[subresourceIndex].msaaHandle : d3d11Texture->handle,
+                    &dsvDesc,
+                    &d3d11Texture->subresources[subresourceIndex].depthStencilTargetView);
+                ERROR_CHECK_RETURN("Could not create DSV!", NULL);
+            } else if (isColorTarget) {
+                d3d11Texture->subresources[subresourceIndex].colorTargetViews = SDL_calloc(depth, sizeof(ID3D11RenderTargetView *));
+
+                for (Uint32 depthIndex = 0; depthIndex < depth; depthIndex += 1) {
+                    D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+
+                    rtvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format];
+
+                    if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+                        rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+                        rtvDesc.Texture2DArray.MipSlice = levelIndex;
+                        rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
+                        rtvDesc.Texture2DArray.ArraySize = 1;
+                    } else if (createInfo->type == SDL_GPU_TEXTURETYPE_3D) {
+                        rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+                        rtvDesc.Texture3D.MipSlice = levelIndex;
+                        rtvDesc.Texture3D.FirstWSlice = depthIndex;
+                        rtvDesc.Texture3D.WSize = 1;
+                    } else {
+                        rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+                        rtvDesc.Texture2D.MipSlice = levelIndex;
+                    }
+
+                    res = ID3D11Device_CreateRenderTargetView(
+                        renderer->device,
+                        d3d11Texture->handle,
+                        &rtvDesc,
+                        &d3d11Texture->subresources[subresourceIndex].colorTargetViews[depthIndex]);
+                    ERROR_CHECK_RETURN("Could not create RTV!", NULL);
+                }
+            }
+
+            if (needSubresourceUAV) {
+                D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+                uavDesc.Format = format;
+
+                if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+                    uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+                    uavDesc.Texture2DArray.MipSlice = levelIndex;
+                    uavDesc.Texture2DArray.FirstArraySlice = layerIndex;
+                    uavDesc.Texture2DArray.ArraySize = 1;
+                } else if (createInfo->type == SDL_GPU_TEXTURETYPE_3D) {
+                    uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
+                    uavDesc.Texture3D.MipSlice = levelIndex;
+                    uavDesc.Texture3D.FirstWSlice = 0;
+                    uavDesc.Texture3D.WSize = depth;
+                } else {
+                    uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
+                    uavDesc.Texture2D.MipSlice = levelIndex;
+                }
+
+                res = ID3D11Device_CreateUnorderedAccessView(
+                    renderer->device,
+                    d3d11Texture->handle,
+                    &uavDesc,
+                    &d3d11Texture->subresources[subresourceIndex].uav);
+                ERROR_CHECK_RETURN("Could not create UAV!", NULL);
+            }
+        }
+    }
+
+    return d3d11Texture;
+}
+
+static SDL_bool D3D11_SupportsSampleCount(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureFormat format,
+    SDL_GpuSampleCount sampleCount)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    Uint32 levels;
+
+    HRESULT res = ID3D11Device_CheckMultisampleQualityLevels(
+        renderer->device,
+        SDLToD3D11_TextureFormat[format],
+        SDLToD3D11_SampleCount[sampleCount],
+        &levels);
+
+    return SUCCEEDED(res) && levels > 0;
+}
+
+static SDL_GpuTexture *D3D11_CreateTexture(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureCreateInfo *textureCreateInfo)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11TextureContainer *container;
+    D3D11Texture *texture;
+
+    texture = D3D11_INTERNAL_CreateTexture(
+        renderer,
+        textureCreateInfo,
+        NULL);
+
+    if (texture == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create texture!");
+        return NULL;
+    }
+
+    container = SDL_malloc(sizeof(D3D11TextureContainer));
+    container->header.info = *textureCreateInfo;
+    container->canBeCycled = 1;
+    container->activeTexture = texture;
+    container->textureCapacity = 1;
+    container->textureCount = 1;
+    container->textures = SDL_malloc(
+        container->textureCapacity * sizeof(D3D11Texture *));
+    container->textures[0] = texture;
+    container->debugName = NULL;
+
+    texture->container = container;
+    texture->containerIndex = 0;
+
+    return (SDL_GpuTexture *)container;
+}
+
+static void D3D11_INTERNAL_CycleActiveTexture(
+    D3D11Renderer *renderer,
+    D3D11TextureContainer *container)
+{
+    for (Uint32 i = 0; i < container->textureCount; i += 1) {
+        if (SDL_AtomicGet(&container->textures[i]->referenceCount) == 0) {
+            container->activeTexture = container->textures[i];
+            return;
+        }
+    }
+
+    D3D11Texture *texture = D3D11_INTERNAL_CreateTexture(
+        renderer,
+        &container->header.info,
+        NULL);
+    if (texture == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to cycle active texture!");
+        return;
+    }
+
+    // No texture is available, generate a new one.
+
+    EXPAND_ARRAY_IF_NEEDED(
+        container->textures,
+        D3D11Texture *,
+        container->textureCount + 1,
+        container->textureCapacity,
+        container->textureCapacity + 1);
+
+    container->textures[container->textureCount] = texture;
+    texture->container = container;
+    texture->containerIndex = container->textureCount;
+    container->textureCount += 1;
+
+    container->activeTexture = container->textures[container->textureCount - 1];
+
+    if (renderer->debugMode && container->debugName != NULL) {
+        D3D11_INTERNAL_SetTextureName(
+            renderer,
+            container->activeTexture,
+            container->debugName);
+    }
+}
+
+static D3D11TextureSubresource *D3D11_INTERNAL_FetchTextureSubresource(
+    D3D11TextureContainer *container,
+    Uint32 layer,
+    Uint32 level)
+{
+    Uint32 index = D3D11_INTERNAL_CalcSubresource(
+        level,
+        layer,
+        container->header.info.levelCount);
+    return &container->activeTexture->subresources[index];
+}
+
+static D3D11TextureSubresource *D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
+    D3D11Renderer *renderer,
+    D3D11TextureContainer *container,
+    Uint32 layer,
+    Uint32 level,
+    SDL_bool cycle)
+{
+    D3D11TextureSubresource *subresource = D3D11_INTERNAL_FetchTextureSubresource(
+        container,
+        layer,
+        level);
+
+    if (
+        container->canBeCycled &&
+        cycle &&
+        SDL_AtomicGet(&subresource->parent->referenceCount) > 0) {
+        D3D11_INTERNAL_CycleActiveTexture(
+            renderer,
+            container);
+
+        subresource = D3D11_INTERNAL_FetchTextureSubresource(
+            container,
+            layer,
+            level);
+    }
+
+    return subresource;
+}
+
+static D3D11Buffer *D3D11_INTERNAL_CreateBuffer(
+    D3D11Renderer *renderer,
+    D3D11_BUFFER_DESC *bufferDesc,
+    Uint32 sizeInBytes)
+{
+    ID3D11Buffer *bufferHandle;
+    ID3D11UnorderedAccessView *uav = NULL;
+    ID3D11ShaderResourceView *srv = NULL;
+    D3D11Buffer *d3d11Buffer;
+    HRESULT res;
+
+    // Storage buffers have to be 4-aligned, so might as well align them all
+    sizeInBytes = D3D11_INTERNAL_NextHighestAlignment(sizeInBytes, 4);
+
+    res = ID3D11Device_CreateBuffer(
+        renderer->device,
+        bufferDesc,
+        NULL,
+        &bufferHandle);
+    ERROR_CHECK_RETURN("Could not create buffer", NULL);
+
+    // Storage buffer
+    if (bufferDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) {
+        // Create a UAV for the buffer
+
+        D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+        uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+        uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
+        uavDesc.Buffer.FirstElement = 0;
+        uavDesc.Buffer.NumElements = sizeInBytes / sizeof(Uint32);
+        uavDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
+
+        res = ID3D11Device_CreateUnorderedAccessView(
+            renderer->device,
+            (ID3D11Resource *)bufferHandle,
+            &uavDesc,
+            &uav);
+        if (FAILED(res)) {
+            ID3D11Buffer_Release(bufferHandle);
+            ERROR_CHECK_RETURN("Could not create UAV for buffer!", NULL);
+        }
+
+        // Create a SRV for the buffer
+
+        D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+        srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+        srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
+        srvDesc.BufferEx.FirstElement = 0;
+        srvDesc.BufferEx.NumElements = sizeInBytes / sizeof(Uint32);
+        srvDesc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW;
+
+        res = ID3D11Device_CreateShaderResourceView(
+            renderer->device,
+            (ID3D11Resource *)bufferHandle,
+            &srvDesc,
+            &srv);
+        if (FAILED(res)) {
+            ID3D11Buffer_Release(bufferHandle);
+            ERROR_CHECK_RETURN("Could not create SRV for buffer!", NULL);
+        }
+    }
+
+    d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer));
+    d3d11Buffer->handle = bufferHandle;
+    d3d11Buffer->size = sizeInBytes;
+    d3d11Buffer->uav = uav;
+    d3d11Buffer->srv = srv;
+    SDL_AtomicSet(&d3d11Buffer->referenceCount, 0);
+
+    return d3d11Buffer;
+}
+
+static SDL_GpuBuffer *D3D11_CreateBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBufferUsageFlags usageFlags,
+    Uint32 sizeInBytes)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11BufferContainer *container;
+    D3D11Buffer *buffer;
+    D3D11_BUFFER_DESC bufferDesc;
+
+    bufferDesc.BindFlags = 0;
+    if (usageFlags & SDL_GPU_BUFFERUSAGE_VERTEX_BIT) {
+        bufferDesc.BindFlags |= D3D11_BIND_VERTEX_BUFFER;
+    }
+    if (usageFlags & SDL_GPU_BUFFERUSAGE_INDEX_BIT) {
+        bufferDesc.BindFlags |= D3D11_BIND_INDEX_BUFFER;
+    }
+    if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT_BIT) {
+        bufferDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+    }
+
+    if (usageFlags & (SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT |
+                      SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ_BIT |
+                      SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT)) {
+        bufferDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
+    }
+
+    bufferDesc.ByteWidth = sizeInBytes;
+    bufferDesc.Usage = D3D11_USAGE_DEFAULT;
+    bufferDesc.CPUAccessFlags = 0;
+    bufferDesc.StructureByteStride = 0;
+    bufferDesc.MiscFlags = 0;
+
+    if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT_BIT) {
+        bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
+    }
+    if (usageFlags & (SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT |
+                      SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ_BIT |
+                      SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT)) {
+        bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
+    }
+
+    buffer = D3D11_INTERNAL_CreateBuffer(
+        renderer,
+        &bufferDesc,
+        sizeInBytes);
+
+    if (buffer == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create buffer!");
+        return NULL;
+    }
+
+    container = SDL_malloc(sizeof(D3D11BufferContainer));
+    container->activeBuffer = buffer;
+    container->bufferCapacity = 1;
+    container->bufferCount = 1;
+    container->buffers = SDL_malloc(
+        container->bufferCapacity * sizeof(D3D11Buffer *));
+    container->buffers[0] = container->activeBuffer;
+    container->bufferDesc = bufferDesc;
+    container->debugName = NULL;
+
+    return (SDL_GpuBuffer *)container;
+}
+
+static D3D11UniformBuffer *D3D11_INTERNAL_CreateUniformBuffer(
+    D3D11Renderer *renderer,
+    Uint32 sizeInBytes)
+{
+    D3D11UniformBuffer *uniformBuffer;
+    ID3D11Buffer *buffer;
+    D3D11_BUFFER_DESC bufferDesc;
+    HRESULT res;
+
+    bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+    bufferDesc.ByteWidth = sizeInBytes;
+    bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+    bufferDesc.MiscFlags = 0;
+    bufferDesc.StructureByteStride = 0;
+    bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+
+    res = ID3D11Device_CreateBuffer(
+        renderer->device,
+        &bufferDesc,
+        NULL,
+        &buffer);
+    ERROR_CHECK_RETURN("Could not create uniform buffer", NULL)
+
+    uniformBuffer = SDL_malloc(sizeof(D3D11UniformBuffer));
+    uniformBuffer->buffer = buffer;
+    uniformBuffer->writeOffset = 0;
+    uniformBuffer->drawOffset = 0;
+    uniformBuffer->currentBlockSize = 0;
+
+    return uniformBuffer;
+}
+
+static void D3D11_INTERNAL_CycleActiveBuffer(
+    D3D11Renderer *renderer,
+    D3D11BufferContainer *container)
+{
+    Uint32 size = container->activeBuffer->size;
+
+    for (Uint32 i = 0; i < container->bufferCount; i += 1) {
+        if (SDL_AtomicGet(&container->buffers[i]->referenceCount) == 0) {
+            container->activeBuffer = container->buffers[i];
+            return;
+        }
+    }
+
+    EXPAND_ARRAY_IF_NEEDED(
+        container->buffers,
+        D3D11Buffer *,
+        container->bufferCount + 1,
+        container->bufferCapacity,
+        container->bufferCapacity + 1);
+
+    container->buffers[container->bufferCount] = D3D11_INTERNAL_CreateBuffer(
+        renderer,
+        &container->bufferDesc,
+        size);
+    container->bufferCount += 1;
+
+    container->activeBuffer = container->buffers[container->bufferCount - 1];
+
+    if (renderer->debugMode && container->debugName != NULL) {
+        D3D11_INTERNAL_SetBufferName(
+            renderer,
+            container->activeBuffer,
+            container->debugName);
+    }
+}
+
+static D3D11Buffer *D3D11_INTERNAL_PrepareBufferForWrite(
+    D3D11Renderer *renderer,
+    D3D11BufferContainer *container,
+    SDL_bool cycle)
+{
+    if (
+        cycle &&
+        SDL_AtomicGet(&container->activeBuffer->referenceCount) > 0) {
+        D3D11_INTERNAL_CycleActiveBuffer(
+            renderer,
+            container);
+    }
+
+    return container->activeBuffer;
+}
+
+static D3D11TransferBuffer *D3D11_INTERNAL_CreateTransferBuffer(
+    D3D11Renderer *renderer,
+    Uint32 sizeInBytes)
+{
+    D3D11TransferBuffer *transferBuffer = SDL_malloc(sizeof(D3D11TransferBuffer));
+
+    transferBuffer->data = (Uint8 *)SDL_malloc(sizeInBytes);
+    transferBuffer->size = sizeInBytes;
+    SDL_AtomicSet(&transferBuffer->referenceCount, 0);
+
+    transferBuffer->bufferDownloads = NULL;
+    transferBuffer->bufferDownloadCount = 0;
+    transferBuffer->bufferDownloadCapacity = 0;
+
+    transferBuffer->textureDownloads = NULL;
+    transferBuffer->textureDownloadCount = 0;
+    transferBuffer->textureDownloadCapacity = 0;
+
+    return transferBuffer;
+}
+
+// This actually returns a container handle so we can rotate buffers on Cycle.
+static SDL_GpuTransferBuffer *D3D11_CreateTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBufferUsage usage, // ignored on D3D11
+    Uint32 sizeInBytes)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer *)SDL_malloc(sizeof(D3D11TransferBufferContainer));
+
+    container->bufferCapacity = 1;
+    container->bufferCount = 1;
+    container->buffers = SDL_malloc(
+        container->bufferCapacity * sizeof(D3D11TransferBuffer *));
+
+    container->buffers[0] = D3D11_INTERNAL_CreateTransferBuffer(
+        renderer,
+        sizeInBytes);
+
+    container->activeBuffer = container->buffers[0];
+
+    return (SDL_GpuTransferBuffer *)container;
+}
+
+// TransferBuffer Data
+
+static void D3D11_INTERNAL_CycleActiveTransferBuffer(
+    D3D11Renderer *renderer,
+    D3D11TransferBufferContainer *container)
+{
+    Uint32 size = container->activeBuffer->size;
+
+    for (Uint32 i = 0; i < container->bufferCount; i += 1) {
+        if (SDL_AtomicGet(&container->buffers[i]->referenceCount) == 0) {
+            container->activeBuffer = container->buffers[i];
+            return;
+        }
+    }
+
+    EXPAND_ARRAY_IF_NEEDED(
+        container->buffers,
+        D3D11TransferBuffer *,
+        container->bufferCount + 1,
+        container->bufferCapacity,
+        container->bufferCapacity + 1);
+
+    container->buffers[container->bufferCount] = D3D11_INTERNAL_CreateTransferBuffer(
+        renderer,
+        size);
+    container->bufferCount += 1;
+
+    container->activeBuffer = container->buffers[container->bufferCount - 1];
+}
+
+static void *D3D11_MapTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer,
+    SDL_bool cycle)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer *)transferBuffer;
+    D3D11TransferBuffer *buffer = container->activeBuffer;
+
+    // Rotate the transfer buffer if necessary
+    if (
+        cycle &&
+        SDL_AtomicGet(&container->activeBuffer->referenceCount) > 0) {
+        D3D11_INTERNAL_CycleActiveTransferBuffer(
+            renderer,
+            container);
+        buffer = container->activeBuffer;
+    }
+
+    return buffer->data;
+}
+
+static void D3D11_UnmapTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer)
+{
+    // no-op
+    (void)driverData;
+    (void)transferBuffer;
+}
+
+// Copy Pass
+
+static void D3D11_BeginCopyPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    // no-op
+}
+
+static void D3D11_UploadToTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureTransferInfo *source,
+    SDL_GpuTextureRegion *destination,
+    SDL_bool cycle)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+    D3D11TransferBufferContainer *srcTransferContainer = (D3D11TransferBufferContainer *)source->transferBuffer;
+    D3D11TransferBuffer *srcTransferBuffer = srcTransferContainer->activeBuffer;
+    D3D11TextureContainer *dstTextureContainer = (D3D11TextureContainer *)destination->texture;
+    SDL_GpuTextureFormat dstFormat = dstTextureContainer->header.info.format;
+    Uint32 bufferStride = source->imagePitch;
+    Uint32 bufferImageHeight = source->imageHeight;
+    Sint32 w = destination->w;
+    Sint32 h = destination->h;
+    D3D11Texture *stagingTexture;
+    SDL_GpuTextureCreateInfo stagingTextureCreateInfo;
+    D3D11_SUBRESOURCE_DATA initialData;
+
+    D3D11TextureSubresource *textureSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
+        renderer,
+        dstTextureContainer,
+        destination->layer,
+        destination->mipLevel,
+        cycle);
+
+    Sint32 blockSize = Texture_GetBlockSize(dstFormat);
+    if (blockSize > 1) {
+        w = (w + blockSize - 1) & ~(blockSize - 1);
+        h = (h + blockSize - 1) & ~(blockSize - 1);
+    }
+
+    if (bufferStride == 0) {
+        bufferStride = w;
+    }
+
+    if (bufferImageHeight == 0) {
+        bufferImageHeight = h;
+    }
+
+    Uint32 bytesPerRow = BytesPerRow(bufferStride, dstFormat);
+    Uint32 bytesPerDepthSlice = bytesPerRow * bufferImageHeight;
+
+    /* UpdateSubresource1 is completely busted on AMD, it truncates after X bytes.
+     * So we get to do this Fun (Tm) workaround where we create a staging texture
+     * with initial data before issuing a copy command.
+     */
+
+    stagingTextureCreateInfo.width = w;
+    stagingTextureCreateInfo.height = h;
+    stagingTextureCreateInfo.layerCountOrDepth = 1;
+    stagingTextureCreateInfo.levelCount = 1;
+    stagingTextureCreateInfo.type = SDL_GPU_TEXTURETYPE_2D;
+    stagingTextureCreateInfo.usageFlags = 0;
+    stagingTextureCreateInfo.sampleCount = SDL_GPU_SAMPLECOUNT_1;
+    stagingTextureCreateInfo.format = dstFormat;
+
+    initialData.pSysMem = srcTransferBuffer->data + source->offset;
+    initialData.SysMemPitch = bytesPerRow;
+    initialData.SysMemSlicePitch = bytesPerDepthSlice;
+
+    stagingTexture = D3D11_INTERNAL_CreateTexture(
+        renderer,
+        &stagingTextureCreateInfo,
+        &initialData);
+
+    if (stagingTexture == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Staging texture creation failed");
+        return;
+    }
+
+    ID3D11DeviceContext_CopySubresourceRegion(
+        d3d11CommandBuffer->context,
+        textureSubresource->parent->handle,
+        textureSubresource->index,
+        destination->x,
+        destination->y,
+        destination->z,
+        stagingTexture->handle,
+        0,
+        NULL);
+
+    // Clean up the staging texture
+    D3D11_INTERNAL_DestroyTexture(stagingTexture);
+
+    D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, textureSubresource->parent);
+    D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, srcTransferBuffer);
+}
+
+static void D3D11_UploadToBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTransferBufferLocation *source,
+    SDL_GpuBufferRegion *destination,
+    SDL_bool cycle)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+    D3D11TransferBufferContainer *transferContainer = (D3D11TransferBufferContainer *)source->transferBuffer;
+    D3D11TransferBuffer *d3d11TransferBuffer = transferContainer->activeBuffer;
+    D3D11BufferContainer *bufferContainer = (D3D11BufferContainer *)destination->buffer;
+    D3D11Buffer *d3d11Buffer = D3D11_INTERNAL_PrepareBufferForWrite(
+        renderer,
+        bufferContainer,
+        cycle);
+    ID3D11Buffer *stagingBuffer;
+    D3D11_BUFFER_DESC stagingBufferDesc;
+    D3D11_SUBRESOURCE_DATA stagingBufferData;
+    HRESULT res;
+
+    // Upload to staging buffer immediately
+    stagingBufferDesc.ByteWidth = destination->size;
+    stagingBufferDesc.Usage = D3D11_USAGE_STAGING;
+    stagingBufferDesc.BindFlags = 0;
+    stagingBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+    stagingBufferDesc.MiscFlags = 0;
+    stagingBufferDesc.StructureByteStride = 0;
+
+    stagingBufferData.pSysMem = d3d11TransferBuffer->data + source->offset;
+    stagingBufferData.SysMemPitch = 0;
+    stagingBufferData.SysMemSlicePitch = 0;
+
+    res = ID3D11Device_CreateBuffer(
+        renderer->device,
+        &stagingBufferDesc,
+        &stagingBufferData,
+        &stagingBuffer);
+    ERROR_CHECK_RETURN("Could not create staging buffer", )
+
+    // Copy from staging buffer to buffer
+    ID3D11DeviceContext1_CopySubresourceRegion(
+        d3d11CommandBuffer->context,
+        (ID3D11Resource *)d3d11Buffer->handle,
+        0,
+        destination->offset,
+        0,
+        0,
+        (ID3D11Resource *)stagingBuffer,
+        0,
+        NULL);
+
+    ID3D11Buffer_Release(stagingBuffer);
+
+    D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer);
+    D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer);
+}
+
+static void D3D11_DownloadFromTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureRegion *source,
+    SDL_GpuTextureTransferInfo *destination)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = d3d11CommandBuffer->renderer;
+    D3D11TransferBufferContainer *dstTransferContainer = (D3D11TransferBufferContainer *)destination->transferBuffer;
+    D3D11TransferBuffer *d3d11TransferBuffer = dstTransferContainer->activeBuffer;
+    D3D11TextureContainer *srcTextureContainer = (D3D11TextureContainer *)source->texture;
+    SDL_GpuTextureFormat srcFormat = srcTextureContainer->header.info.format;
+    D3D11_TEXTURE2D_DESC stagingDesc2D;
+    D3D11_TEXTURE3D_DESC stagingDesc3D;
+    D3D11TextureSubresource *textureSubresource = D3D11_INTERNAL_FetchTextureSubresource(
+        srcTextureContainer,
+        source->layer,
+        source->mipLevel);
+    D3D11TextureDownload *textureDownload;
+    Uint32 bufferStride = destination->imagePitch;
+    Uint32 bufferImageHeight = destination->imageHeight;
+    Uint32 bytesPerRow, bytesPerDepthSlice;
+    D3D11_BOX srcBox = { source->x, source->y, source->z, source->x + source->w, source->y + source->h, source->z + source->d };
+    HRESULT res;
+
+    if (d3d11TransferBuffer->textureDownloadCount >= d3d11TransferBuffer->textureDownloadCapacity) {
+        d3d11TransferBuffer->textureDownloadCapacity += 1;
+        d3d11TransferBuffer->textureDownloads = SDL_realloc(
+            d3d11TransferBuffer->textureDownloads,
+            d3d11TransferBuffer->textureDownloadCapacity * sizeof(D3D11TextureDownload));
+    }
+
+    textureDownload = &d3d11TransferBuffer->textureDownloads[d3d11TransferBuffer->textureDownloadCount];
+    d3d11TransferBuffer->textureDownloadCount += 1;
+
+    if (bufferStride == 0) {
+        bufferStride = source->w;
+    }
+
+    if (bufferImageHeight == 0) {
+        bufferImageHeight = source->h;
+    }
+
+    bytesPerRow = BytesPerRow(bufferStride, srcFormat);
+    bytesPerDepthSlice = bytesPerRow * bufferImageHeight;
+
+    if (source->d == 1) {
+        stagingDesc2D.Width = source->w;
+        stagingDesc2D.Height = source->h;
+        stagingDesc2D.MipLevels = 1;
+        stagingDesc2D.ArraySize = 1;
+        stagingDesc2D.Format = SDLToD3D11_TextureFormat[srcFormat];
+        stagingDesc2D.SampleDesc.Count = 1;
+        stagingDesc2D.SampleDesc.Quality = 0;
+        stagingDesc2D.Usage = D3D11_USAGE_STAGING;
+        stagingDesc2D.BindFlags = 0;
+        stagingDesc2D.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+        stagingDesc2D.MiscFlags = 0;
+
+        res = ID3D11Device_CreateTexture2D(
+            renderer->device,
+            &stagingDesc2D,
+            NULL,
+            (ID3D11Texture2D **)&textureDownload->stagingTexture);
+        ERROR_CHECK_RETURN("Staging texture creation failed", )
+    } else {
+        stagingDesc3D.Width = source->w;
+        stagingDesc3D.Height = source->h;
+        stagingDesc3D.Depth = source->d;
+        stagingDesc3D.MipLevels = 1;
+        stagingDesc3D.Format = SDLToD3D11_TextureFormat[srcFormat];
+        stagingDesc3D.Usage = D3D11_USAGE_STAGING;
+        stagingDesc3D.BindFlags = 0;
+        stagingDesc3D.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+        stagingDesc3D.MiscFlags = 0;
+
+        res = ID3D11Device_CreateTexture3D(
+            renderer->device,
+            &stagingDesc3D,
+            NULL,
+            (ID3D11Texture3D **)&textureDownload->stagingTexture);
+    }
+
+    textureDownload->width = source->w;
+    textureDownload->height = source->h;
+    textureDownload->depth = source->d;
+    textureDownload->bufferOffset = destination->offset;
+    textureDownload->bytesPerRow = bytesPerRow;
+    textureDownload->bytesPerDepthSlice = bytesPerDepthSlice;
+
+    ID3D11DeviceContext1_CopySubresourceRegion1(
+        d3d11CommandBuffer->context,
+        textureDownload->stagingTexture,
+        0,
+        0,
+        0,
+        0,
+        textureSubresource->parent->handle,
+        textureSubresource->index,
+        &srcBox,
+        D3D11_COPY_NO_OVERWRITE);
+
+    D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, textureSubresource->parent);
+    D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer);
+}
+
+static void D3D11_DownloadFromBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferRegion *source,
+    SDL_GpuTransferBufferLocation *destination)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = d3d11CommandBuffer->renderer;
+    D3D11TransferBufferContainer *dstTransferContainer = (D3D11TransferBufferContainer *)destination->transferBuffer;
+    D3D11TransferBuffer *d3d11TransferBuffer = dstTransferContainer->activeBuffer;
+    D3D11BufferContainer *srcBufferContainer = (D3D11BufferContainer *)source->buffer;
+    D3D11BufferDownload *bufferDownload;
+    D3D11_BOX srcBox = { source->offset, 0, 0, source->size, 1, 1 };
+    D3D11_BUFFER_DESC stagingBufferDesc;
+    HRESULT res;
+
+    if (d3d11TransferBuffer->bufferDownloadCount >= d3d11TransferBuffer->bufferDownloadCapacity) {
+        d3d11TransferBuffer->bufferDownloadCapacity += 1;
+        d3d11TransferBuffer->bufferDownloads = SDL_realloc(
+            d3d11TransferBuffer->bufferDownloads,
+            d3d11TransferBuffer->bufferDownloadCapacity * sizeof(D3D11BufferDownload));
+    }
+
+    bufferDownload = &d3d11TransferBuffer->bufferDownloads[d3d11TransferBuffer->bufferDownloadCount];
+    d3d11TransferBuffer->bufferDownloadCount += 1;
+
+    stagingBufferDesc.ByteWidth = source->size;
+    stagingBufferDesc.Usage = D3D11_USAGE_STAGING;
+    stagingBufferDesc.BindFlags = 0;
+    stagingBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+    stagingBufferDesc.MiscFlags = 0;
+    stagingBufferDesc.StructureByteStride = 0;
+
+    res = ID3D11Device_CreateBuffer(
+        renderer->device,
+        &stagingBufferDesc,
+        NULL,
+        &bufferDownload->stagingBuffer);
+    ERROR_CHECK_RETURN("Could not create staging buffer", )
+
+    ID3D11DeviceContext1_CopySubresourceRegion1(
+        d3d11CommandBuffer->context,
+        (ID3D11Resource *)bufferDownload->stagingBuffer,
+        0,
+        0,
+        0,
+        0,
+        (ID3D11Resource *)srcBufferContainer->activeBuffer->handle,
+        0,
+        &srcBox,
+        D3D11_COPY_NO_OVERWRITE);
+
+    bufferDownload->dstOffset = destination->offset;
+    bufferDownload->size = source->size;
+
+    D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, srcBufferContainer->activeBuffer);
+    D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer);
+}
+
+static void D3D11_CopyTextureToTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureLocation *source,
+    SDL_GpuTextureLocation *destination,
+    Uint32 w,
+    Uint32 h,
+    Uint32 d,
+    SDL_bool cycle)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+    D3D11TextureContainer *srcContainer = (D3D11TextureContainer *)source->texture;
+    D3D11TextureContainer *dstContainer = (D3D11TextureContainer *)destination->texture;
+
+    D3D11_BOX srcBox = { source->x, source->y, source->z, source->x + w, source->y + h, source->z + d };
+
+    D3D11TextureSubresource *srcSubresource = D3D11_INTERNAL_FetchTextureSubresource(
+        srcContainer,
+        source->layer,
+        source->mipLevel);
+
+    D3D11TextureSubresource *dstSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
+        renderer,
+        dstContainer,
+        destination->layer,
+        destination->mipLevel,
+        cycle);
+
+    ID3D11DeviceContext1_CopySubresourceRegion(
+        d3d11CommandBuffer->context,
+        dstSubresource->parent->handle,
+        dstSubresource->index,
+        destination->x,
+        destination->y,
+        destination->z,
+        srcSubresource->parent->handle,
+        srcSubresource->index,
+        &srcBox);
+
+    D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, srcSubresource->parent);
+    D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, dstSubresource->parent);
+}
+
+static void D3D11_CopyBufferToBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferLocation *source,
+    SDL_GpuBufferLocation *destination,
+    Uint32 size,
+    SDL_bool cycle)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+    D3D11BufferContainer *srcBufferContainer = (D3D11BufferContainer *)source->buffer;
+    D3D11BufferContainer *dstBufferContainer = (D3D11BufferContainer *)destination->buffer;
+    D3D11_BOX srcBox = { source->offset, 0, 0, source->offset + size, 1, 1 };
+
+    D3D11Buffer *srcBuffer = srcBufferContainer->activeBuffer;
+    D3D11Buffer *dstBuffer = D3D11_INTERNAL_PrepareBufferForWrite(
+        renderer,
+        dstBufferContainer,
+        cycle);
+
+    ID3D11DeviceContext1_CopySubresourceRegion(
+        d3d11CommandBuffer->context,
+        (ID3D11Resource *)dstBuffer->handle,
+        0,
+        destination->offset,
+        0,
+        0,
+        (ID3D11Resource *)srcBuffer->handle,
+        0,
+        &srcBox);
+
+    D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, srcBuffer);
+    D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, dstBuffer);
+}
+
+static void D3D11_GenerateMipmaps(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTexture *texture)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11TextureContainer *d3d11TextureContainer = (D3D11TextureContainer *)texture;
+
+    ID3D11DeviceContext1_GenerateMips(
+        d3d11CommandBuffer->context,
+        d3d11TextureContainer->activeTexture->shaderView);
+
+    D3D11_INTERNAL_TrackTexture(
+        d3d11CommandBuffer,
+        d3d11TextureContainer->activeTexture);
+}
+
+static void D3D11_EndCopyPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    // no-op
+}
+
+// Graphics State
+
+static void D3D11_INTERNAL_AllocateCommandBuffers(
+    D3D11Renderer *renderer,
+    Uint32 allocateCount)
+{
+    D3D11CommandBuffer *commandBuffer;
+    HRESULT res;
+
+    renderer->availableCommandBufferCapacity += allocateCount;
+
+    renderer->availableCommandBuffers = SDL_realloc(
+        renderer->availableCommandBuffers,
+        sizeof(D3D11CommandBuffer *) * renderer->availableCommandBufferCapacity);
+
+    for (Uint32 i = 0; i < allocateCount; i += 1) {
+        commandBuffer = SDL_calloc(1, sizeof(D3D11CommandBuffer));
+        commandBuffer->renderer = renderer;
+
+        // Deferred Device Context
+        res = ID3D11Device1_CreateDeferredContext1(
+            renderer->device,
+            0,
+            &commandBuffer->context);
+        ERROR_CHECK("Could not create deferred context");
+
+        // Initialize debug annotation support, if available
+        ID3D11DeviceContext_QueryInterface(
+            commandBuffer->context,
+            &D3D_IID_ID3DUserDefinedAnnotation,
+            (void **)&commandBuffer->annotation);
+
+        // Window handling
+        commandBuffer->windowDataCapacity = 1;
+        commandBuffer->windowDataCount = 0;
+        commandBuffer->windowDatas = SDL_malloc(
+            commandBuffer->windowDataCapacity * sizeof(D3D11WindowData *));
+
+        // Reference Counting
+        commandBuffer->usedBufferCapacity = 4;
+        commandBuffer->usedBufferCount = 0;
+        commandBuffer->usedBuffers = SDL_malloc(
+            commandBuffer->usedBufferCapacity * sizeof(D3D11Buffer *));
+
+        commandBuffer->usedTransferBufferCapacity = 4;
+        commandBuffer->usedTransferBufferCount = 0;
+        commandBuffer->usedTransferBuffers = SDL_malloc(
+            commandBuffer->usedTransferBufferCapacity * sizeof(D3D11TransferBuffer *));
+
+        commandBuffer->usedTextureCapacity = 4;
+        commandBuffer->usedTextureCount = 0;
+        commandBuffer->usedTextures = SDL_malloc(
+            commandBuffer->usedTextureCapacity * sizeof(D3D11Texture *));
+
+        commandBuffer->usedUniformBufferCapacity = 4;
+        commandBuffer->usedUniformBufferCount = 0;
+        commandBuffer->usedUniformBuffers = SDL_malloc(
+            commandBuffer->usedUniformBufferCapacity * sizeof(D3D11UniformBuffer *));
+
+        renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
+        renderer->availableCommandBufferCount += 1;
+    }
+}
+
+static D3D11CommandBuffer *D3D11_INTERNAL_GetInactiveCommandBufferFromPool(
+    D3D11Renderer *renderer)
+{
+    D3D11CommandBuffer *commandBuffer;
+
+    if (renderer->availableCommandBufferCount == 0) {
+        D3D11_INTERNAL_AllocateCommandBuffers(
+            renderer,
+            renderer->availableCommandBufferCapacity);
+    }
+
+    commandBuffer = renderer->availableCommandBuffers[renderer->availableCommandBufferCount - 1];
+    renderer->availableCommandBufferCount -= 1;
+
+    return commandBuffer;
+}
+
+static SDL_bool D3D11_INTERNAL_CreateFence(
+    D3D11Renderer *renderer)
+{
+    D3D11_QUERY_DESC queryDesc;
+    ID3D11Query *queryHandle;
+    D3D11Fence *fence;
+    HRESULT res;
+
+    queryDesc.Query = D3D11_QUERY_EVENT;
+    queryDesc.MiscFlags = 0;
+    res = ID3D11Device_CreateQuery(
+        renderer->device,
+        &queryDesc,
+        &queryHandle);
+    ERROR_CHECK_RETURN("Could not create query", 0);
+
+    fence = SDL_malloc(sizeof(D3D11Fence));
+    fence->handle = queryHandle;
+    SDL_AtomicSet(&fence->referenceCount, 0);
+
+    // Add it to the available pool
+    if (renderer->availableFenceCount >= renderer->availableFenceCapacity) {
+        renderer->availableFenceCapacity *= 2;
+        renderer->availableFences = SDL_realloc(
+            renderer->availableFences,
+            sizeof(D3D11Fence *) * renderer->availableFenceCapacity);
+    }
+
+    renderer->availableFences[renderer->availableFenceCount] = fence;
+    renderer->availableFenceCount += 1;
+
+    return SDL_TRUE;
+}
+
+static SDL_bool D3D11_INTERNAL_AcquireFence(
+    D3D11CommandBuffer *commandBuffer)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+    D3D11Fence *fence;
+
+    // Acquire a fence from the pool
+    SDL_LockMutex(renderer->fenceLock);
+
+    if (renderer->availableFenceCount == 0) {
+        if (!D3D11_INTERNAL_CreateFence(renderer)) {
+            SDL_UnlockMutex(renderer->fenceLock);
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create fence!");
+            return SDL_FALSE;
+        }
+    }
+
+    fence = renderer->availableFences[renderer->availableFenceCount - 1];
+    renderer->availableFenceCount -= 1;
+
+    SDL_UnlockMutex(renderer->fenceLock);
+
+    // Associate the fence with the command buffer
+    commandBuffer->fence = fence;
+    (void)SDL_AtomicIncRef(&commandBuffer->fence->referenceCount);
+
+    return SDL_TRUE;
+}
+
+static SDL_GpuCommandBuffer *D3D11_AcquireCommandBuffer(
+    SDL_GpuRenderer *driverData)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11CommandBuffer *commandBuffer;
+    Uint32 i;
+
+    SDL_LockMutex(renderer->acquireCommandBufferLock);
+
+    commandBuffer = D3D11_INTERNAL_GetInactiveCommandBufferFromPool(renderer);
+    commandBuffer->graphicsPipeline = NULL;
+    commandBuffer->computePipeline = NULL;
+    for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
+        commandBuffer->colorTargetResolveTexture[i] = NULL;
+        commandBuffer->colorTargetResolveSubresourceIndex[i] = 0;
+        commandBuffer->colorTargetMsaaHandle[i] = NULL;
+        commandBuffer->colorTargetMsaaFormat[i] = DXGI_FORMAT_UNKNOWN;
+    }
+
+    for (i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        commandBuffer->vertexUniformBuffers[i] = NULL;
+        commandBuffer->fragmentUniformBuffers[i] = NULL;
+        commandBuffer->computeUniformBuffers[i] = NULL;
+    }
+
+    commandBuffer->needVertexSamplerBind = SDL_TRUE;
+    commandBuffer->needVertexResourceBind = SDL_TRUE;
+    commandBuffer->needVertexUniformBufferBind = SDL_TRUE;
+    commandBuffer->needFragmentSamplerBind = SDL_TRUE;
+    commandBuffer->needFragmentResourceBind = SDL_TRUE;
+    commandBuffer->needFragmentUniformBufferBind = SDL_TRUE;
+    commandBuffer->needComputeUAVBind = SDL_TRUE;
+    commandBuffer->needComputeSRVBind = SDL_TRUE;
+    commandBuffer->needComputeUniformBufferBind = SDL_TRUE;
+
+    SDL_zeroa(commandBuffer->vertexSamplers);
+    SDL_zeroa(commandBuffer->vertexShaderResourceViews);
+    SDL_zeroa(commandBuffer->fragmentSamplers);
+    SDL_zeroa(commandBuffer->fragmentShaderResourceViews);
+    SDL_zeroa(commandBuffer->computeShaderResourceViews);
+    SDL_zeroa(commandBuffer->computeUnorderedAccessViews);
+
+    D3D11_INTERNAL_AcquireFence(commandBuffer);
+    commandBuffer->autoReleaseFence = 1;
+
+    SDL_UnlockMutex(renderer->acquireCommandBufferLock);
+
+    return (SDL_GpuCommandBuffer *)commandBuffer;
+}
+
+static D3D11UniformBuffer *D3D11_INTERNAL_AcquireUniformBufferFromPool(
+    D3D11CommandBuffer *commandBuffer)
+{
+    D3D11Renderer *renderer = commandBuffer->renderer;
+    D3D11UniformBuffer *uniformBuffer;
+
+    SDL_LockMutex(renderer->acquireUniformBufferLock);
+
+    if (renderer->uniformBufferPoolCount > 0) {
+        uniformBuffer = renderer->uniformBufferPool[renderer->uniformBufferPoolCount - 1];
+        renderer->uniformBufferPoolCount -= 1;
+    } else {
+        uniformBuffer = D3D11_INTERNAL_CreateUniformBuffer(
+            renderer,
+            UNIFORM_BUFFER_SIZE);
+    }
+
+    SDL_UnlockMutex(renderer->acquireUniformBufferLock);
+
+    D3D11_INTERNAL_TrackUniformBuffer(commandBuffer, uniformBuffer);
+
+    return uniformBuffer;
+}
+
+static void D3D11_INTERNAL_ReturnUniformBufferToPool(
+    D3D11Renderer *renderer,
+    D3D11UniformBuffer *uniformBuffer)
+{
+    if (renderer->uniformBufferPoolCount >= renderer->uniformBufferPoolCapacity) {
+        renderer->uniformBufferPoolCapacity *= 2;
+        renderer->uniformBufferPool = SDL_realloc(
+            renderer->uniformBufferPool,
+            renderer->uniformBufferPoolCapacity * sizeof(D3D11UniformBuffer *));
+    }
+
+    renderer->uniformBufferPool[renderer->uniformBufferPoolCount] = uniformBuffer;
+    renderer->uniformBufferPoolCount += 1;
+
+    uniformBuffer->writeOffset = 0;
+    uniformBuffer->drawOffset = 0;
+    uniformBuffer->mappedData = NULL;
+}
+
+static void D3D11_INTERNAL_PushUniformData(
+    D3D11CommandBuffer *d3d11CommandBuffer,
+    SDL_GpuShaderStage shaderStage,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    D3D11Renderer *renderer = d3d11CommandBuffer->renderer;
+    D3D11UniformBuffer *d3d11UniformBuffer;
+    D3D11_MAPPED_SUBRESOURCE subres;
+    HRESULT res;
+
+    if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
+        if (d3d11CommandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
+            d3d11CommandBuffer->vertexUniformBuffers[slotIndex] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
+                d3d11CommandBuffer);
+        }
+        d3d11UniformBuffer = d3d11CommandBuffer->vertexUniformBuffers[slotIndex];
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
+        if (d3d11CommandBuffer->fragmentUniformBuffers[slotIndex] == NULL) {
+            d3d11CommandBuffer->fragmentUniformBuffers[slotIndex] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
+                d3d11CommandBuffer);
+        }
+        d3d11UniformBuffer = d3d11CommandBuffer->fragmentUniformBuffers[slotIndex];
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
+        if (d3d11CommandBuffer->computeUniformBuffers[slotIndex] == NULL) {
+            d3d11CommandBuffer->computeUniformBuffers[slotIndex] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
+                d3d11CommandBuffer);
+        }
+        d3d11UniformBuffer = d3d11CommandBuffer->computeUniformBuffers[slotIndex];
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+        return;
+    }
+
+    d3d11UniformBuffer->currentBlockSize =
+        D3D11_INTERNAL_NextHighestAlignment(
+            dataLengthInBytes,
+            256);
+
+    // If there is no more room, acquire a new uniform buffer
+    if (d3d11UniformBuffer->writeOffset + d3d11UniformBuffer->currentBlockSize >= UNIFORM_BUFFER_SIZE) {
+        ID3D11DeviceContext_Unmap(
+            d3d11CommandBuffer->context,
+            (ID3D11Resource *)d3d11UniformBuffer->buffer,
+            0);
+        d3d11UniformBuffer->mappedData = NULL;
+
+        d3d11UniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool(d3d11CommandBuffer);
+
+        d3d11UniformBuffer->drawOffset = 0;
+        d3d11UniformBuffer->writeOffset = 0;
+
+        if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
+            d3d11CommandBuffer->vertexUniformBuffers[slotIndex] = d3d11UniformBuffer;
+        } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
+            d3d11CommandBuffer->fragmentUniformBuffers[slotIndex] = d3d11UniformBuffer;
+        } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
+            d3d11CommandBuffer->computeUniformBuffers[slotIndex] = d3d11UniformBuffer;
+        } else {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+        }
+    }
+
+    // Map the uniform data on first push
+    if (d3d11UniformBuffer->writeOffset == 0) {
+        res = ID3D11DeviceContext_Map(
+            d3d11CommandBuffer->context,
+            (ID3D11Resource *)d3d11UniformBuffer->buffer,
+            0,
+            D3D11_MAP_WRITE_DISCARD,
+            0,
+            &subres);
+        ERROR_CHECK_RETURN("Failed to map uniform buffer", )
+
+        d3d11UniformBuffer->mappedData = subres.pData;
+    }
+
+    d3d11UniformBuffer->drawOffset = d3d11UniformBuffer->writeOffset;
+
+    SDL_memcpy(
+        (Uint8 *)d3d11UniformBuffer->mappedData + d3d11UniformBuffer->writeOffset,
+        data,
+        dataLengthInBytes);
+
+    d3d11UniformBuffer->writeOffset += d3d11UniformBuffer->currentBlockSize;
+
+    if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
+        d3d11CommandBuffer->needVertexUniformBufferBind = SDL_TRUE;
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
+        d3d11CommandBuffer->needFragmentUniformBufferBind = SDL_TRUE;
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
+        d3d11CommandBuffer->needComputeUniformBufferBind = SDL_TRUE;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+    }
+}
+
+static void D3D11_BeginRenderPass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuColorAttachmentInfo *colorAttachmentInfos,
+    Uint32 colorAttachmentCount,
+    SDL_GpuDepthStencilAttachmentInfo *depthStencilAttachmentInfo)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+    ID3D11RenderTargetView *rtvs[MAX_COLOR_TARGET_BINDINGS];
+    ID3D11DepthStencilView *dsv = NULL;
+    Uint32 vpWidth = SDL_MAX_UINT32;
+    Uint32 vpHeight = SDL_MAX_UINT32;
+    D3D11_VIEWPORT viewport;
+    D3D11_RECT scissorRect;
+
+    d3d11CommandBuffer->needVertexSamplerBind = SDL_TRUE;
+    d3d11CommandBuffer->needVertexResourceBind = SDL_TRUE;
+    d3d11CommandBuffer->needFragmentSamplerBind = SDL_TRUE;
+    d3d11CommandBuffer->needFragmentResourceBind = SDL_TRUE;
+
+    // Clear the bound targets for the current command buffer
+    for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
+        d3d11CommandBuffer->colorTargetResolveTexture[i] = NULL;
+        d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i] = 0;
+        d3d11CommandBuffer->colorTargetMsaaHandle[i] = NULL;
+        d3d11CommandBuffer->colorTargetMsaaFormat[i] = DXGI_FORMAT_UNKNOWN;
+    }
+
+    // Set up the new color target bindings
+    for (Uint32 i = 0; i < colorAttachmentCount; i += 1) {
+        D3D11TextureContainer *container = (D3D11TextureContainer *)colorAttachmentInfos[i].texture;
+        D3D11TextureSubresource *subresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
+            renderer,
+            container,
+            container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorAttachmentInfos[i].layerOrDepthPlane,
+            colorAttachmentInfos[i].mipLevel,
+            colorAttachmentInfos[i].cycle);
+
+        if (subresource->msaaHandle != NULL) {
+            d3d11CommandBuffer->colorTargetResolveTexture[i] = subresource->parent;
+            d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i] = subresource->index;
+            d3d11CommandBuffer->colorTargetMsaaHandle[i] = subresource->msaaHandle;
+            d3d11CommandBuffer->colorTargetMsaaFormat[i] = SDLToD3D11_TextureFormat[container->header.info.format];
+
+            rtvs[i] = subresource->msaaTargetView;
+        } else {
+            Uint32 rtvIndex = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorAttachmentInfos[i].layerOrDepthPlane : 0;
+            rtvs[i] = subresource->colorTargetViews[rtvIndex];
+        }
+
+        if (colorAttachmentInfos[i].loadOp == SDL_GPU_LOADOP_CLEAR) {
+            float clearColor[] = {
+                colorAttachmentInfos[i].clearColor.r,
+                colorAttachmentInfos[i].clearColor.g,
+                colorAttachmentInfos[i].clearColor.b,
+                colorAttachmentInfos[i].clearColor.a
+            };
+            ID3D11DeviceContext_ClearRenderTargetView(
+                d3d11CommandBuffer->context,
+                rtvs[i],
+                clearColor);
+        }
+
+        D3D11_INTERNAL_TrackTexture(
+            d3d11CommandBuffer,
+            subresource->parent);
+    }
+
+    // Get the DSV for the depth stencil attachment, if applicable
+    if (depthStencilAttachmentInfo != NULL) {
+        D3D11TextureContainer *container = (D3D11TextureContainer *)depthStencilAttachmentInfo->texture;
+        D3D11TextureSubresource *subresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
+            renderer,
+            container,
+            0,
+            0,
+            depthStencilAttachmentInfo->cycle);
+
+        dsv = subresource->depthStencilTargetView;
+
+        D3D11_INTERNAL_TrackTexture(
+            d3d11CommandBuffer,
+            subresource->parent);
+    }
+
+    // Actually set the RTs
+    ID3D11DeviceContext_OMSetRenderTargets(
+        d3d11CommandBuffer->context,
+        colorAttachmentCount,
+        colorAttachmentCount > 0 ? rtvs : NULL,
+        dsv);
+
+    if (depthStencilAttachmentInfo != NULL) {
+        D3D11_CLEAR_FLAG dsClearFlags = 0;
+        if (depthStencilAttachmentInfo->loadOp == SDL_GPU_LOADOP_CLEAR) {
+            dsClearFlags |= D3D11_CLEAR_DEPTH;
+        }
+        if (depthStencilAttachmentInfo->stencilLoadOp == SDL_GPU_LOADOP_CLEAR) {
+            dsClearFlags |= D3D11_CLEAR_STENCIL;
+        }
+
+        if (dsClearFlags != 0) {
+            ID3D11DeviceContext_ClearDepthStencilView(
+                d3d11CommandBuffer->context,
+                dsv,
+                dsClearFlags,
+                depthStencilAttachmentInfo->depthStencilClearValue.depth,
+                depthStencilAttachmentInfo->depthStencilClearValue.stencil);
+        }
+    }
+
+    // The viewport cannot be larger than the smallest attachment.
+    for (Uint32 i = 0; i < colorAttachmentCount; i += 1) {
+        D3D11TextureContainer *container = (D3D11TextureContainer *)colorAttachmentInfos[i].texture;
+        Uint32 w = container->header.info.width >> colorAttachmentInfos[i].mipLevel;
+        Uint32 h = container->header.info.height >> colorAttachmentInfos[i].mipLevel;
+
+        if (w < vpWidth) {
+            vpWidth = w;
+        }
+
+        if (h < vpHeight) {
+            vpHeight = h;
+        }
+    }
+
+    if (depthStencilAttachmentInfo != NULL) {
+        D3D11TextureContainer *container = (D3D11TextureContainer *)depthStencilAttachmentInfo->texture;
+        Uint32 w = container->header.info.width;
+        Uint32 h = container->header.info.height;
+
+        if (w < vpWidth) {
+            vpWidth = w;
+        }
+
+        if (h < vpHeight) {
+            vpHeight = h;
+        }
+    }
+
+    // Set default viewport and scissor state
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+    viewport.Width = (FLOAT)vpWidth;
+    viewport.Height = (FLOAT)vpHeight;
+    viewport.MinDepth = 0;
+    viewport.MaxDepth = 1;
+
+    ID3D11DeviceContext_RSSetViewports(
+        d3d11CommandBuffer->context,
+        1,
+        &viewport);
+
+    scissorRect.left = 0;
+    scissorRect.right = (LONG)viewport.Width;
+    scissorRect.top = 0;
+    scissorRect.bottom = (LONG)viewport.Height;
+
+    ID3D11DeviceContext_RSSetScissorRects(
+        d3d11CommandBuffer->context,
+        1,
+        &scissorRect);
+}
+
+static void D3D11_BindGraphicsPipeline(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuGraphicsPipeline *graphicsPipeline)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11GraphicsPipeline *pipeline = (D3D11GraphicsPipeline *)graphicsPipeline;
+
+    d3d11CommandBuffer->graphicsPipeline = pipeline;
+
+    ID3D11DeviceContext_OMSetBlendState(
+        d3d11CommandBuffer->context,
+        pipeline->colorAttachmentBlendState,
+        pipeline->blendConstants,
+        pipeline->multisampleState.sampleMask);
+
+    ID3D11DeviceContext_OMSetDepthStencilState(
+        d3d11CommandBuffer->context,
+        pipeline->depthStencilState,
+        pipeline->stencilRef);
+
+    ID3D11DeviceContext_IASetPrimitiveTopology(
+        d3d11CommandBuffer->context,
+        SDLToD3D11_PrimitiveType[pipeline->primitiveType]);
+
+    ID3D11DeviceContext_IASetInputLayout(
+        d3d11CommandBuffer->context,
+        pipeline->inputLayout);
+
+    ID3D11DeviceContext_RSSetState(
+        d3d11CommandBuffer->context,
+        pipeline->rasterizerState);
+
+    ID3D11DeviceContext_VSSetShader(
+        d3d11CommandBuffer->context,
+        pipeline->vertexShader,
+        NULL,
+        0);
+
+    ID3D11DeviceContext_PSSetShader(
+        d3d11CommandBuffer->context,
+        pipeline->fragmentShader,
+        NULL,
+        0);
+
+    // Acquire uniform buffers if necessary
+    for (Uint32 i = 0; i < pipeline->vertexUniformBufferCount; i += 1) {
+        if (d3d11CommandBuffer->vertexUniformBuffers[i] == NULL) {
+            d3d11CommandBuffer->vertexUniformBuffers[i] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
+                d3d11CommandBuffer);
+        }
+    }
+
+    for (Uint32 i = 0; i < pipeline->fragmentUniformBufferCount; i += 1) {
+        if (d3d11CommandBuffer->fragmentUniformBuffers[i] == NULL) {
+            d3d11CommandBuffer->fragmentUniformBuffers[i] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
+                d3d11CommandBuffer);
+        }
+    }
+
+    // Mark that uniform bindings are needed
+    d3d11CommandBuffer->needVertexUniformBufferBind = SDL_TRUE;
+    d3d11CommandBuffer->needFragmentUniformBufferBind = SDL_TRUE;
+}
+
+static void D3D11_SetViewport(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuViewport *viewport)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11_VIEWPORT vp = {
+        viewport->x,
+        viewport->y,
+        viewport->w,
+        viewport->h,
+        viewport->minDepth,
+        viewport->maxDepth
+    };
+
+    ID3D11DeviceContext_RSSetViewports(
+        d3d11CommandBuffer->context,
+        1,
+        &vp);
+}
+
+static void D3D11_SetScissor(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_Rect *scissor)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11_RECT rect = {
+        scissor->x,
+        scissor->y,
+        scissor->x + scissor->w,
+        scissor->y + scissor->h
+    };
+
+    ID3D11DeviceContext_RSSetScissorRects(
+        d3d11CommandBuffer->context,
+        1,
+        &rect);
+}
+
+static void D3D11_BindVertexBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstBinding,
+    SDL_GpuBufferBinding *pBindings,
+    Uint32 bindingCount)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D11Buffer *currentBuffer = ((D3D11BufferContainer *)pBindings[i].buffer)->activeBuffer;
+        d3d11CommandBuffer->vertexBuffers[firstBinding + i] = currentBuffer->handle;
+        d3d11CommandBuffer->vertexBufferOffsets[firstBinding + i] = pBindings[i].offset;
+        D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, currentBuffer);
+    }
+
+    d3d11CommandBuffer->vertexBufferCount =
+        SDL_max(d3d11CommandBuffer->vertexBufferCount, firstBinding + bindingCount);
+
+    d3d11CommandBuffer->needVertexBufferBind = SDL_TRUE;
+}
+
+static void D3D11_BindIndexBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferBinding *pBinding,
+    SDL_GpuIndexElementSize indexElementSize)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)pBinding->buffer)->activeBuffer;
+
+    D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer);
+
+    ID3D11DeviceContext_IASetIndexBuffer(
+        d3d11CommandBuffer->context,
+        d3d11Buffer->handle,
+        SDLToD3D11_IndexType[indexElementSize],
+        (UINT)pBinding->offset);
+}
+
+static void D3D11_BindVertexSamplers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)textureSamplerBindings[i].texture;
+
+        D3D11_INTERNAL_TrackTexture(
+            d3d11CommandBuffer,
+            textureContainer->activeTexture);
+
+        d3d11CommandBuffer->vertexSamplers[firstSlot + i] =
+            ((D3D11Sampler *)textureSamplerBindings[i].sampler)->handle;
+
+        d3d11CommandBuffer->vertexShaderResourceViews[firstSlot + i] =
+            textureContainer->activeTexture->shaderView;
+    }
+
+    d3d11CommandBuffer->needVertexSamplerBind = SDL_TRUE;
+    d3d11CommandBuffer->needVertexResourceBind = SDL_TRUE;
+}
+
+static void D3D11_BindVertexStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)storageTextures[i];
+
+        D3D11_INTERNAL_TrackTexture(
+            d3d11CommandBuffer,
+            textureContainer->activeTexture);
+
+        d3d11CommandBuffer->vertexShaderResourceViews[firstSlot + i +
+                                                      d3d11CommandBuffer->graphicsPipeline->vertexSamplerCount] = textureContainer->activeTexture->shaderView;
+    }
+
+    d3d11CommandBuffer->needVertexResourceBind = SDL_TRUE;
+}
+
+static void D3D11_BindVertexStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11BufferContainer *bufferContainer;
+    Uint32 i;
+
+    for (i = 0; i < bindingCount; i += 1) {
+        bufferContainer = (D3D11BufferContainer *)storageBuffers[i];
+
+        D3D11_INTERNAL_TrackBuffer(
+            d3d11CommandBuffer,
+            bufferContainer->activeBuffer);
+
+        d3d11CommandBuffer->vertexShaderResourceViews[firstSlot + i +
+                                                      d3d11CommandBuffer->graphicsPipeline->vertexSamplerCount +
+                                                      d3d11CommandBuffer->graphicsPipeline->vertexStorageTextureCount] = bufferContainer->activeBuffer->srv;
+    }
+
+    d3d11CommandBuffer->needVertexResourceBind = SDL_TRUE;
+}
+
+static void D3D11_BindFragmentSamplers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)textureSamplerBindings[i].texture;
+
+        D3D11_INTERNAL_TrackTexture(
+            d3d11CommandBuffer,
+            textureContainer->activeTexture);
+
+        d3d11CommandBuffer->fragmentSamplers[firstSlot + i] =
+            ((D3D11Sampler *)textureSamplerBindings[i].sampler)->handle;
+
+        d3d11CommandBuffer->fragmentShaderResourceViews[firstSlot + i] =
+            textureContainer->activeTexture->shaderView;
+    }
+
+    d3d11CommandBuffer->needFragmentSamplerBind = SDL_TRUE;
+    d3d11CommandBuffer->needFragmentResourceBind = SDL_TRUE;
+}
+
+static void D3D11_BindFragmentStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)storageTextures[i];
+
+        D3D11_INTERNAL_TrackTexture(
+            d3d11CommandBuffer,
+            textureContainer->activeTexture);
+
+        d3d11CommandBuffer->fragmentShaderResourceViews[firstSlot + i +
+                                                        d3d11CommandBuffer->graphicsPipeline->fragmentSamplerCount] = textureContainer->activeTexture->shaderView;
+    }
+
+    d3d11CommandBuffer->needFragmentResourceBind = SDL_TRUE;
+}
+
+static void D3D11_BindFragmentStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11BufferContainer *bufferContainer;
+    Uint32 i;
+
+    for (i = 0; i < bindingCount; i += 1) {
+        bufferContainer = (D3D11BufferContainer *)storageBuffers[i];
+
+        D3D11_INTERNAL_TrackBuffer(
+            d3d11CommandBuffer,
+            bufferContainer->activeBuffer);
+
+        d3d11CommandBuffer->fragmentShaderResourceViews[firstSlot + i +
+                                                        d3d11CommandBuffer->graphicsPipeline->fragmentSamplerCount +
+                                                        d3d11CommandBuffer->graphicsPipeline->fragmentStorageTextureCount] = bufferContainer->activeBuffer->srv;
+    }
+
+    d3d11CommandBuffer->needFragmentResourceBind = SDL_TRUE;
+}
+
+static void D3D11_INTERNAL_BindGraphicsResources(
+    D3D11CommandBuffer *commandBuffer)
+{
+    D3D11GraphicsPipeline *graphicsPipeline = commandBuffer->graphicsPipeline;
+
+    Uint32 vertexResourceCount =
+        graphicsPipeline->vertexSamplerCount +
+        graphicsPipeline->vertexStorageTextureCount +
+        graphicsPipeline->vertexStorageBufferCount;
+
+    Uint32 fragmentResourceCount =
+        graphicsPipeline->fragmentSamplerCount +
+        graphicsPipeline->fragmentStorageTextureCount +
+        graphicsPipeline->fragmentStorageBufferCount;
+
+    ID3D11Buffer *nullBuf = NULL;
+    Uint32 offsetInConstants, blockSizeInConstants, i;
+
+    if (commandBuffer->needVertexBufferBind) {
+        ID3D11DeviceContext_IASetVertexBuffers(
+            commandBuffer->context,
+            0,
+            commandBuffer->vertexBufferCount,
+            commandBuffer->vertexBuffers,
+            graphicsPipeline->vertexStrides,
+            commandBuffer->vertexBufferOffsets);
+    }
+
+    if (commandBuffer->needVertexSamplerBind) {
+        if (graphicsPipeline->vertexSamplerCount > 0) {
+            ID3D11DeviceContext_VSSetSamplers(
+                commandBuffer->context,
+                0,
+                graphicsPipeline->vertexSamplerCount,
+                commandBuffer->vertexSamplers);
+        }
+
+        commandBuffer->needVertexSamplerBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needVertexResourceBind) {
+        if (vertexResourceCount > 0) {
+            ID3D11DeviceContext_VSSetShaderResources(
+                commandBuffer->context,
+                0,
+                vertexResourceCount,
+                commandBuffer->vertexShaderResourceViews);
+        }
+
+        commandBuffer->needVertexResourceBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needVertexUniformBufferBind) {
+        for (i = 0; i < graphicsPipeline->vertexUniformBufferCount; i += 1) {
+            /* stupid workaround for god awful D3D11 drivers
+             * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1#calling-vssetconstantbuffers1-with-command-list-emulation
+             */
+            ID3D11DeviceContext1_VSSetConstantBuffers(
+                commandBuffer->context,
+                i,
+                1,
+                &nullBuf);
+
+            offsetInConstants = commandBuffer->vertexUniformBuffers[i]->drawOffset / 16;
+            blockSizeInConstants = commandBuffer->vertexUniformBuffers[i]->currentBlockSize / 16;
+
+            ID3D11DeviceContext1_VSSetConstantBuffers1(
+                commandBuffer->context,
+                i,
+                1,
+                &commandBuffer->vertexUniformBuffers[i]->buffer,
+                &offsetInConstants,
+                &blockSizeInConstants);
+        }
+
+        commandBuffer->needVertexUniformBufferBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needFragmentSamplerBind) {
+        if (graphicsPipeline->fragmentSamplerCount > 0) {
+            ID3D11DeviceContext_PSSetSamplers(
+                commandBuffer->context,
+                0,
+                graphicsPipeline->fragmentSamplerCount,
+                commandBuffer->fragmentSamplers);
+        }
+
+        commandBuffer->needFragmentSamplerBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needFragmentResourceBind) {
+        if (fragmentResourceCount > 0) {
+            ID3D11DeviceContext_PSSetShaderResources(
+                commandBuffer->context,
+                0,
+                fragmentResourceCount,
+                commandBuffer->fragmentShaderResourceViews);
+        }
+
+        commandBuffer->needFragmentResourceBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needFragmentUniformBufferBind) {
+        for (i = 0; i < graphicsPipeline->fragmentUniformBufferCount; i += 1) {
+            /* stupid workaround for god awful D3D11 drivers
+             * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-pssetconstantbuffers1#calling-pssetconstantbuffers1-with-command-list-emulation
+             */
+            ID3D11DeviceContext1_PSSetConstantBuffers(
+                commandBuffer->context,
+                i,
+                1,
+                &nullBuf);
+
+            offsetInConstants = commandBuffer->fragmentUniformBuffers[i]->drawOffset / 16;
+            blockSizeInConstants = commandBuffer->fragmentUniformBuffers[i]->currentBlockSize / 16;
+
+            ID3D11DeviceContext1_PSSetConstantBuffers1(
+                commandBuffer->context,
+                i,
+                1,
+                &commandBuffer->fragmentUniformBuffers[i]->buffer,
+                &offsetInConstants,
+                &blockSizeInConstants);
+        }
+
+        commandBuffer->needFragmentUniformBufferBind = SDL_FALSE;
+    }
+}
+
+static void D3D11_DrawIndexedPrimitives(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 indexCount,
+    Uint32 instanceCount,
+    Uint32 firstIndex,
+    Sint32 vertexOffset,
+    Uint32 firstInstance)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer);
+
+    ID3D11DeviceContext_DrawIndexedInstanced(
+        d3d11CommandBuffer->context,
+        indexCount,
+        instanceCount,
+        firstIndex,
+        vertexOffset,
+        firstInstance);
+}
+
+static void D3D11_DrawPrimitives(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 vertexCount,
+    Uint32 instanceCount,
+    Uint32 firstVertex,
+    Uint32 firstInstance)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer);
+
+    ID3D11DeviceContext_DrawInstanced(
+        d3d11CommandBuffer->context,
+        vertexCount,
+        instanceCount,
+        firstVertex,
+        firstInstance);
+}
+
+static void D3D11_DrawPrimitivesIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer);
+
+    D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)buffer)->activeBuffer;
+
+    /* D3D11: "We have multi-draw at home!"
+     * Multi-draw at home:
+     */
+    for (Uint32 i = 0; i < drawCount; i += 1) {
+        ID3D11DeviceContext_DrawInstancedIndirect(
+            d3d11CommandBuffer->context,
+            d3d11Buffer->handle,
+            offsetInBytes + (stride * i));
+    }
+
+    D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer);
+}
+
+static void D3D11_DrawIndexedPrimitivesIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer);
+
+    D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)buffer)->activeBuffer;
+
+    /* D3D11: "We have multi-draw at home!"
+     * Multi-draw at home:
+     */
+    for (Uint32 i = 0; i < drawCount; i += 1) {
+        ID3D11DeviceContext_DrawIndexedInstancedIndirect(
+            d3d11CommandBuffer->context,
+            d3d11Buffer->handle,
+            offsetInBytes + (stride * i));
+    }
+
+    D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer);
+}
+
+static void D3D11_EndRenderPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    Uint32 i;
+
+    // Set render target slots to NULL to avoid NULL set behavior
+    // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-pssetshaderresources
+    ID3D11DeviceContext_OMSetRenderTargets(
+        d3d11CommandBuffer->context,
+        MAX_COLOR_TARGET_BINDINGS,
+        nullRTVs,
+        NULL);
+
+    // Resolve MSAA color render targets
+    for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
+        if (d3d11CommandBuffer->colorTargetMsaaHandle[i] != NULL) {
+            ID3D11DeviceContext_ResolveSubresource(
+                d3d11CommandBuffer->context,
+                d3d11CommandBuffer->colorTargetResolveTexture[i]->handle,
+                d3d11CommandBuffer->colorTargetResolveSubresourceIndex[i],
+                d3d11CommandBuffer->colorTargetMsaaHandle[i],
+                0,
+                d3d11CommandBuffer->colorTargetMsaaFormat[i]);
+        }
+    }
+
+    // Reset bind state
+    SDL_zeroa(d3d11CommandBuffer->vertexBuffers);
+    SDL_zeroa(d3d11CommandBuffer->vertexBufferOffsets);
+    d3d11CommandBuffer->vertexBufferCount = 0;
+
+    SDL_zeroa(d3d11CommandBuffer->vertexSamplers);
+    SDL_zeroa(d3d11CommandBuffer->vertexShaderResourceViews);
+
+    SDL_zeroa(d3d11CommandBuffer->fragmentSamplers);
+    SDL_zeroa(d3d11CommandBuffer->fragmentShaderResourceViews);
+}
+
+static void D3D11_PushVertexUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    D3D11_INTERNAL_PushUniformData(
+        (D3D11CommandBuffer *)commandBuffer,
+        SDL_GPU_SHADERSTAGE_VERTEX,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+static void D3D11_PushFragmentUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    D3D11_INTERNAL_PushUniformData(
+        (D3D11CommandBuffer *)commandBuffer,
+        SDL_GPU_SHADERSTAGE_FRAGMENT,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+// Blit
+
+static void D3D11_Blit(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBlitRegion *source,
+    SDL_GpuBlitRegion *destination,
+    SDL_FlipMode flipMode,
+    SDL_GpuFilter filterMode,
+    SDL_bool cycle)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+    BlitPipelineCacheEntry *blitPipelines = &renderer->blitPipelines[0];
+
+    SDL_Gpu_BlitCommon(
+        commandBuffer,
+        source,
+        destination,
+        flipMode,
+        filterMode,
+        cycle,
+        renderer->blitLinearSampler,
+        renderer->blitNearestSampler,
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        &blitPipelines,
+        NULL,
+        NULL);
+}
+
+// Compute State
+
+static void D3D11_BeginComputePass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuStorageTextureWriteOnlyBinding *storageTextureBindings,
+    Uint32 storageTextureBindingCount,
+    SDL_GpuStorageBufferWriteOnlyBinding *storageBufferBindings,
+    Uint32 storageBufferBindingCount)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11TextureContainer *textureContainer;
+    D3D11TextureSubresource *textureSubresource;
+    D3D11BufferContainer *bufferContainer;
+    D3D11Buffer *buffer;
+    Uint32 i;
+
+    for (i = 0; i < storageTextureBindingCount; i += 1) {
+        textureContainer = (D3D11TextureContainer *)storageTextureBindings[i].texture;
+        if (!(textureContainer->header.info.usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT)) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Attempted to bind read-only texture as compute write texture");
+        }
+
+        textureSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite(
+            d3d11CommandBuffer->renderer,
+            textureContainer,
+            storageTextureBindings[i].layer,
+            storageTextureBindings[i].mipLevel,
+            storageTextureBindings[i].cycle);
+
+        D3D11_INTERNAL_TrackTexture(
+            d3d11CommandBuffer,
+            textureSubresource->parent);
+
+        d3d11CommandBuffer->computeUnorderedAccessViews[i] = textureSubresource->uav;
+    }
+
+    for (i = 0; i < storageBufferBindingCount; i += 1) {
+        bufferContainer = (D3D11BufferContainer *)storageBufferBindings[i].buffer;
+
+        buffer = D3D11_INTERNAL_PrepareBufferForWrite(
+            d3d11CommandBuffer->renderer,
+            bufferContainer,
+            storageBufferBindings[i].cycle);
+
+        D3D11_INTERNAL_TrackBuffer(
+            d3d11CommandBuffer,
+            buffer);
+
+        d3d11CommandBuffer->computeUnorderedAccessViews[i + storageTextureBindingCount] = buffer->uav;
+    }
+
+    d3d11CommandBuffer->needComputeUAVBind = SDL_TRUE;
+}
+
+static void D3D11_BindComputePipeline(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuComputePipeline *computePipeline)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11ComputePipeline *pipeline = (D3D11ComputePipeline *)computePipeline;
+
+    d3d11CommandBuffer->computePipeline = pipeline;
+
+    ID3D11DeviceContext_CSSetShader(
+        d3d11CommandBuffer->context,
+        pipeline->computeShader,
+        NULL,
+        0);
+
+    // Acquire uniform buffers if necessary
+    for (Uint32 i = 0; i < pipeline->uniformBufferCount; i += 1) {
+        if (d3d11CommandBuffer->computeUniformBuffers[i] == NULL) {
+            d3d11CommandBuffer->computeUniformBuffers[i] = D3D11_INTERNAL_AcquireUniformBufferFromPool(
+                d3d11CommandBuffer);
+        }
+    }
+
+    d3d11CommandBuffer->needComputeUniformBufferBind = SDL_TRUE;
+}
+
+static void D3D11_BindComputeStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)storageTextures[i];
+
+        D3D11_INTERNAL_TrackTexture(
+            d3d11CommandBuffer,
+            textureContainer->activeTexture);
+
+        d3d11CommandBuffer->computeShaderResourceViews[firstSlot + i] =
+            textureContainer->activeTexture->shaderView;
+    }
+
+    d3d11CommandBuffer->needComputeSRVBind = SDL_TRUE;
+}
+
+static void D3D11_BindComputeStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11BufferContainer *bufferContainer;
+    Uint32 i;
+
+    for (i = 0; i < bindingCount; i += 1) {
+        bufferContainer = (D3D11BufferContainer *)storageBuffers[i];
+
+        D3D11_INTERNAL_TrackBuffer(
+            d3d11CommandBuffer,
+            bufferContainer->activeBuffer);
+
+        d3d11CommandBuffer->computeShaderResourceViews[firstSlot + i +
+                                                       d3d11CommandBuffer->computePipeline->readOnlyStorageTextureCount] = bufferContainer->activeBuffer->srv;
+    }
+
+    d3d11CommandBuffer->needComputeSRVBind = SDL_TRUE;
+}
+
+static void D3D11_PushComputeUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    D3D11_INTERNAL_PushUniformData(
+        (D3D11CommandBuffer *)commandBuffer,
+        SDL_GPU_SHADERSTAGE_COMPUTE,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+static void D3D11_INTERNAL_BindComputeResources(
+    D3D11CommandBuffer *commandBuffer)
+{
+    D3D11ComputePipeline *computePipeline = commandBuffer->computePipeline;
+
+    Uint32 readOnlyResourceCount =
+        computePipeline->readOnlyStorageTextureCount +
+        computePipeline->readOnlyStorageBufferCount;
+
+    Uint32 writeOnlyResourceCount =
+        computePipeline->writeOnlyStorageTextureCount +
+        computePipeline->writeOnlyStorageBufferCount;
+
+    ID3D11Buffer *nullBuf = NULL;
+    Uint32 offsetInConstants, blockSizeInConstants, i;
+
+    if (commandBuffer->needComputeUAVBind) {
+        ID3D11DeviceContext_CSSetUnorderedAccessViews(
+            commandBuffer->context,
+            0,
+            writeOnlyResourceCount,
+            commandBuffer->computeUnorderedAccessViews,
+            NULL);
+
+        commandBuffer->needComputeUAVBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needComputeSRVBind) {
+        ID3D11DeviceContext_CSSetShaderResources(
+            commandBuffer->context,
+            0,
+            readOnlyResourceCount,
+            commandBuffer->computeShaderResourceViews);
+
+        commandBuffer->needComputeSRVBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needComputeUniformBufferBind) {
+        for (i = 0; i < computePipeline->uniformBufferCount; i += 1) {
+            /* stupid workaround for god awful D3D11 drivers
+             * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1#calling-vssetconstantbuffers1-with-command-list-emulation
+             */
+            ID3D11DeviceContext1_CSSetConstantBuffers(
+                commandBuffer->context,
+                i,
+                1,
+                &nullBuf);
+
+            offsetInConstants = commandBuffer->computeUniformBuffers[i]->drawOffset / 16;
+            blockSizeInConstants = commandBuffer->computeUniformBuffers[i]->currentBlockSize / 16;
+
+            ID3D11DeviceContext1_CSSetConstantBuffers1(
+                commandBuffer->context,
+                i,
+                1,
+                &commandBuffer->computeUniformBuffers[i]->buffer,
+                &offsetInConstants,
+                &blockSizeInConstants);
+        }
+        commandBuffer->needComputeUniformBufferBind = SDL_FALSE;
+    }
+}
+
+static void D3D11_DispatchCompute(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 groupCountX,
+    Uint32 groupCountY,
+    Uint32 groupCountZ)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11_INTERNAL_BindComputeResources(d3d11CommandBuffer);
+
+    ID3D11DeviceContext_Dispatch(
+        d3d11CommandBuffer->context,
+        groupCountX,
+        groupCountY,
+        groupCountZ);
+}
+
+static void D3D11_DispatchComputeIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)buffer)->activeBuffer;
+
+    D3D11_INTERNAL_BindComputeResources(d3d11CommandBuffer);
+
+    ID3D11DeviceContext_DispatchIndirect(
+        d3d11CommandBuffer->context,
+        d3d11Buffer->handle,
+        offsetInBytes);
+
+    D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer);
+}
+
+static void D3D11_EndComputePass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+
+    // reset UAV slots to avoid NULL set behavior
+    // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-cssetshaderresources
+    ID3D11DeviceContext_CSSetUnorderedAccessViews(
+        d3d11CommandBuffer->context,
+        0,
+        MAX_COMPUTE_WRITE_TEXTURES + MAX_COMPUTE_WRITE_BUFFERS,
+        nullUAVs,
+        NULL);
+
+    d3d11CommandBuffer->computePipeline = NULL;
+
+    // Reset bind state
+    SDL_zeroa(d3d11CommandBuffer->computeUnorderedAccessViews);
+    SDL_zeroa(d3d11CommandBuffer->computeShaderResourceViews);
+}
+
+// Fence Cleanup
+
+static void D3D11_INTERNAL_ReleaseFenceToPool(
+    D3D11Renderer *renderer,
+    D3D11Fence *fence)
+{
+    SDL_LockMutex(renderer->fenceLock);
+
+    if (renderer->availableFenceCount == renderer->availableFenceCapacity) {
+        renderer->availableFenceCapacity *= 2;
+        renderer->availableFences = SDL_realloc(
+            renderer->availableFences,
+            renderer->availableFenceCapacity * sizeof(D3D11Fence *));
+    }
+    renderer->availableFences[renderer->availableFenceCount] = fence;
+    renderer->availableFenceCount += 1;
+
+    SDL_UnlockMutex(renderer->fenceLock);
+}
+
+static void D3D11_ReleaseFence(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuFence *fence)
+{
+    D3D11Fence *d3d11Fence = (D3D11Fence *)fence;
+
+    if (SDL_AtomicDecRef(&d3d11Fence->referenceCount)) {
+        D3D11_INTERNAL_ReleaseFenceToPool(
+            (D3D11Renderer *)driverData,
+            d3d11Fence);
+    }
+}
+
+// Cleanup
+
+/* D3D11 does not provide a deferred texture-to-buffer copy operation,
+ * so instead of the transfer buffer containing an actual D3D11 buffer,
+ * the transfer buffer data is just a malloc'd pointer.
+ * In the download operation we copy data to a staging resource, and
+ * wait until the command buffer has finished executing to map the staging resource.
+ */
+
+static void D3D11_INTERNAL_MapAndCopyBufferDownload(
+    D3D11Renderer *renderer,
+    D3D11TransferBuffer *transferBuffer,
+    D3D11BufferDownload *bufferDownload)
+{
+    D3D11_MAPPED_SUBRESOURCE subres;
+    HRESULT res;
+
+    SDL_LockMutex(renderer->contextLock);
+    res = ID3D11DeviceContext_Map(
+        renderer->immediateContext,
+        (ID3D11Resource *)bufferDownload->stagingBuffer,
+        0,
+        D3D11_MAP_READ,
+        0,
+        &subres);
+    ERROR_CHECK_RETURN("Failed to map staging buffer", )
+
+    SDL_memcpy(
+        ((Uint8 *)transferBuffer->data) + bufferDownload->dstOffset,
+        ((Uint8 *)subres.pData),
+        bufferDownload->size);
+
+    ID3D11DeviceContext_Unmap(
+        renderer->immediateContext,
+        (ID3D11Resource *)bufferDownload->stagingBuffer,
+        0);
+    SDL_UnlockMutex(renderer->contextLock);
+
+    ID3D11Buffer_Release(bufferDownload->stagingBuffer);
+}
+
+static void D3D11_INTERNAL_MapAndCopyTextureDownload(
+    D3D11Renderer *renderer,
+    D3D11TransferBuffer *transferBuffer,
+    D3D11TextureDownload *textureDownload)
+{
+    D3D11_MAPPED_SUBRESOURCE subres;
+    HRESULT res;
+    Uint32 dataPtrOffset;
+    Uint32 depth, row;
+
+    SDL_LockMutex(renderer->contextLock);
+    res = ID3D11DeviceContext_Map(
+        renderer->immediateContext,
+        (ID3D11Resource *)textureDownload->stagingTexture,
+        0,
+        D3D11_MAP_READ,
+        0,
+        &subres);
+    ERROR_CHECK_RETURN("Could not map staging texture", )
+
+    for (depth = 0; depth < textureDownload->depth; depth += 1) {
+        dataPtrOffset = textureDownload->bufferOffset + (depth * textureDownload->bytesPerDepthSlice);
+
+        for (row = 0; row < textureDownload->height; row += 1) {
+            SDL_memcpy(
+                transferBuffer->data + dataPtrOffset,
+                (Uint8 *)subres.pData + (depth * subres.DepthPitch) + (row * subres.RowPitch),
+                textureDownload->bytesPerRow);
+            dataPtrOffset += textureDownload->bytesPerRow;
+        }
+    }
+
+    ID3D11DeviceContext_Unmap(
+        renderer->immediateContext,
+        textureDownload->stagingTexture,
+        0);
+
+    SDL_UnlockMutex(renderer->contextLock);
+
+    ID3D11Resource_Release(textureDownload->stagingTexture);
+}
+
+static void D3D11_INTERNAL_CleanCommandBuffer(
+    D3D11Renderer *renderer,
+    D3D11CommandBuffer *commandBuffer)
+{
+    Uint32 i, j;
+
+    // Perform deferred download map and copy
+
+    for (i = 0; i < commandBuffer->usedTransferBufferCount; i += 1) {
+        D3D11TransferBuffer *transferBuffer = commandBuffer->usedTransferBuffers[i];
+
+        for (j = 0; j < transferBuffer->bufferDownloadCount; j += 1) {
+            D3D11_INTERNAL_MapAndCopyBufferDownload(
+                renderer,
+                transferBuffer,
+                &transferBuffer->bufferDownloads[j]);
+        }
+
+        for (j = 0; j < transferBuffer->textureDownloadCount; j += 1) {
+            D3D11_INTERNAL_MapAndCopyTextureDownload(
+                renderer,
+                transferBuffer,
+                &transferBuffer->textureDownloads[j]);
+        }
+
+        transferBuffer->bufferDownloadCount = 0;
+        transferBuffer->textureDownloadCount = 0;
+    }
+
+    // Uniform buffers are now available
+
+    SDL_LockMutex(renderer->acquireUniformBufferLock);
+
+    for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
+        D3D11_INTERNAL_ReturnUniformBufferToPool(
+            renderer,
+            commandBuffer->usedUniformBuffers[i]);
+    }
+    commandBuffer->usedUniformBufferCount = 0;
+
+    SDL_UnlockMutex(renderer->acquireUniformBufferLock);
+
+    // Reference Counting
+
+    for (i = 0; i < commandBuffer->usedBufferCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount);
+    }
+    commandBuffer->usedBufferCount = 0;
+
+    for (i = 0; i < commandBuffer->usedTransferBufferCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedTransferBuffers[i]->referenceCount);
+    }
+    commandBuffer->usedTransferBufferCount = 0;
+
+    for (i = 0; i < commandBuffer->usedTextureCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
+    }
+    commandBuffer->usedTextureCount = 0;
+
+    // Reset presentation
+    commandBuffer->windowDataCount = 0;
+
+    // The fence is now available (unless SubmitAndAcquireFence was called)
+    if (commandBuffer->autoReleaseFence) {
+        D3D11_ReleaseFence(
+            (SDL_GpuRenderer *)renderer,
+            (SDL_GpuFence *)commandBuffer->fence);
+    }
+
+    // Return command buffer to pool
+    SDL_LockMutex(renderer->acquireCommandBufferLock);
+    if (renderer->availableCommandBufferCount == renderer->availableCommandBufferCapacity) {
+        renderer->availableCommandBufferCapacity += 1;
+        renderer->availableCommandBuffers = SDL_realloc(
+            renderer->availableCommandBuffers,
+            renderer->availableCommandBufferCapacity * sizeof(D3D11CommandBuffer *));
+    }
+    renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
+    renderer->availableCommandBufferCount += 1;
+    SDL_UnlockMutex(renderer->acquireCommandBufferLock);
+
+    // Remove this command buffer from the submitted list
+    for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
+        if (renderer->submittedCommandBuffers[i] == commandBuffer) {
+            renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
+            renderer->submittedCommandBufferCount -= 1;
+        }
+    }
+}
+
+static void D3D11_INTERNAL_PerformPendingDestroys(
+    D3D11Renderer *renderer)
+{
+    Sint32 referenceCount = 0;
+    Sint32 i;
+    Uint32 j;
+
+    for (i = renderer->transferBufferContainersToDestroyCount - 1; i >= 0; i -= 1) {
+        referenceCount = 0;
+        for (j = 0; j < renderer->transferBufferContainersToDestroy[i]->bufferCount; j += 1) {
+            referenceCount += SDL_AtomicGet(&renderer->transferBufferContainersToDestroy[i]->buffers[j]->referenceCount);
+        }
+
+        if (referenceCount == 0) {
+            D3D11_INTERNAL_DestroyTransferBufferContainer(
+                renderer->transferBufferContainersToDestroy[i]);
+
+            renderer->transferBufferContainersToDestroy[i] = renderer->transferBufferContainersToDestroy[renderer->transferBufferContainersToDestroyCount - 1];
+            renderer->transferBufferContainersToDestroyCount -= 1;
+        }
+    }
+
+    for (i = renderer->bufferContainersToDestroyCount - 1; i >= 0; i -= 1) {
+        referenceCount = 0;
+        for (j = 0; j < renderer->bufferContainersToDestroy[i]->bufferCount; j += 1) {
+            referenceCount += SDL_AtomicGet(&renderer->bufferContainersToDestroy[i]->buffers[j]->referenceCount);
+        }
+
+        if (referenceCount == 0) {
+            D3D11_INTERNAL_DestroyBufferContainer(
+                renderer->bufferContainersToDestroy[i]);
+
+            renderer->bufferContainersToDestroy[i] = renderer->bufferContainersToDestroy[renderer->bufferContainersToDestroyCount - 1];
+            renderer->bufferContainersToDestroyCount -= 1;
+        }
+    }
+
+    for (i = renderer->textureContainersToDestroyCount - 1; i >= 0; i -= 1) {
+        referenceCount = 0;
+        for (j = 0; j < renderer->textureContainersToDestroy[i]->textureCount; j += 1) {
+            referenceCount += SDL_AtomicGet(&renderer->textureContainersToDestroy[i]->textures[j]->referenceCount);
+        }
+
+        if (referenceCount == 0) {
+            D3D11_INTERNAL_DestroyTextureContainer(
+                renderer->textureContainersToDestroy[i]);
+
+            renderer->textureContainersToDestroy[i] = renderer->textureContainersToDestroy[renderer->textureContainersToDestroyCount - 1];
+            renderer->textureContainersToDestroyCount -= 1;
+        }
+    }
+}
+
+// Fences
+
+static void D3D11_INTERNAL_WaitForFence(
+    D3D11Renderer *renderer,
+    D3D11Fence *fence)
+{
+    BOOL queryData;
+    HRESULT res;
+
+    SDL_LockMutex(renderer->contextLock);
+
+    do {
+        res = ID3D11DeviceContext_GetData(
+            renderer->immediateContext,
+            (ID3D11Asynchronous *)fence->handle,
+            &queryData,
+            sizeof(queryData),
+            0);
+    } while (res != S_OK); // Spin until we get a result back...
+
+    SDL_UnlockMutex(renderer->contextLock);
+}
+
+static void D3D11_WaitForFences(
+    SDL_GpuRenderer *driverData,
+    SDL_bool waitAll,
+    SDL_GpuFence **pFences,
+    Uint32 fenceCount)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11Fence *fence;
+    BOOL queryData;
+    HRESULT res = S_FALSE;
+
+    if (waitAll) {
+        for (Uint32 i = 0; i < fenceCount; i += 1) {
+            fence = (D3D11Fence *)pFences[i];
+            D3D11_INTERNAL_WaitForFence(renderer, fence);
+        }
+    } else {
+        SDL_LockMutex(renderer->contextLock);
+
+        while (res != S_OK) {
+            for (Uint32 i = 0; i < fenceCount; i += 1) {
+                fence = (D3D11Fence *)pFences[i];
+                res = ID3D11DeviceContext_GetData(
+                    renderer->immediateContext,
+                    (ID3D11Asynchronous *)fence->handle,
+                    &queryData,
+                    sizeof(queryData),
+                    0);
+                if (res == S_OK) {
+                    break;
+                }
+            }
+        }
+
+        SDL_UnlockMutex(renderer->contextLock);
+    }
+
+    SDL_LockMutex(renderer->contextLock);
+
+    // Check if we can perform any cleanups
+    for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+        res = ID3D11DeviceContext_GetData(
+            renderer->immediateContext,
+            (ID3D11Asynchronous *)renderer->submittedCommandBuffers[i]->fence->handle,
+            &queryData,
+            sizeof(queryData),
+            0);
+        if (res == S_OK) {
+            D3D11_INTERNAL_CleanCommandBuffer(
+                renderer,
+                renderer->submittedCommandBuffers[i]);
+        }
+    }
+
+    D3D11_INTERNAL_PerformPendingDestroys(renderer);
+
+    SDL_UnlockMutex(renderer->contextLock);
+}
+
+static SDL_bool D3D11_QueryFence(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuFence *fence)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11Fence *d3d11Fence = (D3D11Fence *)fence;
+    BOOL queryData;
+    HRESULT res;
+
+    SDL_LockMutex(renderer->contextLock);
+
+    res = ID3D11DeviceContext_GetData(
+        renderer->immediateContext,
+        (ID3D11Asynchronous *)d3d11Fence->handle,
+        &queryData,
+        sizeof(queryData),
+        0);
+
+    SDL_UnlockMutex(renderer->contextLock);
+
+    return res == S_OK;
+}
+
+// Window and Swapchain Management
+
+static D3D11WindowData *D3D11_INTERNAL_FetchWindowData(
+    SDL_Window *window)
+{
+    SDL_PropertiesID properties = SDL_GetWindowProperties(window);
+    return (D3D11WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
+}
+
+static SDL_bool D3D11_INTERNAL_InitializeSwapchainTexture(
+    D3D11Renderer *renderer,
+    IDXGISwapChain *swapchain,
+    DXGI_FORMAT swapchainFormat,
+    DXGI_FORMAT rtvFormat,
+    D3D11Texture *pTexture)
+{
+    ID3D11Texture2D *swapchainTexture;
+    D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+    ID3D11RenderTargetView *rtv;
+    HRESULT res;
+
+    // Clear all the texture data
+    SDL_zerop(pTexture);
+
+    // Grab the buffer from the swapchain
+    res = IDXGISwapChain_GetBuffer(
+        swapchain,
+        0,
+        &D3D_IID_ID3D11Texture2D,
+        (void **)&swapchainTexture);
+    ERROR_CHECK_RETURN("Could not get buffer from swapchain!", 0);
+
+    // Create the RTV for the swapchain
+    rtvDesc.Format = rtvFormat;
+    rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+    rtvDesc.Texture2D.MipSlice = 0;
+
+    res = ID3D11Device_CreateRenderTargetView(
+        renderer->device,
+        (ID3D11Resource *)swapchainTexture,
+        &rtvDesc,
+        &rtv);
+    if (FAILED(res)) {
+        ID3D11Texture2D_Release(swapchainTexture);
+        D3D11_INTERNAL_LogError(renderer->device, "Swapchain RTV creation failed", res);
+        return SDL_FALSE;
+    }
+
+    // Create container
+
+    // Fill out the texture struct
+    pTexture->handle = NULL;     // This will be set in AcquireSwapchainTexture.
+    pTexture->shaderView = NULL; // We don't allow swapchain texture to be sampled
+    SDL_AtomicSet(&pTexture->referenceCount, 0);
+    pTexture->subresourceCount = 1;
+    pTexture->subresources = SDL_malloc(sizeof(D3D11TextureSubresource));
+    pTexture->subresources[0].colorTargetViews = SDL_calloc(1, sizeof(ID3D11RenderTargetView *));
+    pTexture->subresources[0].colorTargetViews[0] = rtv;
+    pTexture->subresources[0].uav = NULL;
+    pTexture->subresources[0].depthStencilTargetView = NULL;
+    pTexture->subresources[0].msaaHandle = NULL;
+    pTexture->subresources[0].msaaTargetView = NULL;
+    pTexture->subresources[0].layer = 0;
+    pTexture->subresources[0].level = 0;
+    pTexture->subresources[0].depth = 1;
+    pTexture->subresources[0].index = 0;
+    pTexture->subresources[0].parent = pTexture;
+
+    // Cleanup
+    ID3D11Texture2D_Release(swapchainTexture);
+
+    return SDL_TRUE;
+}
+
+static SDL_bool D3D11_INTERNAL_CreateSwapchain(
+    D3D11Renderer *renderer,
+    D3D11WindowData *windowData,
+    SDL_GpuSwapchainComposition swapchainComposition,
+    SDL_GpuPresentMode presentMode)
+{
+    HWND dxgiHandle;
+    int width, height;
+    Uint32 i;
+    DXGI_SWAP_CHAIN_DESC swapchainDesc;
+    DXGI_FORMAT swapchainFormat;
+    IDXGIFactory1 *pParent;
+    IDXGISwapChain *swapchain;
+    IDXGISwapChain3 *swapchain3;
+    HRESULT res;
+
+    // Get the DXGI handle
+#ifdef _WIN32
+    dxgiHandle = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(windowData->window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
+#else
+    dxgiHandle = (HWND)windowData->window;
+#endif
+
+    // Get the window size
+    SDL_GetWindowSize(windowData->window, &width, &height);
+
+    swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
+
+    // Initialize the swapchain buffer descriptor
+    swapchainDesc.BufferDesc.Width = 0;
+    swapchainDesc.BufferDesc.Height = 0;
+    swapchainDesc.BufferDesc.RefreshRate.Numerator = 0;
+    swapchainDesc.BufferDesc.RefreshRate.Denominator = 0;
+    swapchainDesc.BufferDesc.Format = swapchainFormat;
+    swapchainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+    swapchainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+
+    // Initialize the rest of the swapchain descriptor
+    swapchainDesc.SampleDesc.Count = 1;
+    swapchainDesc.SampleDesc.Quality = 0;
+    swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+    swapchainDesc.BufferCount = 2;
+    swapchainDesc.OutputWindow = dxgiHandle;
+    swapchainDesc.Windowed = 1;
+
+    if (renderer->supportsTearing) {
+        swapchainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
+        // We know this is supported because tearing support implies DXGI 1.5+
+        swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+    } else {
+        swapchainDesc.Flags = 0;
+        swapchainDesc.SwapEffect = (renderer->supportsFlipDiscard ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD);
+    }
+
+    // Create the swapchain!
+    res = IDXGIFactory1_CreateSwapChain(
+        (IDXGIFactory1 *)renderer->factory,
+        (IUnknown *)renderer->device,
+        &swapchainDesc,
+        &swapchain);
+    ERROR_CHECK_RETURN("Could not create swapchain", 0);
+
+    /*
+     * The swapchain's parent is a separate factory from the factory that
+     * we used to create the swapchain, and only that parent can be used to
+     * set the window association. Trying to set an association on our factory
+     * will silently fail and doesn't even verify arguments or return errors.
+     * See https://gamedev.net/forums/topic/634235-dxgidisabling-altenter/4999955/
+     */
+    res = IDXGISwapChain_GetParent(
+        swapchain,
+        &D3D_IID_IDXGIFactory1,
+        (void **)&pParent);
+    if (FAILED(res)) {
+        SDL_LogWarn(
+            SDL_LOG_CATEGORY_GPU,
+            "Could not get swapchain parent! Error Code: " HRESULT_FMT,
+            res);
+    } else {
+        // Disable DXGI window crap
+        res = IDXGIFactory1_MakeWindowAssociation(
+            pParent,
+            dxgiHandle,
+            DXGI_MWA_NO_WINDOW_CHANGES);
+        if (FAILED(res)) {
+            SDL_LogWarn(
+                SDL_LOG_CATEGORY_GPU,
+                "MakeWindowAssociation failed! Error Code: " HRESULT_FMT,
+                res);
+        }
+
+        // We're done with the parent now
+        IDXGIFactory1_Release(pParent);
+    }
+
+    if (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR) {
+        // Set the color space, support already verified if we hit this block
+        IDXGISwapChain3_QueryInterface(
+            swapchain,
+            &D3D_IID_IDXGISwapChain3,
+            (void **)&swapchain3);
+
+        IDXGISwapChain3_SetColorSpace1(
+            swapchain3,
+            SwapchainCompositionToColorSpace[swapchainComposition]);
+
+        IDXGISwapChain3_Release(swapchain3);
+    }
+
+    // Initialize the swapchain data
+    windowData->swapchain = swapchain;
+    windowData->presentMode = presentMode;
+    windowData->swapchainComposition = swapchainComposition;
+    windowData->swapchainFormat = swapchainFormat;
+    windowData->swapchainColorSpace = SwapchainCompositionToColorSpace[swapchainComposition];
+    windowData->frameCounter = 0;
+
+    for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+        windowData->inFlightFences[i] = NULL;
+    }
+
+    /* If a you are using a FLIP model format you can't create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM_SRGB.
+     * You have to create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM and then set the render target view's format to DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
+     */
+    if (!D3D11_INTERNAL_InitializeSwapchainTexture(
+            renderer,
+            swapchain,
+            swapchainFormat,
+            (swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : windowData->swapchainFormat,
+            &windowData->texture)) {
+        IDXGISwapChain_Release(swapchain);
+        return SDL_FALSE;
+    }
+
+    // Initialize dummy container, width/height will be filled out in AcquireSwapchainTexture
+    SDL_zerop(&windowData->textureContainer);
+    windowData->textureContainer.textures = SDL_calloc(1, sizeof(D3D11Texture *));
+    windowData->textureContainer.activeTexture = &windowData->texture;
+    windowData->textureContainer.textures[0] = &windowData->texture;
+    windowData->textureContainer.canBeCycled = SDL_FALSE;
+    windowData->textureContainer.textureCount = 1;
+    windowData->textureContainer.textureCapacity = 1;
+
+    windowData->textureContainer.header.info.layerCountOrDepth = 1;
+    windowData->textureContainer.header.info.format = SwapchainCompositionToSDLTextureFormat[windowData->swapchainComposition];
+    windowData->textureContainer.header.info.type = SDL_GPU_TEXTURETYPE_2D;
+    windowData->textureContainer.header.info.levelCount = 1;
+    windowData->textureContainer.header.info.sampleCount = SDL_GPU_SAMPLECOUNT_1;
+    windowData->textureContainer.header.info.usageFlags = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT;
+
+    windowData->texture.container = &windowData->textureContainer;
+    windowData->texture.containerIndex = 0;
+
+    return SDL_TRUE;
+}
+
+static SDL_bool D3D11_INTERNAL_ResizeSwapchain(
+    D3D11Renderer *renderer,
+    D3D11WindowData *windowData,
+    Sint32 width,
+    Sint32 height)
+{
+    // Release the old RTV
+    ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetViews[0]);
+    SDL_free(windowData->texture.subresources[0].colorTargetViews);
+    SDL_free(windowData->texture.subresources);
+
+    // Resize the swapchain
+    HRESULT res = IDXGISwapChain_ResizeBuffers(
+        windowData->swapchain,
+        0, // Keep buffer count the same
+        width,
+        height,
+        DXGI_FORMAT_UNKNOWN, // Keep the old format
+        renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
+    ERROR_CHECK_RETURN("Could not resize swapchain buffers", 0);
+
+    // Create the texture object for the swapchain
+    return D3D11_INTERNAL_InitializeSwapchainTexture(
+        renderer,
+        windowData->swapchain,
+        windowData->swapchainFormat,
+        (windowData->swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : windowData->swapchainFormat,
+        &windowData->texture);
+}
+
+static SDL_bool D3D11_SupportsSwapchainComposition(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    DXGI_FORMAT format;
+    Uint32 formatSupport = 0;
+    IDXGISwapChain3 *swapchain3;
+    Uint32 colorSpaceSupport;
+    HRESULT res;
+
+    format = SwapchainCompositionToTextureFormat[swapchainComposition];
+
+    res = ID3D11Device_CheckFormatSupport(
+        renderer->device,
+        format,
+        &formatSupport);
+    if (FAILED(res)) {
+        // Format is apparently unknown
+        return SDL_FALSE;
+    }
+
+    if (!(formatSupport & D3D11_FORMAT_SUPPORT_DISPLAY)) {
+        return SDL_FALSE;
+    }
+
+    D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
+    if (windowData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Must claim window before querying swapchain composition support!");
+        return SDL_FALSE;
+    }
+
+    // Check the color space support if necessary
+    if (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR) {
+        if (SUCCEEDED(IDXGISwapChain3_QueryInterface(
+                windowData->swapchain,
+                &D3D_IID_IDXGISwapChain3,
+                (void **)&swapchain3))) {
+            IDXGISwapChain3_CheckColorSpaceSupport(
+                swapchain3,
+                SwapchainCompositionToColorSpace[swapchainComposition],
+                &colorSpaceSupport);
+
+            IDXGISwapChain3_Release(swapchain3);
+
+            if (!(colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) {
+                return SDL_FALSE;
+            }
+        } else {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "DXGI 1.4 not supported, cannot use composition other than SDL_GPU_SWAPCHAINCOMPOSITION_SDR!");
+            return SDL_FALSE;
+        }
+    }
+
+    return SDL_TRUE;
+}
+
+static SDL_bool D3D11_SupportsPresentMode(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuPresentMode presentMode)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    (void)window; // used by other backends
+    switch (presentMode) {
+    case SDL_GPU_PRESENTMODE_IMMEDIATE:
+    case SDL_GPU_PRESENTMODE_VSYNC:
+        return SDL_TRUE;
+    case SDL_GPU_PRESENTMODE_MAILBOX:
+        return renderer->supportsFlipDiscard;
+    }
+    SDL_assert(!"Unrecognized present mode");
+    return SDL_FALSE;
+}
+
+static SDL_bool D3D11_ClaimWindow(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        windowData = (D3D11WindowData *)SDL_malloc(sizeof(D3D11WindowData));
+        windowData->window = window;
+
+        if (D3D11_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
+            SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
+
+            SDL_LockMutex(renderer->windowLock);
+
+            if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
+                renderer->claimedWindowCapacity *= 2;
+                renderer->claimedWindows = SDL_realloc(
+                    renderer->claimedWindows,
+                    renderer->claimedWindowCapacity * sizeof(D3D11WindowData *));
+            }
+            renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
+            renderer->claimedWindowCount += 1;
+
+            SDL_UnlockMutex(renderer->windowLock);
+
+            return SDL_TRUE;
+        } else {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not create swapchain, failed to claim window!");
+            SDL_free(windowData);
+            return SDL_FALSE;
+        }
+    } else {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Window already claimed!");
+        return SDL_FALSE;
+    }
+}
+
+static void D3D11_INTERNAL_DestroySwapchain(
+    D3D11Renderer *renderer,
+    D3D11WindowData *windowData)
+{
+    Uint32 i;
+
+    D3D11_Wait((SDL_GpuRenderer *)renderer);
+
+    ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetViews[0]);
+    SDL_free(windowData->texture.subresources[0].colorTargetViews);
+    SDL_free(windowData->texture.subresources);
+    SDL_free(windowData->textureContainer.textures);
+    IDXGISwapChain_Release(windowData->swapchain);
+
+    // DXGI will crash if we don't flush deferred swapchain destruction
+    SDL_LockMutex(renderer->contextLock);
+    ID3D11DeviceContext_ClearState(renderer->immediateContext);
+    ID3D11DeviceContext_Flush(renderer->immediateContext);
+    SDL_UnlockMutex(renderer->contextLock);
+
+    windowData->swapchain = NULL;
+
+    for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+        if (windowData->inFlightFences[i] != NULL) {
+            D3D11_ReleaseFence(
+                (SDL_GpuRenderer *)renderer,
+                (SDL_GpuFence *)windowData->inFlightFences[i]);
+        }
+    }
+}
+
+static void D3D11_UnclaimWindow(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        return;
+    }
+
+    D3D11_INTERNAL_DestroySwapchain(
+        renderer,
+        windowData);
+
+    SDL_LockMutex(renderer->windowLock);
+    for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
+        if (renderer->claimedWindows[i]->window == window) {
+            renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1];
+            renderer->claimedWindowCount -= 1;
+            break;
+        }
+    }
+    SDL_UnlockMutex(renderer->windowLock);
+
+    SDL_free(windowData);
+
+    SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
+}
+
+static SDL_GpuTexture *D3D11_AcquireSwapchainTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_Window *window,
+    Uint32 *pWidth,
+    Uint32 *pHeight)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+    D3D11WindowData *windowData;
+    DXGI_SWAP_CHAIN_DESC swapchainDesc;
+    int w, h;
+    HRESULT res;
+
+    windowData = D3D11_INTERNAL_FetchWindowData(window);
+    if (windowData == NULL) {
+        return NULL;
+    }
+
+    // Check for window size changes and resize the swapchain if needed.
+    IDXGISwapChain_GetDesc(windowData->swapchain, &swapchainDesc);
+    SDL_GetWindowSize(window, &w, &h);
+
+    if (w != swapchainDesc.BufferDesc.Width || h != swapchainDesc.BufferDesc.Height) {
+        res = D3D11_INTERNAL_ResizeSwapchain(
+            renderer,
+            windowData,
+            w,
+            h);
+        ERROR_CHECK_RETURN("Could not resize swapchain", NULL);
+    }
+
+    if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
+        if (windowData->presentMode == SDL_GPU_PRESENTMODE_VSYNC) {
+            // In VSYNC mode, block until the least recent presented frame is done
+            D3D11_WaitForFences(
+                (SDL_GpuRenderer *)renderer,
+                SDL_TRUE,
+                (SDL_GpuFence **)&windowData->inFlightFences[windowData->frameCounter],
+                1);
+        } else {
+            if (!D3D11_QueryFence(
+                    (SDL_GpuRenderer *)d3d11CommandBuffer->renderer,
+                    (SDL_GpuFence *)windowData->inFlightFences[windowData->frameCounter])) {
+                /*
+                 * In MAILBOX or IMMEDIATE mode, if the least recent fence is not signaled,
+                 * return NULL to indicate that rendering should be skipped
+                 */
+                return NULL;
+            }
+        }
+
+        D3D11_ReleaseFence(
+            (SDL_GpuRenderer *)d3d11CommandBuffer->renderer,
+            (SDL_GpuFence *)windowData->inFlightFences[windowData->frameCounter]);
+
+        windowData->inFlightFences[windowData->frameCounter] = NULL;
+    }
+
+    // Set the handle on the windowData texture data.
+    res = IDXGISwapChain_GetBuffer(
+        windowData->swapchain,
+        0,
+        &D3D_IID_ID3D11Texture2D,
+        (void **)&windowData->texture.handle);
+    ERROR_CHECK_RETURN("Could not acquire swapchain!", NULL);
+
+    // Send the dimensions to the out parameters.
+    *pWidth = w;
+    *pHeight = h;
+
+    // Update the texture container dimensions
+    windowData->textureContainer.header.info.width = w;
+    windowData->textureContainer.header.info.height = h;
+
+    // Set up presentation
+    if (d3d11CommandBuffer->windowDataCount == d3d11CommandBuffer->windowDataCapacity) {
+        d3d11CommandBuffer->windowDataCapacity += 1;
+        d3d11CommandBuffer->windowDatas = SDL_realloc(
+            d3d11CommandBuffer->windowDatas,
+            d3d11CommandBuffer->windowDataCapacity * sizeof(D3D11WindowData *));
+    }
+    d3d11CommandBuffer->windowDatas[d3d11CommandBuffer->windowDataCount] = windowData;
+    d3d11CommandBuffer->windowDataCount += 1;
+
+    // Return the swapchain texture
+    return (SDL_GpuTexture *)&windowData->textureContainer;
+}
+
+static SDL_GpuTextureFormat D3D11_GetSwapchainTextureFormat(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Cannot get swapchain format, window has not been claimed!");
+        return 0;
+    }
+
+    return windowData->textureContainer.header.info.format;
+}
+
+static SDL_bool D3D11_SetSwapchainParameters(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition,
+    SDL_GpuPresentMode presentMode)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Cannot set swapchain parameters on unclaimed window!");
+        return SDL_FALSE;
+    }
+
+    if (!D3D11_SupportsSwapchainComposition(driverData, window, swapchainComposition)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Swapchain composition not supported!");
+        return SDL_FALSE;
+    }
+
+    if (!D3D11_SupportsPresentMode(driverData, window, presentMode)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Present mode not supported!");
+        return SDL_FALSE;
+    }
+
+    if (
+        swapchainComposition != windowData->swapchainComposition ||
+        presentMode != windowData->presentMode) {
+        D3D11_Wait(driverData);
+
+        // Recreate the swapchain
+        D3D11_INTERNAL_DestroySwapchain(
+            renderer,
+            windowData);
+
+        return D3D11_INTERNAL_CreateSwapchain(
+            renderer,
+            windowData,
+            swapchainComposition,
+            presentMode);
+    }
+
+    return SDL_TRUE;
+}
+
+// Submission
+
+static void D3D11_Submit(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
+    ID3D11CommandList *commandList;
+    HRESULT res;
+
+    // Unmap uniform buffers
+
+    for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        if (d3d11CommandBuffer->vertexUniformBuffers[i] != NULL) {
+            ID3D11DeviceContext_Unmap(
+                d3d11CommandBuffer->context,
+                (ID3D11Resource *)d3d11CommandBuffer->vertexUniformBuffers[i]->buffer,
+                0);
+        }
+
+        if (d3d11CommandBuffer->fragmentUniformBuffers[i] != NULL) {
+            ID3D11DeviceContext_Unmap(
+                d3d11CommandBuffer->context,
+                (ID3D11Resource *)d3d11CommandBuffer->fragmentUniformBuffers[i]->buffer,
+                0);
+        }
+
+        if (d3d11CommandBuffer->computeUniformBuffers[i] != NULL) {
+            ID3D11DeviceContext_Unmap(
+                d3d11CommandBuffer->context,
+                (ID3D11Resource *)d3d11CommandBuffer->computeUniformBuffers[i]->buffer,
+                0);
+        }
+    }
+
+    SDL_LockMutex(renderer->contextLock);
+
+    // Notify the command buffer completion query that we have completed recording
+    ID3D11DeviceContext_End(
+        renderer->immediateContext,
+        (ID3D11Asynchronous *)d3d11CommandBuffer->fence->handle);
+
+    // Serialize the commands into the command list
+    res = ID3D11DeviceContext_FinishCommandList(
+        d3d11CommandBuffer->context,
+        0,
+        &commandList);
+    ERROR_CHECK("Could not finish command list recording!");
+
+    // Submit the command list to the immediate context
+    ID3D11DeviceContext_ExecuteCommandList(
+        renderer->immediateContext,
+        commandList,
+        0);
+    ID3D11CommandList_Release(commandList);
+
+    // Mark the command buffer as submitted
+    if (renderer->submittedCommandBufferCount >= renderer->submittedCommandBufferCapacity) {
+        renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1;
+
+        renderer->submittedCommandBuffers = SDL_realloc(
+            renderer->submittedCommandBuffers,
+            sizeof(D3D11CommandBuffer *) * renderer->submittedCommandBufferCapacity);
+    }
+
+    renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = d3d11CommandBuffer;
+    renderer->submittedCommandBufferCount += 1;
+
+    // Present, if applicable
+    for (Uint32 i = 0; i < d3d11CommandBuffer->windowDataCount; i += 1) {
+        D3D11WindowData *windowData = d3d11CommandBuffer->windowDatas[i];
+
+        Uint32 syncInterval = 1;
+        if (windowData->presentMode == SDL_GPU_PRESENTMODE_IMMEDIATE ||
+            (renderer->supportsFlipDiscard && windowData->presentMode == SDL_GPU_PRESENTMODE_MAILBOX)) {
+            syncInterval = 0;
+        }
+
+        Uint32 presentFlags = 0;
+        if (renderer->supportsTearing &&
+            windowData->presentMode == SDL_GPU_PRESENTMODE_IMMEDIATE) {
+            presentFlags = DXGI_PRESENT_ALLOW_TEARING;
+        }
+
+        IDXGISwapChain_Present(
+            windowData->swapchain,
+            syncInterval,
+            presentFlags);
+
+        ID3D11Texture2D_Release(windowData->texture.handle);
+
+        windowData->inFlightFences[windowData->frameCounter] = d3d11CommandBuffer->fence;
+
+        (void)SDL_AtomicIncRef(&d3d11CommandBuffer->fence->referenceCount);
+
+        windowData->frameCounter = (windowData->frameCounter + 1) % MAX_FRAMES_IN_FLIGHT;
+    }
+
+    // Check if we can perform any cleanups
+    for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+        BOOL queryData;
+        res = ID3D11DeviceContext_GetData(
+            renderer->immediateContext,
+            (ID3D11Asynchronous *)renderer->submittedCommandBuffers[i]->fence->handle,
+            &queryData,
+            sizeof(queryData),
+            0);
+        if (res == S_OK) {
+            D3D11_INTERNAL_CleanCommandBuffer(
+                renderer,
+                renderer->submittedCommandBuffers[i]);
+        }
+    }
+
+    D3D11_INTERNAL_PerformPendingDestroys(renderer);
+
+    SDL_UnlockMutex(renderer->contextLock);
+}
+
+static SDL_GpuFence *D3D11_SubmitAndAcquireFence(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
+    D3D11Fence *fence = d3d11CommandBuffer->fence;
+
+    d3d11CommandBuffer->autoReleaseFence = 0;
+    D3D11_Submit(commandBuffer);
+
+    return (SDL_GpuFence *)fence;
+}
+
+static void D3D11_Wait(
+    SDL_GpuRenderer *driverData)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11CommandBuffer *commandBuffer;
+
+    /*
+     * Wait for all submitted command buffers to complete.
+     * Sort of equivalent to vkDeviceWaitIdle.
+     */
+    for (Uint32 i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
+        D3D11_INTERNAL_WaitForFence(
+            renderer,
+            renderer->submittedCommandBuffers[i]->fence);
+    }
+
+    SDL_LockMutex(renderer->contextLock); // This effectively acts as a lock around submittedCommandBuffers
+
+    for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+        commandBuffer = renderer->submittedCommandBuffers[i];
+        D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
+    }
+
+    D3D11_INTERNAL_PerformPendingDestroys(renderer);
+
+    SDL_UnlockMutex(renderer->contextLock);
+}
+
+// Format Info
+
+static SDL_bool D3D11_SupportsTextureFormat(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureFormat format,
+    SDL_GpuTextureType type,
+    SDL_GpuTextureUsageFlags usage)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    DXGI_FORMAT dxgiFormat = SDLToD3D11_TextureFormat[format];
+    DXGI_FORMAT typelessFormat = D3D11_INTERNAL_GetTypelessFormat(dxgiFormat);
+    UINT formatSupport, sampleableFormatSupport;
+    HRESULT res;
+
+    res = ID3D11Device_CheckFormatSupport(
+        renderer->device,
+        dxgiFormat,
+        &formatSupport);
+    if (FAILED(res)) {
+        // Format is apparently unknown
+        return SDL_FALSE;
+    }
+
+    /* Depth textures are stored as typeless textures, but interpreted as color textures for sampling.
+     * In order to get supported usages for both interpretations, we have to do this.
+     */
+    if (typelessFormat != DXGI_FORMAT_UNKNOWN) {
+        res = ID3D11Device_CheckFormatSupport(
+            renderer->device,
+            D3D11_INTERNAL_GetSampleableFormat(typelessFormat),
+            &sampleableFormatSupport);
+        if (SUCCEEDED(res)) {
+            formatSupport |= sampleableFormatSupport;
+        }
+    }
+
+    // Is the texture type supported?
+    if (type == SDL_GPU_TEXTURETYPE_2D && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)) {
+        return SDL_FALSE;
+    }
+    if (type == SDL_GPU_TEXTURETYPE_2D_ARRAY && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)) {
+        return SDL_FALSE;
+    }
+    if (type == SDL_GPU_TEXTURETYPE_3D && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D)) {
+        return SDL_FALSE;
+    }
+    if (type == SDL_GPU_TEXTURETYPE_CUBE && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE)) {
+        return SDL_FALSE;
+    }
+
+    // Are the usage flags supported?
+    if ((usage & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) && !(formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) {
+        return SDL_FALSE;
+    }
+    if ((usage & (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT)) && !(formatSupport & D3D11_FORMAT_SUPPORT_SHADER_LOAD)) {
+        return SDL_FALSE;
+    }
+    if ((usage & (SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT) && !(formatSupport & D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW))) {
+        // TYPED_UNORDERED_ACCESS_VIEW implies support for typed UAV stores
+        return SDL_FALSE;
+    }
+    if ((usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) && !(formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) {
+        return SDL_FALSE;
+    }
+    if ((usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) && !(formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)) {
+        return SDL_FALSE;
+    }
+
+    return SDL_TRUE;
+}
+
+// Device Creation
+
+static SDL_bool D3D11_PrepareDriver(SDL_VideoDevice *_this)
+{
+    void *d3d11_dll, *dxgi_dll;
+    PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc;
+    D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 };
+    PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc;
+    HRESULT res;
+
+    // Can we load D3D11?
+
+    d3d11_dll = SDL_LoadObject(D3D11_DLL);
+    if (d3d11_dll == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find " D3D11_DLL);
+        return SDL_FALSE;
+    }
+
+    D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE)SDL_LoadFunction(
+        d3d11_dll,
+        D3D11_CREATE_DEVICE_FUNC);
+    if (D3D11CreateDeviceFunc == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find function " D3D11_CREATE_DEVICE_FUNC " in " D3D11_DLL);
+        SDL_UnloadObject(d3d11_dll);
+        return SDL_FALSE;
+    }
+
+    // Can we create a device?
+
+    res = D3D11CreateDeviceFunc(
+        NULL,
+        D3D_DRIVER_TYPE_HARDWARE,
+        NULL,
+        D3D11_CREATE_DEVICE_BGRA_SUPPORT,
+        levels,
+        SDL_arraysize(levels),
+        D3D11_SDK_VERSION,
+        NULL,
+        NULL,
+        NULL);
+
+    SDL_UnloadObject(d3d11_dll);
+
+    if (FAILED(res)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not create D3D11Device with feature level 11_1");
+        return SDL_FALSE;
+    }
+
+    // Can we load DXGI?
+
+    dxgi_dll = SDL_LoadObject(DXGI_DLL);
+    if (dxgi_dll == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find " DXGI_DLL);
+        return SDL_FALSE;
+    }
+
+    CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY1)SDL_LoadFunction(
+        dxgi_dll,
+        CREATE_DXGI_FACTORY1_FUNC);
+    SDL_UnloadObject(dxgi_dll); // We're not going to call this function, so we can just unload now.
+    if (CreateDXGIFactoryFunc == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find function " CREATE_DXGI_FACTORY1_FUNC " in " DXGI_DLL);
+        return SDL_FALSE;
+    }
+
+    return SDL_TRUE;
+}
+
+static void D3D11_INTERNAL_TryInitializeDXGIDebug(D3D11Renderer *renderer)
+{
+    PFN_DXGI_GET_DEBUG_INTERFACE DXGIGetDebugInterfaceFunc;
+    HRESULT res;
+
+    renderer->dxgidebug_dll = SDL_LoadObject(DXGIDEBUG_DLL);
+    if (renderer->dxgidebug_dll == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not find " DXGIDEBUG_DLL);
+        return;
+    }
+
+    DXGIGetDebugInterfaceFunc = (PFN_DXGI_GET_DEBUG_INTERFACE)SDL_LoadFunction(
+        renderer->dxgidebug_dll,
+        DXGI_GET_DEBUG_INTERFACE_FUNC);
+    if (DXGIGetDebugInterfaceFunc == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not load function: " DXGI_GET_DEBUG_INTERFACE_FUNC);
+        return;
+    }
+
+    res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIDebug, (void **)&renderer->dxgiDebug);
+    if (FAILED(res)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIDebug interface");
+    }
+
+#ifdef HAVE_IDXGIINFOQUEUE
+    res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, (void **)&renderer->dxgiInfoQueue);
+    if (FAILED(res)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIInfoQueue interface");
+    }
+#endif
+}
+
+static void D3D11_INTERNAL_InitBlitPipelines(
+    D3D11Renderer *renderer)
+{
+    SDL_GpuShaderCreateInfo shaderCreateInfo;
+    SDL_GpuShader *fullscreenVertexShader;
+    SDL_GpuShader *blitFrom2DPixelShader;
+    SDL_GpuShader *blitFrom2DArrayPixelShader;
+    SDL_GpuShader *blitFrom3DPixelShader;
+    SDL_GpuShader *blitFromCubePixelShader;
+    SDL_GpuGraphicsPipelineCreateInfo blitPipelineCreateInfo;
+    SDL_GpuGraphicsPipeline *blitPipeline;
+    SDL_GpuSamplerCreateInfo samplerCreateInfo;
+    SDL_GpuColorAttachmentDescription colorAttachmentDesc;
+
+    // Fullscreen vertex shader
+    SDL_zero(shaderCreateInfo);
+    shaderCreateInfo.code = (Uint8 *)D3D11_FullscreenVert;
+    shaderCreateInfo.codeSize = sizeof(D3D11_FullscreenVert);
+    shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_VERTEX;
+    shaderCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC;
+    shaderCreateInfo.entryPointName = "main";
+
+    fullscreenVertexShader = D3D11_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (fullscreenVertexShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile vertex shader for blit!");
+    }
+
+    // BlitFrom2D pixel shader
+    shaderCreateInfo.code = (Uint8 *)D3D11_BlitFrom2D;
+    shaderCreateInfo.codeSize = sizeof(D3D11_BlitFrom2D);
+    shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_FRAGMENT;
+    shaderCreateInfo.samplerCount = 1;
+    shaderCreateInfo.uniformBufferCount = 1;
+
+    blitFrom2DPixelShader = D3D11_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (blitFrom2DPixelShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2D pixel shader!");
+    }
+
+    // BlitFrom2DArray pixel shader
+    shaderCreateInfo.code = (Uint8 *)D3D11_BlitFrom2DArray;
+    shaderCreateInfo.codeSize = sizeof(D3D11_BlitFrom2DArray);
+
+    blitFrom2DArrayPixelShader = D3D11_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (blitFrom2DArrayPixelShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2DArray pixel shader!");
+    }
+
+    // BlitFrom3D pixel shader
+    shaderCreateInfo.code = (Uint8 *)D3D11_BlitFrom3D;
+    shaderCreateInfo.codeSize = sizeof(D3D11_BlitFrom3D);
+
+    blitFrom3DPixelShader = D3D11_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (blitFrom3DPixelShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom3D pixel shader!");
+    }
+
+    // BlitFromCube pixel shader
+    shaderCreateInfo.code = (Uint8 *)D3D11_BlitFromCube;
+    shaderCreateInfo.codeSize = sizeof(D3D11_BlitFromCube);
+
+    blitFromCubePixelShader = D3D11_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (blitFromCubePixelShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCube pixel shader!");
+    }
+
+    // BlitFrom2D pipeline
+    SDL_zero(blitPipelineCreateInfo);
+
+    SDL_zero(colorAttachmentDesc);
+    colorAttachmentDesc.blendState.colorWriteMask = 0xF;
+    colorAttachmentDesc.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; // format doesn't matter in d3d11
+
+    blitPipelineCreateInfo.attachmentInfo.colorAttachmentDescriptions = &colorAttachmentDesc;
+    blitPipelineCreateInfo.attachmentInfo.colorAttachmentCount = 1;
+    blitPipelineCreateInfo.attachmentInfo.depthStencilFormat = SDL_GPU_TEXTUREFORMAT_D16_UNORM; // arbitrary
+    blitPipelineCreateInfo.attachmentInfo.hasDepthStencilAttachment = SDL_FALSE;
+
+    blitPipelineCreateInfo.vertexShader = fullscreenVertexShader;
+    blitPipelineCreateInfo.fragmentShader = blitFrom2DPixelShader;
+
+    blitPipelineCreateInfo.multisampleState.sampleCount = SDL_GPU_SAMPLECOUNT_1;
+    blitPipelineCreateInfo.multisampleState.sampleMask = 0xFFFFFFFF;
+
+    blitPipelineCreateInfo.primitiveType = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST;
+
+    blitPipelineCreateInfo.blendConstants[0] = 1.0f;
+    blitPipelineCreateInfo.blendConstants[1] = 1.0f;
+    blitPipelineCreateInfo.blendConstants[2] = 1.0f;
+    blitPipelineCreateInfo.blendConstants[3] = 1.0f;
+
+    blitPipeline = D3D11_CreateGraphicsPipeline(
+        (SDL_GpuRenderer *)renderer,
+        &blitPipelineCreateInfo);
+
+    if (blitPipeline == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFrom2D pipeline!");
+    }
+
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D].pipeline = blitPipeline;
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D].type = SDL_GPU_TEXTURETYPE_2D;
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D].format = SDL_GPU_TEXTUREFORMAT_INVALID;
+
+    // BlitFrom2DArrayPipeline
+    blitPipelineCreateInfo.fragmentShader = blitFrom2DArrayPixelShader;
+    blitPipeline = D3D11_CreateGraphicsPipeline(
+        (SDL_GpuRenderer *)renderer,
+        &blitPipelineCreateInfo);
+
+    if (blitPipeline == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFrom2DArray pipeline!");
+    }
+
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D_ARRAY].pipeline = blitPipeline;
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D_ARRAY].type = SDL_GPU_TEXTURETYPE_2D_ARRAY;
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D_ARRAY].format = SDL_GPU_TEXTUREFORMAT_INVALID;
+
+    // BlitFrom3DPipeline
+    blitPipelineCreateInfo.fragmentShader = blitFrom3DPixelShader;
+    blitPipeline = D3D11_CreateGraphicsPipeline(
+        (SDL_GpuRenderer *)renderer,
+        &blitPipelineCreateInfo);
+
+    if (blitPipeline == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFrom3D pipeline!");
+    }
+
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_3D].pipeline = blitPipeline;
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_3D].type = SDL_GPU_TEXTURETYPE_3D;
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_3D].format = SDL_GPU_TEXTUREFORMAT_INVALID;
+
+    // BlitFromCubePipeline
+    blitPipelineCreateInfo.fragmentShader = blitFromCubePixelShader;
+    blitPipeline = D3D11_CreateGraphicsPipeline(
+        (SDL_GpuRenderer *)renderer,
+        &blitPipelineCreateInfo);
+
+    if (blitPipeline == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFromCube pipeline!");
+    }
+
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].pipeline = blitPipeline;
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].type = SDL_GPU_TEXTURETYPE_CUBE;
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].format = SDL_GPU_TEXTUREFORMAT_INVALID;
+
+    // Create samplers
+    samplerCreateInfo.addressModeU = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.addressModeV = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.addressModeW = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.anisotropyEnable = 0;
+    samplerCreateInfo.compareEnable = 0;
+    samplerCreateInfo.magFilter = SDL_GPU_FILTER_NEAREST;
+    samplerCreateInfo.minFilter = SDL_GPU_FILTER_NEAREST;
+    samplerCreateInfo.mipmapMode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
+    samplerCreateInfo.mipLodBias = 0.0f;
+    samplerCreateInfo.minLod = 0;
+    samplerCreateInfo.maxLod = 1000;
+
+    renderer->blitNearestSampler = D3D11_CreateSampler(
+        (SDL_GpuRenderer *)renderer,
+        &samplerCreateInfo);
+
+    if (renderer->blitNearestSampler == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit nearest sampler!");
+    }
+
+    samplerCreateInfo.magFilter = SDL_GPU_FILTER_LINEAR;
+    samplerCreateInfo.minFilter = SDL_GPU_FILTER_LINEAR;
+    samplerCreateInfo.mipmapMode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR;
+
+    renderer->blitLinearSampler = D3D11_CreateSampler(
+        (SDL_GpuRenderer *)renderer,
+        &samplerCreateInfo);
+
+    if (renderer->blitLinearSampler == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit linear sampler!");
+    }
+
+    // Clean up
+    D3D11_ReleaseShader((SDL_GpuRenderer *)renderer, fullscreenVertexShader);
+    D3D11_ReleaseShader((SDL_GpuRenderer *)renderer, blitFrom2DPixelShader);
+    D3D11_ReleaseShader((SDL_GpuRenderer *)renderer, blitFrom2DArrayPixelShader);
+    D3D11_ReleaseShader((SDL_GpuRenderer *)renderer, blitFrom3DPixelShader);
+    D3D11_ReleaseShader((SDL_GpuRenderer *)renderer, blitFromCubePixelShader);
+}
+
+static void D3D11_INTERNAL_DestroyBlitPipelines(
+    SDL_GpuRenderer *driverData)
+{
+    D3D11Renderer *renderer = (D3D11Renderer *)driverData;
+    D3D11_ReleaseSampler(driverData, renderer->blitLinearSampler);
+    D3D11_ReleaseSampler(driverData, renderer->blitNearestSampler);
+    for (int i = 0; i < SDL_arraysize(renderer->blitPipelines); i += 1) {
+        D3D11_ReleaseGraphicsPipeline(driverData, renderer->blitPipelines[i].pipeline);
+    }
+}
+
+static SDL_GpuDevice *D3D11_CreateDevice(SDL_bool debugMode, SDL_bool preferLowPower, SDL_PropertiesID props)
+{
+    D3D11Renderer *renderer;
+    PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc;
+    PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc;
+    D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 };
+    IDXGIFactory4 *factory4;
+    IDXGIFactory5 *factory5;
+    IDXGIFactory6 *factory6;
+    Uint32 flags;
+    DXGI_ADAPTER_DESC1 adapterDesc;
+    HRESULT res;
+    SDL_GpuDevice *result;
+
+    // Allocate and zero out the renderer
+    renderer = (D3D11Renderer *)SDL_calloc(1, sizeof(D3D11Renderer));
+
+    // Load the DXGI library
+    renderer->dxgi_dll = SDL_LoadObject(DXGI_DLL);
+    if (renderer->dxgi_dll == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not find " DXGI_DLL);
+        return NULL;
+    }
+
+    // Load the CreateDXGIFactory1 function
+    CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY1)SDL_LoadFunction(
+        renderer->dxgi_dll,
+        CREATE_DXGI_FACTORY1_FUNC);
+    if (CreateDXGIFactoryFunc == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not load function: " CREATE_DXGI_FACTORY1_FUNC);
+        return NULL;
+    }
+
+    // Create the DXGI factory
+    res = CreateDXGIFactoryFunc(
+        &D3D_IID_IDXGIFactory1,
+        (void **)&renderer->factory);
+    ERROR_CHECK_RETURN("Could not create DXGIFactory", NULL);
+
+    // Check for flip-model discard support (supported on Windows 10+)
+    res = IDXGIFactory1_QueryInterface(
+        renderer->factory,
+        &D3D_IID_IDXGIFactory4,
+        (void **)&factory4);
+    if (SUCCEEDED(res)) {
+        renderer->supportsFlipDiscard = 1;
+        IDXGIFactory4_Release(factory4);
+    }
+
+    // Check for explicit tearing support
+    res = IDXGIFactory1_QueryInterface(
+        renderer->factory,
+        &D3D_IID_IDXGIFactory5,
+        (void **)&factory5);
+    if (SUCCEEDED(res)) {
+        res = IDXGIFactory5_CheckFeatureSupport(
+            factory5,
+            DXGI_FEATURE_PRESENT_ALLOW_TEARING,
+            &renderer->supportsTearing,
+            sizeof(renderer->supportsTearing));
+        if (FAILED(res)) {
+            renderer->supportsTearing = FALSE;
+        }
+        IDXGIFactory5_Release(factory5);
+    }
+
+    // Select the appropriate device for rendering
+    res = IDXGIAdapter1_QueryInterface(
+        renderer->factory,
+        &D3D_IID_IDXGIFactory6,
+        (void **)&factory6);
+    if (SUCCEEDED(res)) {
+        IDXGIFactory6_EnumAdapterByGpuPreference(
+            factory6,
+            0,
+            preferLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER : DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
+            &D3D_IID_IDXGIAdapter1,
+            (void **)&renderer->adapter);
+        IDXGIFactory6_Release(factory6);
+    } else {
+        IDXGIFactory1_EnumAdapters1(
+            renderer->factory,
+            0,
+            &renderer->adapter);
+    }
+
+    // Get information about the selected adapter. Used for logging info.
+    IDXGIAdapter1_GetDesc1(renderer->adapter, &adapterDesc);
+
+    // Initialize the DXGI debug layer, if applicable
+    if (debugMode) {
+        D3D11_INTERNAL_TryInitializeDXGIDebug(renderer);
+    }
+
+    // Load the D3D library
+    renderer->d3d11_dll = SDL_LoadObject(D3D11_DLL);
+    if (renderer->d3d11_dll == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not find " D3D11_DLL);
+        return NULL;
+    }
+
+    // Load the CreateDevice function
+    D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE)SDL_LoadFunction(
+        renderer->d3d11_dll,
+        D3D11_CREATE_DEVICE_FUNC);
+    if (D3D11CreateDeviceFunc == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not load function: " D3D11_CREATE_DEVICE_FUNC);
+        return NULL;
+    }
+
+    // Set up device flags
+    flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+    if (debugMode) {
+        flags |= D3D11_CREATE_DEVICE_DEBUG;
+    }
+
+    // Create the device
+    ID3D11Device *d3d11Device;
+tryCreateDevice:
+    res = D3D11CreateDeviceFunc(
+        (IDXGIAdapter *)renderer->adapter,
+        D3D_DRIVER_TYPE_UNKNOWN, // Must be UNKNOWN if adapter is non-null according to spec
+        NULL,
+        flags,
+        levels,
+        SDL_arraysize(levels),
+        D3D11_SDK_VERSION,
+        &d3d11Device,
+        NULL,
+        &renderer->immediateContext);
+    if (FAILED(res) && debugMode) {
+        // If device creation failed, and we're in debug mode, remove the debug flag and try again.
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Creating device in debug mode failed with error " HRESULT_FMT ". Trying non-debug.", res);
+        flags &= ~D3D11_CREATE_DEVICE_DEBUG;
+        debugMode = 0;
+        goto tryCreateDevice;
+    }
+
+    ERROR_CHECK_RETURN("Could not create D3D11 device", NULL);
+
+    // The actual device we want is the ID3D11Device1 interface...
+    res = ID3D11Device_QueryInterface(
+        d3d11Device,
+        &D3D_IID_ID3D11Device1,
+        (void **)&renderer->device);
+    ERROR_CHECK_RETURN("Could not get ID3D11Device1 interface", NULL);
+
+    // Release the old device interface, we don't need it anymore
+    ID3D11Device_Release(d3d11Device);
+
+#ifdef HAVE_IDXGIINFOQUEUE
+    // Set up the info queue
+    if (renderer->dxgiInfoQueue) {
+        DXGI_INFO_QUEUE_MESSAGE_SEVERITY sevList[] = {
+            DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION,
+            DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR,
+            DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING,
+            // DXGI_INFO_QUEUE_MESSAGE_SEVERITY_INFO, // This can be a bit much, so toggle as needed for debugging.
+            DXGI_INFO_QUEUE_MESSAGE_SEVERITY_MESSAGE
+        };
+        DXGI_INFO_QUEUE_FILTER filter = { 0 };
+        filter.AllowList.NumSeverities = SDL_arraysize(sevList);
+        filter.AllowList.pSeverityList = sevList;
+
+        IDXGIInfoQueue_PushStorageFilter(
+            renderer->dxgiInfoQueue,
+            D3D_IID_DXGI_DEBUG_ALL,
+            &filter);
+    }
+#endif
+
+    // Print driver info
+    SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL GPU Driver: D3D11");
+    SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "D3D11 Adapter: %S", adapterDesc.Description);
+
+    // Create mutexes
+    renderer->contextLock = SDL_CreateMutex();
+    renderer->acquireCommandBufferLock = SDL_CreateMutex();
+    renderer->acquireUniformBufferLock = SDL_CreateMutex();
+    renderer->fenceLock = SDL_CreateMutex();
+    renderer->windowLock = SDL_CreateMutex();
+
+    // Initialize miscellaneous renderer members
+    renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG);
+
+    // Create command buffer pool
+    D3D11_INTERNAL_AllocateCommandBuffers(renderer, 2);
+
+    // Create fence pool
+    renderer->availableFenceCapacity = 2;
+    renderer->availableFences = SDL_malloc(
+        sizeof(D3D11Fence *) * renderer->availableFenceCapacity);
+
+    // Create uniform buffer pool
+
+    renderer->uniformBufferPoolCapacity = 32;
+    renderer->uniformBufferPoolCount = 32;
+    renderer->uniformBufferPool = SDL_malloc(
+        renderer->uniformBufferPoolCapacity * sizeof(D3D11UniformBuffer *));
+
+    for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
+        renderer->uniformBufferPool[i] = D3D11_INTERNAL_CreateUniformBuffer(
+            renderer,
+            UNIFORM_BUFFER_SIZE);
+    }
+
+    // Create deferred destroy arrays
+    renderer->transferBufferContainersToDestroyCapacity = 2;
+    renderer->transferBufferContainersToDestroyCount = 0;
+    renderer->transferBufferContainersToDestroy = SDL_malloc(
+        renderer->transferBufferContainersToDestroyCapacity * sizeof(D3D11TransferBufferContainer *));
+
+    renderer->bufferContainersToDestroyCapacity = 2;
+    renderer->bufferContainersToDestroyCount = 0;
+    renderer->bufferContainersToDestroy = SDL_malloc(
+        renderer->bufferContainersToDestroyCapacity * sizeof(D3D11BufferContainer *));
+
+    renderer->textureContainersToDestroyCapacity = 2;
+    renderer->textureContainersToDestroyCount = 0;
+    renderer->textureContainersToDestroy = SDL_malloc(
+        renderer->textureContainersToDestroyCapacity * sizeof(D3D11TextureContainer *));
+
+    // Create claimed window list
+    renderer->claimedWindowCapacity = 1;
+    renderer->claimedWindows = SDL_malloc(
+        sizeof(D3D11WindowData *) * renderer->claimedWindowCapacity);
+
+    // Initialize null states
+
+    SDL_zeroa(nullRTVs);
+    SDL_zeroa(nullSRVs);
+    SDL_zeroa(nullSamplers);
+    SDL_zeroa(nullUAVs);
+
+    // Initialize built-in pipelines
+    D3D11_INTERNAL_InitBlitPipelines(renderer);
+
+    // Create the SDL_Gpu Device
+    result = (SDL_GpuDevice *)SDL_malloc(sizeof(SDL_GpuDevice));
+    ASSIGN_DRIVER(D3D11)
+    result->driverData = (SDL_GpuRenderer *)renderer;
+
+    return result;
+}
+
+SDL_GpuBootstrap D3D11Driver = {
+    "D3D11",
+    SDL_GPU_DRIVER_D3D11,
+    SDL_GPU_SHADERFORMAT_DXBC,
+    D3D11_PrepareDriver,
+    D3D11_CreateDevice
+};
+
+#endif // SDL_GPU_D3D11

+ 7 - 0
src/gpu/d3d11/compile_shaders.bat

@@ -0,0 +1,7 @@
+fxc /T vs_5_0 /E FullscreenVert /Fh D3D11_FullscreenVert.h ..\d3dcommon\D3D_Blit.hlsl
+fxc /T ps_5_0 /E BlitFrom2D /Fh D3D11_BlitFrom2D.h ..\d3dcommon\D3D_Blit.hlsl
+fxc /T ps_5_0 /E BlitFrom2DArray /Fh D3D11_BlitFrom2DArray.h ..\d3dcommon\D3D_Blit.hlsl
+fxc /T ps_5_0 /E BlitFrom3D /Fh D3D11_BlitFrom3D.h ..\d3dcommon\D3D_Blit.hlsl
+fxc /T ps_5_0 /E BlitFromCube /Fh D3D11_BlitFromCube.h ..\d3dcommon\D3D_Blit.hlsl
+copy /b D3D11_FullscreenVert.h+D3D11_BlitFrom2D.h+D3D11_BlitFrom2DArray.h+D3D11_BlitFrom3D.h+D3D11_BlitFromCube.h D3D11_Blit.h
+del D3D11_FullscreenVert.h D3D11_BlitFrom2D.h D3D11_BlitFrom2DArray.h D3D11_BlitFrom3D.h D3D11_BlitFromCube.h

+ 2665 - 0
src/gpu/d3d12/D3D12_Blit.h

@@ -0,0 +1,2665 @@
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_VertexID              0   x           0   VERTID    uint   x   
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xy          0     NONE   float   xy  
+; SV_Position              0   xyzw        1      POS   float   xyzw
+;
+; shader hash: 347572259f9a9ea84d2f90bafbd0e1ae
+;
+; Pipeline Runtime Information: 
+;
+; Vertex Shader
+; OutputPositionPresent=1
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_VertexID              0                              
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; SV_Position              0          noperspective       
+;
+; Buffer Definitions:
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+;
+;
+; ViewId state:
+;
+; Number of inputs: 1, outputs: 8
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 0 }
+;   output 1 depends on inputs: { 0 }
+;   output 4 depends on inputs: { 0 }
+;   output 5 depends on inputs: { 0 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+define void @FullscreenVert() {
+  %1 = call i32 @dx.op.loadInput.i32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %2 = shl i32 %1, 1
+  %3 = and i32 %2, 2
+  %4 = uitofp i32 %3 to float
+  %5 = and i32 %1, 2
+  %6 = uitofp i32 %5 to float
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float 0.000000e+00)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float 0.000000e+00)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 0, float 0.000000e+00)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 1, float 0.000000e+00)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 2, float 0.000000e+00)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 3, float 0.000000e+00)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %4)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %6)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  %7 = fmul fast float %4, 2.000000e+00
+  %8 = fmul fast float %6, 2.000000e+00
+  %9 = fadd fast float %7, -1.000000e+00
+  %10 = fsub fast float 1.000000e+00, %8
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 0, float %9)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 1, float %10)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 2, float 0.000000e+00)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 3, float 1.000000e+00)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare i32 @dx.op.loadInput.i32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.viewIdState = !{!4}
+!dx.entryPoints = !{!5}
+
+!0 = !{!"clang version 3.7 (tags/RELEASE_370/final)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 6}
+!3 = !{!"vs", i32 6, i32 0}
+!4 = !{[3 x i32] [i32 1, i32 8, i32 51]}
+!5 = !{void ()* @FullscreenVert, !"FullscreenVert", !6, null, null}
+!6 = !{!7, !11, null}
+!7 = !{!8}
+!8 = !{i32 0, !"SV_VertexID", i8 5, i8 1, !9, i8 0, i32 1, i8 1, i32 0, i8 0, !10}
+!9 = !{i32 0}
+!10 = !{i32 3, i32 1}
+!11 = !{!12, !14}
+!12 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !9, i8 2, i32 1, i8 2, i32 0, i8 0, !13}
+!13 = !{i32 3, i32 3}
+!14 = !{i32 1, !"SV_Position", i8 9, i8 3, !9, i8 4, i32 1, i8 4, i32 1, i8 0, !15}
+!15 = !{i32 3, i32 15}
+
+#endif
+
+const unsigned char g_FullscreenVert[] = {
+  0x44, 0x58, 0x42, 0x43, 0x9a, 0xbe, 0xe2, 0x88, 0x72, 0x7c, 0xa1, 0x03,
+  0xa6, 0x2d, 0x0a, 0x39, 0x62, 0x29, 0x6c, 0x96, 0x01, 0x00, 0x00, 0x00,
+  0xb9, 0x0c, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00,
+  0x89, 0x01, 0x00, 0x00, 0x15, 0x07, 0x00, 0x00, 0x31, 0x07, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x56, 0x65, 0x72, 0x74, 0x65,
+  0x78, 0x49, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x5d, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5f,
+  0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x50, 0x53, 0x56,
+  0x30, 0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f,
+  0x52, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x41, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x03, 0x02, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x44,
+  0x03, 0x03, 0x04, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41,
+  0x54, 0x84, 0x05, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x61, 0x01, 0x00,
+  0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00,
+  0x00, 0x6c, 0x05, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00,
+  0x00, 0x58, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00,
+  0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04,
+  0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08,
+  0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92, 0x0b,
+  0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42,
+  0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32,
+  0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81,
+  0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, 0x06, 0x51, 0x18, 0x00,
+  0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff,
+  0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03,
+  0x20, 0x01, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x02, 0x00, 0x00,
+  0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00,
+  0x00, 0x15, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, 0x20, 0x64, 0x85,
+  0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90,
+  0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x3c, 0x23,
+  0x00, 0x25, 0x00, 0x8a, 0x39, 0x02, 0x30, 0x98, 0x23, 0x40, 0x8a, 0x31,
+  0x33, 0x43, 0x43, 0x35, 0x03, 0x50, 0x0c, 0x98, 0x19, 0x3a, 0xc2, 0x81,
+  0x80, 0x61, 0x04, 0xe1, 0x18, 0x46, 0x20, 0x8e, 0xa3, 0xa4, 0x29, 0xa2,
+  0x84, 0xc9, 0x7f, 0x89, 0x68, 0x22, 0xae, 0xd6, 0x49, 0x91, 0x8b, 0x58,
+  0x90, 0xb0, 0x9c, 0x03, 0x03, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60,
+  0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf,
+  0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a,
+  0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6,
+  0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71,
+  0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43,
+  0x9e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x86, 0x3c, 0x05, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc8, 0x02, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98,
+  0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43,
+  0x9a, 0x12, 0x18, 0x01, 0x28, 0x86, 0x02, 0x2a, 0x83, 0x42, 0x28, 0x87,
+  0x92, 0x28, 0x90, 0xf2, 0x28, 0x97, 0xc2, 0x20, 0x2a, 0x85, 0x12, 0x18,
+  0x01, 0x28, 0x89, 0x22, 0x28, 0x83, 0x42, 0xa0, 0x9e, 0x01, 0x20, 0x1f,
+  0x6b, 0x08, 0x90, 0x39, 0x00, 0x79, 0x18, 0x00, 0x00, 0x84, 0x00, 0x00,
+  0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x35, 0x18, 0x63,
+  0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03,
+  0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a,
+  0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b,
+  0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, 0x84, 0x61, 0x98, 0x20,
+  0x0c, 0xc4, 0x06, 0x61, 0x20, 0x36, 0x08, 0x04, 0x41, 0xc1, 0x6e, 0x6e,
+  0x82, 0x30, 0x14, 0x1b, 0x86, 0x03, 0x21, 0x26, 0x08, 0x8d, 0x35, 0x41,
+  0x18, 0x0c, 0x0e, 0x74, 0x65, 0x78, 0x13, 0x84, 0xe1, 0x98, 0x20, 0x0c,
+  0x08, 0x13, 0xaa, 0x22, 0xac, 0xa1, 0xa7, 0x27, 0x29, 0x22, 0x98, 0x09,
+  0xc2, 0x90, 0x4c, 0x10, 0x06, 0x65, 0x03, 0x82, 0x30, 0x0d, 0xe1, 0x3c,
+  0x50, 0xc4, 0x01, 0xee, 0x6d, 0x6e, 0x82, 0x30, 0x2c, 0x5c, 0xa6, 0xac,
+  0xbe, 0xa0, 0x9e, 0xa6, 0x92, 0xa8, 0x92, 0x9e, 0x9c, 0x36, 0x20, 0xc8,
+  0xd4, 0x50, 0x4e, 0x05, 0x45, 0x1b, 0x86, 0x45, 0xb2, 0x36, 0x0c, 0x84,
+  0x72, 0x4d, 0x10, 0x04, 0x60, 0x03, 0xb0, 0x61, 0x20, 0x34, 0x6d, 0x43,
+  0xb0, 0x6d, 0x18, 0x86, 0x8c, 0x9b, 0x20, 0x38, 0xd7, 0x86, 0xc0, 0xa3,
+  0x63, 0x54, 0xc7, 0xc6, 0x36, 0x37, 0x26, 0x57, 0x56, 0xe6, 0x66, 0x55,
+  0x26, 0x47, 0xc7, 0x65, 0xca, 0xea, 0xcb, 0xaa, 0x4c, 0x8e, 0xae, 0x0c,
+  0x2f, 0x89, 0x68, 0x82, 0x40, 0x3c, 0x13, 0x04, 0x02, 0xda, 0x10, 0x10,
+  0x13, 0x04, 0x22, 0xda, 0x20, 0x34, 0xc3, 0x86, 0x85, 0x08, 0x03, 0x31,
+  0x18, 0x03, 0x32, 0x28, 0x83, 0x61, 0x0c, 0x88, 0x32, 0x30, 0x83, 0x0d,
+  0xc1, 0x19, 0x10, 0xa1, 0x2a, 0xc2, 0x1a, 0x7a, 0x7a, 0x92, 0x22, 0x9a,
+  0x20, 0x10, 0xd2, 0x04, 0x81, 0x98, 0x36, 0x08, 0x4d, 0xb3, 0x61, 0x21,
+  0xd2, 0x40, 0x0d, 0xca, 0x80, 0x0c, 0xd6, 0x60, 0x58, 0x03, 0xa2, 0x0c,
+  0xd8, 0x80, 0xcb, 0x94, 0xd5, 0x17, 0xd4, 0xdb, 0x5c, 0x1a, 0x5d, 0xda,
+  0x9b, 0xdb, 0x04, 0x81, 0xa0, 0x26, 0x08, 0x44, 0x35, 0x41, 0x18, 0x98,
+  0x0d, 0x42, 0x13, 0x07, 0x1b, 0x96, 0xc1, 0x0d, 0xd4, 0xe0, 0x0d, 0xc8,
+  0x00, 0x0e, 0x06, 0x38, 0x18, 0xca, 0x40, 0x0e, 0x36, 0x08, 0x6d, 0x30,
+  0x07, 0x1b, 0x06, 0x34, 0xa0, 0x03, 0x60, 0x43, 0x91, 0x81, 0x41, 0x1d,
+  0x00, 0x00, 0x0d, 0x33, 0xb6, 0xb7, 0x30, 0xba, 0x39, 0x16, 0x69, 0x6e,
+  0x73, 0x74, 0x73, 0x13, 0x84, 0xa1, 0xa1, 0x31, 0x97, 0x76, 0xf6, 0xc5,
+  0x46, 0x46, 0x63, 0x2e, 0xed, 0xec, 0x6b, 0x8e, 0x6e, 0x82, 0x30, 0x38,
+  0x2c, 0xea, 0xd2, 0xdc, 0xe8, 0xe6, 0x36, 0x28, 0x77, 0x80, 0xe0, 0x41,
+  0x1e, 0xe8, 0xc1, 0xb0, 0x07, 0x7c, 0xd0, 0x07, 0x4d, 0x15, 0x36, 0x36,
+  0xbb, 0x36, 0x97, 0x34, 0xb2, 0x32, 0x37, 0xba, 0x29, 0x41, 0x50, 0x85,
+  0x0c, 0xcf, 0xc5, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x6d, 0x4a, 0x40,
+  0x34, 0x21, 0xc3, 0x73, 0xb1, 0x0b, 0x63, 0xb3, 0x2b, 0x93, 0x9b, 0x12,
+  0x14, 0x75, 0xc8, 0xf0, 0x5c, 0xe6, 0xd0, 0xc2, 0xc8, 0xca, 0xe4, 0x9a,
+  0xde, 0xc8, 0xca, 0xd8, 0xa6, 0x04, 0x48, 0x25, 0x32, 0x3c, 0x17, 0xba,
+  0x3c, 0xb8, 0xb2, 0x20, 0x37, 0xb7, 0x37, 0xba, 0x30, 0xba, 0xb4, 0x37,
+  0xb7, 0xb9, 0x29, 0xc2, 0xc5, 0xd5, 0x21, 0xc3, 0x73, 0xb1, 0x4b, 0x2b,
+  0xbb, 0x4b, 0x22, 0x9b, 0xa2, 0x0b, 0xa3, 0x2b, 0x9b, 0x12, 0x78, 0x75,
+  0xc8, 0xf0, 0x5c, 0xca, 0xdc, 0xe8, 0xe4, 0xf2, 0xa0, 0xde, 0xd2, 0xdc,
+  0xe8, 0xe6, 0xa6, 0x04, 0x75, 0xd0, 0x85, 0x0c, 0xcf, 0x65, 0xec, 0xad,
+  0xce, 0x8d, 0xae, 0x4c, 0x6e, 0x6e, 0x4a, 0xd0, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80,
+  0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84,
+  0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c,
+  0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42,
+  0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88,
+  0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c,
+  0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79,
+  0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70,
+  0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f,
+  0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4,
+  0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30,
+  0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc,
+  0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b,
+  0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70,
+  0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76,
+  0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72,
+  0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e,
+  0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21,
+  0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94,
+  0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc,
+  0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c,
+  0x70, 0x03, 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e,
+  0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e,
+  0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00,
+  0x00, 0x71, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0xe0, 0x7c,
+  0xd4, 0xb2, 0x48, 0x42, 0x44, 0x10, 0xcd, 0x4b, 0x44, 0x93, 0x05, 0x4c,
+  0xc3, 0xe5, 0x3b, 0x8f, 0xbf, 0x38, 0xc0, 0x20, 0x36, 0x0f, 0x35, 0xf9,
+  0xc8, 0x6d, 0x9b, 0x40, 0x35, 0x5c, 0xbe, 0xf3, 0xf8, 0xd2, 0xe4, 0x44,
+  0x04, 0x4a, 0x4d, 0x0f, 0x35, 0xf9, 0xc5, 0x6d, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x34, 0x75, 0x72, 0x25, 0x9f, 0x9a, 0x9e, 0xa8, 0x4d, 0x2f, 0x90,
+  0xba, 0xfb, 0xd0, 0xe1, 0xae, 0x44, 0x58, 0x49, 0x4c, 0x80, 0x05, 0x00,
+  0x00, 0x60, 0x00, 0x01, 0x00, 0x60, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49,
+  0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x68, 0x05, 0x00,
+  0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x57, 0x01, 0x00,
+  0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00,
+  0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32,
+  0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b,
+  0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32,
+  0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14,
+  0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e,
+  0x90, 0x11, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5,
+  0x8a, 0x04, 0x21, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x06, 0x00, 0x00,
+  0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8,
+  0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x01, 0x00, 0x00,
+  0x00, 0x49, 0x18, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60,
+  0x42, 0x20, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x0f, 0x00, 0x00,
+  0x00, 0x32, 0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4,
+  0x84, 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88,
+  0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x30, 0x23, 0x00, 0x25, 0x00, 0x8a,
+  0x39, 0x02, 0x30, 0x98, 0x23, 0x40, 0x8a, 0x31, 0x33, 0x43, 0x43, 0x35,
+  0x03, 0x50, 0x0c, 0x98, 0x19, 0x3a, 0xc2, 0x81, 0x80, 0x1c, 0x18, 0x00,
+  0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87,
+  0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0,
+  0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x05, 0x10,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10,
+  0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x02,
+  0x01, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c,
+  0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x9a, 0x12, 0x18, 0x01,
+  0x28, 0x86, 0x32, 0x28, 0x0f, 0xa2, 0x52, 0x28, 0x81, 0x11, 0x80, 0x92,
+  0x28, 0x82, 0x32, 0x28, 0x04, 0xda, 0xb1, 0x86, 0x00, 0x99, 0x03, 0x00,
+  0x00, 0x79, 0x18, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c,
+  0x90, 0x46, 0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03,
+  0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, 0xb9, 0x01,
+  0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a,
+  0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b,
+  0xd9, 0x10, 0x04, 0x13, 0x84, 0x61, 0x98, 0x20, 0x0c, 0xc4, 0x06, 0x61,
+  0x20, 0x26, 0x08, 0x43, 0xb1, 0x41, 0x18, 0x0c, 0x0a, 0x76, 0x73, 0x1b,
+  0x06, 0xc4, 0x20, 0x26, 0x08, 0xcb, 0xb3, 0x21, 0x50, 0x26, 0x08, 0x02,
+  0x40, 0xc7, 0xa8, 0x8e, 0x8d, 0x6d, 0x6e, 0x4c, 0xae, 0xac, 0xcc, 0xcd,
+  0xaa, 0x4c, 0x8e, 0x8e, 0xcb, 0x94, 0xd5, 0x97, 0x55, 0x99, 0x1c, 0x5d,
+  0x19, 0x5e, 0x12, 0xd1, 0x04, 0x81, 0x40, 0x26, 0x08, 0x44, 0xb2, 0x21,
+  0x20, 0x26, 0x08, 0x84, 0x32, 0x41, 0x18, 0x8c, 0x0d, 0xc2, 0x34, 0x6c,
+  0x58, 0x08, 0xe7, 0x81, 0x22, 0x69, 0x80, 0x08, 0x89, 0xda, 0x10, 0x54,
+  0x44, 0xa8, 0x8a, 0xb0, 0x86, 0x9e, 0x9e, 0xa4, 0x88, 0x26, 0x08, 0xc4,
+  0x32, 0x41, 0x20, 0x98, 0x0d, 0xc2, 0x34, 0x6d, 0x58, 0x88, 0x0b, 0x93,
+  0xa2, 0x6c, 0xc8, 0x08, 0x49, 0xe3, 0x32, 0x65, 0xf5, 0x05, 0xf5, 0x36,
+  0x97, 0x46, 0x97, 0xf6, 0xe6, 0x36, 0x41, 0x20, 0x9a, 0x09, 0x02, 0xe1,
+  0x4c, 0x10, 0x86, 0x63, 0x83, 0x30, 0x7d, 0x1b, 0x96, 0x81, 0xc3, 0xba,
+  0xc8, 0x1b, 0xbc, 0x41, 0x02, 0x83, 0x0d, 0xc2, 0x16, 0x06, 0x1b, 0x06,
+  0x4b, 0x0c, 0x80, 0x0d, 0x05, 0xd3, 0x8c, 0x01, 0x00, 0x54, 0x61, 0x63,
+  0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3, 0x9b, 0x12, 0x04, 0x55,
+  0xc8, 0xf0, 0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2, 0xde, 0xdc, 0xa6, 0x04,
+  0x44, 0x13, 0x32, 0x3c, 0x17, 0xbb, 0x30, 0x36, 0xbb, 0x32, 0xb9, 0x29,
+  0x81, 0x51, 0x87, 0x0c, 0xcf, 0x65, 0x0e, 0x2d, 0x8c, 0xac, 0x4c, 0xae,
+  0xe9, 0x8d, 0xac, 0x8c, 0x6d, 0x4a, 0x80, 0xd4, 0x21, 0xc3, 0x73, 0xb1,
+  0x4b, 0x2b, 0xbb, 0x4b, 0x22, 0x9b, 0xa2, 0x0b, 0xa3, 0x2b, 0x9b, 0x12,
+  0x28, 0x75, 0xc8, 0xf0, 0x5c, 0xca, 0xdc, 0xe8, 0xe4, 0xf2, 0xa0, 0xde,
+  0xd2, 0xdc, 0xe8, 0xe6, 0xa6, 0x04, 0x63, 0x00, 0x00, 0x79, 0x18, 0x00,
+  0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c,
+  0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80,
+  0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed,
+  0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d,
+  0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83,
+  0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78,
+  0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70,
+  0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc,
+  0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3,
+  0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c,
+  0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83,
+  0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03,
+  0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68,
+  0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60,
+  0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80,
+  0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98,
+  0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec,
+  0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d,
+  0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43,
+  0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03,
+  0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03,
+  0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28,
+  0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4,
+  0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1,
+  0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00,
+  0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0xe0, 0x7c, 0xd4, 0xb2, 0x48, 0x42,
+  0x44, 0x10, 0xcd, 0x4b, 0x44, 0x93, 0x05, 0x4c, 0xc3, 0xe5, 0x3b, 0x8f,
+  0xbf, 0x38, 0xc0, 0x20, 0x36, 0x0f, 0x35, 0xf9, 0xc8, 0x6d, 0x9b, 0x40,
+  0x35, 0x5c, 0xbe, 0xf3, 0xf8, 0xd2, 0xe4, 0x44, 0x04, 0x4a, 0x4d, 0x0f,
+  0x35, 0xf9, 0xc5, 0x6d, 0x03, 0x61, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00,
+  0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x34, 0xa5, 0x50, 0x04, 0x85, 0x30, 0x03, 0x40, 0x37, 0x02, 0x30,
+  0x46, 0x00, 0x82, 0x20, 0x08, 0x82, 0xc1, 0x18, 0x01, 0x08, 0x82, 0x20,
+  0xfe, 0x8d, 0x11, 0x80, 0x20, 0x08, 0xe2, 0xbf, 0x00, 0x23, 0x06, 0x09,
+  0x00, 0x82, 0x60, 0x50, 0x5c, 0x06, 0x45, 0x39, 0x45, 0x05, 0xd6, 0x55,
+  0x90, 0xe8, 0x05, 0x57, 0x45, 0x2c, 0x7a, 0xc1, 0xd5, 0x88, 0x41, 0x02,
+  0x80, 0x20, 0x18, 0x20, 0x9c, 0xa3, 0x69, 0x94, 0x32, 0x62, 0x90, 0x00,
+  0x20, 0x08, 0x06, 0x08, 0xe7, 0x68, 0x5a, 0xa5, 0x8c, 0x18, 0x24, 0x00,
+  0x08, 0x82, 0x01, 0xc2, 0x39, 0x9b, 0x46, 0x29, 0x23, 0x06, 0x09, 0x00,
+  0x82, 0x60, 0x80, 0x70, 0xce, 0xa6, 0x55, 0xca, 0x88, 0x41, 0x02, 0x80,
+  0x20, 0x18, 0x20, 0x9c, 0xb3, 0x69, 0x92, 0x32, 0x62, 0x90, 0x00, 0x20,
+  0x08, 0x06, 0x08, 0xe7, 0x6c, 0x5a, 0xa4, 0x8c, 0x18, 0x24, 0x00, 0x08,
+  0x82, 0x01, 0xc2, 0x39, 0x9a, 0x46, 0x0d, 0x23, 0x06, 0x09, 0x00, 0x82,
+  0x60, 0x80, 0x70, 0x8e, 0xa6, 0x55, 0x81, 0x0d, 0x89, 0x7c, 0x4c, 0x50,
+  0xe4, 0x63, 0x42, 0x02, 0x1f, 0x5b, 0x84, 0xf8, 0x8c, 0x18, 0x24, 0x00,
+  0x08, 0x82, 0x01, 0x02, 0x06, 0xd2, 0xe7, 0x61, 0xc2, 0x88, 0x41, 0x02,
+  0x80, 0x20, 0x18, 0x20, 0x60, 0x20, 0x7d, 0x5e, 0x16, 0x8c, 0x18, 0x24,
+  0x00, 0x08, 0x82, 0x01, 0x02, 0x06, 0xd2, 0xe7, 0x59, 0xce, 0x88, 0x41,
+  0x02, 0x80, 0x20, 0x18, 0x20, 0x60, 0x20, 0x7d, 0x5e, 0xc5, 0x20, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00
+};
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xy          0     NONE   float   xy  
+; SV_Position              0   xyzw        1      POS   float       
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_Target                0   xyzw        0   TARGET   float   xyzw
+;
+; shader hash: 964a7513a7ff5558ed84391b53971f63
+;
+; Pipeline Runtime Information: 
+;
+; Pixel Shader
+; DepthOutput=0
+; SampleFrequency=0
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; SV_Position              0          noperspective       
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_Target                0                              
+;
+; Buffer Definitions:
+;
+; cbuffer SourceRegionBuffer
+; {
+;
+;   struct SourceRegionBuffer
+;   {
+;
+;       float2 UVLeftTop;                             ; Offset:    0
+;       float2 UVDimensions;                          ; Offset:    8
+;       uint MipLevel;                                ; Offset:   16
+;       float LayerOrDepth;                           ; Offset:   20
+;   
+;   } SourceRegionBuffer;                             ; Offset:    0 Size:    24
+;
+; }
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; SourceRegionBuffer                cbuffer      NA          NA     CB0     cb0,space3     1
+; SourceSampler                     sampler      NA          NA      S0      s0,space2     1
+; SourceTexture2D                   texture     f32          2d      T0      t0,space2     1
+;
+;
+; ViewId state:
+;
+; Number of inputs: 8, outputs: 4
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 0, 1 }
+;   output 1 depends on inputs: { 0, 1 }
+;   output 2 depends on inputs: { 0, 1 }
+;   output 3 depends on inputs: { 0, 1 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+%dx.types.Handle = type { i8* }
+%dx.types.CBufRet.f32 = type { float, float, float, float }
+%dx.types.CBufRet.i32 = type { i32, i32, i32, i32 }
+%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
+%"class.Texture2D<vector<float, 4> >" = type { <4 x float>, %"class.Texture2D<vector<float, 4> >::mips_type" }
+%"class.Texture2D<vector<float, 4> >::mips_type" = type { i32 }
+%SourceRegionBuffer = type { <2 x float>, <2 x float>, i32, float }
+%struct.SamplerState = type { i32 }
+
+define void @BlitFrom2D() {
+  %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %6 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 0)  ; CBufferLoadLegacy(handle,regIndex)
+  %7 = extractvalue %dx.types.CBufRet.f32 %6, 0
+  %8 = extractvalue %dx.types.CBufRet.f32 %6, 1
+  %9 = extractvalue %dx.types.CBufRet.f32 %6, 2
+  %10 = extractvalue %dx.types.CBufRet.f32 %6, 3
+  %11 = fmul fast float %9, %4
+  %12 = fmul fast float %10, %5
+  %13 = fadd fast float %11, %7
+  %14 = fadd fast float %12, %8
+  %15 = call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %3, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %16 = extractvalue %dx.types.CBufRet.i32 %15, 0
+  %17 = uitofp i32 %16 to float
+  %18 = call %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32 62, %dx.types.Handle %1, %dx.types.Handle %2, float %13, float %14, float undef, float undef, i32 0, i32 0, i32 undef, float %17)  ; SampleLevel(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,LOD)
+  %19 = extractvalue %dx.types.ResRet.f32 %18, 0
+  %20 = extractvalue %dx.types.ResRet.f32 %18, 1
+  %21 = extractvalue %dx.types.ResRet.f32 %18, 2
+  %22 = extractvalue %dx.types.ResRet.f32 %18, 3
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %19)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %20)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %21)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %22)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+; Function Attrs: nounwind readonly
+declare %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.resources = !{!4}
+!dx.viewIdState = !{!12}
+!dx.entryPoints = !{!13}
+
+!0 = !{!"clang version 3.7 (tags/RELEASE_370/final)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 6}
+!3 = !{!"ps", i32 6, i32 0}
+!4 = !{!5, null, !8, !10}
+!5 = !{!6}
+!6 = !{i32 0, %"class.Texture2D<vector<float, 4> >"* undef, !"", i32 2, i32 0, i32 1, i32 2, i32 0, !7}
+!7 = !{i32 0, i32 9}
+!8 = !{!9}
+!9 = !{i32 0, %SourceRegionBuffer* undef, !"", i32 3, i32 0, i32 1, i32 24, null}
+!10 = !{!11}
+!11 = !{i32 0, %struct.SamplerState* undef, !"", i32 2, i32 0, i32 1, i32 0, null}
+!12 = !{[10 x i32] [i32 8, i32 4, i32 15, i32 15, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0]}
+!13 = !{void ()* @BlitFrom2D, !"BlitFrom2D", !14, !4, null}
+!14 = !{!15, !20, null}
+!15 = !{!16, !19}
+!16 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !17, i8 2, i32 1, i8 2, i32 0, i8 0, !18}
+!17 = !{i32 0}
+!18 = !{i32 3, i32 3}
+!19 = !{i32 1, !"SV_Position", i8 9, i8 3, !17, i8 4, i32 1, i8 4, i32 1, i8 0, null}
+!20 = !{!21}
+!21 = !{i32 0, !"SV_Target", i8 9, i8 16, !17, i8 0, i32 1, i8 4, i32 0, i8 0, !22}
+!22 = !{i32 3, i32 15}
+
+#endif
+
+const unsigned char g_BlitFrom2D[] = {
+  0x44, 0x58, 0x42, 0x43, 0x88, 0xd8, 0x55, 0x7c, 0x96, 0x93, 0xc1, 0x86,
+  0xcd, 0x75, 0xbd, 0x9a, 0xec, 0x55, 0x00, 0x0b, 0x01, 0x00, 0x00, 0x00,
+  0x97, 0x11, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00,
+  0xe3, 0x01, 0x00, 0x00, 0xc7, 0x09, 0x00, 0x00, 0xe3, 0x09, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x5d, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5f,
+  0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x4f, 0x53, 0x47,
+  0x31, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f,
+  0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x50, 0x53, 0x56, 0x30, 0xf0,
+  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18,
+  0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43,
+  0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x44, 0x03, 0x03,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x44, 0x10, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xdc, 0x07, 0x00, 0x00, 0x60,
+  0x00, 0x00, 0x00, 0xf7, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00,
+  0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc4, 0x07, 0x00, 0x00, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xee, 0x01, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43,
+  0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11,
+  0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04,
+  0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b,
+  0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84,
+  0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04,
+  0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8c, 0x8c, 0x0b,
+  0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40, 0x09, 0x00, 0x0a, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x40, 0x10, 0x44,
+  0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, 0x20, 0xe4, 0xa6, 0xe1,
+  0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, 0x95, 0x98, 0xfc, 0xe2,
+  0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, 0xcf, 0x70, 0xf9, 0x13,
+  0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, 0x28, 0x58, 0x0a, 0xa3,
+  0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, 0x40, 0xcd, 0x51, 0xc3,
+  0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, 0xc5, 0x4a, 0x4c, 0x3e,
+  0x72, 0xdb, 0x88, 0x20, 0x08, 0x82, 0x28, 0xc4, 0x43, 0x30, 0x04, 0x41,
+  0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, 0x15, 0x2b,
+  0x31, 0xf9, 0xc5, 0x6d, 0x23, 0x62, 0x18, 0x86, 0xa1, 0x10, 0x12, 0xc1,
+  0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, 0x82, 0x20, 0x2a, 0xb2,
+  0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0xa6, 0x36, 0x18, 0x07, 0x76, 0x08,
+  0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, 0xc0, 0x07, 0x7a, 0xa8,
+  0x07, 0x79, 0x28, 0x07, 0x39, 0x20, 0x05, 0x3e, 0xb0, 0x87, 0x72, 0x18,
+  0x07, 0x7a, 0x78, 0x07, 0x79, 0xe0, 0x03, 0x73, 0x60, 0x87, 0x77, 0x08,
+  0x07, 0x7a, 0x60, 0x03, 0x30, 0xa0, 0x03, 0x3f, 0x00, 0x03, 0x3f, 0xd0,
+  0x03, 0x3d, 0x68, 0x87, 0x74, 0x80, 0x87, 0x79, 0xf8, 0x05, 0x7a, 0xc8,
+  0x07, 0x78, 0x28, 0x07, 0x14, 0x10, 0x33, 0x89, 0xc1, 0x38, 0xb0, 0x43,
+  0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, 0x94, 0x03, 0x3e, 0xd0, 0x43,
+  0x3d, 0xc8, 0x43, 0x39, 0xc8, 0x01, 0x29, 0xf0, 0x81, 0x3d, 0x94, 0xc3,
+  0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43,
+  0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x01,
+  0x12, 0x32, 0x8d, 0xb6, 0x61, 0x04, 0x61, 0x38, 0x89, 0x75, 0xa8, 0x48,
+  0x20, 0x56, 0xc2, 0x40, 0x9c, 0x66, 0xa3, 0x8a, 0x82, 0x88, 0x10, 0xd1,
+  0x75, 0xc4, 0x40, 0xde, 0x4d, 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xb3, 0x00,
+  0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, 0x80, 0x20, 0x30, 0x15,
+  0x08, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36,
+  0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e,
+  0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06,
+  0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c,
+  0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+  0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x14, 0x00, 0x00, 0x00, 0x32,
+  0x1e, 0x98, 0x18, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6,
+  0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x24, 0xca,
+  0xa0, 0x60, 0xca, 0xa1, 0x20, 0x0a, 0xa4, 0x14, 0x0a, 0xa5, 0x3c, 0xca,
+  0xa6, 0x10, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, 0x28, 0x83, 0x42, 0x28,
+  0x10, 0xaa, 0x6a, 0x80, 0xb8, 0x19, 0x00, 0xf2, 0x66, 0x00, 0xe8, 0x9b,
+  0x01, 0xa0, 0x70, 0x06, 0x80, 0xc4, 0xb1, 0x14, 0x84, 0x78, 0x1e, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0xae,
+  0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x35,
+  0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b,
+  0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b,
+  0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79,
+  0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xe2,
+  0x98, 0x20, 0x10, 0xc8, 0x06, 0x61, 0x20, 0x36, 0x08, 0x04, 0x41, 0x01,
+  0x6e, 0x6e, 0x82, 0x40, 0x24, 0x1b, 0x86, 0x03, 0x21, 0x26, 0x08, 0x5c,
+  0xc7, 0x67, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x8c, 0xaa, 0x0c, 0x8f, 0xae,
+  0x4e, 0xae, 0x4c, 0x86, 0x68, 0x82, 0x40, 0x28, 0x13, 0x04, 0x62, 0xd9,
+  0x20, 0x10, 0xcd, 0x86, 0x84, 0x50, 0x16, 0x86, 0x18, 0x18, 0xc2, 0xd9,
+  0x10, 0x3c, 0x13, 0x84, 0xef, 0xa3, 0x34, 0xf5, 0x56, 0x27, 0x37, 0x56,
+  0x26, 0x55, 0x76, 0x96, 0xf6, 0xe6, 0x26, 0x54, 0x67, 0x66, 0x56, 0x26,
+  0x37, 0x41, 0x20, 0x98, 0x09, 0x02, 0xd1, 0x6c, 0x40, 0x88, 0x48, 0x9a,
+  0x88, 0x81, 0x02, 0x36, 0x04, 0xd5, 0x04, 0x21, 0x0c, 0xc0, 0x80, 0xcd,
+  0xd4, 0x5b, 0x9d, 0xdc, 0x58, 0xd9, 0x54, 0x58, 0x1b, 0x1c, 0x5b, 0x99,
+  0xdc, 0x06, 0x84, 0xb8, 0x30, 0x86, 0x18, 0x08, 0x60, 0x43, 0x90, 0x6d,
+  0x20, 0x20, 0xc0, 0xd2, 0x26, 0x08, 0x9e, 0xc7, 0xa4, 0xca, 0x8a, 0xa9,
+  0xcc, 0x8c, 0x8e, 0xea, 0x0d, 0x6e, 0x82, 0x40, 0x38, 0x13, 0x84, 0x8a,
+  0xdb, 0x80, 0x20, 0xdd, 0x44, 0x78, 0x4d, 0xf3, 0x91, 0xa9, 0xb2, 0x22,
+  0x4a, 0x6b, 0x2b, 0x73, 0x9b, 0x4b, 0x7b, 0x73, 0x9b, 0x9b, 0x20, 0x10,
+  0xcf, 0x06, 0x04, 0x09, 0x83, 0x49, 0x0c, 0xbc, 0xa6, 0xf9, 0x88, 0x34,
+  0xa5, 0xc1, 0x31, 0x95, 0xd9, 0x95, 0xb1, 0x4d, 0x10, 0x08, 0x68, 0x82,
+  0x40, 0x44, 0x1b, 0x10, 0x84, 0x0c, 0xa6, 0x32, 0xf0, 0xcc, 0xa0, 0xf9,
+  0xc8, 0x30, 0x85, 0xe5, 0x95, 0xc9, 0x3d, 0xc9, 0x11, 0x95, 0xc1, 0xd1,
+  0xa1, 0x4d, 0x10, 0x08, 0x69, 0x83, 0x81, 0xa0, 0xc1, 0x94, 0x06, 0x5e,
+  0xb3, 0xa1, 0xa0, 0xc0, 0x60, 0x0c, 0xce, 0x40, 0x0d, 0x36, 0x0c, 0x04,
+  0xb7, 0x06, 0x13, 0x04, 0x01, 0xd8, 0x00, 0x6c, 0x18, 0x08, 0x37, 0x70,
+  0x83, 0x0d, 0xc1, 0x1b, 0x6c, 0x18, 0x86, 0x36, 0x80, 0x83, 0x09, 0x82,
+  0x18, 0x84, 0xc1, 0x86, 0x40, 0x0e, 0xa8, 0x08, 0xb1, 0xa5, 0xd1, 0x19,
+  0xc9, 0xbd, 0xb5, 0xc9, 0x10, 0x11, 0xa1, 0x2a, 0xc2, 0x1a, 0x7a, 0x7a,
+  0x92, 0x22, 0x9a, 0x20, 0x14, 0xd6, 0x04, 0xa1, 0xb8, 0x36, 0x04, 0xc4,
+  0x04, 0xa1, 0xc0, 0x36, 0x08, 0xd3, 0xb4, 0x61, 0x21, 0xea, 0xc0, 0x0e,
+  0xee, 0x00, 0x0f, 0xf2, 0x60, 0xc8, 0x03, 0xe2, 0x0e, 0xf4, 0x80, 0xcb,
+  0x94, 0xd5, 0x17, 0xd4, 0xdb, 0x5c, 0x1a, 0x5d, 0xda, 0x9b, 0xdb, 0x04,
+  0xa1, 0xc8, 0x26, 0x08, 0x85, 0xb6, 0x61, 0x19, 0xf8, 0xc0, 0x0e, 0xfa,
+  0x00, 0x0f, 0xfc, 0x60, 0xf0, 0x83, 0xe1, 0x0e, 0x80, 0x0d, 0xc2, 0x1e,
+  0xfc, 0x01, 0x93, 0x29, 0xab, 0x2f, 0xaa, 0x30, 0xb9, 0xb3, 0x32, 0xba,
+  0x09, 0x42, 0xb1, 0x4d, 0x10, 0x88, 0x69, 0x83, 0x30, 0x8d, 0xc2, 0x86,
+  0x85, 0x08, 0x05, 0x3b, 0x10, 0x05, 0x3c, 0xb8, 0x83, 0xc1, 0x0f, 0x88,
+  0x3b, 0x20, 0x85, 0x0d, 0x41, 0x29, 0x6c, 0x18, 0x40, 0xc1, 0x14, 0x80,
+  0x0d, 0x45, 0x1b, 0xd0, 0xc1, 0x29, 0x6c, 0x00, 0x0d, 0x33, 0xb6, 0xb7,
+  0x30, 0xba, 0x39, 0x16, 0x69, 0x6e, 0x73, 0x74, 0x73, 0x13, 0x04, 0x82,
+  0xa2, 0x31, 0x97, 0x76, 0xf6, 0xc5, 0x46, 0x46, 0x63, 0x2e, 0xed, 0xec,
+  0x6b, 0x8e, 0x6e, 0x82, 0x40, 0x54, 0x44, 0xe8, 0xca, 0xf0, 0xbe, 0xdc,
+  0xde, 0xe4, 0xda, 0x36, 0x28, 0xa9, 0x60, 0x06, 0xaa, 0xb0, 0x0a, 0xac,
+  0xc0, 0xb4, 0x82, 0x2b, 0xbc, 0xc2, 0x50, 0x85, 0x8d, 0xcd, 0xae, 0xcd,
+  0x25, 0x8d, 0xac, 0xcc, 0x8d, 0x6e, 0x4a, 0x10, 0x54, 0x21, 0xc3, 0x73,
+  0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x9b, 0x12, 0x10, 0x4d, 0xc8,
+  0xf0, 0x5c, 0xec, 0xc2, 0xd8, 0xec, 0xca, 0xe4, 0xa6, 0x04, 0x45, 0x1d,
+  0x32, 0x3c, 0x97, 0x39, 0xb4, 0x30, 0xb2, 0x32, 0xb9, 0xa6, 0x37, 0xb2,
+  0x32, 0xb6, 0x29, 0x01, 0x52, 0x86, 0x0c, 0xcf, 0x45, 0xae, 0x6c, 0xee,
+  0xad, 0x4e, 0x6e, 0xac, 0x6c, 0x6e, 0x4a, 0xa0, 0x55, 0x22, 0xc3, 0x73,
+  0xa1, 0xcb, 0x83, 0x2b, 0x0b, 0x72, 0x73, 0x7b, 0xa3, 0x0b, 0xa3, 0x4b,
+  0x7b, 0x73, 0x9b, 0x9b, 0x22, 0xac, 0x01, 0x1c, 0xd4, 0x21, 0xc3, 0x73,
+  0xb1, 0x4b, 0x2b, 0xbb, 0x4b, 0x22, 0x9b, 0xa2, 0x0b, 0xa3, 0x2b, 0x9b,
+  0x12, 0xc8, 0x41, 0x1d, 0x32, 0x3c, 0x97, 0x32, 0x37, 0x3a, 0xb9, 0x3c,
+  0xa8, 0xb7, 0x34, 0x37, 0xba, 0xb9, 0x29, 0xc1, 0x29, 0x74, 0x21, 0xc3,
+  0x73, 0x19, 0x7b, 0xab, 0x73, 0xa3, 0x2b, 0x93, 0x9b, 0x9b, 0x12, 0xbc,
+  0x02, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33,
+  0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98,
+  0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33,
+  0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05,
+  0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43,
+  0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08,
+  0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78,
+  0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1,
+  0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33,
+  0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e,
+  0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03,
+  0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60,
+  0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80,
+  0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8,
+  0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18,
+  0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee,
+  0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c,
+  0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43,
+  0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3,
+  0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83,
+  0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21,
+  0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1,
+  0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6,
+  0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4,
+  0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x06,
+  0xa0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0xd8, 0x9d, 0x15, 0x6c, 0xc3,
+  0xe5, 0x3b, 0x8f, 0x2f, 0x04, 0x54, 0x51, 0x10, 0x51, 0xe9, 0x00, 0x43,
+  0x49, 0x18, 0x80, 0x80, 0xf9, 0xc5, 0x6d, 0x1b, 0xc1, 0x36, 0x5c, 0xbe,
+  0xf3, 0xf8, 0x42, 0x40, 0x15, 0x05, 0x11, 0x95, 0x0e, 0x30, 0x94, 0x84,
+  0x01, 0x08, 0x98, 0x8f, 0xdc, 0xb6, 0x19, 0x48, 0xc3, 0xe5, 0x3b, 0x8f,
+  0x2f, 0x44, 0x04, 0x30, 0x11, 0x21, 0xd0, 0x0c, 0x0b, 0x61, 0x01, 0xd3,
+  0x70, 0xf9, 0xce, 0xe3, 0x2f, 0x0e, 0x30, 0x88, 0xcd, 0x43, 0x4d, 0x7e,
+  0x71, 0xdb, 0x36, 0x50, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x04, 0x30, 0xcf,
+  0x42, 0x94, 0x44, 0x45, 0x2c, 0x7e, 0x71, 0xdb, 0x26, 0x50, 0x0d, 0x97,
+  0xef, 0x3c, 0xbe, 0x34, 0x39, 0x11, 0x81, 0x52, 0xd3, 0x43, 0x4d, 0x7e,
+  0x71, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x4a, 0x75, 0x13, 0xa7,
+  0xff, 0x55, 0x58, 0xed, 0x84, 0x39, 0x1b, 0x53, 0x97, 0x1f, 0x63, 0x44,
+  0x58, 0x49, 0x4c, 0xac, 0x07, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xeb,
+  0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x94, 0x07, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21,
+  0x0c, 0x00, 0x00, 0xe2, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41,
+  0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25,
+  0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x18, 0x45, 0x02, 0x42,
+  0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a,
+  0x32, 0x62, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00,
+  0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x23, 0xc4, 0x50, 0x41,
+  0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x31, 0x46, 0x06, 0x51,
+  0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff,
+  0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff,
+  0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+  0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13,
+  0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89,
+  0x20, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x32, 0x22, 0x88, 0x09, 0x20,
+  0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04, 0x13, 0x23, 0xe3, 0x84,
+  0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8c, 0x8c, 0x0b, 0x84, 0xc4, 0x4c, 0x10,
+  0x8c, 0xc1, 0x08, 0x40, 0x09, 0x00, 0x0a, 0x66, 0x00, 0xe6, 0x08, 0xc0,
+  0x60, 0x8e, 0x00, 0x29, 0xc6, 0x40, 0x10, 0x44, 0x41, 0x90, 0x51, 0x0c,
+  0x80, 0x20, 0x88, 0x62, 0x20, 0xe4, 0xa6, 0xe1, 0xf2, 0x27, 0xec, 0x21,
+  0x24, 0x7f, 0x25, 0xa4, 0x95, 0x98, 0xfc, 0xe2, 0xb6, 0x51, 0x31, 0x0c,
+  0xc3, 0x40, 0x50, 0x71, 0xcf, 0x70, 0xf9, 0x13, 0xf6, 0x10, 0x92, 0x1f,
+  0x02, 0xcd, 0xb0, 0x10, 0x28, 0x58, 0x0a, 0xa3, 0x10, 0x0c, 0x33, 0x0c,
+  0xc3, 0x40, 0x10, 0xc4, 0x40, 0xcd, 0x51, 0xc3, 0xe5, 0x4f, 0xd8, 0x43,
+  0x48, 0x3e, 0xb7, 0x51, 0xc5, 0x4a, 0x4c, 0x3e, 0x72, 0xdb, 0x88, 0x20,
+  0x08, 0x82, 0x28, 0xc4, 0x43, 0x30, 0x04, 0x41, 0x47, 0x0d, 0x97, 0x3f,
+  0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, 0x15, 0x2b, 0x31, 0xf9, 0xc5, 0x6d,
+  0x23, 0x62, 0x18, 0x86, 0xa1, 0x10, 0x12, 0xc1, 0x10, 0x34, 0xcd, 0x11,
+  0x04, 0xc5, 0x60, 0x88, 0x82, 0x20, 0x2a, 0xb2, 0x06, 0x02, 0x86, 0x11,
+  0x88, 0x61, 0xa6, 0x36, 0x18, 0x07, 0x76, 0x08, 0x87, 0x79, 0x98, 0x07,
+  0x37, 0xa0, 0x85, 0x72, 0xc0, 0x07, 0x7a, 0xa8, 0x07, 0x79, 0x28, 0x07,
+  0x39, 0x20, 0x05, 0x3e, 0xb0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07,
+  0x79, 0xe0, 0x03, 0x73, 0x60, 0x87, 0x77, 0x08, 0x07, 0x7a, 0x60, 0x03,
+  0x30, 0xa0, 0x03, 0x3f, 0x00, 0x03, 0x3f, 0xd0, 0x03, 0x3d, 0x68, 0x87,
+  0x74, 0x80, 0x87, 0x79, 0xf8, 0x05, 0x7a, 0xc8, 0x07, 0x78, 0x28, 0x07,
+  0x14, 0x10, 0x33, 0x89, 0xc1, 0x38, 0xb0, 0x43, 0x38, 0xcc, 0xc3, 0x3c,
+  0xb8, 0x01, 0x2d, 0x94, 0x03, 0x3e, 0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39,
+  0xc8, 0x01, 0x29, 0xf0, 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b,
+  0xc8, 0x03, 0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b,
+  0x80, 0x01, 0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x01, 0x12, 0x32, 0x8d, 0xb6,
+  0x61, 0x04, 0x61, 0x38, 0x89, 0x75, 0xa8, 0x48, 0x20, 0x56, 0xc2, 0x40,
+  0x9c, 0x66, 0xa3, 0x8a, 0x82, 0x88, 0x10, 0xd1, 0x75, 0xc4, 0x40, 0xde,
+  0x4d, 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4,
+  0x4e, 0xc0, 0x44, 0xa0, 0x80, 0x20, 0x30, 0x15, 0x08, 0x00, 0x00, 0x13,
+  0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68,
+  0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a,
+  0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71,
+  0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d,
+  0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40,
+  0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81,
+  0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8,
+  0x33, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x90, 0xc7, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x2c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19,
+  0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a,
+  0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x24, 0xca, 0xa0, 0x60, 0xca, 0x83,
+  0x8a, 0x92, 0x18, 0x01, 0x28, 0x82, 0x32, 0x28, 0x84, 0x02, 0x21, 0x6e,
+  0x06, 0x80, 0xbe, 0x19, 0x00, 0x0a, 0x67, 0x00, 0x48, 0x1c, 0x4b, 0x41,
+  0x88, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79,
+  0x18, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46,
+  0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b,
+  0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1,
+  0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa,
+  0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10,
+  0x04, 0x13, 0x04, 0xe2, 0x98, 0x20, 0x10, 0xc8, 0x06, 0x61, 0x20, 0x26,
+  0x08, 0x44, 0xb2, 0x41, 0x18, 0x0c, 0x0a, 0x70, 0x73, 0x1b, 0x06, 0xc4,
+  0x20, 0x26, 0x08, 0x5c, 0x45, 0x60, 0x82, 0x40, 0x28, 0x13, 0x04, 0x62,
+  0xd9, 0x20, 0x10, 0xcd, 0x86, 0x84, 0x50, 0x16, 0x86, 0x18, 0x18, 0xc2,
+  0xd9, 0x10, 0x3c, 0x13, 0x84, 0xcf, 0x9a, 0x20, 0x10, 0xcc, 0x04, 0x81,
+  0x68, 0x36, 0x20, 0x44, 0xb4, 0x48, 0xc4, 0x30, 0x01, 0x1b, 0x02, 0x6a,
+  0x82, 0x10, 0x06, 0xd7, 0x06, 0x84, 0xb0, 0x16, 0x86, 0x18, 0x08, 0x60,
+  0x43, 0x70, 0x6d, 0x20, 0x20, 0xa0, 0xc2, 0x26, 0x08, 0x62, 0x80, 0x6d,
+  0x08, 0xb4, 0x09, 0x82, 0x00, 0x50, 0x11, 0x62, 0x4b, 0xa3, 0x33, 0x92,
+  0x7b, 0x6b, 0x93, 0x21, 0x22, 0x42, 0x55, 0x84, 0x35, 0xf4, 0xf4, 0x24,
+  0x45, 0x34, 0x41, 0x28, 0x9e, 0x09, 0x42, 0x01, 0x6d, 0x08, 0x88, 0x09,
+  0x42, 0x11, 0x6d, 0x10, 0x24, 0x69, 0xc3, 0x42, 0x78, 0x1f, 0x18, 0x84,
+  0x81, 0x18, 0x0c, 0x62, 0x40, 0x80, 0xc1, 0x18, 0x70, 0x99, 0xb2, 0xfa,
+  0x82, 0x7a, 0x9b, 0x4b, 0xa3, 0x4b, 0x7b, 0x73, 0x9b, 0x20, 0x14, 0xd2,
+  0x04, 0xa1, 0x98, 0x36, 0x2c, 0x43, 0x19, 0x7c, 0x66, 0x10, 0x06, 0x67,
+  0x30, 0x9c, 0xc1, 0x00, 0x06, 0xc0, 0x06, 0x81, 0x0c, 0xd0, 0x80, 0xc9,
+  0x94, 0xd5, 0x17, 0x55, 0x98, 0xdc, 0x59, 0x19, 0xdd, 0x04, 0xa1, 0xa0,
+  0x26, 0x08, 0x84, 0xb3, 0x41, 0x90, 0xd8, 0x60, 0xc3, 0x42, 0xa8, 0xc1,
+  0xb7, 0x06, 0x61, 0x00, 0x06, 0xc3, 0x19, 0x10, 0x60, 0xd0, 0x06, 0x1b,
+  0x02, 0x37, 0xd8, 0x30, 0xa4, 0xc1, 0x1b, 0x00, 0x1b, 0x0a, 0xae, 0x83,
+  0x83, 0x0c, 0xa8, 0xc2, 0xc6, 0x66, 0xd7, 0xe6, 0x92, 0x46, 0x56, 0xe6,
+  0x46, 0x37, 0x25, 0x08, 0xaa, 0x90, 0xe1, 0xb9, 0xd8, 0x95, 0xc9, 0xcd,
+  0xa5, 0xbd, 0xb9, 0x4d, 0x09, 0x88, 0x26, 0x64, 0x78, 0x2e, 0x76, 0x61,
+  0x6c, 0x76, 0x65, 0x72, 0x53, 0x02, 0xa3, 0x0e, 0x19, 0x9e, 0xcb, 0x1c,
+  0x5a, 0x18, 0x59, 0x99, 0x5c, 0xd3, 0x1b, 0x59, 0x19, 0xdb, 0x94, 0x00,
+  0x29, 0x43, 0x86, 0xe7, 0x22, 0x57, 0x36, 0xf7, 0x56, 0x27, 0x37, 0x56,
+  0x36, 0x37, 0x25, 0xc0, 0xea, 0x90, 0xe1, 0xb9, 0xd8, 0xa5, 0x95, 0xdd,
+  0x25, 0x91, 0x4d, 0xd1, 0x85, 0xd1, 0x95, 0x4d, 0x09, 0xb4, 0x3a, 0x64,
+  0x78, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74,
+  0x73, 0x53, 0x02, 0x38, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76,
+  0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e,
+  0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f,
+  0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x1f,
+  0x00, 0x00, 0x00, 0x06, 0xa0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0xd8,
+  0x9d, 0x15, 0x6c, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x04, 0x54, 0x51, 0x10,
+  0x51, 0xe9, 0x00, 0x43, 0x49, 0x18, 0x80, 0x80, 0xf9, 0xc5, 0x6d, 0x1b,
+  0xc1, 0x36, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x40, 0x15, 0x05, 0x11, 0x95,
+  0x0e, 0x30, 0x94, 0x84, 0x01, 0x08, 0x98, 0x8f, 0xdc, 0xb6, 0x19, 0x48,
+  0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x44, 0x04, 0x30, 0x11, 0x21, 0xd0, 0x0c,
+  0x0b, 0x61, 0x01, 0xd3, 0x70, 0xf9, 0xce, 0xe3, 0x2f, 0x0e, 0x30, 0x88,
+  0xcd, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x36, 0x50, 0x0d, 0x97, 0xef, 0x3c,
+  0xbe, 0x04, 0x30, 0xcf, 0x42, 0x94, 0x44, 0x45, 0x2c, 0x7e, 0x71, 0xdb,
+  0x26, 0x50, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x34, 0x39, 0x11, 0x81, 0x52,
+  0xd3, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x00, 0x61, 0x20, 0x00, 0x00, 0x3e,
+  0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x06,
+  0x00, 0x00, 0x00, 0x54, 0x8d, 0x00, 0x10, 0x51, 0x0a, 0x25, 0x37, 0x03,
+  0x50, 0x08, 0x65, 0x57, 0x7c, 0x54, 0x94, 0x00, 0x0d, 0x33, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x60, 0x71, 0x87,
+  0xa4, 0x69, 0xc9, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x58, 0x1d, 0x12,
+  0x6d, 0x9b, 0x32, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x96, 0x97, 0x4c,
+  0x1c, 0xb7, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x81, 0x41, 0x06, 0x48,
+  0xd7, 0x55, 0xc9, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x65, 0x90,
+  0x78, 0x9e, 0xa1, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0xc1, 0x24, 0x06,
+  0xc9, 0xf0, 0x8d, 0x26, 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c, 0x26, 0x0c,
+  0xc2, 0x68, 0x02, 0x31, 0x98, 0x70, 0xc8, 0xc7, 0x84, 0x43, 0x3e, 0x26,
+  0x18, 0xf0, 0x31, 0xc1, 0x80, 0xcf, 0x88, 0xc1, 0x01, 0x80, 0x20, 0x18,
+  0x40, 0x6c, 0x20, 0x31, 0x69, 0x30, 0x9a, 0x10, 0x00, 0x17, 0x0c, 0x35,
+  0x62, 0xf0, 0x00, 0x20, 0x08, 0x06, 0x0d, 0x1c, 0x50, 0x11, 0x54, 0x10,
+  0x92, 0xb4, 0x06, 0x6b, 0x70, 0x05, 0xa3, 0x09, 0x01, 0x30, 0x9a, 0x20,
+  0x04, 0xa3, 0x09, 0x83, 0x30, 0x9a, 0x40, 0x0c, 0x23, 0x06, 0x09, 0x00,
+  0x82, 0x60, 0x80, 0xd8, 0x81, 0x07, 0x07, 0x70, 0x80, 0x06, 0xc4, 0x88,
+  0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x76, 0xe0, 0xc1, 0x01, 0x1c, 0x60,
+  0xc3, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x76, 0xe0, 0xc1, 0x01,
+  0x1c, 0x9c, 0x81, 0x30, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x88, 0x1d,
+  0x78, 0x70, 0x00, 0x07, 0x66, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00
+};
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xy          0     NONE   float   xy  
+; SV_Position              0   xyzw        1      POS   float       
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_Target                0   xyzw        0   TARGET   float   xyzw
+;
+; shader hash: 2e13f04e8780c355f36dba74b811bc6f
+;
+; Pipeline Runtime Information: 
+;
+; Pixel Shader
+; DepthOutput=0
+; SampleFrequency=0
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; SV_Position              0          noperspective       
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_Target                0                              
+;
+; Buffer Definitions:
+;
+; cbuffer SourceRegionBuffer
+; {
+;
+;   struct SourceRegionBuffer
+;   {
+;
+;       float2 UVLeftTop;                             ; Offset:    0
+;       float2 UVDimensions;                          ; Offset:    8
+;       uint MipLevel;                                ; Offset:   16
+;       float LayerOrDepth;                           ; Offset:   20
+;   
+;   } SourceRegionBuffer;                             ; Offset:    0 Size:    24
+;
+; }
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; SourceRegionBuffer                cbuffer      NA          NA     CB0     cb0,space3     1
+; SourceSampler                     sampler      NA          NA      S0      s0,space2     1
+; SourceTexture2DArray              texture     f32     2darray      T0      t0,space2     1
+;
+;
+; ViewId state:
+;
+; Number of inputs: 8, outputs: 4
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 0, 1 }
+;   output 1 depends on inputs: { 0, 1 }
+;   output 2 depends on inputs: { 0, 1 }
+;   output 3 depends on inputs: { 0, 1 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+%dx.types.Handle = type { i8* }
+%dx.types.CBufRet.f32 = type { float, float, float, float }
+%dx.types.CBufRet.i32 = type { i32, i32, i32, i32 }
+%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
+%"class.Texture2DArray<vector<float, 4> >" = type { <4 x float>, %"class.Texture2DArray<vector<float, 4> >::mips_type" }
+%"class.Texture2DArray<vector<float, 4> >::mips_type" = type { i32 }
+%SourceRegionBuffer = type { <2 x float>, <2 x float>, i32, float }
+%struct.SamplerState = type { i32 }
+
+define void @BlitFrom2DArray() {
+  %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %6 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 0)  ; CBufferLoadLegacy(handle,regIndex)
+  %7 = extractvalue %dx.types.CBufRet.f32 %6, 0
+  %8 = extractvalue %dx.types.CBufRet.f32 %6, 1
+  %9 = extractvalue %dx.types.CBufRet.f32 %6, 2
+  %10 = extractvalue %dx.types.CBufRet.f32 %6, 3
+  %11 = fmul fast float %9, %4
+  %12 = fmul fast float %10, %5
+  %13 = fadd fast float %11, %7
+  %14 = fadd fast float %12, %8
+  %15 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %16 = extractvalue %dx.types.CBufRet.f32 %15, 1
+  %17 = fptoui float %16 to i32
+  %18 = uitofp i32 %17 to float
+  %19 = call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %3, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %20 = extractvalue %dx.types.CBufRet.i32 %19, 0
+  %21 = uitofp i32 %20 to float
+  %22 = call %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32 62, %dx.types.Handle %1, %dx.types.Handle %2, float %13, float %14, float %18, float undef, i32 0, i32 0, i32 undef, float %21)  ; SampleLevel(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,LOD)
+  %23 = extractvalue %dx.types.ResRet.f32 %22, 0
+  %24 = extractvalue %dx.types.ResRet.f32 %22, 1
+  %25 = extractvalue %dx.types.ResRet.f32 %22, 2
+  %26 = extractvalue %dx.types.ResRet.f32 %22, 3
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %23)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %24)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %25)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %26)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+; Function Attrs: nounwind readonly
+declare %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.resources = !{!4}
+!dx.viewIdState = !{!12}
+!dx.entryPoints = !{!13}
+
+!0 = !{!"clang version 3.7 (tags/RELEASE_370/final)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 6}
+!3 = !{!"ps", i32 6, i32 0}
+!4 = !{!5, null, !8, !10}
+!5 = !{!6}
+!6 = !{i32 0, %"class.Texture2DArray<vector<float, 4> >"* undef, !"", i32 2, i32 0, i32 1, i32 7, i32 0, !7}
+!7 = !{i32 0, i32 9}
+!8 = !{!9}
+!9 = !{i32 0, %SourceRegionBuffer* undef, !"", i32 3, i32 0, i32 1, i32 24, null}
+!10 = !{!11}
+!11 = !{i32 0, %struct.SamplerState* undef, !"", i32 2, i32 0, i32 1, i32 0, null}
+!12 = !{[10 x i32] [i32 8, i32 4, i32 15, i32 15, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0]}
+!13 = !{void ()* @BlitFrom2DArray, !"BlitFrom2DArray", !14, !4, null}
+!14 = !{!15, !20, null}
+!15 = !{!16, !19}
+!16 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !17, i8 2, i32 1, i8 2, i32 0, i8 0, !18}
+!17 = !{i32 0}
+!18 = !{i32 3, i32 3}
+!19 = !{i32 1, !"SV_Position", i8 9, i8 3, !17, i8 4, i32 1, i8 4, i32 1, i8 0, null}
+!20 = !{!21}
+!21 = !{i32 0, !"SV_Target", i8 9, i8 16, !17, i8 0, i32 1, i8 4, i32 0, i8 0, !22}
+!22 = !{i32 3, i32 15}
+
+#endif
+
+const unsigned char g_BlitFrom2DArray[] = {
+  0x44, 0x58, 0x42, 0x43, 0x97, 0x9b, 0xe2, 0xe6, 0x7c, 0x9a, 0x59, 0x06,
+  0xdd, 0x35, 0x7a, 0xab, 0x5f, 0x91, 0x3d, 0xe1, 0x01, 0x00, 0x00, 0x00,
+  0xef, 0x11, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00,
+  0xe3, 0x01, 0x00, 0x00, 0xe7, 0x09, 0x00, 0x00, 0x03, 0x0a, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x5d, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5f,
+  0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x4f, 0x53, 0x47,
+  0x31, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f,
+  0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x50, 0x53, 0x56, 0x30, 0xf0,
+  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18,
+  0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43,
+  0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x44, 0x03, 0x03,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x44, 0x10, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xfc, 0x07, 0x00, 0x00, 0x60,
+  0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00,
+  0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe4, 0x07, 0x00, 0x00, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xf6, 0x01, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43,
+  0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11,
+  0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04,
+  0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b,
+  0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84,
+  0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04,
+  0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8c, 0x8c, 0x0b,
+  0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40, 0x09, 0x00, 0x0a, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x40, 0x10, 0x44,
+  0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, 0x20, 0xe4, 0xa6, 0xe1,
+  0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, 0x95, 0x98, 0xfc, 0xe2,
+  0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, 0xcf, 0x70, 0xf9, 0x13,
+  0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, 0x28, 0x58, 0x0a, 0xa3,
+  0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, 0x40, 0xcd, 0x51, 0xc3,
+  0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, 0xc5, 0x4a, 0x4c, 0x7e,
+  0x71, 0xdb, 0x88, 0x18, 0x86, 0x61, 0x28, 0xc4, 0x43, 0x30, 0x04, 0x41,
+  0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, 0x15, 0x2b,
+  0x31, 0xf9, 0xc8, 0x6d, 0x23, 0x82, 0x20, 0x08, 0xa2, 0x10, 0x12, 0xc1,
+  0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, 0x82, 0x20, 0x2a, 0xb2,
+  0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0x26, 0x39, 0x18, 0x07, 0x76, 0x08,
+  0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, 0xc0, 0x07, 0x7a, 0xa8,
+  0x07, 0x79, 0x28, 0x07, 0x39, 0x20, 0x85, 0x50, 0x90, 0x07, 0x79, 0x08,
+  0x87, 0x7c, 0xe0, 0x03, 0x7b, 0x28, 0x87, 0x71, 0xa0, 0x87, 0x77, 0x90,
+  0x07, 0x3e, 0x30, 0x07, 0x76, 0x78, 0x87, 0x70, 0xa0, 0x07, 0x36, 0x00,
+  0x03, 0x3a, 0xf0, 0x03, 0x30, 0xf0, 0x03, 0x3d, 0xd0, 0x83, 0x76, 0x48,
+  0x07, 0x78, 0x98, 0x87, 0x5f, 0xa0, 0x87, 0x7c, 0x80, 0x87, 0x72, 0x40,
+  0x01, 0x31, 0xd3, 0x19, 0x8c, 0x03, 0x3b, 0x84, 0xc3, 0x3c, 0xcc, 0x83,
+  0x1b, 0xd0, 0x42, 0x39, 0xe0, 0x03, 0x3d, 0xd4, 0x83, 0x3c, 0x94, 0x83,
+  0x1c, 0x90, 0x42, 0x28, 0xc8, 0x83, 0x3c, 0x84, 0x43, 0x3e, 0xf0, 0x81,
+  0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, 0x03,
+  0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, 0x01,
+  0x18, 0xf8, 0x01, 0x12, 0x32, 0x8d, 0xb6, 0x61, 0x04, 0x61, 0x38, 0x89,
+  0x75, 0xa8, 0x48, 0x20, 0x56, 0xc2, 0x40, 0x9c, 0x66, 0xa3, 0x8a, 0x82,
+  0x88, 0x10, 0xd1, 0x75, 0xc4, 0x40, 0xde, 0x4d, 0xd2, 0x14, 0x51, 0xc2,
+  0xe4, 0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, 0x80,
+  0x20, 0x30, 0x15, 0x08, 0x00, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87,
+  0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87,
+  0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00,
+  0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0,
+  0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60,
+  0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60,
+  0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0,
+  0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x14,
+  0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x18, 0x19, 0x11, 0x4c, 0x90, 0x8c,
+  0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18,
+  0x8a, 0xa0, 0x1c, 0x4a, 0xa2, 0x0c, 0x0a, 0xa6, 0x20, 0x0a, 0xa4, 0x14,
+  0x0a, 0xa5, 0x3c, 0xca, 0xa7, 0x10, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22,
+  0x28, 0x83, 0x42, 0x28, 0x10, 0xaa, 0x6a, 0x80, 0xb8, 0x19, 0x00, 0xf2,
+  0x66, 0x00, 0xe8, 0x9b, 0x01, 0xa0, 0x70, 0x06, 0x80, 0xc4, 0xb1, 0x14,
+  0x84, 0x78, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79,
+  0x18, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46,
+  0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b,
+  0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1,
+  0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa,
+  0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10,
+  0x04, 0x13, 0x04, 0xe2, 0x98, 0x20, 0x10, 0xc8, 0x06, 0x61, 0x20, 0x36,
+  0x08, 0x04, 0x41, 0x01, 0x6e, 0x6e, 0x82, 0x40, 0x24, 0x1b, 0x86, 0x03,
+  0x21, 0x26, 0x08, 0x5c, 0x47, 0x6a, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x8c,
+  0xaa, 0x0c, 0x8f, 0xae, 0x4e, 0xae, 0x4c, 0x86, 0x28, 0x48, 0x4e, 0x2e,
+  0x2c, 0x6f, 0x82, 0x40, 0x28, 0x13, 0x04, 0x62, 0x99, 0x20, 0x10, 0xcc,
+  0x06, 0x81, 0x70, 0x36, 0x24, 0x84, 0xb2, 0x30, 0xc4, 0xd0, 0x10, 0xcf,
+  0x86, 0x00, 0x9a, 0x20, 0x7c, 0x1f, 0xa5, 0xa9, 0xb7, 0x3a, 0xb9, 0xb1,
+  0x32, 0xa9, 0xb2, 0xb3, 0xb4, 0x37, 0x37, 0xa1, 0x3a, 0x33, 0xb3, 0x32,
+  0xb9, 0x09, 0x02, 0xd1, 0x4c, 0x10, 0x08, 0x67, 0x03, 0x42, 0x48, 0x13,
+  0x45, 0x0c, 0x15, 0xb0, 0x21, 0xb0, 0x26, 0x08, 0x61, 0x00, 0x06, 0x6c,
+  0xa6, 0xde, 0xea, 0xe4, 0xc6, 0xca, 0xa6, 0xc2, 0xda, 0xe0, 0xd8, 0xca,
+  0xe4, 0x36, 0x20, 0x04, 0x96, 0x31, 0xc4, 0x40, 0x00, 0x1b, 0x02, 0x6d,
+  0x03, 0x11, 0x01, 0xd7, 0x36, 0x41, 0xf0, 0x3c, 0x26, 0x55, 0x56, 0x4c,
+  0x65, 0x66, 0x74, 0x54, 0x6f, 0x70, 0x13, 0x84, 0x8a, 0xdb, 0x80, 0x20,
+  0x1e, 0x45, 0x34, 0x8e, 0xf3, 0x91, 0xa9, 0xb2, 0x22, 0x4a, 0x6b, 0x2b,
+  0x73, 0x9b, 0x4b, 0x7b, 0x73, 0x9b, 0x9b, 0x20, 0x10, 0xcf, 0x06, 0x04,
+  0x09, 0x03, 0x4a, 0x0c, 0x1a, 0xc7, 0xf9, 0x88, 0x34, 0xa5, 0xc1, 0x31,
+  0x95, 0xd9, 0x95, 0xb1, 0x4d, 0x10, 0x08, 0x68, 0x82, 0x40, 0x44, 0x1b,
+  0x10, 0x84, 0x0c, 0xa8, 0x32, 0x68, 0xcc, 0xc0, 0xf9, 0xc8, 0x30, 0x85,
+  0xe5, 0x95, 0xc9, 0x3d, 0xc9, 0x11, 0x95, 0xc1, 0xd1, 0xa1, 0x4d, 0x10,
+  0x08, 0x69, 0x03, 0x82, 0xa0, 0x01, 0x95, 0x06, 0x8d, 0xe3, 0x7c, 0x1b,
+  0x8a, 0x0a, 0x0c, 0xc6, 0xe0, 0x0c, 0xd4, 0x60, 0xc3, 0x40, 0x74, 0x6b,
+  0x30, 0x41, 0x10, 0x80, 0x0d, 0xc0, 0x86, 0x81, 0x70, 0x03, 0x37, 0xd8,
+  0x10, 0xbc, 0xc1, 0x86, 0x61, 0x68, 0x03, 0x38, 0x98, 0x20, 0x88, 0x41,
+  0x18, 0x6c, 0x08, 0xe4, 0x80, 0x8f, 0x10, 0x5b, 0x1a, 0x9d, 0x91, 0xdc,
+  0x5b, 0x9b, 0x0c, 0x51, 0x90, 0x9c, 0x5c, 0x58, 0x1e, 0x11, 0xaa, 0x22,
+  0xac, 0xa1, 0xa7, 0x27, 0x29, 0xa2, 0x09, 0x42, 0x61, 0x4d, 0x10, 0x8a,
+  0x6b, 0x43, 0x40, 0x4c, 0x10, 0x0a, 0x6c, 0x83, 0x40, 0x51, 0x1b, 0x16,
+  0xa2, 0x0e, 0xec, 0xe0, 0x0e, 0xf0, 0x20, 0x0f, 0x86, 0x3c, 0x20, 0xee,
+  0x40, 0x0f, 0xb8, 0x4c, 0x59, 0x7d, 0x41, 0xbd, 0xcd, 0xa5, 0xd1, 0xa5,
+  0xbd, 0xb9, 0x4d, 0x10, 0x8a, 0x6c, 0x82, 0x50, 0x68, 0x1b, 0x96, 0x81,
+  0x0f, 0xec, 0xa0, 0x0f, 0xf0, 0xc0, 0x0f, 0x06, 0x3f, 0x18, 0xee, 0x00,
+  0xd8, 0x20, 0xec, 0xc1, 0x1f, 0x30, 0x99, 0xb2, 0xfa, 0xa2, 0x0a, 0x93,
+  0x3b, 0x2b, 0xa3, 0x9b, 0x20, 0x14, 0xdb, 0x04, 0x81, 0x98, 0x36, 0x08,
+  0xd4, 0x28, 0x6c, 0x58, 0x88, 0x50, 0xb0, 0x03, 0x51, 0xc0, 0x83, 0x3b,
+  0x18, 0xfc, 0x80, 0xb8, 0x03, 0x52, 0xd8, 0x10, 0x94, 0xc2, 0x86, 0x01,
+  0x14, 0x4c, 0x01, 0xd8, 0x50, 0xb4, 0x01, 0x1d, 0x9c, 0x02, 0x07, 0xd0,
+  0x30, 0x63, 0x7b, 0x0b, 0xa3, 0x9b, 0x63, 0x91, 0xe6, 0x36, 0x47, 0x37,
+  0x37, 0x41, 0x20, 0x28, 0x1a, 0x73, 0x69, 0x67, 0x5f, 0x6c, 0x64, 0x34,
+  0xe6, 0xd2, 0xce, 0xbe, 0xe6, 0xe8, 0x26, 0x08, 0x44, 0x45, 0x84, 0xae,
+  0x0c, 0xef, 0xcb, 0xed, 0x4d, 0xae, 0x6d, 0x83, 0x92, 0x0a, 0x8d, 0x2a,
+  0xac, 0x02, 0x2b, 0x30, 0xad, 0xe0, 0x0a, 0xaf, 0x30, 0x54, 0x61, 0x63,
+  0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3, 0x9b, 0x12, 0x04, 0x55,
+  0xc8, 0xf0, 0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2, 0xde, 0xdc, 0xa6, 0x04,
+  0x44, 0x13, 0x32, 0x3c, 0x17, 0xbb, 0x30, 0x36, 0xbb, 0x32, 0xb9, 0x29,
+  0x41, 0x51, 0x87, 0x0c, 0xcf, 0x65, 0x0e, 0x2d, 0x8c, 0xac, 0x4c, 0xae,
+  0xe9, 0x8d, 0xac, 0x8c, 0x6d, 0x4a, 0x80, 0x94, 0x21, 0xc3, 0x73, 0x91,
+  0x2b, 0x9b, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0x9b, 0x9b, 0x12, 0x6c, 0x95,
+  0xc8, 0xf0, 0x5c, 0xe8, 0xf2, 0xe0, 0xca, 0x82, 0xdc, 0xdc, 0xde, 0xe8,
+  0xc2, 0xe8, 0xd2, 0xde, 0xdc, 0xe6, 0xa6, 0x08, 0x6b, 0x00, 0x07, 0x75,
+  0xc8, 0xf0, 0x5c, 0xec, 0xd2, 0xca, 0xee, 0x92, 0xc8, 0xa6, 0xe8, 0xc2,
+  0xe8, 0xca, 0xa6, 0x04, 0x72, 0x50, 0x87, 0x0c, 0xcf, 0xa5, 0xcc, 0x8d,
+  0x4e, 0x2e, 0x0f, 0xea, 0x2d, 0xcd, 0x8d, 0x6e, 0x6e, 0x4a, 0x70, 0x0a,
+  0x5d, 0xc8, 0xf0, 0x5c, 0xc6, 0xde, 0xea, 0xdc, 0xe8, 0xca, 0xe4, 0xe6,
+  0xa6, 0x04, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76,
+  0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e,
+  0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f,
+  0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x20,
+  0x00, 0x00, 0x00, 0x06, 0xf0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0xd8,
+  0x9d, 0x16, 0x45, 0x00, 0x66, 0x04, 0xdb, 0x70, 0xf9, 0xce, 0xe3, 0x0b,
+  0x01, 0x55, 0x14, 0x44, 0x54, 0x3a, 0xc0, 0x50, 0x12, 0x06, 0x20, 0x60,
+  0x7e, 0x71, 0xdb, 0x56, 0xb0, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x10, 0x50,
+  0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25, 0x61, 0x00, 0x02, 0xe6, 0x23,
+  0xb7, 0x6d, 0x06, 0xd2, 0x70, 0xf9, 0xce, 0xe3, 0x0b, 0x11, 0x01, 0x4c,
+  0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0xc0, 0x34, 0x5c, 0xbe, 0xf3, 0xf8,
+  0x8b, 0x03, 0x0c, 0x62, 0xf3, 0x50, 0x93, 0x5f, 0xdc, 0xb6, 0x0d, 0x54,
+  0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x01, 0xcc, 0xb3, 0x10, 0x25, 0x51, 0x11,
+  0x8b, 0x5f, 0xdc, 0xb6, 0x09, 0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x4d,
+  0x4e, 0x44, 0xa0, 0xd4, 0xf4, 0x50, 0x93, 0x5f, 0xdc, 0x36, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x2e, 0x13, 0xf0, 0x4e, 0x87, 0x80, 0xc3, 0x55, 0xf3,
+  0x6d, 0xba, 0x74, 0xb8, 0x11, 0xbc, 0x6f, 0x44, 0x58, 0x49, 0x4c, 0xe4,
+  0x07, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xf9, 0x01, 0x00, 0x00, 0x44,
+  0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcc,
+  0x07, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xf0,
+  0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13,
+  0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06,
+  0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e,
+  0x04, 0x8b, 0x62, 0x80, 0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4,
+  0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48,
+  0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4,
+  0x48, 0x0e, 0x90, 0x11, 0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1,
+  0x83, 0xe5, 0x8a, 0x04, 0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40,
+  0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d,
+  0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49,
+  0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20,
+  0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x5c,
+  0x00, 0x00, 0x00, 0x32, 0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13,
+  0x23, 0xa4, 0x84, 0x04, 0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12,
+  0x4c, 0x8c, 0x8c, 0x0b, 0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40,
+  0x09, 0x00, 0x0a, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29,
+  0xc6, 0x40, 0x10, 0x44, 0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62,
+  0x20, 0xe4, 0xa6, 0xe1, 0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4,
+  0x95, 0x98, 0xfc, 0xe2, 0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71,
+  0xcf, 0x70, 0xf9, 0x13, 0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10,
+  0x28, 0x58, 0x0a, 0xa3, 0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4,
+  0x40, 0xcd, 0x51, 0xc3, 0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51,
+  0xc5, 0x4a, 0x4c, 0x7e, 0x71, 0xdb, 0x88, 0x18, 0x86, 0x61, 0x28, 0xc4,
+  0x43, 0x30, 0x04, 0x41, 0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9,
+  0xdc, 0x46, 0x15, 0x2b, 0x31, 0xf9, 0xc8, 0x6d, 0x23, 0x82, 0x20, 0x08,
+  0xa2, 0x10, 0x12, 0xc1, 0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88,
+  0x82, 0x20, 0x2a, 0xb2, 0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0x26, 0x39,
+  0x18, 0x07, 0x76, 0x08, 0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72,
+  0xc0, 0x07, 0x7a, 0xa8, 0x07, 0x79, 0x28, 0x07, 0x39, 0x20, 0x85, 0x50,
+  0x90, 0x07, 0x79, 0x08, 0x87, 0x7c, 0xe0, 0x03, 0x7b, 0x28, 0x87, 0x71,
+  0xa0, 0x87, 0x77, 0x90, 0x07, 0x3e, 0x30, 0x07, 0x76, 0x78, 0x87, 0x70,
+  0xa0, 0x07, 0x36, 0x00, 0x03, 0x3a, 0xf0, 0x03, 0x30, 0xf0, 0x03, 0x3d,
+  0xd0, 0x83, 0x76, 0x48, 0x07, 0x78, 0x98, 0x87, 0x5f, 0xa0, 0x87, 0x7c,
+  0x80, 0x87, 0x72, 0x40, 0x01, 0x31, 0xd3, 0x19, 0x8c, 0x03, 0x3b, 0x84,
+  0xc3, 0x3c, 0xcc, 0x83, 0x1b, 0xd0, 0x42, 0x39, 0xe0, 0x03, 0x3d, 0xd4,
+  0x83, 0x3c, 0x94, 0x83, 0x1c, 0x90, 0x42, 0x28, 0xc8, 0x83, 0x3c, 0x84,
+  0x43, 0x3e, 0xf0, 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8,
+  0x03, 0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80,
+  0x01, 0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x01, 0x12, 0x32, 0x8d, 0xb6, 0x61,
+  0x04, 0x61, 0x38, 0x89, 0x75, 0xa8, 0x48, 0x20, 0x56, 0xc2, 0x40, 0x9c,
+  0x66, 0xa3, 0x8a, 0x82, 0x88, 0x10, 0xd1, 0x75, 0xc4, 0x40, 0xde, 0x4d,
+  0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4, 0x4e,
+  0xc0, 0x44, 0xa0, 0x80, 0x20, 0x30, 0x15, 0x08, 0x00, 0x00, 0x00, 0x13,
+  0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68,
+  0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a,
+  0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71,
+  0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d,
+  0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40,
+  0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81,
+  0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8,
+  0x33, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x90, 0xc7, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x2c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19,
+  0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a,
+  0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x1c, 0x4a, 0xa2, 0x0c, 0x0a, 0xa6,
+  0x3c, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, 0x28, 0x83, 0x42, 0x28, 0x10,
+  0xe2, 0x66, 0x00, 0xe8, 0x9b, 0x01, 0xa0, 0x70, 0x06, 0x80, 0xc4, 0xb1,
+  0x14, 0x84, 0x78, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79,
+  0x18, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46,
+  0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b,
+  0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1,
+  0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa,
+  0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10,
+  0x04, 0x13, 0x04, 0xe2, 0x98, 0x20, 0x10, 0xc8, 0x06, 0x61, 0x20, 0x26,
+  0x08, 0x44, 0xb2, 0x41, 0x18, 0x0c, 0x0a, 0x70, 0x73, 0x1b, 0x06, 0xc4,
+  0x20, 0x26, 0x08, 0x9c, 0x45, 0x60, 0x82, 0x40, 0x28, 0x13, 0x04, 0x62,
+  0x99, 0x20, 0x10, 0xcc, 0x06, 0x81, 0x70, 0x36, 0x24, 0x84, 0xb2, 0x30,
+  0xc4, 0xd0, 0x10, 0xcf, 0x86, 0x00, 0x9a, 0x20, 0x7c, 0xd7, 0x04, 0x81,
+  0x68, 0x26, 0x08, 0x84, 0xb3, 0x01, 0x21, 0xa4, 0x65, 0x22, 0x06, 0x0a,
+  0xd8, 0x10, 0x54, 0x13, 0x84, 0x30, 0xc0, 0x36, 0x20, 0xc4, 0xb5, 0x30,
+  0xc4, 0x40, 0x00, 0x1b, 0x02, 0x6c, 0x03, 0x11, 0x01, 0x56, 0x36, 0x41,
+  0x10, 0x83, 0x6c, 0x43, 0xb0, 0x4d, 0x10, 0x04, 0x80, 0x8f, 0x10, 0x5b,
+  0x1a, 0x9d, 0x91, 0xdc, 0x5b, 0x9b, 0x0c, 0x51, 0x90, 0x9c, 0x5c, 0x58,
+  0x1e, 0x11, 0xaa, 0x22, 0xac, 0xa1, 0xa7, 0x27, 0x29, 0xa2, 0x09, 0x42,
+  0x01, 0x4d, 0x10, 0x8a, 0x68, 0x43, 0x40, 0x4c, 0x10, 0x0a, 0x69, 0x83,
+  0x30, 0x4d, 0x1b, 0x16, 0xe2, 0x03, 0x83, 0x30, 0x10, 0x83, 0x31, 0x18,
+  0xc6, 0x80, 0x08, 0x03, 0x32, 0xe0, 0x32, 0x65, 0xf5, 0x05, 0xf5, 0x36,
+  0x97, 0x46, 0x97, 0xf6, 0xe6, 0x36, 0x41, 0x28, 0xa6, 0x09, 0x42, 0x41,
+  0x6d, 0x58, 0x06, 0x33, 0x00, 0x83, 0x33, 0x10, 0x03, 0x34, 0x18, 0xd0,
+  0x60, 0x08, 0x03, 0x60, 0x83, 0x50, 0x06, 0x69, 0xc0, 0x64, 0xca, 0xea,
+  0x8b, 0x2a, 0x4c, 0xee, 0xac, 0x8c, 0x6e, 0x82, 0x50, 0x54, 0x13, 0x04,
+  0xe2, 0xd9, 0x20, 0x4c, 0x6d, 0xb0, 0x61, 0x21, 0xd6, 0x00, 0x0c, 0xd8,
+  0x40, 0x0c, 0xc2, 0x60, 0x40, 0x03, 0x22, 0x0c, 0xdc, 0x60, 0x43, 0xf0,
+  0x06, 0x1b, 0x06, 0x35, 0x80, 0x03, 0x60, 0x43, 0xd1, 0x79, 0x71, 0xa0,
+  0x01, 0x55, 0xd8, 0xd8, 0xec, 0xda, 0x5c, 0xd2, 0xc8, 0xca, 0xdc, 0xe8,
+  0xa6, 0x04, 0x41, 0x15, 0x32, 0x3c, 0x17, 0xbb, 0x32, 0xb9, 0xb9, 0xb4,
+  0x37, 0xb7, 0x29, 0x01, 0xd1, 0x84, 0x0c, 0xcf, 0xc5, 0x2e, 0x8c, 0xcd,
+  0xae, 0x4c, 0x6e, 0x4a, 0x60, 0xd4, 0x21, 0xc3, 0x73, 0x99, 0x43, 0x0b,
+  0x23, 0x2b, 0x93, 0x6b, 0x7a, 0x23, 0x2b, 0x63, 0x9b, 0x12, 0x20, 0x65,
+  0xc8, 0xf0, 0x5c, 0xe4, 0xca, 0xe6, 0xde, 0xea, 0xe4, 0xc6, 0xca, 0xe6,
+  0xa6, 0x04, 0x59, 0x1d, 0x32, 0x3c, 0x17, 0xbb, 0xb4, 0xb2, 0xbb, 0x24,
+  0xb2, 0x29, 0xba, 0x30, 0xba, 0xb2, 0x29, 0xc1, 0x56, 0x87, 0x0c, 0xcf,
+  0xa5, 0xcc, 0x8d, 0x4e, 0x2e, 0x0f, 0xea, 0x2d, 0xcd, 0x8d, 0x6e, 0x6e,
+  0x4a, 0x10, 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76,
+  0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e,
+  0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f,
+  0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x20,
+  0x00, 0x00, 0x00, 0x06, 0xf0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0xd8,
+  0x9d, 0x16, 0x45, 0x00, 0x66, 0x04, 0xdb, 0x70, 0xf9, 0xce, 0xe3, 0x0b,
+  0x01, 0x55, 0x14, 0x44, 0x54, 0x3a, 0xc0, 0x50, 0x12, 0x06, 0x20, 0x60,
+  0x7e, 0x71, 0xdb, 0x56, 0xb0, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x10, 0x50,
+  0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25, 0x61, 0x00, 0x02, 0xe6, 0x23,
+  0xb7, 0x6d, 0x06, 0xd2, 0x70, 0xf9, 0xce, 0xe3, 0x0b, 0x11, 0x01, 0x4c,
+  0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0xc0, 0x34, 0x5c, 0xbe, 0xf3, 0xf8,
+  0x8b, 0x03, 0x0c, 0x62, 0xf3, 0x50, 0x93, 0x5f, 0xdc, 0xb6, 0x0d, 0x54,
+  0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x01, 0xcc, 0xb3, 0x10, 0x25, 0x51, 0x11,
+  0x8b, 0x5f, 0xdc, 0xb6, 0x09, 0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x4d,
+  0x4e, 0x44, 0xa0, 0xd4, 0xf4, 0x50, 0x93, 0x5f, 0xdc, 0x36, 0x00, 0x61,
+  0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10,
+  0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, 0x8d, 0x00, 0x10, 0x51,
+  0x0a, 0x25, 0x37, 0x03, 0x50, 0x76, 0x85, 0x50, 0x7c, 0x54, 0x94, 0x00,
+  0x0d, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x06, 0x09, 0x00, 0x82,
+  0x60, 0x60, 0x75, 0x87, 0xb4, 0x6d, 0xc9, 0x88, 0x41, 0x02, 0x80, 0x20,
+  0x18, 0x58, 0x1e, 0x12, 0x71, 0x9c, 0x32, 0x62, 0x90, 0x00, 0x20, 0x08,
+  0x06, 0xd6, 0x97, 0x4c, 0x5d, 0xb7, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82,
+  0x81, 0x51, 0x06, 0x87, 0xe7, 0x55, 0xc9, 0x88, 0x41, 0x02, 0x80, 0x20,
+  0x18, 0x18, 0x66, 0x80, 0x7c, 0x9f, 0xa1, 0x8c, 0x18, 0x1c, 0x00, 0x08,
+  0x82, 0x01, 0x44, 0x06, 0xca, 0x00, 0x06, 0xa3, 0x09, 0x01, 0x30, 0x9a,
+  0x20, 0x04, 0xa3, 0x09, 0x83, 0x30, 0x9a, 0x40, 0x0c, 0x26, 0x1c, 0xf2,
+  0x31, 0xe1, 0x90, 0x8f, 0x09, 0x06, 0x7c, 0x4c, 0x30, 0xe0, 0x33, 0x62,
+  0x70, 0x00, 0x20, 0x08, 0x06, 0x50, 0x1b, 0x4c, 0x8c, 0x1a, 0x8c, 0x26,
+  0x04, 0xc1, 0x05, 0xc4, 0x5c, 0x30, 0xd4, 0x88, 0xc1, 0x01, 0x80, 0x20,
+  0x18, 0x4c, 0x70, 0x70, 0x41, 0x6e, 0x30, 0x9a, 0x10, 0x00, 0x17, 0x0c,
+  0x35, 0x62, 0xf0, 0x00, 0x20, 0x08, 0x06, 0x4d, 0x1d, 0x60, 0x15, 0x95,
+  0x20, 0x84, 0x05, 0x07, 0x70, 0xb0, 0x05, 0xa3, 0x09, 0x01, 0x30, 0x9a,
+  0x20, 0x04, 0xa3, 0x09, 0x83, 0x30, 0x9a, 0x40, 0x0c, 0x23, 0x06, 0x09,
+  0x00, 0x82, 0x60, 0x80, 0xec, 0x81, 0x18, 0xd4, 0x41, 0x1d, 0xb0, 0x01,
+  0x31, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xc8, 0x1e, 0x88, 0x41, 0x1d,
+  0xd4, 0x01, 0x37, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0xb2, 0x07,
+  0x62, 0x50, 0x07, 0x75, 0xb0, 0x06, 0xc2, 0x88, 0x41, 0x02, 0x80, 0x20,
+  0x18, 0x20, 0x7b, 0x20, 0x06, 0x75, 0x50, 0x07, 0x6a, 0x10, 0x20, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xy          0     NONE   float   xy  
+; SV_Position              0   xyzw        1      POS   float       
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_Target                0   xyzw        0   TARGET   float   xyzw
+;
+; shader hash: 49c2f4be133400e07c3f23e9798b27f4
+;
+; Pipeline Runtime Information: 
+;
+; Pixel Shader
+; DepthOutput=0
+; SampleFrequency=0
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; SV_Position              0          noperspective       
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_Target                0                              
+;
+; Buffer Definitions:
+;
+; cbuffer SourceRegionBuffer
+; {
+;
+;   struct SourceRegionBuffer
+;   {
+;
+;       float2 UVLeftTop;                             ; Offset:    0
+;       float2 UVDimensions;                          ; Offset:    8
+;       uint MipLevel;                                ; Offset:   16
+;       float LayerOrDepth;                           ; Offset:   20
+;   
+;   } SourceRegionBuffer;                             ; Offset:    0 Size:    24
+;
+; }
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; SourceRegionBuffer                cbuffer      NA          NA     CB0     cb0,space3     1
+; SourceSampler                     sampler      NA          NA      S0      s0,space2     1
+; SourceTexture3D                   texture     f32          3d      T0      t0,space2     1
+;
+;
+; ViewId state:
+;
+; Number of inputs: 8, outputs: 4
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 0, 1 }
+;   output 1 depends on inputs: { 0, 1 }
+;   output 2 depends on inputs: { 0, 1 }
+;   output 3 depends on inputs: { 0, 1 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+%dx.types.Handle = type { i8* }
+%dx.types.CBufRet.f32 = type { float, float, float, float }
+%dx.types.CBufRet.i32 = type { i32, i32, i32, i32 }
+%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
+%"class.Texture3D<vector<float, 4> >" = type { <4 x float>, %"class.Texture3D<vector<float, 4> >::mips_type" }
+%"class.Texture3D<vector<float, 4> >::mips_type" = type { i32 }
+%SourceRegionBuffer = type { <2 x float>, <2 x float>, i32, float }
+%struct.SamplerState = type { i32 }
+
+define void @BlitFrom3D() {
+  %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %6 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 0)  ; CBufferLoadLegacy(handle,regIndex)
+  %7 = extractvalue %dx.types.CBufRet.f32 %6, 0
+  %8 = extractvalue %dx.types.CBufRet.f32 %6, 1
+  %9 = extractvalue %dx.types.CBufRet.f32 %6, 2
+  %10 = extractvalue %dx.types.CBufRet.f32 %6, 3
+  %11 = fmul fast float %9, %4
+  %12 = fmul fast float %10, %5
+  %13 = fadd fast float %11, %7
+  %14 = fadd fast float %12, %8
+  %15 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %16 = extractvalue %dx.types.CBufRet.f32 %15, 1
+  %17 = call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %3, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %18 = extractvalue %dx.types.CBufRet.i32 %17, 0
+  %19 = uitofp i32 %18 to float
+  %20 = call %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32 62, %dx.types.Handle %1, %dx.types.Handle %2, float %13, float %14, float %16, float undef, i32 0, i32 0, i32 0, float %19)  ; SampleLevel(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,LOD)
+  %21 = extractvalue %dx.types.ResRet.f32 %20, 0
+  %22 = extractvalue %dx.types.ResRet.f32 %20, 1
+  %23 = extractvalue %dx.types.ResRet.f32 %20, 2
+  %24 = extractvalue %dx.types.ResRet.f32 %20, 3
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %21)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %22)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %23)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %24)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+; Function Attrs: nounwind readonly
+declare %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.resources = !{!4}
+!dx.viewIdState = !{!12}
+!dx.entryPoints = !{!13}
+
+!0 = !{!"clang version 3.7 (tags/RELEASE_370/final)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 6}
+!3 = !{!"ps", i32 6, i32 0}
+!4 = !{!5, null, !8, !10}
+!5 = !{!6}
+!6 = !{i32 0, %"class.Texture3D<vector<float, 4> >"* undef, !"", i32 2, i32 0, i32 1, i32 4, i32 0, !7}
+!7 = !{i32 0, i32 9}
+!8 = !{!9}
+!9 = !{i32 0, %SourceRegionBuffer* undef, !"", i32 3, i32 0, i32 1, i32 24, null}
+!10 = !{!11}
+!11 = !{i32 0, %struct.SamplerState* undef, !"", i32 2, i32 0, i32 1, i32 0, null}
+!12 = !{[10 x i32] [i32 8, i32 4, i32 15, i32 15, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0]}
+!13 = !{void ()* @BlitFrom3D, !"BlitFrom3D", !14, !4, null}
+!14 = !{!15, !20, null}
+!15 = !{!16, !19}
+!16 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !17, i8 2, i32 1, i8 2, i32 0, i8 0, !18}
+!17 = !{i32 0}
+!18 = !{i32 3, i32 3}
+!19 = !{i32 1, !"SV_Position", i8 9, i8 3, !17, i8 4, i32 1, i8 4, i32 1, i8 0, null}
+!20 = !{!21}
+!21 = !{i32 0, !"SV_Target", i8 9, i8 16, !17, i8 0, i32 1, i8 4, i32 0, i8 0, !22}
+!22 = !{i32 3, i32 15}
+
+#endif
+
+const unsigned char g_BlitFrom3D[] = {
+  0x44, 0x58, 0x42, 0x43, 0x92, 0xfc, 0xc9, 0x36, 0x8a, 0xa4, 0xdc, 0xb9,
+  0x51, 0xa8, 0x46, 0x69, 0x09, 0x0b, 0x8e, 0x8e, 0x01, 0x00, 0x00, 0x00,
+  0xab, 0x11, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00,
+  0xe3, 0x01, 0x00, 0x00, 0xcb, 0x09, 0x00, 0x00, 0xe7, 0x09, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x5d, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5f,
+  0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x4f, 0x53, 0x47,
+  0x31, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f,
+  0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x50, 0x53, 0x56, 0x30, 0xf0,
+  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18,
+  0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43,
+  0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x44, 0x03, 0x03,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x44, 0x10, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xe0, 0x07, 0x00, 0x00, 0x60,
+  0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00,
+  0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc8, 0x07, 0x00, 0x00, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xef, 0x01, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43,
+  0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11,
+  0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04,
+  0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b,
+  0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84,
+  0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04,
+  0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8c, 0x8c, 0x0b,
+  0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40, 0x09, 0x00, 0x0a, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x40, 0x10, 0x44,
+  0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, 0x20, 0xe4, 0xa6, 0xe1,
+  0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, 0x95, 0x98, 0xfc, 0xe2,
+  0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, 0xcf, 0x70, 0xf9, 0x13,
+  0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, 0x28, 0x58, 0x0a, 0xa3,
+  0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, 0x40, 0xcd, 0x51, 0xc3,
+  0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, 0xc5, 0x4a, 0x4c, 0x7e,
+  0x71, 0xdb, 0x88, 0x18, 0x86, 0x61, 0x28, 0xc4, 0x43, 0x30, 0x04, 0x41,
+  0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, 0x15, 0x2b,
+  0x31, 0xf9, 0xc8, 0x6d, 0x23, 0x82, 0x20, 0x08, 0xa2, 0x10, 0x12, 0xc1,
+  0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, 0x82, 0x20, 0x2a, 0xb2,
+  0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0xa6, 0x36, 0x18, 0x07, 0x76, 0x08,
+  0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, 0xc0, 0x07, 0x7a, 0xa8,
+  0x07, 0x79, 0x28, 0x87, 0x39, 0x20, 0x05, 0x3e, 0xb0, 0x87, 0x72, 0x18,
+  0x07, 0x7a, 0x78, 0x07, 0x79, 0xe0, 0x03, 0x73, 0x60, 0x87, 0x77, 0x08,
+  0x07, 0x7a, 0x60, 0x03, 0x30, 0xa0, 0x03, 0x3f, 0x00, 0x03, 0x3f, 0xd0,
+  0x03, 0x3d, 0x68, 0x87, 0x74, 0x80, 0x87, 0x79, 0xf8, 0x05, 0x7a, 0xc8,
+  0x07, 0x78, 0x28, 0x07, 0x14, 0x10, 0x33, 0x89, 0xc1, 0x38, 0xb0, 0x43,
+  0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, 0x94, 0x03, 0x3e, 0xd0, 0x43,
+  0x3d, 0xc8, 0x43, 0x39, 0xcc, 0x01, 0x29, 0xf0, 0x81, 0x3d, 0x94, 0xc3,
+  0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43,
+  0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x01,
+  0x12, 0x32, 0x8d, 0xb6, 0x61, 0x04, 0x61, 0x38, 0x89, 0x75, 0xa8, 0x48,
+  0x20, 0x56, 0xc2, 0x40, 0x9c, 0x66, 0xa3, 0x8a, 0x82, 0x88, 0x10, 0xd1,
+  0x75, 0xc4, 0x40, 0xde, 0x4d, 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xb3, 0x00,
+  0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, 0x80, 0x20, 0x30, 0x15,
+  0x08, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36,
+  0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e,
+  0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06,
+  0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c,
+  0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+  0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x14, 0x00, 0x00, 0x00, 0x32,
+  0x1e, 0x98, 0x18, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6,
+  0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x10, 0x4a,
+  0xa2, 0x0c, 0x0a, 0xa6, 0x1c, 0x0a, 0xa2, 0x40, 0x4a, 0xa1, 0x50, 0xca,
+  0xa3, 0x74, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, 0x28, 0x83, 0x42, 0x28,
+  0x10, 0xaa, 0x6a, 0x80, 0xb8, 0x19, 0x00, 0xf2, 0x66, 0x00, 0xe8, 0x9b,
+  0x01, 0xa0, 0x70, 0x06, 0x80, 0xc4, 0xb1, 0x14, 0x84, 0x78, 0x1e, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0xaf,
+  0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x35,
+  0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b,
+  0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b,
+  0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79,
+  0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xe2,
+  0x98, 0x20, 0x10, 0xc8, 0x06, 0x61, 0x20, 0x36, 0x08, 0x04, 0x41, 0x01,
+  0x6e, 0x6e, 0x82, 0x40, 0x24, 0x1b, 0x86, 0x03, 0x21, 0x26, 0x08, 0x5c,
+  0xc7, 0x67, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x8c, 0xaa, 0x0c, 0x8f, 0xae,
+  0x4e, 0xae, 0x6c, 0x86, 0x68, 0x82, 0x40, 0x28, 0x13, 0x04, 0x62, 0x99,
+  0x20, 0x10, 0xcc, 0x06, 0x81, 0x70, 0x36, 0x24, 0x84, 0xb2, 0x30, 0xc4,
+  0xd0, 0x10, 0xcf, 0x86, 0x00, 0x9a, 0x20, 0x7c, 0x1f, 0xa5, 0xa9, 0xb7,
+  0x3a, 0xb9, 0xb1, 0x32, 0xa9, 0xb2, 0xb3, 0xb4, 0x37, 0x37, 0xa1, 0x3a,
+  0x33, 0xb3, 0x32, 0xb9, 0x09, 0x02, 0xd1, 0x4c, 0x10, 0x08, 0x67, 0x03,
+  0x42, 0x48, 0x13, 0x45, 0x0c, 0x15, 0xb0, 0x21, 0xb0, 0x26, 0x08, 0x61,
+  0x00, 0x06, 0x6c, 0xa6, 0xde, 0xea, 0xe4, 0xc6, 0xca, 0xa6, 0xc2, 0xda,
+  0xe0, 0xd8, 0xca, 0xe4, 0x36, 0x20, 0x04, 0x96, 0x31, 0xc4, 0x40, 0x00,
+  0x1b, 0x02, 0x6d, 0x03, 0x11, 0x01, 0xd7, 0x36, 0x41, 0xf0, 0x3c, 0x26,
+  0x55, 0x56, 0x4c, 0x65, 0x66, 0x74, 0x54, 0x6f, 0x70, 0x13, 0x04, 0xe2,
+  0x99, 0x20, 0x54, 0xdc, 0x06, 0x04, 0xf1, 0x28, 0xe2, 0x73, 0x1c, 0x30,
+  0x20, 0x53, 0x65, 0x45, 0x94, 0xd6, 0x56, 0xe6, 0x36, 0x97, 0xf6, 0xe6,
+  0x36, 0x37, 0x41, 0x20, 0xa0, 0x0d, 0x08, 0x22, 0x06, 0xd4, 0x18, 0x7c,
+  0x8e, 0x03, 0x06, 0x44, 0x9a, 0xd2, 0xe0, 0x98, 0xca, 0xec, 0xca, 0xd8,
+  0x26, 0x08, 0x44, 0x34, 0x41, 0x20, 0xa4, 0x0d, 0x08, 0x52, 0x06, 0x94,
+  0x19, 0x7c, 0x67, 0xe0, 0x80, 0x01, 0x19, 0xa6, 0xb0, 0xbc, 0x32, 0xb9,
+  0x27, 0x39, 0xa2, 0x32, 0x38, 0x3a, 0xb4, 0x09, 0x02, 0x31, 0x6d, 0x40,
+  0x90, 0x34, 0xa0, 0xd4, 0xe0, 0x73, 0x1c, 0x30, 0xd8, 0x50, 0x54, 0x61,
+  0x40, 0x06, 0x68, 0xb0, 0x06, 0x1b, 0x06, 0xa2, 0x63, 0x83, 0x09, 0x82,
+  0x00, 0x6c, 0x00, 0x36, 0x0c, 0xc4, 0x1b, 0xbc, 0xc1, 0x86, 0x00, 0x0e,
+  0x36, 0x0c, 0x83, 0x1b, 0xc4, 0xc1, 0x04, 0x41, 0x0c, 0xc2, 0x60, 0x43,
+  0x30, 0x07, 0x54, 0x84, 0xd8, 0xd2, 0xe8, 0x8c, 0xe4, 0xde, 0xda, 0x66,
+  0x88, 0x88, 0x50, 0x15, 0x61, 0x0d, 0x3d, 0x3d, 0x49, 0x11, 0x4d, 0x10,
+  0x0a, 0x6b, 0x82, 0x50, 0x5c, 0x1b, 0x02, 0x62, 0x82, 0x50, 0x60, 0x1b,
+  0x04, 0x8a, 0xda, 0xb0, 0x10, 0x76, 0x70, 0x07, 0x78, 0x90, 0x07, 0x7a,
+  0x30, 0xe8, 0x01, 0x81, 0x07, 0x7b, 0xc0, 0x65, 0xca, 0xea, 0x0b, 0xea,
+  0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x6d, 0x82, 0x50, 0x64, 0x13, 0x84,
+  0x42, 0xdb, 0xb0, 0x0c, 0x7d, 0x70, 0x07, 0x7e, 0x90, 0x07, 0x7f, 0x30,
+  0xfc, 0xc1, 0x80, 0x07, 0xc0, 0x06, 0x81, 0x0f, 0x40, 0x81, 0xc9, 0x94,
+  0xd5, 0x17, 0x55, 0x98, 0xdc, 0x59, 0x19, 0xdd, 0x04, 0xa1, 0xd8, 0x26,
+  0x08, 0x04, 0xb5, 0x41, 0xa0, 0x48, 0x61, 0xc3, 0x42, 0x88, 0xc2, 0x1d,
+  0x8c, 0x42, 0x1e, 0xe0, 0xc1, 0xf0, 0x07, 0x04, 0x1e, 0x94, 0xc2, 0x86,
+  0xc0, 0x14, 0x36, 0x0c, 0xa1, 0x70, 0x0a, 0xc0, 0x86, 0xc2, 0x0d, 0xea,
+  0x00, 0x15, 0x38, 0x80, 0x86, 0x19, 0xdb, 0x5b, 0x18, 0xdd, 0x1c, 0x8b,
+  0x34, 0xb7, 0x39, 0xba, 0xb9, 0x09, 0x02, 0x51, 0xd1, 0x98, 0x4b, 0x3b,
+  0xfb, 0x62, 0x23, 0xa3, 0x31, 0x97, 0x76, 0xf6, 0x35, 0x47, 0x47, 0x84,
+  0xae, 0x0c, 0xef, 0xcb, 0xed, 0x4d, 0xae, 0x6d, 0x83, 0xa2, 0x0a, 0x67,
+  0xb0, 0x0a, 0xac, 0xd0, 0x0a, 0x8c, 0x2b, 0x34, 0xaf, 0x30, 0x54, 0x61,
+  0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3, 0x9b, 0x12, 0x04,
+  0x55, 0xc8, 0xf0, 0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2, 0xde, 0xdc, 0xa6,
+  0x04, 0x44, 0x13, 0x32, 0x3c, 0x17, 0xbb, 0x30, 0x36, 0xbb, 0x32, 0xb9,
+  0x29, 0x41, 0x51, 0x87, 0x0c, 0xcf, 0x65, 0x0e, 0x2d, 0x8c, 0xac, 0x4c,
+  0xae, 0xe9, 0x8d, 0xac, 0x8c, 0x6d, 0x4a, 0x80, 0x94, 0x21, 0xc3, 0x73,
+  0x91, 0x2b, 0x9b, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0x9b, 0x9b, 0x12, 0x6c,
+  0x95, 0xc8, 0xf0, 0x5c, 0xe8, 0xf2, 0xe0, 0xca, 0x82, 0xdc, 0xdc, 0xde,
+  0xe8, 0xc2, 0xe8, 0xd2, 0xde, 0xdc, 0xe6, 0xa6, 0x08, 0x6c, 0x10, 0x07,
+  0x75, 0xc8, 0xf0, 0x5c, 0xec, 0xd2, 0xca, 0xee, 0x92, 0xc8, 0xa6, 0xe8,
+  0xc2, 0xe8, 0xca, 0xa6, 0x04, 0x73, 0x50, 0x87, 0x0c, 0xcf, 0xa5, 0xcc,
+  0x8d, 0x4e, 0x2e, 0x0f, 0xea, 0x2d, 0xcd, 0x8d, 0x6e, 0x6e, 0x4a, 0x80,
+  0x0a, 0x5d, 0xc8, 0xf0, 0x5c, 0xc6, 0xde, 0xea, 0xdc, 0xe8, 0xca, 0xe4,
+  0xe6, 0xa6, 0x04, 0xaf, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76,
+  0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e,
+  0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f,
+  0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x1f,
+  0x00, 0x00, 0x00, 0x06, 0xa0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0xdc,
+  0x9d, 0x11, 0x6c, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x04, 0x54, 0x51, 0x10,
+  0x51, 0xe9, 0x00, 0x43, 0x49, 0x18, 0x80, 0x80, 0xf9, 0xc5, 0x6d, 0x5b,
+  0xc1, 0x36, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x40, 0x15, 0x05, 0x11, 0x95,
+  0x0e, 0x30, 0x94, 0x84, 0x01, 0x08, 0x98, 0x8f, 0xdc, 0xb6, 0x19, 0x48,
+  0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x44, 0x04, 0x30, 0x11, 0x21, 0xd0, 0x0c,
+  0x0b, 0x61, 0x01, 0xd3, 0x70, 0xf9, 0xce, 0xe3, 0x2f, 0x0e, 0x30, 0x88,
+  0xcd, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x36, 0x50, 0x0d, 0x97, 0xef, 0x3c,
+  0xbe, 0x04, 0x30, 0xcf, 0x42, 0x94, 0x44, 0x45, 0x2c, 0x7e, 0x71, 0xdb,
+  0x26, 0x50, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x34, 0x39, 0x11, 0x81, 0x52,
+  0xd3, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+  0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49,
+  0xc2, 0xf4, 0xbe, 0x13, 0x34, 0x00, 0xe0, 0x7c, 0x3f, 0x23, 0xe9, 0x79,
+  0x8b, 0x27, 0xf4, 0x44, 0x58, 0x49, 0x4c, 0xbc, 0x07, 0x00, 0x00, 0x60,
+  0x00, 0x00, 0x00, 0xef, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00,
+  0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xa4, 0x07, 0x00, 0x00, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43,
+  0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11,
+  0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04,
+  0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b,
+  0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84,
+  0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04,
+  0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8c, 0x8c, 0x0b,
+  0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40, 0x09, 0x00, 0x0a, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x40, 0x10, 0x44,
+  0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, 0x20, 0xe4, 0xa6, 0xe1,
+  0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, 0x95, 0x98, 0xfc, 0xe2,
+  0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, 0xcf, 0x70, 0xf9, 0x13,
+  0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, 0x28, 0x58, 0x0a, 0xa3,
+  0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, 0x40, 0xcd, 0x51, 0xc3,
+  0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, 0xc5, 0x4a, 0x4c, 0x7e,
+  0x71, 0xdb, 0x88, 0x18, 0x86, 0x61, 0x28, 0xc4, 0x43, 0x30, 0x04, 0x41,
+  0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, 0x15, 0x2b,
+  0x31, 0xf9, 0xc8, 0x6d, 0x23, 0x82, 0x20, 0x08, 0xa2, 0x10, 0x12, 0xc1,
+  0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, 0x82, 0x20, 0x2a, 0xb2,
+  0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0xa6, 0x36, 0x18, 0x07, 0x76, 0x08,
+  0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, 0xc0, 0x07, 0x7a, 0xa8,
+  0x07, 0x79, 0x28, 0x87, 0x39, 0x20, 0x05, 0x3e, 0xb0, 0x87, 0x72, 0x18,
+  0x07, 0x7a, 0x78, 0x07, 0x79, 0xe0, 0x03, 0x73, 0x60, 0x87, 0x77, 0x08,
+  0x07, 0x7a, 0x60, 0x03, 0x30, 0xa0, 0x03, 0x3f, 0x00, 0x03, 0x3f, 0xd0,
+  0x03, 0x3d, 0x68, 0x87, 0x74, 0x80, 0x87, 0x79, 0xf8, 0x05, 0x7a, 0xc8,
+  0x07, 0x78, 0x28, 0x07, 0x14, 0x10, 0x33, 0x89, 0xc1, 0x38, 0xb0, 0x43,
+  0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, 0x94, 0x03, 0x3e, 0xd0, 0x43,
+  0x3d, 0xc8, 0x43, 0x39, 0xcc, 0x01, 0x29, 0xf0, 0x81, 0x3d, 0x94, 0xc3,
+  0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43,
+  0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x01,
+  0x12, 0x32, 0x8d, 0xb6, 0x61, 0x04, 0x61, 0x38, 0x89, 0x75, 0xa8, 0x48,
+  0x20, 0x56, 0xc2, 0x40, 0x9c, 0x66, 0xa3, 0x8a, 0x82, 0x88, 0x10, 0xd1,
+  0x75, 0xc4, 0x40, 0xde, 0x4d, 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xb3, 0x00,
+  0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, 0x80, 0x20, 0x30, 0x15,
+  0x08, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36,
+  0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e,
+  0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06,
+  0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c,
+  0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+  0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x32,
+  0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6,
+  0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x10, 0x4a,
+  0xa2, 0x0c, 0x0a, 0xa6, 0x3c, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, 0x28,
+  0x83, 0x42, 0x28, 0x10, 0xe2, 0x66, 0x00, 0xe8, 0x9b, 0x01, 0xa0, 0x70,
+  0x06, 0x80, 0xc4, 0xb1, 0x14, 0x84, 0x78, 0x1e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x67, 0x00, 0x00, 0x00, 0x1a,
+  0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73,
+  0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71,
+  0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a,
+  0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b,
+  0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xe2, 0x98, 0x20, 0x10, 0xc8,
+  0x06, 0x61, 0x20, 0x26, 0x08, 0x44, 0xb2, 0x41, 0x18, 0x0c, 0x0a, 0x70,
+  0x73, 0x1b, 0x06, 0xc4, 0x20, 0x26, 0x08, 0x9c, 0x45, 0x60, 0x82, 0x40,
+  0x28, 0x13, 0x04, 0x62, 0x99, 0x20, 0x10, 0xcc, 0x06, 0x81, 0x70, 0x36,
+  0x24, 0x84, 0xb2, 0x30, 0xc4, 0xd0, 0x10, 0xcf, 0x86, 0x00, 0x9a, 0x20,
+  0x7c, 0xd7, 0x04, 0x81, 0x68, 0x26, 0x08, 0x84, 0xb3, 0x01, 0x21, 0xa4,
+  0x65, 0x22, 0x06, 0x0a, 0xd8, 0x10, 0x54, 0x13, 0x84, 0x30, 0xc0, 0x36,
+  0x20, 0xc4, 0xb5, 0x30, 0xc4, 0x40, 0x00, 0x1b, 0x02, 0x6c, 0x03, 0x11,
+  0x01, 0x56, 0x36, 0x41, 0x10, 0x83, 0x6c, 0x43, 0xb0, 0x4d, 0x10, 0x04,
+  0x80, 0x8a, 0x10, 0x5b, 0x1a, 0x9d, 0x91, 0xdc, 0x5b, 0xdb, 0x0c, 0x11,
+  0x11, 0xaa, 0x22, 0xac, 0xa1, 0xa7, 0x27, 0x29, 0xa2, 0x09, 0x42, 0x01,
+  0x4d, 0x10, 0x8a, 0x68, 0x43, 0x40, 0x4c, 0x10, 0x0a, 0x69, 0x83, 0x30,
+  0x4d, 0x1b, 0x16, 0xe2, 0x03, 0x83, 0x30, 0x10, 0x83, 0x31, 0x18, 0xc6,
+  0x80, 0x08, 0x03, 0x32, 0xe0, 0x32, 0x65, 0xf5, 0x05, 0xf5, 0x36, 0x97,
+  0x46, 0x97, 0xf6, 0xe6, 0x36, 0x41, 0x28, 0xa6, 0x09, 0x42, 0x41, 0x6d,
+  0x58, 0x06, 0x33, 0x00, 0x83, 0x33, 0x10, 0x03, 0x34, 0x18, 0xd0, 0x60,
+  0x08, 0x03, 0x60, 0x83, 0x50, 0x06, 0x69, 0xc0, 0x64, 0xca, 0xea, 0x8b,
+  0x2a, 0x4c, 0xee, 0xac, 0x8c, 0x6e, 0x82, 0x50, 0x54, 0x13, 0x04, 0xe2,
+  0xd9, 0x20, 0x4c, 0x6d, 0xb0, 0x61, 0x21, 0xd6, 0x00, 0x0c, 0xd8, 0x40,
+  0x0c, 0xc2, 0x60, 0x40, 0x03, 0x22, 0x0c, 0xdc, 0x60, 0x43, 0xf0, 0x06,
+  0x1b, 0x06, 0x35, 0x80, 0x03, 0x60, 0x43, 0xd1, 0x79, 0x71, 0xa0, 0x01,
+  0x55, 0xd8, 0xd8, 0xec, 0xda, 0x5c, 0xd2, 0xc8, 0xca, 0xdc, 0xe8, 0xa6,
+  0x04, 0x41, 0x15, 0x32, 0x3c, 0x17, 0xbb, 0x32, 0xb9, 0xb9, 0xb4, 0x37,
+  0xb7, 0x29, 0x01, 0xd1, 0x84, 0x0c, 0xcf, 0xc5, 0x2e, 0x8c, 0xcd, 0xae,
+  0x4c, 0x6e, 0x4a, 0x60, 0xd4, 0x21, 0xc3, 0x73, 0x99, 0x43, 0x0b, 0x23,
+  0x2b, 0x93, 0x6b, 0x7a, 0x23, 0x2b, 0x63, 0x9b, 0x12, 0x20, 0x65, 0xc8,
+  0xf0, 0x5c, 0xe4, 0xca, 0xe6, 0xde, 0xea, 0xe4, 0xc6, 0xca, 0xe6, 0xa6,
+  0x04, 0x59, 0x1d, 0x32, 0x3c, 0x17, 0xbb, 0xb4, 0xb2, 0xbb, 0x24, 0xb2,
+  0x29, 0xba, 0x30, 0xba, 0xb2, 0x29, 0xc1, 0x56, 0x87, 0x0c, 0xcf, 0xa5,
+  0xcc, 0x8d, 0x4e, 0x2e, 0x0f, 0xea, 0x2d, 0xcd, 0x8d, 0x6e, 0x6e, 0x4a,
+  0x10, 0x07, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33,
+  0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98,
+  0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33,
+  0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05,
+  0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43,
+  0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08,
+  0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78,
+  0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1,
+  0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33,
+  0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e,
+  0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03,
+  0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60,
+  0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80,
+  0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8,
+  0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18,
+  0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee,
+  0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c,
+  0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43,
+  0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3,
+  0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83,
+  0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21,
+  0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1,
+  0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6,
+  0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4,
+  0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x06,
+  0xa0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0xdc, 0x9d, 0x11, 0x6c, 0xc3,
+  0xe5, 0x3b, 0x8f, 0x2f, 0x04, 0x54, 0x51, 0x10, 0x51, 0xe9, 0x00, 0x43,
+  0x49, 0x18, 0x80, 0x80, 0xf9, 0xc5, 0x6d, 0x5b, 0xc1, 0x36, 0x5c, 0xbe,
+  0xf3, 0xf8, 0x42, 0x40, 0x15, 0x05, 0x11, 0x95, 0x0e, 0x30, 0x94, 0x84,
+  0x01, 0x08, 0x98, 0x8f, 0xdc, 0xb6, 0x19, 0x48, 0xc3, 0xe5, 0x3b, 0x8f,
+  0x2f, 0x44, 0x04, 0x30, 0x11, 0x21, 0xd0, 0x0c, 0x0b, 0x61, 0x01, 0xd3,
+  0x70, 0xf9, 0xce, 0xe3, 0x2f, 0x0e, 0x30, 0x88, 0xcd, 0x43, 0x4d, 0x7e,
+  0x71, 0xdb, 0x36, 0x50, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x04, 0x30, 0xcf,
+  0x42, 0x94, 0x44, 0x45, 0x2c, 0x7e, 0x71, 0xdb, 0x26, 0x50, 0x0d, 0x97,
+  0xef, 0x3c, 0xbe, 0x34, 0x39, 0x11, 0x81, 0x52, 0xd3, 0x43, 0x4d, 0x7e,
+  0x71, 0xdb, 0x00, 0x61, 0x20, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x13,
+  0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x54,
+  0x8d, 0x00, 0x10, 0x51, 0x0a, 0x25, 0x57, 0x76, 0x33, 0x00, 0xc5, 0x47,
+  0x45, 0x09, 0xd0, 0x30, 0x03, 0x00, 0x00, 0x23, 0x06, 0x09, 0x00, 0x82,
+  0x60, 0x60, 0x71, 0x46, 0xa4, 0x69, 0xc8, 0x88, 0x41, 0x02, 0x80, 0x20,
+  0x18, 0x58, 0xdd, 0x01, 0x6d, 0x5b, 0x32, 0x62, 0x90, 0x00, 0x20, 0x08,
+  0x06, 0x96, 0x87, 0x48, 0x1c, 0xa7, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82,
+  0x81, 0x41, 0x06, 0x5a, 0xd7, 0x51, 0xc7, 0x88, 0x41, 0x02, 0x80, 0x20,
+  0x18, 0x18, 0x65, 0xb0, 0x79, 0x9e, 0x81, 0x8c, 0x18, 0x1c, 0x00, 0x08,
+  0x82, 0x01, 0x34, 0x06, 0xca, 0xf0, 0x8d, 0x26, 0x04, 0xc0, 0x68, 0x82,
+  0x10, 0x8c, 0x26, 0x0c, 0xc2, 0x68, 0x02, 0x31, 0x98, 0x70, 0xc8, 0xc7,
+  0x84, 0x43, 0x3e, 0x26, 0x18, 0xf0, 0x31, 0xc1, 0x80, 0xcf, 0x88, 0xc1,
+  0x01, 0x80, 0x20, 0x18, 0x40, 0x6c, 0x30, 0x31, 0x69, 0x30, 0x9a, 0x10,
+  0x04, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, 0x30, 0xb5, 0x41, 0xe5, 0xac,
+  0xc1, 0x68, 0x42, 0x00, 0x5c, 0x30, 0xd4, 0x88, 0xc1, 0x03, 0x80, 0x20,
+  0x18, 0x34, 0x72, 0x60, 0x4d, 0xd2, 0x61, 0x10, 0x54, 0x1b, 0xb4, 0x41,
+  0x1b, 0x04, 0xa3, 0x09, 0x01, 0x30, 0x9a, 0x20, 0x04, 0xa3, 0x09, 0x83,
+  0x30, 0x9a, 0x40, 0x0c, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x80, 0xe0,
+  0xc1, 0x27, 0x07, 0x72, 0x90, 0x06, 0xc4, 0x88, 0x41, 0x02, 0x80, 0x20,
+  0x18, 0x20, 0x78, 0xf0, 0xc9, 0x81, 0x1c, 0x68, 0xc3, 0x88, 0x41, 0x02,
+  0x80, 0x20, 0x18, 0x20, 0x78, 0xf0, 0xc9, 0x81, 0x1c, 0xa0, 0x81, 0x30,
+  0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x08, 0x1e, 0x7c, 0x72, 0x20, 0x07,
+  0x67, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xy          0     NONE   float   xy  
+; SV_Position              0   xyzw        1      POS   float       
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_Target                0   xyzw        0   TARGET   float   xyzw
+;
+; shader hash: 3f9b5204e5a68b236febe48b54bfc9f3
+;
+; Pipeline Runtime Information: 
+;
+; Pixel Shader
+; DepthOutput=0
+; SampleFrequency=0
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; SV_Position              0          noperspective       
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_Target                0                              
+;
+; Buffer Definitions:
+;
+; cbuffer SourceRegionBuffer
+; {
+;
+;   struct SourceRegionBuffer
+;   {
+;
+;       float2 UVLeftTop;                             ; Offset:    0
+;       float2 UVDimensions;                          ; Offset:    8
+;       uint MipLevel;                                ; Offset:   16
+;       float LayerOrDepth;                           ; Offset:   20
+;   
+;   } SourceRegionBuffer;                             ; Offset:    0 Size:    24
+;
+; }
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; SourceRegionBuffer                cbuffer      NA          NA     CB0     cb0,space3     1
+; SourceSampler                     sampler      NA          NA      S0      s0,space2     1
+; SourceTextureCube                 texture     f32        cube      T0      t0,space2     1
+;
+;
+; ViewId state:
+;
+; Number of inputs: 8, outputs: 4
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 0, 1 }
+;   output 1 depends on inputs: { 0, 1 }
+;   output 2 depends on inputs: { 0, 1 }
+;   output 3 depends on inputs: { 0, 1 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+%dx.types.Handle = type { i8* }
+%dx.types.CBufRet.f32 = type { float, float, float, float }
+%dx.types.CBufRet.i32 = type { i32, i32, i32, i32 }
+%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
+%"class.TextureCube<vector<float, 4> >" = type { <4 x float> }
+%SourceRegionBuffer = type { <2 x float>, <2 x float>, i32, float }
+%struct.SamplerState = type { i32 }
+
+define void @BlitFromCube() {
+  %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %6 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 0)  ; CBufferLoadLegacy(handle,regIndex)
+  %7 = extractvalue %dx.types.CBufRet.f32 %6, 0
+  %8 = extractvalue %dx.types.CBufRet.f32 %6, 1
+  %9 = extractvalue %dx.types.CBufRet.f32 %6, 2
+  %10 = extractvalue %dx.types.CBufRet.f32 %6, 3
+  %11 = fmul fast float %9, %4
+  %12 = fmul fast float %10, %5
+  %13 = fadd fast float %11, %7
+  %14 = fadd fast float %12, %8
+  %15 = fmul fast float %13, 2.000000e+00
+  %16 = fadd fast float %15, -1.000000e+00
+  %17 = fmul fast float %14, 2.000000e+00
+  %18 = fadd fast float %17, -1.000000e+00
+  %19 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %20 = extractvalue %dx.types.CBufRet.f32 %19, 1
+  %21 = fptoui float %20 to i32
+  switch i32 %21, label %35 [
+    i32 0, label %22
+    i32 1, label %25
+    i32 2, label %27
+    i32 3, label %29
+    i32 4, label %30
+    i32 5, label %32
+  ]
+
+; <label>:22                                      ; preds = %0
+  %23 = fsub fast float -0.000000e+00, %18
+  %24 = fsub fast float -0.000000e+00, %16
+  br label %35
+
+; <label>:25                                      ; preds = %0
+  %26 = fsub fast float -0.000000e+00, %18
+  br label %35
+
+; <label>:27                                      ; preds = %0
+  %28 = fsub fast float -0.000000e+00, %18
+  br label %35
+
+; <label>:29                                      ; preds = %0
+  br label %35
+
+; <label>:30                                      ; preds = %0
+  %31 = fsub fast float -0.000000e+00, %18
+  br label %35
+
+; <label>:32                                      ; preds = %0
+  %33 = fsub fast float -0.000000e+00, %16
+  %34 = fsub fast float -0.000000e+00, %18
+  br label %35
+
+; <label>:35                                      ; preds = %32, %30, %29, %27, %25, %22, %0
+  %36 = phi float [ %33, %32 ], [ %16, %30 ], [ %16, %29 ], [ %16, %27 ], [ -1.000000e+00, %25 ], [ 1.000000e+00, %22 ], [ 0.000000e+00, %0 ]
+  %37 = phi float [ %34, %32 ], [ %31, %30 ], [ 1.000000e+00, %29 ], [ -1.000000e+00, %27 ], [ %26, %25 ], [ %23, %22 ], [ 0.000000e+00, %0 ]
+  %38 = phi float [ -1.000000e+00, %32 ], [ 1.000000e+00, %30 ], [ %18, %29 ], [ %28, %27 ], [ %16, %25 ], [ %24, %22 ], [ 0.000000e+00, %0 ]
+  %39 = call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %3, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %40 = extractvalue %dx.types.CBufRet.i32 %39, 0
+  %41 = uitofp i32 %40 to float
+  %42 = call %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32 62, %dx.types.Handle %1, %dx.types.Handle %2, float %36, float %37, float %38, float undef, i32 undef, i32 undef, i32 undef, float %41)  ; SampleLevel(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,LOD)
+  %43 = extractvalue %dx.types.ResRet.f32 %42, 0
+  %44 = extractvalue %dx.types.ResRet.f32 %42, 1
+  %45 = extractvalue %dx.types.ResRet.f32 %42, 2
+  %46 = extractvalue %dx.types.ResRet.f32 %42, 3
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %43)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %44)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %45)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %46)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+; Function Attrs: nounwind readonly
+declare %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.resources = !{!4}
+!dx.viewIdState = !{!12}
+!dx.entryPoints = !{!13}
+
+!0 = !{!"clang version 3.7 (tags/RELEASE_370/final)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 6}
+!3 = !{!"ps", i32 6, i32 0}
+!4 = !{!5, null, !8, !10}
+!5 = !{!6}
+!6 = !{i32 0, %"class.TextureCube<vector<float, 4> >"* undef, !"", i32 2, i32 0, i32 1, i32 5, i32 0, !7}
+!7 = !{i32 0, i32 9}
+!8 = !{!9}
+!9 = !{i32 0, %SourceRegionBuffer* undef, !"", i32 3, i32 0, i32 1, i32 24, null}
+!10 = !{!11}
+!11 = !{i32 0, %struct.SamplerState* undef, !"", i32 2, i32 0, i32 1, i32 0, null}
+!12 = !{[10 x i32] [i32 8, i32 4, i32 15, i32 15, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0]}
+!13 = !{void ()* @BlitFromCube, !"BlitFromCube", !14, !4, null}
+!14 = !{!15, !20, null}
+!15 = !{!16, !19}
+!16 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !17, i8 2, i32 1, i8 2, i32 0, i8 0, !18}
+!17 = !{i32 0}
+!18 = !{i32 3, i32 3}
+!19 = !{i32 1, !"SV_Position", i8 9, i8 3, !17, i8 4, i32 1, i8 4, i32 1, i8 0, null}
+!20 = !{!21}
+!21 = !{i32 0, !"SV_Target", i8 9, i8 16, !17, i8 0, i32 1, i8 4, i32 0, i8 0, !22}
+!22 = !{i32 3, i32 15}
+
+#endif
+
+const unsigned char g_BlitFromCube[] = {
+  0x44, 0x58, 0x42, 0x43, 0xa5, 0x03, 0x31, 0xd3, 0xcd, 0x90, 0xc6, 0x14,
+  0xa9, 0xeb, 0xd5, 0x90, 0x83, 0xe5, 0x94, 0xf9, 0x01, 0x00, 0x00, 0x00,
+  0x03, 0x12, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00,
+  0xe3, 0x01, 0x00, 0x00, 0xa7, 0x09, 0x00, 0x00, 0xc3, 0x09, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x5d, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5f,
+  0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x4f, 0x53, 0x47,
+  0x31, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f,
+  0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x50, 0x53, 0x56, 0x30, 0xf0,
+  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18,
+  0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43,
+  0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x44, 0x03, 0x03,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x44, 0x10, 0x03, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xbc, 0x07, 0x00, 0x00, 0x60,
+  0x00, 0x00, 0x00, 0xef, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00,
+  0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xa4, 0x07, 0x00, 0x00, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xe6, 0x01, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43,
+  0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11,
+  0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04,
+  0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b,
+  0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84,
+  0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04,
+  0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8c, 0x8c, 0x0b,
+  0x84, 0xc4, 0x4c, 0x10, 0x88, 0xc1, 0x08, 0x40, 0x09, 0x00, 0x0a, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x40, 0x10, 0x44,
+  0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, 0x20, 0xe4, 0xa6, 0xe1,
+  0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, 0x95, 0x98, 0xfc, 0xe2,
+  0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, 0xcf, 0x70, 0xf9, 0x13,
+  0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, 0x28, 0x58, 0x0a, 0xa3,
+  0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, 0x40, 0xcd, 0x51, 0xc3,
+  0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, 0xc5, 0x4a, 0x4c, 0x7e,
+  0x71, 0xdb, 0x88, 0x18, 0x86, 0x61, 0x28, 0xc4, 0x43, 0x30, 0x04, 0x41,
+  0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, 0x15, 0x2b,
+  0x31, 0xf9, 0xc8, 0x6d, 0x23, 0x82, 0x20, 0x08, 0xa2, 0x10, 0x12, 0xc1,
+  0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, 0x82, 0x20, 0x2a, 0xb2,
+  0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0x26, 0x32, 0x18, 0x07, 0x76, 0x08,
+  0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, 0xc0, 0x07, 0x7a, 0xa8,
+  0x07, 0x79, 0x28, 0x87, 0x51, 0xa8, 0x07, 0x71, 0x28, 0x07, 0x3e, 0xb0,
+  0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0xe0, 0x03, 0x73, 0x60,
+  0x87, 0x77, 0x08, 0x07, 0x7a, 0x60, 0x03, 0x30, 0xa0, 0x03, 0x3f, 0x00,
+  0x03, 0x3f, 0x40, 0x41, 0x46, 0xda, 0x30, 0x82, 0x30, 0x9c, 0xc4, 0x3a,
+  0x54, 0x24, 0x10, 0x2b, 0x61, 0x20, 0x4e, 0xb3, 0x51, 0x45, 0x41, 0x44,
+  0x88, 0xe0, 0x38, 0x62, 0xa0, 0xee, 0x26, 0x69, 0x8a, 0x28, 0x61, 0xf2,
+  0x59, 0x80, 0x79, 0x16, 0x22, 0x62, 0x27, 0x60, 0x22, 0x50, 0x40, 0xd0,
+  0x97, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87,
+  0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87,
+  0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00,
+  0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0,
+  0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60,
+  0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60,
+  0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0,
+  0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x14,
+  0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x18, 0x19, 0x11, 0x4c, 0x90, 0x8c,
+  0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18,
+  0x8a, 0xa0, 0x14, 0x4a, 0xa2, 0x0c, 0x0a, 0xa6, 0x1c, 0x0a, 0xa2, 0x40,
+  0x0a, 0xa5, 0x3c, 0x4a, 0xa4, 0xcc, 0x0a, 0x81, 0x8a, 0x92, 0x18, 0x01,
+  0x28, 0x82, 0x32, 0x28, 0x84, 0x02, 0xa1, 0xaa, 0x06, 0x68, 0x9b, 0x01,
+  0xa0, 0x6e, 0x06, 0x80, 0xbc, 0x19, 0x00, 0x02, 0x67, 0x00, 0x28, 0x1c,
+  0x4b, 0x41, 0x88, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79,
+  0x18, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46,
+  0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b,
+  0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1,
+  0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa,
+  0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10,
+  0x04, 0x13, 0x04, 0xe2, 0x98, 0x20, 0x10, 0xc8, 0x06, 0x61, 0x20, 0x36,
+  0x08, 0x04, 0x41, 0x01, 0x6e, 0x6e, 0x82, 0x40, 0x24, 0x1b, 0x86, 0x03,
+  0x21, 0x26, 0x08, 0x9b, 0xc7, 0x68, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x8c,
+  0xaa, 0x0c, 0x8f, 0xae, 0x4e, 0xae, 0x6c, 0xa8, 0x4e, 0xac, 0x6c, 0x82,
+  0x40, 0x28, 0x13, 0x04, 0x62, 0x99, 0x20, 0x10, 0xcc, 0x06, 0x81, 0x70,
+  0x36, 0x24, 0x84, 0xb2, 0x30, 0xc4, 0xd0, 0x10, 0xcf, 0x86, 0x00, 0x9a,
+  0x20, 0x78, 0x60, 0x40, 0x69, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x4c, 0xaa,
+  0xec, 0x2c, 0xed, 0xcd, 0x4d, 0xa8, 0xce, 0xcc, 0xac, 0x4c, 0x6e, 0x82,
+  0x40, 0x34, 0x13, 0x04, 0xc2, 0xd9, 0x80, 0x10, 0xd2, 0x44, 0x11, 0x43,
+  0x05, 0x6c, 0x08, 0xac, 0x09, 0x02, 0x18, 0x84, 0x01, 0x9b, 0xa9, 0xb7,
+  0x3a, 0xb9, 0xb1, 0xb2, 0xa9, 0xb0, 0x36, 0x38, 0xb6, 0x32, 0xb9, 0x0d,
+  0x08, 0x81, 0x65, 0x0c, 0x31, 0x10, 0xc0, 0x86, 0x40, 0xdb, 0x40, 0x44,
+  0xc0, 0xb5, 0x4d, 0x10, 0xba, 0x8f, 0x49, 0x95, 0x15, 0x53, 0x99, 0x19,
+  0x1d, 0xd5, 0x1b, 0xdc, 0x04, 0x81, 0x78, 0x26, 0x08, 0x55, 0xb7, 0x01,
+  0x41, 0x3c, 0x8a, 0xf8, 0x1c, 0x07, 0x0c, 0xc8, 0x54, 0x59, 0x11, 0xa5,
+  0xb5, 0x95, 0xb9, 0xcd, 0xa5, 0xbd, 0xb9, 0xcd, 0x4d, 0x10, 0x08, 0x68,
+  0x03, 0x82, 0x88, 0x01, 0x35, 0x06, 0x9f, 0xe3, 0x80, 0x01, 0x91, 0xa6,
+  0x34, 0x38, 0xa6, 0x32, 0xbb, 0x32, 0xb6, 0x09, 0x02, 0x11, 0x6d, 0x40,
+  0x90, 0x32, 0xa0, 0xcc, 0xe0, 0x6b, 0x1c, 0x30, 0x20, 0xc3, 0x14, 0x96,
+  0x57, 0x26, 0xf7, 0x24, 0x47, 0x54, 0x06, 0x47, 0x87, 0x36, 0x41, 0x20,
+  0xa4, 0x0d, 0x08, 0x82, 0x06, 0x54, 0x1a, 0x7c, 0x8e, 0x03, 0x06, 0x1b,
+  0x8a, 0x2a, 0x0c, 0xc8, 0xe0, 0x0c, 0xd4, 0x60, 0xc3, 0x40, 0x74, 0x6b,
+  0x30, 0x41, 0x10, 0x80, 0x0d, 0xc0, 0x86, 0x81, 0x70, 0x03, 0x37, 0xd8,
+  0x10, 0xbc, 0xc1, 0x86, 0x61, 0x68, 0x03, 0x38, 0x98, 0x20, 0x84, 0x81,
+  0x18, 0x6c, 0x08, 0xe4, 0x80, 0x8c, 0x10, 0x5b, 0x1a, 0x9d, 0x91, 0xdc,
+  0x5b, 0xdb, 0x50, 0x9d, 0x58, 0x19, 0x11, 0xaa, 0x22, 0xac, 0xa1, 0xa7,
+  0x27, 0x29, 0xa2, 0x09, 0x42, 0x71, 0x4d, 0x10, 0x0a, 0x6c, 0x43, 0x40,
+  0x4c, 0x10, 0x8a, 0x6c, 0x83, 0x40, 0x51, 0x1b, 0x16, 0xa2, 0x0e, 0xec,
+  0xe0, 0x0e, 0xf0, 0x20, 0x0f, 0x86, 0x3c, 0x20, 0xee, 0x40, 0x0f, 0xb8,
+  0x4c, 0x59, 0x7d, 0x41, 0xbd, 0xcd, 0xa5, 0xd1, 0xa5, 0xbd, 0xb9, 0x4d,
+  0x10, 0x0a, 0x6d, 0x82, 0x50, 0x6c, 0x1b, 0x96, 0x81, 0x0f, 0xec, 0xa0,
+  0x0f, 0xf0, 0xc0, 0x0f, 0x06, 0x3f, 0x18, 0xee, 0x00, 0xd8, 0x20, 0xec,
+  0xc1, 0x1f, 0x30, 0x99, 0xb2, 0xfa, 0xa2, 0x0a, 0x93, 0x3b, 0x2b, 0xa3,
+  0x9b, 0x20, 0x14, 0xdc, 0x04, 0x81, 0x98, 0x36, 0x08, 0xd4, 0x28, 0x6c,
+  0x58, 0x88, 0x50, 0xb0, 0x03, 0x51, 0xc0, 0x83, 0x3b, 0x18, 0xfc, 0x80,
+  0xb8, 0x03, 0x52, 0xd8, 0x10, 0x94, 0xc2, 0x86, 0x01, 0x14, 0x4c, 0x01,
+  0xd8, 0x50, 0xb4, 0x01, 0x1d, 0x9c, 0x02, 0x07, 0xd0, 0x30, 0x63, 0x7b,
+  0x0b, 0xa3, 0x9b, 0x9b, 0x20, 0x10, 0x14, 0x8b, 0x34, 0xb7, 0x39, 0xba,
+  0xb9, 0x09, 0x02, 0x51, 0xd1, 0x98, 0x4b, 0x3b, 0xfb, 0x62, 0x23, 0xa3,
+  0x31, 0x97, 0x76, 0xf6, 0x35, 0x47, 0x37, 0x41, 0x20, 0x2c, 0x22, 0x74,
+  0x65, 0x78, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x1b, 0x94, 0x54, 0x50, 0x85,
+  0x55, 0x60, 0x85, 0x56, 0x60, 0x5c, 0xe1, 0x15, 0x60, 0x61, 0xa8, 0xc2,
+  0xc6, 0x66, 0xd7, 0xe6, 0x92, 0x46, 0x56, 0xe6, 0x46, 0x37, 0x25, 0x08,
+  0xaa, 0x90, 0xe1, 0xb9, 0xd8, 0x95, 0xc9, 0xcd, 0xa5, 0xbd, 0xb9, 0x4d,
+  0x09, 0x88, 0x26, 0x64, 0x78, 0x2e, 0x76, 0x61, 0x6c, 0x76, 0x65, 0x72,
+  0x53, 0x82, 0xa2, 0x0e, 0x19, 0x9e, 0xcb, 0x1c, 0x5a, 0x18, 0x59, 0x99,
+  0x5c, 0xd3, 0x1b, 0x59, 0x19, 0xdb, 0x94, 0x00, 0x29, 0x43, 0x86, 0xe7,
+  0x22, 0x57, 0x36, 0xf7, 0x56, 0x27, 0x37, 0x56, 0x36, 0x37, 0x25, 0xd8,
+  0x2a, 0x91, 0xe1, 0xb9, 0xd0, 0xe5, 0xc1, 0x95, 0x05, 0xb9, 0xb9, 0xbd,
+  0xd1, 0x85, 0xd1, 0xa5, 0xbd, 0xb9, 0xcd, 0x4d, 0x11, 0xd6, 0x00, 0x0e,
+  0xea, 0x90, 0xe1, 0xb9, 0xd8, 0xa5, 0x95, 0xdd, 0x25, 0x91, 0x4d, 0xd1,
+  0x85, 0xd1, 0x95, 0x4d, 0x09, 0xe4, 0xa0, 0x0e, 0x19, 0x9e, 0x4b, 0x99,
+  0x1b, 0x9d, 0x5c, 0x1e, 0xd4, 0x5b, 0x9a, 0x1b, 0xdd, 0xdc, 0x94, 0xe0,
+  0x14, 0xba, 0x90, 0xe1, 0xb9, 0x8c, 0xbd, 0xd5, 0xb9, 0xd1, 0x95, 0xc9,
+  0xcd, 0x4d, 0x09, 0x60, 0x01, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x51,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76,
+  0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e,
+  0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f,
+  0xef, 0x50, 0x0f, 0xf4, 0x30, 0x83, 0x81, 0xc8, 0x01, 0x1f, 0xdc, 0x40,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xc2, 0x61, 0x1d, 0xdc, 0x40, 0x1c, 0xe4, 0x01,
+  0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06,
+  0xc0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0x70, 0x54, 0x40, 0x18, 0xc1,
+  0x36, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x40, 0x15, 0x05, 0x11, 0x95, 0x0e,
+  0x30, 0x94, 0x84, 0x01, 0x08, 0x98, 0x5f, 0xdc, 0xb6, 0x15, 0x6c, 0xc3,
+  0xe5, 0x3b, 0x8f, 0x2f, 0x04, 0x54, 0x51, 0x10, 0x51, 0xe9, 0x00, 0x43,
+  0x49, 0x18, 0x80, 0x80, 0xf9, 0xc8, 0x6d, 0x9b, 0x81, 0x34, 0x5c, 0xbe,
+  0xf3, 0xf8, 0x42, 0x44, 0x00, 0x13, 0x11, 0x02, 0xcd, 0xb0, 0x10, 0x16,
+  0x30, 0x0d, 0x97, 0xef, 0x3c, 0xfe, 0xe2, 0x00, 0x83, 0xd8, 0x3c, 0xd4,
+  0xe4, 0x17, 0xb7, 0x6d, 0x03, 0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x00,
+  0xf3, 0x2c, 0x44, 0x49, 0x54, 0xc4, 0xe2, 0x17, 0xb7, 0x6d, 0x02, 0xd5,
+  0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4,
+  0xe4, 0x17, 0xb7, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+  0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0x9b, 0x52, 0x04, 0xe5, 0xa6, 0x8b, 0x23, 0x6f, 0xeb, 0xe4, 0x8b, 0x54,
+  0xbf, 0xc9, 0xf3, 0x44, 0x58, 0x49, 0x4c, 0x38, 0x08, 0x00, 0x00, 0x60,
+  0x00, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00,
+  0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x05, 0x02, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43,
+  0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11,
+  0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04,
+  0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b,
+  0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84,
+  0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04,
+  0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8c, 0x8c, 0x0b,
+  0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40, 0x09, 0x00, 0x0a, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x40, 0x10, 0x44,
+  0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, 0x20, 0xe4, 0xa6, 0xe1,
+  0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, 0x95, 0x98, 0xfc, 0xe2,
+  0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, 0xcf, 0x70, 0xf9, 0x13,
+  0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, 0x28, 0x58, 0x0a, 0xa3,
+  0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, 0x40, 0xcd, 0x51, 0xc3,
+  0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, 0xc5, 0x4a, 0x4c, 0x7e,
+  0x71, 0xdb, 0x88, 0x18, 0x86, 0x61, 0x28, 0xc4, 0x43, 0x30, 0x04, 0x41,
+  0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, 0x15, 0x2b,
+  0x31, 0xf9, 0xc8, 0x6d, 0x23, 0x82, 0x20, 0x08, 0xa2, 0x10, 0x12, 0xc1,
+  0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, 0x82, 0x20, 0x2a, 0xb2,
+  0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0x26, 0x32, 0x18, 0x07, 0x76, 0x08,
+  0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, 0xc0, 0x07, 0x7a, 0xa8,
+  0x07, 0x79, 0x28, 0x87, 0x51, 0xa8, 0x07, 0x71, 0x28, 0x07, 0x3e, 0xb0,
+  0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0xe0, 0x03, 0x73, 0x60,
+  0x87, 0x77, 0x08, 0x07, 0x7a, 0x60, 0x03, 0x30, 0xa0, 0x03, 0x3f, 0x00,
+  0x03, 0x3f, 0x40, 0x41, 0x46, 0xda, 0x30, 0x82, 0x30, 0x9c, 0xc4, 0x3a,
+  0x54, 0x24, 0x10, 0x2b, 0x61, 0x20, 0x4e, 0xb3, 0x51, 0x45, 0x41, 0x44,
+  0x88, 0xe0, 0x38, 0x62, 0xa0, 0xee, 0x26, 0x69, 0x8a, 0x28, 0x61, 0xf2,
+  0x59, 0x80, 0x79, 0x16, 0x22, 0x62, 0x27, 0x60, 0x22, 0x50, 0x40, 0xd0,
+  0x97, 0x0a, 0xc4, 0x14, 0x00, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87,
+  0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87,
+  0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00,
+  0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0,
+  0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60,
+  0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60,
+  0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0,
+  0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x10,
+  0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c,
+  0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18,
+  0x8a, 0xa0, 0x14, 0x4a, 0xa2, 0x0c, 0x0a, 0xa6, 0x3c, 0xa8, 0x28, 0x89,
+  0x11, 0x80, 0x22, 0x28, 0x83, 0x42, 0x28, 0x10, 0xda, 0x66, 0x00, 0xc8,
+  0x9b, 0x01, 0x20, 0x70, 0x06, 0x80, 0xc2, 0xb1, 0x14, 0x84, 0x78, 0x1e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x68,
+  0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x35,
+  0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b,
+  0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b,
+  0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79,
+  0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xe2,
+  0x98, 0x20, 0x10, 0xc8, 0x06, 0x61, 0x20, 0x26, 0x08, 0x44, 0xb2, 0x41,
+  0x18, 0x0c, 0x0a, 0x70, 0x73, 0x1b, 0x06, 0xc4, 0x20, 0x26, 0x08, 0x9b,
+  0x45, 0x60, 0x82, 0x40, 0x28, 0x13, 0x04, 0x62, 0x99, 0x20, 0x10, 0xcc,
+  0x06, 0x81, 0x70, 0x36, 0x24, 0x84, 0xb2, 0x30, 0xc4, 0xd0, 0x10, 0xcf,
+  0x86, 0x00, 0x9a, 0x20, 0x78, 0xd7, 0x04, 0x81, 0x68, 0x26, 0x08, 0x84,
+  0xb3, 0x01, 0x21, 0xa4, 0x65, 0x22, 0x06, 0x0a, 0xd8, 0x10, 0x54, 0x13,
+  0x04, 0x30, 0xc0, 0x36, 0x20, 0xc4, 0xb5, 0x30, 0xc4, 0x40, 0x00, 0x1b,
+  0x02, 0x6c, 0x03, 0x11, 0x01, 0x56, 0x36, 0x41, 0x08, 0x83, 0x6c, 0x43,
+  0xb0, 0x4d, 0x10, 0x04, 0x80, 0x8c, 0x10, 0x5b, 0x1a, 0x9d, 0x91, 0xdc,
+  0x5b, 0xdb, 0x50, 0x9d, 0x58, 0x19, 0x11, 0xaa, 0x22, 0xac, 0xa1, 0xa7,
+  0x27, 0x29, 0xa2, 0x09, 0x42, 0x01, 0x4d, 0x10, 0x8a, 0x68, 0x43, 0x40,
+  0x4c, 0x10, 0x0a, 0x69, 0x83, 0x30, 0x4d, 0x1b, 0x16, 0xe2, 0x03, 0x83,
+  0x30, 0x10, 0x83, 0x31, 0x18, 0xc6, 0x80, 0x08, 0x03, 0x32, 0xe0, 0x32,
+  0x65, 0xf5, 0x05, 0xf5, 0x36, 0x97, 0x46, 0x97, 0xf6, 0xe6, 0x36, 0x41,
+  0x28, 0xa6, 0x09, 0x42, 0x41, 0x6d, 0x58, 0x06, 0x33, 0x00, 0x83, 0x33,
+  0x10, 0x03, 0x34, 0x18, 0xd0, 0x60, 0x08, 0x03, 0x60, 0x83, 0x50, 0x06,
+  0x69, 0xc0, 0x64, 0xca, 0xea, 0x8b, 0x2a, 0x4c, 0xee, 0xac, 0x8c, 0x6e,
+  0x82, 0x50, 0x54, 0x13, 0x04, 0xe2, 0xd9, 0x20, 0x4c, 0x6d, 0xb0, 0x61,
+  0x21, 0xd6, 0x00, 0x0c, 0xd8, 0x40, 0x0c, 0xc2, 0x60, 0x40, 0x03, 0x22,
+  0x0c, 0xdc, 0x60, 0x43, 0xf0, 0x06, 0x1b, 0x06, 0x35, 0x80, 0x03, 0x60,
+  0x43, 0xd1, 0x79, 0x71, 0xa0, 0x01, 0x55, 0xd8, 0xd8, 0xec, 0xda, 0x5c,
+  0xd2, 0xc8, 0xca, 0xdc, 0xe8, 0xa6, 0x04, 0x41, 0x15, 0x32, 0x3c, 0x17,
+  0xbb, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x29, 0x01, 0xd1, 0x84, 0x0c,
+  0xcf, 0xc5, 0x2e, 0x8c, 0xcd, 0xae, 0x4c, 0x6e, 0x4a, 0x60, 0xd4, 0x21,
+  0xc3, 0x73, 0x99, 0x43, 0x0b, 0x23, 0x2b, 0x93, 0x6b, 0x7a, 0x23, 0x2b,
+  0x63, 0x9b, 0x12, 0x20, 0x65, 0xc8, 0xf0, 0x5c, 0xe4, 0xca, 0xe6, 0xde,
+  0xea, 0xe4, 0xc6, 0xca, 0xe6, 0xa6, 0x04, 0x59, 0x1d, 0x32, 0x3c, 0x17,
+  0xbb, 0xb4, 0xb2, 0xbb, 0x24, 0xb2, 0x29, 0xba, 0x30, 0xba, 0xb2, 0x29,
+  0xc1, 0x56, 0x87, 0x0c, 0xcf, 0xa5, 0xcc, 0x8d, 0x4e, 0x2e, 0x0f, 0xea,
+  0x2d, 0xcd, 0x8d, 0x6e, 0x6e, 0x4a, 0x10, 0x07, 0x00, 0x00, 0x00, 0x79,
+  0x18, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4,
+  0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c,
+  0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00,
+  0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2,
+  0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38,
+  0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d,
+  0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87,
+  0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87,
+  0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30,
+  0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde,
+  0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b,
+  0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c,
+  0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07,
+  0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87,
+  0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87,
+  0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87,
+  0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0,
+  0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc,
+  0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4,
+  0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39,
+  0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38,
+  0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b,
+  0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03,
+  0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0,
+  0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0,
+  0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x30, 0x83, 0x81, 0xc8,
+  0x01, 0x1f, 0xdc, 0x40, 0x1c, 0xe4, 0xa1, 0x1c, 0xc2, 0x61, 0x1d, 0xdc,
+  0x40, 0x1c, 0xe4, 0x01, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x20,
+  0x00, 0x00, 0x00, 0x06, 0xc0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0x70,
+  0x54, 0x40, 0x18, 0xc1, 0x36, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x40, 0x15,
+  0x05, 0x11, 0x95, 0x0e, 0x30, 0x94, 0x84, 0x01, 0x08, 0x98, 0x5f, 0xdc,
+  0xb6, 0x15, 0x6c, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x04, 0x54, 0x51, 0x10,
+  0x51, 0xe9, 0x00, 0x43, 0x49, 0x18, 0x80, 0x80, 0xf9, 0xc8, 0x6d, 0x9b,
+  0x81, 0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x44, 0x00, 0x13, 0x11, 0x02,
+  0xcd, 0xb0, 0x10, 0x16, 0x30, 0x0d, 0x97, 0xef, 0x3c, 0xfe, 0xe2, 0x00,
+  0x83, 0xd8, 0x3c, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x03, 0xd5, 0x70, 0xf9,
+  0xce, 0xe3, 0x4b, 0x00, 0xf3, 0x2c, 0x44, 0x49, 0x54, 0xc4, 0xe2, 0x17,
+  0xb7, 0x6d, 0x02, 0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11,
+  0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7, 0x0d, 0x00, 0x00, 0x00, 0x61,
+  0x20, 0x00, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x13, 0x04, 0x48, 0x2c, 0x10,
+  0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x54, 0x8d, 0x00, 0x50, 0x51,
+  0x02, 0x44, 0x14, 0x5f, 0xd9, 0x15, 0x42, 0xc9, 0xcd, 0x00, 0xd0, 0x30,
+  0x03, 0x30, 0x46, 0x00, 0x82, 0x20, 0x08, 0x82, 0xc1, 0x08, 0xc0, 0x18,
+  0x01, 0x08, 0x82, 0x20, 0xfe, 0x8d, 0x11, 0x80, 0x20, 0x08, 0xe2, 0xbf,
+  0x30, 0x46, 0x00, 0x82, 0x20, 0x08, 0x82, 0x02, 0x00, 0x00, 0x00, 0x23,
+  0x06, 0x09, 0x00, 0x82, 0x60, 0x60, 0x85, 0x01, 0x62, 0x7d, 0x5f, 0x33,
+  0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x96, 0x18, 0x24, 0x15, 0x18, 0x80,
+  0x81, 0x33, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xd6, 0x18, 0x28, 0x57,
+  0x18, 0x84, 0xc1, 0x33, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x46, 0x1a,
+  0x30, 0x62, 0x20, 0x06, 0x99, 0x32, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06,
+  0x86, 0x1a, 0x34, 0x63, 0x30, 0x06, 0xd0, 0x32, 0x62, 0x70, 0x00, 0x20,
+  0x08, 0x06, 0x10, 0x1a, 0x3c, 0x03, 0x19, 0x8c, 0x26, 0x04, 0xc0, 0x68,
+  0x82, 0x10, 0x8c, 0x26, 0x0c, 0xc2, 0x68, 0x02, 0x31, 0x98, 0x70, 0xc8,
+  0xc7, 0x84, 0x43, 0x3e, 0x26, 0x18, 0xf0, 0x31, 0xc1, 0x80, 0x8f, 0x09,
+  0x93, 0x7c, 0x2c, 0x88, 0xe0, 0x63, 0x43, 0x25, 0x1f, 0x0b, 0x26, 0xf8,
+  0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0x01, 0x54, 0x07, 0x1c, 0x24, 0x07,
+  0xa3, 0x09, 0x41, 0x70, 0x01, 0x31, 0xc3, 0x3c, 0x44, 0x70, 0x20, 0xc1,
+  0x21, 0x28, 0x43, 0x43, 0x78, 0xc5, 0x62, 0x98, 0x45, 0xc4, 0xc7, 0xae,
+  0x23, 0x3e, 0xb3, 0x04, 0x87, 0x61, 0x46, 0x7c, 0x66, 0x09, 0x0e, 0xcb,
+  0x8e, 0xf8, 0xcc, 0x12, 0x1c, 0xb3, 0x04, 0x87, 0x69, 0x48, 0x7c, 0x66,
+  0x09, 0x0e, 0xdb, 0x96, 0xf8, 0x18, 0xa7, 0xc4, 0x67, 0x96, 0xe0, 0x18,
+  0xe8, 0x19, 0x08, 0x43, 0x2b, 0x34, 0x42, 0x1b, 0xf8, 0x40, 0xf0, 0x83,
+  0x00, 0x14, 0x80, 0x81, 0x9e, 0x81, 0x30, 0x90, 0x02, 0x14, 0x08, 0x3f,
+  0x18, 0x18, 0x01, 0x0a, 0x44, 0x01, 0x18, 0xe8, 0x19, 0x40, 0xc1, 0x10,
+  0x85, 0x42, 0x23, 0x98, 0xc1, 0x13, 0xa0, 0x80, 0x14, 0x80, 0x11, 0x83,
+  0x03, 0x00, 0x41, 0x30, 0x98, 0x42, 0x21, 0x0d, 0xba, 0x3f, 0x18, 0x4d,
+  0x08, 0x80, 0x0b, 0x86, 0x1a, 0x31, 0x78, 0x00, 0x10, 0x04, 0x83, 0xc6,
+  0x14, 0xda, 0x40, 0x0c, 0xc2, 0xc0, 0x28, 0x08, 0x34, 0x48, 0x83, 0x34,
+  0x48, 0x83, 0x60, 0x34, 0x21, 0x00, 0x46, 0x13, 0x84, 0x60, 0x34, 0x61,
+  0x10, 0x46, 0x13, 0x88, 0x61, 0xc4, 0x20, 0x01, 0x40, 0x10, 0x0c, 0x10,
+  0x56, 0x18, 0x05, 0x53, 0x30, 0x85, 0x3e, 0x20, 0x46, 0x0c, 0x12, 0x00,
+  0x04, 0xc1, 0x00, 0x61, 0x85, 0x51, 0x30, 0x05, 0x53, 0x98, 0x83, 0x61,
+  0xc4, 0x20, 0x01, 0x40, 0x10, 0x0c, 0x10, 0x56, 0x18, 0x05, 0x53, 0x30,
+  0x05, 0x3e, 0x10, 0x46, 0x0c, 0x12, 0x00, 0x04, 0xc1, 0x00, 0x61, 0x85,
+  0x51, 0x30, 0x05, 0x53, 0xd8, 0x83, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00
+};

+ 8255 - 0
src/gpu/d3d12/SDL_gpu_d3d12.c

@@ -0,0 +1,8255 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_internal.h"
+
+#if SDL_GPU_D3D12
+
+#include "../../video/directx/SDL_d3d12.h"
+#include "../SDL_sysgpu.h"
+#include "SDL_hashtable.h"
+
+// Built-in shaders, compiled with compile_shaders.bat
+
+#define g_FullscreenVert  D3D12_FullscreenVert
+#define g_BlitFrom2D      D3D12_BlitFrom2D
+#define g_BlitFrom2DArray D3D12_BlitFrom2DArray
+#define g_BlitFrom3D      D3D12_BlitFrom3D
+#define g_BlitFromCube    D3D12_BlitFromCube
+#if defined(SDL_PLATFORM_XBOXSERIES)
+#include "D3D12_Blit_Series.h"
+#elif defined(SDL_PLATFORM_XBOXONE)
+#include "D3D12_Blit_One.h"
+#else
+#include "D3D12_Blit.h"
+#endif
+#undef g_FullscreenVert
+#undef g_BlitFrom2D
+#undef g_BlitFrom2DArray
+#undef g_BlitFrom3D
+#undef g_BlitFromCube
+
+// Macros
+
+#define ERROR_CHECK(msg)                                     \
+    if (FAILED(res)) {                                       \
+        D3D12_INTERNAL_LogError(renderer->device, msg, res); \
+    }
+
+#define ERROR_CHECK_RETURN(msg, ret)                         \
+    if (FAILED(res)) {                                       \
+        D3D12_INTERNAL_LogError(renderer->device, msg, res); \
+        return ret;                                          \
+    }
+
+// Defines
+#if defined(_WIN32)
+#if defined(SDL_PLATFORM_XBOXSERIES)
+#define D3D12_DLL "d3d12_xs.dll"
+#elif defined(SDL_PLATFORM_XBOXONE)
+#define D3D12_DLL "d3d12_x.dll"
+#else
+#define D3D12_DLL "d3d12.dll"
+#endif
+#define DXGI_DLL      "dxgi.dll"
+#define DXGIDEBUG_DLL "dxgidebug.dll"
+#elif defined(__APPLE__)
+#define D3D12_DLL     "libdxvk_d3d12.dylib"
+#define DXGI_DLL      "libdxvk_dxgi.dylib"
+#define DXGIDEBUG_DLL "libdxvk_dxgidebug.dylib"
+#else
+#define D3D12_DLL     "libdxvk_d3d12.so"
+#define DXGI_DLL      "libdxvk_dxgi.so"
+#define DXGIDEBUG_DLL "libdxvk_dxgidebug.so"
+#endif
+
+#define D3D12_CREATE_DEVICE_FUNC            "D3D12CreateDevice"
+#define D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC "D3D12SerializeRootSignature"
+#define CREATE_DXGI_FACTORY1_FUNC           "CreateDXGIFactory1"
+#define DXGI_GET_DEBUG_INTERFACE_FUNC       "DXGIGetDebugInterface"
+#define D3D12_GET_DEBUG_INTERFACE_FUNC      "D3D12GetDebugInterface"
+#define WINDOW_PROPERTY_DATA                "SDL_GpuD3D12WindowPropertyData"
+#define D3D_FEATURE_LEVEL_CHOICE            D3D_FEATURE_LEVEL_11_1
+#define D3D_FEATURE_LEVEL_CHOICE_STR        "11_1"
+// FIXME: just use sysgpu.h defines
+#define MAX_ROOT_SIGNATURE_PARAMETERS         64
+#define VIEW_GPU_DESCRIPTOR_COUNT             65536
+#define SAMPLER_GPU_DESCRIPTOR_COUNT          2048
+#define VIEW_SAMPLER_STAGING_DESCRIPTOR_COUNT 1000000
+#define TARGET_STAGING_DESCRIPTOR_COUNT       1000000
+#define D3D12_FENCE_UNSIGNALED_VALUE          0
+#define D3D12_FENCE_SIGNAL_VALUE              1
+
+#define SDL_GPU_SHADERSTAGE_COMPUTE (SDL_GpuShaderStage)2
+
+#define EXPAND_ELEMENTS_IF_NEEDED(arr, initialValue, type) \
+    if (arr->count == arr->capacity) {                     \
+        if (arr->capacity == 0) {                          \
+            arr->capacity = initialValue;                  \
+        } else {                                           \
+            arr->capacity *= 2;                            \
+        }                                                  \
+        arr->elements = (type *)SDL_realloc(               \
+            arr->elements,                                 \
+            arr->capacity * sizeof(type));                 \
+    }
+
+#ifdef _WIN32
+#define HRESULT_FMT "(0x%08lX)"
+#else
+#define HRESULT_FMT "(0x%08X)"
+#endif
+
+// Function Pointer Signatures
+typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY1)(const GUID *riid, void **ppFactory);
+typedef HRESULT(WINAPI *PFN_DXGI_GET_DEBUG_INTERFACE)(const GUID *riid, void **ppDebug);
+
+// IIDs (from https://www.magnumdb.com/)
+static const IID D3D_IID_IDXGIFactory1 = { 0x770aae78, 0xf26f, 0x4dba, { 0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87 } };
+static const IID D3D_IID_IDXGIFactory4 = { 0x1bc6ea02, 0xef36, 0x464f, { 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a } };
+static const IID D3D_IID_IDXGIFactory5 = { 0x7632e1f5, 0xee65, 0x4dca, { 0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d } };
+static const IID D3D_IID_IDXGIFactory6 = { 0xc1b6694f, 0xff09, 0x44a9, { 0xb0, 0x3c, 0x77, 0x90, 0x0a, 0x0a, 0x1d, 0x17 } };
+static const IID D3D_IID_IDXGIAdapter1 = { 0x29038f61, 0x3839, 0x4626, { 0x91, 0xfd, 0x08, 0x68, 0x79, 0x01, 0x1a, 0x05 } };
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+static const IID D3D_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
+#endif
+static const IID D3D_IID_IDXGISwapChain3 = { 0x94d99bdb, 0xf1f8, 0x4ab0, { 0xb2, 0x36, 0x7d, 0xa0, 0x17, 0x0e, 0xda, 0xb1 } };
+static const IID D3D_IID_IDXGIDebug = { 0x119e7452, 0xde9e, 0x40fe, { 0x88, 0x06, 0x88, 0xf9, 0x0c, 0x12, 0xb4, 0x41 } };
+static const IID D3D_IID_IDXGIInfoQueue = { 0xd67441c7, 0x672a, 0x476f, { 0x9e, 0x82, 0xcd, 0x55, 0xb4, 0x49, 0x49, 0xce } };
+static const GUID D3D_IID_DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x08 } };
+static const GUID D3D_IID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, { 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 } };
+
+static const IID D3D_IID_ID3D12Device = { 0x189819f1, 0x1db6, 0x4b57, { 0xbe, 0x54, 0x18, 0x21, 0x33, 0x9b, 0x85, 0xf7 } };
+static const IID D3D_IID_ID3D12CommandQueue = { 0x0ec870a6, 0x5d7e, 0x4c22, { 0x8c, 0xfc, 0x5b, 0xaa, 0xe0, 0x76, 0x16, 0xed } };
+static const IID D3D_IID_ID3D12DescriptorHeap = { 0x8efb471d, 0x616c, 0x4f49, { 0x90, 0xf7, 0x12, 0x7b, 0xb7, 0x63, 0xfa, 0x51 } };
+static const IID D3D_IID_ID3D12Resource = { 0x696442be, 0xa72e, 0x4059, { 0xbc, 0x79, 0x5b, 0x5c, 0x98, 0x04, 0x0f, 0xad } };
+static const IID D3D_IID_ID3D12CommandAllocator = { 0x6102dee4, 0xaf59, 0x4b09, { 0xb9, 0x99, 0xb4, 0x4d, 0x73, 0xf0, 0x9b, 0x24 } };
+static const IID D3D_IID_ID3D12CommandList = { 0x7116d91c, 0xe7e4, 0x47ce, { 0xb8, 0xc6, 0xec, 0x81, 0x68, 0xf4, 0x37, 0xe5 } };
+static const IID D3D_IID_ID3D12GraphicsCommandList = { 0x5b160d0f, 0xac1b, 0x4185, { 0x8b, 0xa8, 0xb3, 0xae, 0x42, 0xa5, 0xa4, 0x55 } };
+static const IID D3D_IID_ID3D12Fence = { 0x0a753dcf, 0xc4d8, 0x4b91, { 0xad, 0xf6, 0xbe, 0x5a, 0x60, 0xd9, 0x5a, 0x76 } };
+static const IID D3D_IID_ID3D12RootSignature = { 0xc54a6b66, 0x72df, 0x4ee8, { 0x8b, 0xe5, 0xa9, 0x46, 0xa1, 0x42, 0x92, 0x14 } };
+static const IID D3D_IID_ID3D12CommandSignature = { 0xc36a797c, 0xec80, 0x4f0a, { 0x89, 0x85, 0xa7, 0xb2, 0x47, 0x50, 0x82, 0xd1 } };
+static const IID D3D_IID_ID3D12PipelineState = { 0x765a30f3, 0xf624, 0x4c6f, { 0xa8, 0x28, 0xac, 0xe9, 0x48, 0x62, 0x24, 0x45 } };
+static const IID D3D_IID_ID3D12Debug = { 0x344488b7, 0x6846, 0x474b, { 0xb9, 0x89, 0xf0, 0x27, 0x44, 0x82, 0x45, 0xe0 } };
+static const IID D3D_IID_ID3D12InfoQueue = { 0x0742a90b, 0xc387, 0x483f, { 0xb9, 0x46, 0x30, 0xa7, 0xe4, 0xe6, 0x14, 0x58 } };
+
+// Enums
+
+typedef enum D3D12BufferType
+{
+    D3D12_BUFFER_TYPE_GPU,
+    D3D12_BUFFER_TYPE_UNIFORM,
+    D3D12_BUFFER_TYPE_UPLOAD,
+    D3D12_BUFFER_TYPE_DOWNLOAD
+} D3D12BufferType;
+
+// Conversions
+
+static SDL_GpuTextureFormat SwapchainCompositionToSDLTextureFormat[] = {
+    SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM,      // SDR
+    SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, // SDR_SRGB
+    SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT,  // HDR
+    SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM,   // HDR_ADVANCED
+};
+
+static DXGI_FORMAT SwapchainCompositionToTextureFormat[] = {
+    DXGI_FORMAT_B8G8R8A8_UNORM,                // SDR
+    DXGI_FORMAT_B8G8R8A8_UNORM, /* SDR_SRGB */ // NOTE: The RTV uses the sRGB format
+    DXGI_FORMAT_R16G16B16A16_FLOAT,            // HDR
+    DXGI_FORMAT_R10G10B10A2_UNORM,             // HDR_ADVANCED
+};
+
+static DXGI_COLOR_SPACE_TYPE SwapchainCompositionToColorSpace[] = {
+    DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709,   // SDR
+    DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709,   // SDR_SRGB
+    DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709,   // HDR
+    DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 // HDR_ADVANCED
+};
+
+static D3D12_BLEND SDLToD3D12_BlendFactor[] = {
+    D3D12_BLEND_ZERO,             // ZERO
+    D3D12_BLEND_ONE,              // ONE
+    D3D12_BLEND_SRC_COLOR,        // SRC_COLOR
+    D3D12_BLEND_INV_SRC_COLOR,    // ONE_MINUS_SRC_COLOR
+    D3D12_BLEND_DEST_COLOR,       // DST_COLOR
+    D3D12_BLEND_INV_DEST_COLOR,   // ONE_MINUS_DST_COLOR
+    D3D12_BLEND_SRC_ALPHA,        // SRC_ALPHA
+    D3D12_BLEND_INV_SRC_ALPHA,    // ONE_MINUS_SRC_ALPHA
+    D3D12_BLEND_DEST_ALPHA,       // DST_ALPHA
+    D3D12_BLEND_INV_DEST_ALPHA,   // ONE_MINUS_DST_ALPHA
+    D3D12_BLEND_BLEND_FACTOR,     // CONSTANT_COLOR
+    D3D12_BLEND_INV_BLEND_FACTOR, // ONE_MINUS_CONSTANT_COLOR
+    D3D12_BLEND_SRC_ALPHA_SAT,    // SRC_ALPHA_SATURATE
+};
+
+static D3D12_BLEND SDLToD3D12_BlendFactorAlpha[] = {
+    D3D12_BLEND_ZERO,             // ZERO
+    D3D12_BLEND_ONE,              // ONE
+    D3D12_BLEND_SRC_ALPHA,        // SRC_COLOR
+    D3D12_BLEND_INV_SRC_ALPHA,    // ONE_MINUS_SRC_COLOR
+    D3D12_BLEND_DEST_ALPHA,       // DST_COLOR
+    D3D12_BLEND_INV_DEST_ALPHA,   // ONE_MINUS_DST_COLOR
+    D3D12_BLEND_SRC_ALPHA,        // SRC_ALPHA
+    D3D12_BLEND_INV_SRC_ALPHA,    // ONE_MINUS_SRC_ALPHA
+    D3D12_BLEND_DEST_ALPHA,       // DST_ALPHA
+    D3D12_BLEND_INV_DEST_ALPHA,   // ONE_MINUS_DST_ALPHA
+    D3D12_BLEND_BLEND_FACTOR,     // CONSTANT_COLOR
+    D3D12_BLEND_INV_BLEND_FACTOR, // ONE_MINUS_CONSTANT_COLOR
+    D3D12_BLEND_SRC_ALPHA_SAT,    // SRC_ALPHA_SATURATE
+};
+
+static D3D12_BLEND_OP SDLToD3D12_BlendOp[] = {
+    D3D12_BLEND_OP_ADD,          // ADD
+    D3D12_BLEND_OP_SUBTRACT,     // SUBTRACT
+    D3D12_BLEND_OP_REV_SUBTRACT, // REVERSE_SUBTRACT
+    D3D12_BLEND_OP_MIN,          // MIN
+    D3D12_BLEND_OP_MAX           // MAX
+};
+
+static DXGI_FORMAT SDLToD3D12_TextureFormat[] = {
+    DXGI_FORMAT_R8G8B8A8_UNORM,       // R8G8B8A8_UNORM
+    DXGI_FORMAT_B8G8R8A8_UNORM,       // B8G8R8A8_UNORM
+    DXGI_FORMAT_B5G6R5_UNORM,         // B5G6R5_UNORM
+    DXGI_FORMAT_B5G5R5A1_UNORM,       // B5G5R5A1_UNORM
+    DXGI_FORMAT_B4G4R4A4_UNORM,       // B4G4R4A4_UNORM
+    DXGI_FORMAT_R10G10B10A2_UNORM,    // R10G10B10A2_UNORM
+    DXGI_FORMAT_R16G16_UNORM,         // R16G16_UNORM
+    DXGI_FORMAT_R16G16B16A16_UNORM,   // R16G16B16A16_UNORM
+    DXGI_FORMAT_R8_UNORM,             // R8_UNORM
+    DXGI_FORMAT_A8_UNORM,             // A8_UNORM
+    DXGI_FORMAT_BC1_UNORM,            // BC1_UNORM
+    DXGI_FORMAT_BC2_UNORM,            // BC2_UNORM
+    DXGI_FORMAT_BC3_UNORM,            // BC3_UNORM
+    DXGI_FORMAT_BC7_UNORM,            // BC7_UNORM
+    DXGI_FORMAT_R8G8_SNORM,           // R8G8_SNORM
+    DXGI_FORMAT_R8G8B8A8_SNORM,       // R8G8B8A8_SNORM
+    DXGI_FORMAT_R16_FLOAT,            // R16_FLOAT
+    DXGI_FORMAT_R16G16_FLOAT,         // R16G16_FLOAT
+    DXGI_FORMAT_R16G16B16A16_FLOAT,   // R16G16B16A16_FLOAT
+    DXGI_FORMAT_R32_FLOAT,            // R32_FLOAT
+    DXGI_FORMAT_R32G32_FLOAT,         // R32G32_FLOAT
+    DXGI_FORMAT_R32G32B32A32_FLOAT,   // R32G32B32A32_FLOAT
+    DXGI_FORMAT_R8_UINT,              // R8_UINT
+    DXGI_FORMAT_R8G8_UINT,            // R8G8_UINT
+    DXGI_FORMAT_R8G8B8A8_UINT,        // R8G8B8A8_UINT
+    DXGI_FORMAT_R16_UINT,             // R16_UINT
+    DXGI_FORMAT_R16G16_UINT,          // R16G16_UINT
+    DXGI_FORMAT_R16G16B16A16_UINT,    // R16G16B16A16_UINT
+    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,  // R8G8B8A8_UNORM_SRGB
+    DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,  // B8G8R8A8_UNORM_SRGB
+    DXGI_FORMAT_BC3_UNORM_SRGB,       // BC3_UNORM_SRGB
+    DXGI_FORMAT_BC7_UNORM_SRGB,       // BC7_UNORM_SRGB
+    DXGI_FORMAT_D16_UNORM,            // D16_UNORM
+    DXGI_FORMAT_D24_UNORM_S8_UINT,    // D24_UNORM
+    DXGI_FORMAT_D32_FLOAT,            // D32_FLOAT
+    DXGI_FORMAT_D24_UNORM_S8_UINT,    // D24_UNORM_S8_UINT
+    DXGI_FORMAT_D32_FLOAT_S8X24_UINT, // D32_FLOAT_S8_UINT
+};
+SDL_COMPILE_TIME_ASSERT(SDLToD3D12_TextureFormat, SDL_arraysize(SDLToD3D12_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX);
+
+static D3D12_COMPARISON_FUNC SDLToD3D12_CompareOp[] = {
+    D3D12_COMPARISON_FUNC_NEVER,         // NEVER
+    D3D12_COMPARISON_FUNC_LESS,          // LESS
+    D3D12_COMPARISON_FUNC_EQUAL,         // EQUAL
+    D3D12_COMPARISON_FUNC_LESS_EQUAL,    // LESS_OR_EQUAL
+    D3D12_COMPARISON_FUNC_GREATER,       // GREATER
+    D3D12_COMPARISON_FUNC_NOT_EQUAL,     // NOT_EQUAL
+    D3D12_COMPARISON_FUNC_GREATER_EQUAL, // GREATER_OR_EQUAL
+    D3D12_COMPARISON_FUNC_ALWAYS         // ALWAYS
+};
+
+static D3D12_STENCIL_OP SDLToD3D12_StencilOp[] = {
+    D3D12_STENCIL_OP_KEEP,     // KEEP
+    D3D12_STENCIL_OP_ZERO,     // ZERO
+    D3D12_STENCIL_OP_REPLACE,  // REPLACE
+    D3D12_STENCIL_OP_INCR_SAT, // INCREMENT_AND_CLAMP
+    D3D12_STENCIL_OP_DECR_SAT, // DECREMENT_AND_CLAMP
+    D3D12_STENCIL_OP_INVERT,   // INVERT
+    D3D12_STENCIL_OP_INCR,     // INCREMENT_AND_WRAP
+    D3D12_STENCIL_OP_DECR      // DECREMENT_AND_WRAP
+};
+
+static D3D12_CULL_MODE SDLToD3D12_CullMode[] = {
+    D3D12_CULL_MODE_NONE,  // NONE
+    D3D12_CULL_MODE_FRONT, // FRONT
+    D3D12_CULL_MODE_BACK   // BACK
+};
+
+static D3D12_FILL_MODE SDLToD3D12_FillMode[] = {
+    D3D12_FILL_MODE_SOLID,    // FILL
+    D3D12_FILL_MODE_WIREFRAME // LINE
+};
+
+static D3D12_INPUT_CLASSIFICATION SDLToD3D12_InputRate[] = {
+    D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,  // VERTEX
+    D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA // INSTANCE
+};
+
+static DXGI_FORMAT SDLToD3D12_VertexFormat[] = {
+    DXGI_FORMAT_R32_SINT,           // INT
+    DXGI_FORMAT_R32G32_SINT,        // INT2
+    DXGI_FORMAT_R32G32B32_SINT,     // INT3
+    DXGI_FORMAT_R32G32B32A32_SINT,  // INT4
+    DXGI_FORMAT_R32_UINT,           // UINT
+    DXGI_FORMAT_R32G32_UINT,        // UINT2
+    DXGI_FORMAT_R32G32B32_UINT,     // UINT3
+    DXGI_FORMAT_R32G32B32A32_UINT,  // UINT4
+    DXGI_FORMAT_R32_FLOAT,          // FLOAT
+    DXGI_FORMAT_R32G32_FLOAT,       // FLOAT2
+    DXGI_FORMAT_R32G32B32_FLOAT,    // FLOAT3
+    DXGI_FORMAT_R32G32B32A32_FLOAT, // FLOAT4
+    DXGI_FORMAT_R8G8_SINT,          // BYTE2
+    DXGI_FORMAT_R8G8B8A8_SINT,      // BYTE4
+    DXGI_FORMAT_R8G8_UINT,          // UBYTE2
+    DXGI_FORMAT_R8G8B8A8_UINT,      // UBYTE4
+    DXGI_FORMAT_R8G8_SNORM,         // BYTE2_NORM
+    DXGI_FORMAT_R8G8B8A8_SNORM,     // BYTE4_NORM
+    DXGI_FORMAT_R8G8_UNORM,         // UBYTE2_NORM
+    DXGI_FORMAT_R8G8B8A8_UNORM,     // UBYTE4_NORM
+    DXGI_FORMAT_R16G16_SINT,        // SHORT2
+    DXGI_FORMAT_R16G16B16A16_SINT,  // SHORT4
+    DXGI_FORMAT_R16G16_UINT,        // USHORT2
+    DXGI_FORMAT_R16G16B16A16_UINT,  // USHORT4
+    DXGI_FORMAT_R16G16_SNORM,       // SHORT2_NORM
+    DXGI_FORMAT_R16G16B16A16_SNORM, // SHORT4_NORM
+    DXGI_FORMAT_R16G16_UNORM,       // USHORT2_NORM
+    DXGI_FORMAT_R16G16B16A16_UNORM, // USHORT4_NORM
+    DXGI_FORMAT_R16G16_FLOAT,       // HALF2
+    DXGI_FORMAT_R16G16B16A16_FLOAT  // HALF4
+};
+
+static Uint32 SDLToD3D12_SampleCount[] = {
+    1, // SDL_GPU_SAMPLECOUNT_1
+    2, // SDL_GPU_SAMPLECOUNT_2
+    4, // SDL_GPU_SAMPLECOUNT_4
+    8, // SDL_GPU_SAMPLECOUNT_8
+};
+
+static D3D12_PRIMITIVE_TOPOLOGY SDLToD3D12_PrimitiveType[] = {
+    D3D_PRIMITIVE_TOPOLOGY_POINTLIST,    // POINTLIST
+    D3D_PRIMITIVE_TOPOLOGY_LINELIST,     // LINELIST
+    D3D_PRIMITIVE_TOPOLOGY_LINESTRIP,    // LINESTRIP
+    D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // TRIANGLELIST
+    D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP // TRIANGLESTRIP
+};
+
+static D3D12_TEXTURE_ADDRESS_MODE SDLToD3D12_SamplerAddressMode[] = {
+    D3D12_TEXTURE_ADDRESS_MODE_WRAP,   // REPEAT
+    D3D12_TEXTURE_ADDRESS_MODE_MIRROR, // MIRRORED_REPEAT
+    D3D12_TEXTURE_ADDRESS_MODE_CLAMP   // CLAMP_TO_EDGE
+};
+
+static D3D12_FILTER SDLToD3D12_Filter(
+    SDL_GpuFilter minFilter,
+    SDL_GpuFilter magFilter,
+    SDL_GpuSamplerMipmapMode mipmapMode,
+    SDL_bool comparisonEnabled,
+    SDL_bool anisotropyEnabled)
+{
+    D3D12_FILTER result = D3D12_ENCODE_BASIC_FILTER(
+        (minFilter == SDL_GPU_FILTER_LINEAR) ? 1 : 0,
+        (magFilter == SDL_GPU_FILTER_LINEAR) ? 1 : 0,
+        (mipmapMode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) ? 1 : 0,
+        comparisonEnabled ? 1 : 0);
+
+    if (anisotropyEnabled) {
+        result = (D3D12_FILTER)(result | D3D12_ANISOTROPIC_FILTERING_BIT);
+    }
+
+    return result;
+}
+
+// Structures
+typedef struct D3D12Renderer D3D12Renderer;
+typedef struct D3D12CommandBufferPool D3D12CommandBufferPool;
+typedef struct D3D12CommandBuffer D3D12CommandBuffer;
+typedef struct D3D12Texture D3D12Texture;
+typedef struct D3D12Shader D3D12Shader;
+typedef struct D3D12GraphicsPipeline D3D12GraphicsPipeline;
+typedef struct D3D12ComputePipeline D3D12ComputePipeline;
+typedef struct D3D12Buffer D3D12Buffer;
+typedef struct D3D12BufferContainer D3D12BufferContainer;
+typedef struct D3D12UniformBuffer D3D12UniformBuffer;
+typedef struct D3D12DescriptorHeap D3D12DescriptorHeap;
+typedef struct D3D12TextureDownload D3D12TextureDownload;
+
+typedef struct D3D12Fence
+{
+    ID3D12Fence *handle;
+    HANDLE event; // used for blocking
+    SDL_AtomicInt referenceCount;
+} D3D12Fence;
+
+struct D3D12DescriptorHeap
+{
+    ID3D12DescriptorHeap *handle;
+    D3D12_DESCRIPTOR_HEAP_TYPE heapType;
+    D3D12_CPU_DESCRIPTOR_HANDLE descriptorHeapCPUStart;
+    D3D12_GPU_DESCRIPTOR_HANDLE descriptorHeapGPUStart; // only exists if staging is SDL_TRUE
+    Uint32 maxDescriptors;
+    Uint32 descriptorSize;
+    SDL_bool staging;
+
+    Uint32 currentDescriptorIndex;
+
+    Uint32 *inactiveDescriptorIndices; // only exists if staging is SDL_TRUE
+    Uint32 inactiveDescriptorCount;
+};
+
+typedef struct D3D12DescriptorHeapPool
+{
+    Uint32 capacity;
+    Uint32 count;
+    D3D12DescriptorHeap **heaps;
+    SDL_Mutex *lock;
+} D3D12DescriptorHeapPool;
+
+typedef struct D3D12CPUDescriptor
+{
+    D3D12DescriptorHeap *heap;
+    D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle;
+    Uint32 cpuHandleIndex;
+} D3D12CPUDescriptor;
+
+typedef struct D3D12TextureContainer
+{
+    TextureCommonHeader header;
+
+    D3D12Texture *activeTexture;
+
+    D3D12Texture **textures;
+    Uint32 textureCapacity;
+    Uint32 textureCount;
+
+    // Swapchain images cannot be cycled
+    SDL_bool canBeCycled;
+
+    char *debugName;
+} D3D12TextureContainer;
+
+// Null views represent by heap = NULL
+typedef struct D3D12TextureSubresource
+{
+    D3D12Texture *parent;
+    Uint32 layer;
+    Uint32 level;
+    Uint32 depth;
+    Uint32 index;
+
+    // One per depth slice
+    D3D12CPUDescriptor *rtvHandles; // NULL if not a color target
+
+    D3D12CPUDescriptor uavHandle; // NULL if not a compute storage write texture
+    D3D12CPUDescriptor dsvHandle; // NULL if not a depth stencil target
+} D3D12TextureSubresource;
+
+struct D3D12Texture
+{
+    D3D12TextureContainer *container;
+    Uint32 containerIndex;
+
+    D3D12TextureSubresource *subresources;
+    Uint32 subresourceCount; /* layerCount * levelCount */
+
+    ID3D12Resource *resource;
+    D3D12CPUDescriptor srvHandle;
+
+    SDL_AtomicInt referenceCount;
+};
+
+typedef struct D3D12Sampler
+{
+    SDL_GpuSamplerCreateInfo createInfo;
+    D3D12CPUDescriptor handle;
+    SDL_AtomicInt referenceCount;
+} D3D12Sampler;
+
+typedef struct D3D12WindowData
+{
+    SDL_Window *window;
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    D3D12XBOX_FRAME_PIPELINE_TOKEN frameToken;
+    Uint32 swapchainWidth, swapchainHeight;
+#else
+    IDXGISwapChain3 *swapchain;
+#endif
+    SDL_GpuPresentMode presentMode;
+    SDL_GpuSwapchainComposition swapchainComposition;
+    DXGI_COLOR_SPACE_TYPE swapchainColorSpace;
+    Uint32 frameCounter;
+
+    D3D12TextureContainer textureContainers[MAX_FRAMES_IN_FLIGHT];
+    D3D12Fence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
+} D3D12WindowData;
+
+typedef struct D3D12PresentData
+{
+    D3D12WindowData *windowData;
+    Uint32 swapchainImageIndex;
+} D3D12PresentData;
+
+struct D3D12Renderer
+{
+    // Reference to the parent device
+    SDL_GpuDevice *sdlGpuDevice;
+
+#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    IDXGIDebug *dxgiDebug;
+    IDXGIFactory4 *factory;
+    IDXGIInfoQueue *dxgiInfoQueue;
+    IDXGIAdapter1 *adapter;
+    void *dxgi_dll;
+    void *dxgidebug_dll;
+#endif
+    ID3D12Debug *d3d12Debug;
+    SDL_bool supportsTearing;
+    void *d3d12_dll;
+    ID3D12Device *device;
+    PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignature_func;
+    const char *semantic;
+    SDL_iconv_t iconv;
+
+    ID3D12CommandQueue *commandQueue;
+
+    SDL_bool debugMode;
+    SDL_bool GPUUploadHeapSupported;
+    // FIXME: these might not be necessary since we're not using custom heaps
+    SDL_bool UMA;
+    SDL_bool UMACacheCoherent;
+
+    // Indirect command signatures
+    ID3D12CommandSignature *indirectDrawCommandSignature;
+    ID3D12CommandSignature *indirectIndexedDrawCommandSignature;
+    ID3D12CommandSignature *indirectDispatchCommandSignature;
+
+    // Blit
+    SDL_GpuShader *blitVertexShader;
+    SDL_GpuShader *blitFrom2DShader;
+    SDL_GpuShader *blitFrom2DArrayShader;
+    SDL_GpuShader *blitFrom3DShader;
+    SDL_GpuShader *blitFromCubeShader;
+
+    SDL_GpuSampler *blitNearestSampler;
+    SDL_GpuSampler *blitLinearSampler;
+
+    BlitPipelineCacheEntry *blitPipelines;
+    Uint32 blitPipelineCount;
+    Uint32 blitPipelineCapacity;
+
+    // Resources
+
+    D3D12CommandBuffer **availableCommandBuffers;
+    Uint32 availableCommandBufferCount;
+    Uint32 availableCommandBufferCapacity;
+
+    D3D12CommandBuffer **submittedCommandBuffers;
+    Uint32 submittedCommandBufferCount;
+    Uint32 submittedCommandBufferCapacity;
+
+    D3D12UniformBuffer **uniformBufferPool;
+    Uint32 uniformBufferPoolCount;
+    Uint32 uniformBufferPoolCapacity;
+
+    D3D12WindowData **claimedWindows;
+    Uint32 claimedWindowCount;
+    Uint32 claimedWindowCapacity;
+
+    D3D12Fence **availableFences;
+    Uint32 availableFenceCount;
+    Uint32 availableFenceCapacity;
+
+    D3D12DescriptorHeap *stagingDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES];
+    D3D12DescriptorHeapPool descriptorHeapPools[2];
+
+    // Deferred resource releasing
+
+    D3D12Buffer **buffersToDestroy;
+    Uint32 buffersToDestroyCount;
+    Uint32 buffersToDestroyCapacity;
+
+    D3D12Texture **texturesToDestroy;
+    Uint32 texturesToDestroyCount;
+    Uint32 texturesToDestroyCapacity;
+
+    D3D12Sampler **samplersToDestroy;
+    Uint32 samplersToDestroyCount;
+    Uint32 samplersToDestroyCapacity;
+
+    D3D12GraphicsPipeline **graphicsPipelinesToDestroy;
+    Uint32 graphicsPipelinesToDestroyCount;
+    Uint32 graphicsPipelinesToDestroyCapacity;
+
+    D3D12ComputePipeline **computePipelinesToDestroy;
+    Uint32 computePipelinesToDestroyCount;
+    Uint32 computePipelinesToDestroyCapacity;
+
+    // Locks
+    SDL_Mutex *stagingDescriptorHeapLock;
+    SDL_Mutex *acquireCommandBufferLock;
+    SDL_Mutex *acquireUniformBufferLock;
+    SDL_Mutex *submitLock;
+    SDL_Mutex *windowLock;
+    SDL_Mutex *fenceLock;
+    SDL_Mutex *disposeLock;
+};
+
+struct D3D12CommandBuffer
+{
+    // reserved for SDL_gpu
+    CommandBufferCommonHeader common;
+
+    // non owning parent reference
+    D3D12Renderer *renderer;
+
+    ID3D12CommandAllocator *commandAllocator;
+    ID3D12GraphicsCommandList *graphicsCommandList;
+    D3D12Fence *inFlightFence;
+    SDL_bool autoReleaseFence;
+
+    // Presentation data
+    D3D12PresentData *presentDatas;
+    Uint32 presentDataCount;
+    Uint32 presentDataCapacity;
+
+    Uint32 colorAttachmentTextureSubresourceCount;
+    D3D12TextureSubresource *colorAttachmentTextureSubresources[MAX_COLOR_TARGET_BINDINGS];
+    D3D12TextureSubresource *depthStencilTextureSubresource;
+    D3D12GraphicsPipeline *currentGraphicsPipeline;
+    D3D12ComputePipeline *currentComputePipeline;
+
+    // Set at acquire time
+    D3D12DescriptorHeap *gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER + 1];
+
+    D3D12UniformBuffer **usedUniformBuffers;
+    Uint32 usedUniformBufferCount;
+    Uint32 usedUniformBufferCapacity;
+
+    // Resource slot state
+    SDL_bool needVertexBufferBind;
+    SDL_bool needVertexSamplerBind;
+    SDL_bool needVertexStorageTextureBind;
+    SDL_bool needVertexStorageBufferBind;
+    SDL_bool needVertexUniformBufferBind[MAX_UNIFORM_BUFFERS_PER_STAGE];
+    SDL_bool needFragmentSamplerBind;
+    SDL_bool needFragmentStorageTextureBind;
+    SDL_bool needFragmentStorageBufferBind;
+    SDL_bool needFragmentUniformBufferBind[MAX_UNIFORM_BUFFERS_PER_STAGE];
+
+    SDL_bool needComputeReadOnlyStorageTextureBind;
+    SDL_bool needComputeReadOnlyStorageBufferBind;
+    SDL_bool needComputeUniformBufferBind[MAX_UNIFORM_BUFFERS_PER_STAGE];
+
+    D3D12Buffer *vertexBuffers[MAX_BUFFER_BINDINGS];
+    Uint32 vertexBufferOffsets[MAX_BUFFER_BINDINGS];
+    Uint32 vertexBufferCount;
+
+    D3D12Texture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12Sampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12Texture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
+    D3D12Buffer *vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+    D3D12UniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+
+    D3D12Texture *fragmentSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12Sampler *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12Texture *fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
+    D3D12Buffer *fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+    D3D12UniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+
+    D3D12Texture *computeReadOnlyStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
+    D3D12Buffer *computeReadOnlyStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+    D3D12TextureSubresource *computeWriteOnlyStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
+    Uint32 computeWriteOnlyStorageTextureSubresourceCount;
+    D3D12Buffer *computeWriteOnlyStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
+    Uint32 computeWriteOnlyStorageBufferCount;
+    D3D12UniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+
+    // Resource tracking
+    D3D12Texture **usedTextures;
+    Uint32 usedTextureCount;
+    Uint32 usedTextureCapacity;
+
+    D3D12Buffer **usedBuffers;
+    Uint32 usedBufferCount;
+    Uint32 usedBufferCapacity;
+
+    D3D12Sampler **usedSamplers;
+    Uint32 usedSamplerCount;
+    Uint32 usedSamplerCapacity;
+
+    D3D12GraphicsPipeline **usedGraphicsPipelines;
+    Uint32 usedGraphicsPipelineCount;
+    Uint32 usedGraphicsPipelineCapacity;
+
+    D3D12ComputePipeline **usedComputePipelines;
+    Uint32 usedComputePipelineCount;
+    Uint32 usedComputePipelineCapacity;
+
+    // Used for texture pitch hack
+    D3D12TextureDownload **textureDownloads;
+    Uint32 textureDownloadCount;
+    Uint32 textureDownloadCapacity;
+};
+
+struct D3D12Shader
+{
+    // todo cleanup
+    void *bytecode;
+    size_t bytecodeSize;
+
+    Uint32 samplerCount;
+    Uint32 uniformBufferCount;
+    Uint32 storageBufferCount;
+    Uint32 storageTextureCount;
+};
+
+typedef struct D3D12GraphicsRootSignature
+{
+    ID3D12RootSignature *handle;
+
+    Sint32 vertexSamplerRootIndex;
+    Sint32 vertexSamplerTextureRootIndex;
+    Sint32 vertexStorageTextureRootIndex;
+    Sint32 vertexStorageBufferRootIndex;
+
+    Sint32 vertexUniformBufferRootIndex[MAX_UNIFORM_BUFFERS_PER_STAGE];
+
+    Sint32 fragmentSamplerRootIndex;
+    Sint32 fragmentSamplerTextureRootIndex;
+    Sint32 fragmentStorageTextureRootIndex;
+    Sint32 fragmentStorageBufferRootIndex;
+
+    Sint32 fragmentUniformBufferRootIndex[MAX_UNIFORM_BUFFERS_PER_STAGE];
+} D3D12GraphicsRootSignature;
+
+struct D3D12GraphicsPipeline
+{
+    ID3D12PipelineState *pipelineState;
+    D3D12GraphicsRootSignature *rootSignature;
+    SDL_GpuPrimitiveType primitiveType;
+
+    Uint32 vertexStrides[MAX_BUFFER_BINDINGS];
+
+    float blendConstants[4];
+    Uint8 stencilRef;
+
+    Uint32 vertexSamplerCount;
+    Uint32 vertexUniformBufferCount;
+    Uint32 vertexStorageBufferCount;
+    Uint32 vertexStorageTextureCount;
+
+    Uint32 fragmentSamplerCount;
+    Uint32 fragmentUniformBufferCount;
+    Uint32 fragmentStorageBufferCount;
+    Uint32 fragmentStorageTextureCount;
+
+    SDL_AtomicInt referenceCount;
+};
+
+typedef struct D3D12ComputeRootSignature
+{
+    ID3D12RootSignature *handle;
+
+    Uint32 readOnlyStorageTextureRootIndex;
+    Uint32 readOnlyStorageBufferRootIndex;
+    Uint32 writeOnlyStorageTextureRootIndex;
+    Uint32 writeOnlyStorageBufferRootIndex;
+    Uint32 uniformBufferRootIndex[MAX_UNIFORM_BUFFERS_PER_STAGE];
+} D3D12ComputeRootSignature;
+
+struct D3D12ComputePipeline
+{
+    ID3D12PipelineState *pipelineState;
+    D3D12ComputeRootSignature *rootSignature;
+
+    Uint32 readOnlyStorageTextureCount;
+    Uint32 readOnlyStorageBufferCount;
+    Uint32 writeOnlyStorageTextureCount;
+    Uint32 writeOnlyStorageBufferCount;
+    Uint32 uniformBufferCount;
+
+    SDL_AtomicInt referenceCount;
+};
+
+struct D3D12TextureDownload
+{
+    D3D12Buffer *destinationBuffer;
+    D3D12Buffer *temporaryBuffer;
+    Uint32 width;
+    Uint32 height;
+    Uint32 depth;
+    Uint32 bufferOffset;
+    Uint32 bytesPerRow;
+    Uint32 bytesPerDepthSlice;
+    Uint32 alignedBytesPerRow;
+};
+
+struct D3D12Buffer
+{
+    D3D12BufferContainer *container;
+    Uint32 containerIndex;
+
+    ID3D12Resource *handle;
+    D3D12CPUDescriptor uavDescriptor;
+    D3D12CPUDescriptor srvDescriptor;
+    D3D12CPUDescriptor cbvDescriptor;
+    D3D12_GPU_VIRTUAL_ADDRESS virtualAddress;
+    Uint8 *mapPointer; // NULL except for upload buffers and fast uniform buffers
+    SDL_AtomicInt referenceCount;
+    SDL_bool transitioned; // used for initial resource barrier
+};
+
+struct D3D12BufferContainer
+{
+    SDL_GpuBufferUsageFlags usageFlags;
+    Uint32 size;
+    D3D12BufferType type;
+
+    D3D12Buffer *activeBuffer;
+
+    D3D12Buffer **buffers;
+    Uint32 bufferCapacity;
+    Uint32 bufferCount;
+
+    D3D12_RESOURCE_DESC bufferDesc;
+
+    char *debugName;
+};
+
+struct D3D12UniformBuffer
+{
+    D3D12Buffer *buffer;
+    Uint32 writeOffset;
+    Uint32 drawOffset;
+    Uint32 currentBlockSize;
+};
+
+// Foward function declarations
+
+static void D3D12_UnclaimWindow(SDL_GpuRenderer *driverData, SDL_Window *window);
+static void D3D12_Wait(SDL_GpuRenderer *driverData);
+static void D3D12_WaitForFences(SDL_GpuRenderer *driverData, SDL_bool waitAll, SDL_GpuFence **pFences, Uint32 fenceCount);
+static void D3D12_INTERNAL_ReleaseBlitPipelines(SDL_GpuRenderer *driverData);
+
+// Helpers
+
+static Uint32 D3D12_INTERNAL_Align(Uint32 location, Uint32 alignment)
+{
+    return (location + (alignment - 1)) & ~(alignment - 1);
+}
+
+// Xbox Hack
+
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+// FIXME: This is purely to work around a presentation bug when recreating the device/command queue.
+static ID3D12Device *s_Device;
+static ID3D12CommandQueue *s_CommandQueue;
+#endif
+
+// Logging
+
+static void
+D3D12_INTERNAL_LogError(
+    ID3D12Device *device,
+    const char *msg,
+    HRESULT res)
+{
+#define MAX_ERROR_LEN 1024 // FIXME: Arbitrary!
+
+    // Buffer for text, ensure space for \0 terminator after buffer
+    char wszMsgBuff[MAX_ERROR_LEN + 1];
+    DWORD dwChars; // Number of chars returned.
+
+    if (res == DXGI_ERROR_DEVICE_REMOVED) {
+        if (device) {
+            res = ID3D12Device_GetDeviceRemovedReason(device);
+        }
+    }
+
+    // Try to get the message from the system errors.
+    dwChars = FormatMessageA(
+        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+        NULL,
+        res,
+        0,
+        wszMsgBuff,
+        MAX_ERROR_LEN,
+        NULL);
+
+    // No message? Screw it, just post the code.
+    if (dwChars == 0) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: " HRESULT_FMT, msg, res);
+        return;
+    }
+
+    // Ensure valid range
+    dwChars = SDL_min(dwChars, MAX_ERROR_LEN);
+
+    // Trim whitespace from tail of message
+    while (dwChars > 0) {
+        if (wszMsgBuff[dwChars - 1] <= ' ') {
+            dwChars--;
+        } else {
+            break;
+        }
+    }
+
+    // Ensure null-terminated string
+    wszMsgBuff[dwChars] = '\0';
+
+    SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res);
+}
+
+// Debug Naming
+
+static void D3D12_INTERNAL_SetResourceName(
+    D3D12Renderer *renderer,
+    ID3D12Resource *resource,
+    const char *text)
+{
+    if (renderer->debugMode) {
+        ID3D12DeviceChild_SetPrivateData(
+            resource,
+            D3D_GUID(D3D_IID_D3DDebugObjectName),
+            (UINT)SDL_strlen(text),
+            text);
+    }
+}
+
+// Release / Cleanup
+
+// TODO: call this when releasing resources
+static void D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+    D3D12Renderer *renderer,
+    D3D12CPUDescriptor *cpuDescriptor)
+{
+    D3D12DescriptorHeap *heap = cpuDescriptor->heap;
+
+    if (heap != NULL) {
+        SDL_LockMutex(renderer->stagingDescriptorHeapLock);
+        heap->inactiveDescriptorIndices[heap->inactiveDescriptorCount] = cpuDescriptor->cpuHandleIndex;
+        heap->inactiveDescriptorCount += 1;
+        SDL_UnlockMutex(renderer->stagingDescriptorHeapLock);
+    }
+
+    cpuDescriptor->heap = NULL;
+    cpuDescriptor->cpuHandle.ptr = 0;
+    cpuDescriptor->cpuHandleIndex = SDL_MAX_UINT32;
+}
+
+static void D3D12_INTERNAL_DestroyBuffer(
+    D3D12Renderer *renderer,
+    D3D12Buffer *buffer)
+{
+    if (!buffer) {
+        return;
+    }
+
+    if (buffer->mapPointer != NULL) {
+        ID3D12Resource_Unmap(
+            buffer->handle,
+            0,
+            NULL);
+    }
+    D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+        renderer,
+        &buffer->srvDescriptor);
+    D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+        renderer,
+        &buffer->uavDescriptor);
+    D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+        renderer,
+        &buffer->cbvDescriptor);
+
+    if (buffer->handle) {
+        ID3D12Resource_Release(buffer->handle);
+    }
+    SDL_free(buffer);
+}
+
+static void D3D12_INTERNAL_ReleaseBuffer(
+    D3D12Renderer *renderer,
+    D3D12Buffer *buffer)
+{
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->buffersToDestroy,
+        D3D12Buffer *,
+        renderer->buffersToDestroyCount + 1,
+        renderer->buffersToDestroyCapacity,
+        renderer->buffersToDestroyCapacity * 2)
+
+    renderer->buffersToDestroy[renderer->buffersToDestroyCount] = buffer;
+    renderer->buffersToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void D3D12_INTERNAL_ReleaseBufferContainer(
+    D3D12Renderer *renderer,
+    D3D12BufferContainer *container)
+{
+    SDL_LockMutex(renderer->disposeLock);
+
+    for (Uint32 i = 0; i < container->bufferCount; i += 1) {
+        D3D12_INTERNAL_ReleaseBuffer(
+            renderer,
+            container->buffers[i]);
+    }
+
+    // Containers are just client handles, so we can free immediately
+    if (container->debugName) {
+        SDL_free(container->debugName);
+    }
+    SDL_free(container->buffers);
+    SDL_free(container);
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void D3D12_INTERNAL_DestroyTexture(
+    D3D12Renderer *renderer,
+    D3D12Texture *texture)
+{
+    if (!texture) {
+        return;
+    }
+    for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
+        D3D12TextureSubresource *subresource = &texture->subresources[i];
+        if (subresource->rtvHandles) {
+            for (Uint32 depthIndex = 0; depthIndex < subresource->depth; depthIndex += 1) {
+                D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+                    renderer,
+                    &subresource->rtvHandles[depthIndex]);
+            }
+            SDL_free(subresource->rtvHandles);
+        }
+
+        D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+            renderer,
+            &subresource->uavHandle);
+
+        D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+            renderer,
+            &subresource->dsvHandle);
+    }
+    SDL_free(texture->subresources);
+
+    D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+        renderer,
+        &texture->srvHandle);
+
+    if (texture->resource) {
+        ID3D12Resource_Release(texture->resource);
+    }
+
+    SDL_free(texture);
+}
+
+static void D3D12_INTERNAL_ReleaseTexture(
+    D3D12Renderer *renderer,
+    D3D12Texture *texture)
+{
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->texturesToDestroy,
+        D3D12Texture *,
+        renderer->texturesToDestroyCount + 1,
+        renderer->texturesToDestroyCapacity,
+        renderer->texturesToDestroyCapacity * 2)
+
+    renderer->texturesToDestroy[renderer->texturesToDestroyCount] = texture;
+    renderer->texturesToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void D3D12_INTERNAL_ReleaseTextureContainer(
+    D3D12Renderer *renderer,
+    D3D12TextureContainer *container)
+{
+    SDL_LockMutex(renderer->disposeLock);
+
+    for (Uint32 i = 0; i < container->textureCount; i += 1) {
+        D3D12_INTERNAL_ReleaseTexture(
+            renderer,
+            container->textures[i]);
+    }
+
+    // Containers are just client handles, so we can destroy immediately
+    if (container->debugName) {
+        SDL_free(container->debugName);
+    }
+    SDL_free(container->textures);
+    SDL_free(container);
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void D3D12_INTERNAL_DestroySampler(
+    D3D12Renderer *renderer,
+    D3D12Sampler *sampler)
+{
+    D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+        renderer,
+        &sampler->handle);
+
+    SDL_free(sampler);
+}
+
+static void D3D12_INTERNAL_DestroyGraphicsRootSignature(
+    D3D12GraphicsRootSignature *rootSignature)
+{
+    if (!rootSignature) {
+        return;
+    }
+    if (rootSignature->handle) {
+        ID3D12RootSignature_Release(rootSignature->handle);
+    }
+    SDL_free(rootSignature);
+}
+
+static void D3D12_INTERNAL_DestroyGraphicsPipeline(
+    D3D12GraphicsPipeline *graphicsPipeline)
+{
+    if (graphicsPipeline->pipelineState) {
+        ID3D12PipelineState_Release(graphicsPipeline->pipelineState);
+    }
+    D3D12_INTERNAL_DestroyGraphicsRootSignature(graphicsPipeline->rootSignature);
+    SDL_free(graphicsPipeline);
+}
+
+static void D3D12_INTERNAL_DestroyComputeRootSignature(
+    D3D12ComputeRootSignature *rootSignature)
+{
+    if (!rootSignature) {
+        return;
+    }
+    if (rootSignature->handle) {
+        ID3D12RootSignature_Release(rootSignature->handle);
+    }
+    SDL_free(rootSignature);
+}
+
+static void D3D12_INTERNAL_DestroyComputePipeline(
+    D3D12ComputePipeline *computePipeline)
+{
+    if (computePipeline->pipelineState) {
+        ID3D12PipelineState_Release(computePipeline->pipelineState);
+    }
+    D3D12_INTERNAL_DestroyComputeRootSignature(computePipeline->rootSignature);
+    SDL_free(computePipeline);
+}
+
+static void D3D12_INTERNAL_ReleaseFenceToPool(
+    D3D12Renderer *renderer,
+    D3D12Fence *fence)
+{
+    SDL_LockMutex(renderer->fenceLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->availableFences,
+        D3D12Fence *,
+        renderer->availableFenceCount + 1,
+        renderer->availableFenceCapacity,
+        renderer->availableFenceCapacity * 2);
+
+    renderer->availableFences[renderer->availableFenceCount] = fence;
+    renderer->availableFenceCount += 1;
+
+    SDL_UnlockMutex(renderer->fenceLock);
+}
+
+static void D3D12_ReleaseFence(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuFence *fence)
+{
+    D3D12Fence *d3d12Fence = (D3D12Fence *)fence;
+
+    if (SDL_AtomicDecRef(&d3d12Fence->referenceCount)) {
+        D3D12_INTERNAL_ReleaseFenceToPool(
+            (D3D12Renderer *)driverData,
+            d3d12Fence);
+    }
+}
+
+static SDL_bool D3D12_QueryFence(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuFence *fence)
+{
+    D3D12Fence *d3d12Fence = (D3D12Fence *)fence;
+    return ID3D12Fence_GetCompletedValue(d3d12Fence->handle) == D3D12_FENCE_SIGNAL_VALUE;
+}
+
+static void D3D12_INTERNAL_DestroyDescriptorHeap(D3D12DescriptorHeap *descriptorHeap)
+{
+    if (!descriptorHeap) {
+        return;
+    }
+    SDL_free(descriptorHeap->inactiveDescriptorIndices);
+    if (descriptorHeap->handle) {
+        ID3D12DescriptorHeap_Release(descriptorHeap->handle);
+    }
+    SDL_free(descriptorHeap);
+}
+
+static void D3D12_INTERNAL_DestroyCommandBuffer(D3D12CommandBuffer *commandBuffer)
+{
+    if (!commandBuffer) {
+        return;
+    }
+    if (commandBuffer->graphicsCommandList) {
+        ID3D12GraphicsCommandList_Release(commandBuffer->graphicsCommandList);
+    }
+    if (commandBuffer->commandAllocator) {
+        ID3D12CommandAllocator_Release(commandBuffer->commandAllocator);
+    }
+    SDL_free(commandBuffer->presentDatas);
+    SDL_free(commandBuffer->usedTextures);
+    SDL_free(commandBuffer->usedBuffers);
+    SDL_free(commandBuffer->usedSamplers);
+    SDL_free(commandBuffer->usedGraphicsPipelines);
+    SDL_free(commandBuffer->usedComputePipelines);
+    SDL_free(commandBuffer->usedUniformBuffers);
+    SDL_free(commandBuffer);
+}
+
+static void D3D12_INTERNAL_DestroyFence(D3D12Fence *fence)
+{
+    if (!fence) {
+        return;
+    }
+    if (fence->handle) {
+        ID3D12Fence_Release(fence->handle);
+    }
+    if (fence->event) {
+        CloseHandle(fence->event);
+    }
+    SDL_free(fence);
+}
+
+// FIXME: just move this into DestroyDevice
+static void D3D12_INTERNAL_DestroyRenderer(D3D12Renderer *renderer)
+{
+    if (!renderer) {
+        return;
+    }
+
+    // Release blit pipeline structures
+    D3D12_INTERNAL_ReleaseBlitPipelines((SDL_GpuRenderer *)renderer);
+
+    // Flush any remaining GPU work...
+    D3D12_Wait((SDL_GpuRenderer *)renderer);
+
+    // Release window data
+    for (Sint32 i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) {
+        D3D12_UnclaimWindow((SDL_GpuRenderer *)renderer, renderer->claimedWindows[i]->window);
+    }
+    SDL_free(renderer->claimedWindows);
+
+    // Release uniform buffers
+    for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
+        D3D12_INTERNAL_DestroyBuffer(
+            renderer,
+            renderer->uniformBufferPool[i]->buffer);
+        SDL_free(renderer->uniformBufferPool[i]);
+    }
+
+    // Clean up descriptor heaps
+    for (Uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1) {
+        if (renderer->stagingDescriptorHeaps[i]) {
+            D3D12_INTERNAL_DestroyDescriptorHeap(renderer->stagingDescriptorHeaps[i]);
+            renderer->stagingDescriptorHeaps[i] = NULL;
+        }
+    }
+
+    for (Uint32 i = 0; i < 2; i += 1) {
+        if (renderer->descriptorHeapPools[i].heaps) {
+            for (Uint32 j = 0; j < renderer->descriptorHeapPools[i].count; j += 1) {
+                if (renderer->descriptorHeapPools[i].heaps[j]) {
+                    D3D12_INTERNAL_DestroyDescriptorHeap(renderer->descriptorHeapPools[i].heaps[j]);
+                    renderer->descriptorHeapPools[i].heaps[j] = NULL;
+                }
+            }
+            SDL_free(renderer->descriptorHeapPools[i].heaps);
+        }
+        if (renderer->descriptorHeapPools[i].lock) {
+            SDL_DestroyMutex(renderer->descriptorHeapPools[i].lock);
+            renderer->descriptorHeapPools[i].lock = NULL;
+        }
+    }
+
+    // Release command buffers
+    for (Uint32 i = 0; i < renderer->availableCommandBufferCount; i += 1) {
+        if (renderer->availableCommandBuffers[i]) {
+            D3D12_INTERNAL_DestroyCommandBuffer(renderer->availableCommandBuffers[i]);
+            renderer->availableCommandBuffers[i] = NULL;
+        }
+    }
+
+    // Release fences
+    for (Uint32 i = 0; i < renderer->availableFenceCount; i += 1) {
+        if (renderer->availableFences[i]) {
+            D3D12_INTERNAL_DestroyFence(renderer->availableFences[i]);
+            renderer->availableFences[i] = NULL;
+        }
+    }
+
+    // Clean up allocations
+    SDL_free(renderer->availableCommandBuffers);
+    SDL_free(renderer->submittedCommandBuffers);
+    SDL_free(renderer->availableFences);
+    SDL_free(renderer->uniformBufferPool);
+
+    // Tear down D3D12 objects
+    if (renderer->indirectDrawCommandSignature) {
+        ID3D12CommandSignature_Release(renderer->indirectDrawCommandSignature);
+        renderer->indirectDrawCommandSignature = NULL;
+    }
+    if (renderer->indirectIndexedDrawCommandSignature) {
+        ID3D12CommandSignature_Release(renderer->indirectIndexedDrawCommandSignature);
+        renderer->indirectIndexedDrawCommandSignature = NULL;
+    }
+    if (renderer->indirectDispatchCommandSignature) {
+        ID3D12CommandSignature_Release(renderer->indirectDispatchCommandSignature);
+        renderer->indirectDispatchCommandSignature = NULL;
+    }
+#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    if (renderer->commandQueue) {
+        ID3D12CommandQueue_Release(renderer->commandQueue);
+        renderer->commandQueue = NULL;
+    }
+    if (renderer->device) {
+        ID3D12Device_Release(renderer->device);
+        renderer->device = NULL;
+    }
+    if (renderer->adapter) {
+        IDXGIAdapter1_Release(renderer->adapter);
+        renderer->adapter = NULL;
+    }
+    if (renderer->factory) {
+        IDXGIFactory4_Release(renderer->factory);
+        renderer->factory = NULL;
+    }
+    if (renderer->dxgiDebug) {
+        IDXGIDebug_ReportLiveObjects(
+            renderer->dxgiDebug,
+            D3D_IID_DXGI_DEBUG_ALL,
+            (DXGI_DEBUG_RLO_FLAGS)(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL));
+        IDXGIDebug_Release(renderer->dxgiDebug);
+        renderer->dxgiDebug = NULL;
+    }
+#endif
+    if (renderer->d3d12_dll) {
+        SDL_UnloadObject(renderer->d3d12_dll);
+        renderer->d3d12_dll = NULL;
+    }
+#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    if (renderer->dxgi_dll) {
+        SDL_UnloadObject(renderer->dxgi_dll);
+        renderer->dxgi_dll = NULL;
+    }
+    if (renderer->dxgidebug_dll) {
+        SDL_UnloadObject(renderer->dxgidebug_dll);
+        renderer->dxgidebug_dll = NULL;
+    }
+#endif
+    renderer->D3D12SerializeRootSignature_func = NULL;
+
+    if (renderer->iconv) {
+        SDL_iconv_close(renderer->iconv);
+    }
+
+    SDL_DestroyMutex(renderer->stagingDescriptorHeapLock);
+    SDL_DestroyMutex(renderer->acquireCommandBufferLock);
+    SDL_DestroyMutex(renderer->acquireUniformBufferLock);
+    SDL_DestroyMutex(renderer->submitLock);
+    SDL_DestroyMutex(renderer->windowLock);
+    SDL_DestroyMutex(renderer->fenceLock);
+    SDL_DestroyMutex(renderer->disposeLock);
+    SDL_free(renderer);
+}
+
+static void D3D12_DestroyDevice(SDL_GpuDevice *device)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)device->driverData;
+    D3D12_INTERNAL_DestroyRenderer(renderer);
+    SDL_free(device);
+}
+
+// Barriers
+
+static inline Uint32 D3D12_INTERNAL_CalcSubresource(
+    Uint32 mipLevel,
+    Uint32 layer,
+    Uint32 numLevels)
+{
+    return mipLevel + (layer * numLevels);
+}
+
+static void D3D12_INTERNAL_ResourceBarrier(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_RESOURCE_STATES sourceState,
+    D3D12_RESOURCE_STATES destinationState,
+    ID3D12Resource *resource,
+    Uint32 subresourceIndex,
+    SDL_bool needsUavBarrier)
+{
+    D3D12_RESOURCE_BARRIER barrierDesc[2];
+    Uint32 numBarriers = 0;
+
+    // No transition barrier is needed if the state is not changing.
+    if (sourceState != destinationState) {
+        barrierDesc[numBarriers].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+        barrierDesc[numBarriers].Flags = (D3D12_RESOURCE_BARRIER_FLAGS)0;
+        barrierDesc[numBarriers].Transition.StateBefore = sourceState;
+        barrierDesc[numBarriers].Transition.StateAfter = destinationState;
+        barrierDesc[numBarriers].Transition.pResource = resource;
+        barrierDesc[numBarriers].Transition.Subresource = subresourceIndex;
+
+        numBarriers += 1;
+    }
+
+    if (needsUavBarrier) {
+        barrierDesc[numBarriers].Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
+        barrierDesc[numBarriers].Flags = (D3D12_RESOURCE_BARRIER_FLAGS)0;
+        barrierDesc[numBarriers].UAV.pResource = resource;
+
+        numBarriers += 1;
+    }
+
+    if (numBarriers > 0) {
+        ID3D12GraphicsCommandList_ResourceBarrier(
+            commandBuffer->graphicsCommandList,
+            numBarriers,
+            barrierDesc);
+    }
+}
+
+static void D3D12_INTERNAL_TextureSubresourceBarrier(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_RESOURCE_STATES sourceState,
+    D3D12_RESOURCE_STATES destinationState,
+    D3D12TextureSubresource *textureSubresource)
+{
+    D3D12_INTERNAL_ResourceBarrier(
+        commandBuffer,
+        sourceState,
+        destinationState,
+        textureSubresource->parent->resource,
+        textureSubresource->index,
+        textureSubresource->parent->container->header.info.usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT);
+}
+
+static D3D12_RESOURCE_STATES D3D12_INTERNAL_DefaultTextureResourceState(
+    SDL_GpuTextureUsageFlags usageFlags)
+{
+    // NOTE: order matters here!
+
+    if (usageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) {
+        return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
+    } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT) {
+        return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
+    } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) {
+        return D3D12_RESOURCE_STATE_RENDER_TARGET;
+    } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) {
+        return D3D12_RESOURCE_STATE_DEPTH_WRITE;
+    } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT) {
+        return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+    } else if (usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+        return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Texture has no default usage mode!");
+        return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
+    }
+}
+
+static void D3D12_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_RESOURCE_STATES destinationUsageMode,
+    D3D12TextureSubresource *textureSubresource)
+{
+    D3D12_INTERNAL_TextureSubresourceBarrier(
+        commandBuffer,
+        D3D12_INTERNAL_DefaultTextureResourceState(textureSubresource->parent->container->header.info.usageFlags),
+        destinationUsageMode,
+        textureSubresource);
+}
+
+static void D3D12_INTERNAL_TextureTransitionFromDefaultUsage(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_RESOURCE_STATES destinationUsageMode,
+    D3D12Texture *texture)
+{
+    for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
+        D3D12_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+            commandBuffer,
+            destinationUsageMode,
+            &texture->subresources[i]);
+    }
+}
+
+static void D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_RESOURCE_STATES sourceUsageMode,
+    D3D12TextureSubresource *textureSubresource)
+{
+    D3D12_INTERNAL_TextureSubresourceBarrier(
+        commandBuffer,
+        sourceUsageMode,
+        D3D12_INTERNAL_DefaultTextureResourceState(textureSubresource->parent->container->header.info.usageFlags),
+        textureSubresource);
+}
+
+static void D3D12_INTERNAL_TextureTransitionToDefaultUsage(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_RESOURCE_STATES sourceUsageMode,
+    D3D12Texture *texture)
+{
+    for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
+        D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+            commandBuffer,
+            sourceUsageMode,
+            &texture->subresources[i]);
+    }
+}
+
+static D3D12_RESOURCE_STATES D3D12_INTERNAL_DefaultBufferResourceState(
+    D3D12Buffer *buffer)
+{
+    if (buffer->container->usageFlags & SDL_GPU_BUFFERUSAGE_VERTEX_BIT) {
+        return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
+    } else if (buffer->container->usageFlags & SDL_GPU_BUFFERUSAGE_INDEX_BIT) {
+        return D3D12_RESOURCE_STATE_INDEX_BUFFER;
+    } else if (buffer->container->usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT_BIT) {
+        return D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT;
+    } else if (buffer->container->usageFlags & SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT) {
+        return D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE;
+    } else if (buffer->container->usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ_BIT) {
+        return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
+    } else if (buffer->container->usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+        return D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Buffer has no default usage mode!");
+        return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
+    }
+}
+
+static void D3D12_INTERNAL_BufferBarrier(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_RESOURCE_STATES sourceState,
+    D3D12_RESOURCE_STATES destinationState,
+    D3D12Buffer *buffer)
+{
+    D3D12_INTERNAL_ResourceBarrier(
+        commandBuffer,
+        buffer->transitioned ? sourceState : D3D12_RESOURCE_STATE_COMMON,
+        destinationState,
+        buffer->handle,
+        0,
+        buffer->container->usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT);
+
+    buffer->transitioned = SDL_TRUE;
+}
+
+static void D3D12_INTERNAL_BufferTransitionFromDefaultUsage(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_RESOURCE_STATES destinationState,
+    D3D12Buffer *buffer)
+{
+    D3D12_INTERNAL_BufferBarrier(
+        commandBuffer,
+        D3D12_INTERNAL_DefaultBufferResourceState(buffer),
+        destinationState,
+        buffer);
+}
+
+static void D3D12_INTERNAL_BufferTransitionToDefaultUsage(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_RESOURCE_STATES sourceState,
+    D3D12Buffer *buffer)
+{
+    D3D12_INTERNAL_BufferBarrier(
+        commandBuffer,
+        sourceState,
+        D3D12_INTERNAL_DefaultBufferResourceState(buffer),
+        buffer);
+}
+
+// Resource tracking
+
+#define TRACK_RESOURCE(resource, type, array, count, capacity) \
+    Uint32 i;                                                  \
+                                                               \
+    for (i = 0; i < commandBuffer->count; i += 1) {            \
+        if (commandBuffer->array[i] == resource) {             \
+            return;                                            \
+        }                                                      \
+    }                                                          \
+                                                               \
+    if (commandBuffer->count == commandBuffer->capacity) {     \
+        commandBuffer->capacity += 1;                          \
+        commandBuffer->array = (type *)SDL_realloc(            \
+            commandBuffer->array,                              \
+            commandBuffer->capacity * sizeof(type));           \
+    }                                                          \
+    commandBuffer->array[commandBuffer->count] = resource;     \
+    commandBuffer->count += 1;                                 \
+    SDL_AtomicIncRef(&resource->referenceCount);
+
+static void D3D12_INTERNAL_TrackTexture(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12Texture *texture)
+{
+    TRACK_RESOURCE(
+        texture,
+        D3D12Texture *,
+        usedTextures,
+        usedTextureCount,
+        usedTextureCapacity)
+}
+
+static void D3D12_INTERNAL_TrackBuffer(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12Buffer *buffer)
+{
+    TRACK_RESOURCE(
+        buffer,
+        D3D12Buffer *,
+        usedBuffers,
+        usedBufferCount,
+        usedBufferCapacity)
+}
+
+static void D3D12_INTERNAL_TrackSampler(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12Sampler *sampler)
+{
+    TRACK_RESOURCE(
+        sampler,
+        D3D12Sampler *,
+        usedSamplers,
+        usedSamplerCount,
+        usedSamplerCapacity)
+}
+
+static void D3D12_INTERNAL_TrackGraphicsPipeline(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12GraphicsPipeline *graphicsPipeline)
+{
+    TRACK_RESOURCE(
+        graphicsPipeline,
+        D3D12GraphicsPipeline *,
+        usedGraphicsPipelines,
+        usedGraphicsPipelineCount,
+        usedGraphicsPipelineCapacity)
+}
+
+static void D3D12_INTERNAL_TrackComputePipeline(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12ComputePipeline *computePipeline)
+{
+    TRACK_RESOURCE(
+        computePipeline,
+        D3D12ComputePipeline *,
+        usedComputePipelines,
+        usedComputePipelineCount,
+        usedComputePipelineCapacity)
+}
+
+#undef TRACK_RESOURCE
+
+// State Creation
+
+static D3D12DescriptorHeap *D3D12_INTERNAL_CreateDescriptorHeap(
+    D3D12Renderer *renderer,
+    D3D12_DESCRIPTOR_HEAP_TYPE type,
+    Uint32 descriptorCount,
+    SDL_bool staging)
+{
+    D3D12DescriptorHeap *heap;
+    ID3D12DescriptorHeap *handle;
+    D3D12_DESCRIPTOR_HEAP_DESC heapDesc;
+    HRESULT res;
+
+    heap = (D3D12DescriptorHeap *)SDL_calloc(1, sizeof(D3D12DescriptorHeap));
+    if (!heap) {
+        return NULL;
+    }
+
+    heap->currentDescriptorIndex = 0;
+    heap->inactiveDescriptorCount = 0;
+    heap->inactiveDescriptorIndices = NULL;
+
+    if (staging) {
+        heap->inactiveDescriptorIndices = (Uint32 *)SDL_calloc(descriptorCount, sizeof(Uint32));
+        if (!heap->inactiveDescriptorIndices) {
+            D3D12_INTERNAL_DestroyDescriptorHeap(heap);
+            return NULL;
+        }
+    }
+
+    heapDesc.NumDescriptors = descriptorCount;
+    heapDesc.Type = type;
+    heapDesc.Flags = staging ? D3D12_DESCRIPTOR_HEAP_FLAG_NONE : D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
+    heapDesc.NodeMask = 0;
+
+    res = ID3D12Device_CreateDescriptorHeap(
+        renderer->device,
+        &heapDesc,
+        D3D_GUID(D3D_IID_ID3D12DescriptorHeap),
+        (void **)&handle);
+
+    if (FAILED(res)) {
+        D3D12_INTERNAL_LogError(renderer->device, "Failed to create descriptor heap!", res);
+        D3D12_INTERNAL_DestroyDescriptorHeap(heap);
+        return NULL;
+    }
+
+    heap->handle = handle;
+    heap->heapType = type;
+    heap->maxDescriptors = descriptorCount;
+    heap->staging = staging;
+    heap->descriptorSize = ID3D12Device_GetDescriptorHandleIncrementSize(renderer->device, type);
+    D3D_CALL_RET(handle, GetCPUDescriptorHandleForHeapStart, &heap->descriptorHeapCPUStart);
+    if (!staging) {
+        D3D_CALL_RET(handle, GetGPUDescriptorHandleForHeapStart, &heap->descriptorHeapGPUStart);
+    }
+
+    return heap;
+}
+
+static D3D12DescriptorHeap *D3D12_INTERNAL_AcquireDescriptorHeapFromPool(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_DESCRIPTOR_HEAP_TYPE descriptorHeapType)
+{
+    D3D12DescriptorHeap *result;
+    D3D12Renderer *renderer = commandBuffer->renderer;
+    D3D12DescriptorHeapPool *pool = &renderer->descriptorHeapPools[descriptorHeapType];
+
+    SDL_LockMutex(pool->lock);
+    if (pool->count > 0) {
+        result = pool->heaps[pool->count - 1];
+        pool->count -= 1;
+    } else {
+        result = D3D12_INTERNAL_CreateDescriptorHeap(
+            renderer,
+            descriptorHeapType,
+            descriptorHeapType == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ? VIEW_GPU_DESCRIPTOR_COUNT : SAMPLER_GPU_DESCRIPTOR_COUNT,
+            SDL_FALSE);
+    }
+    SDL_UnlockMutex(pool->lock);
+
+    return result;
+}
+
+static void D3D12_INTERNAL_ReturnDescriptorHeapToPool(
+    D3D12Renderer *renderer,
+    D3D12DescriptorHeap *heap)
+{
+    D3D12DescriptorHeapPool *pool = &renderer->descriptorHeapPools[heap->heapType];
+
+    heap->currentDescriptorIndex = 0;
+
+    SDL_LockMutex(pool->lock);
+    if (pool->count >= pool->capacity) {
+        pool->capacity *= 2;
+        pool->heaps = (D3D12DescriptorHeap **)SDL_realloc(
+            pool->heaps,
+            pool->capacity * sizeof(D3D12DescriptorHeap *));
+    }
+
+    pool->heaps[pool->count] = heap;
+    pool->count += 1;
+    SDL_UnlockMutex(pool->lock);
+}
+
+/*
+ * The root signature lets us define "root parameters" which are essentially bind points for resources.
+ * These let us define the register ranges as well as the register "space".
+ * The register space is akin to the descriptor set index in Vulkan, which allows us to group resources
+ * by stage so that the registers from the vertex and fragment shaders don't clobber each other.
+ *
+ * Most of our root parameters are implemented as "descriptor tables" so we can
+ * copy and then point to contiguous descriptor regions.
+ * Uniform buffers are the exception - these have to be implemented as raw "root descriptors" so
+ * that we can dynamically update the address that the constant buffer view points to.
+ *
+ * The root signature has a maximum size of 64 DWORDs.
+ * A descriptor table uses 1 DWORD.
+ * A root descriptor uses 2 DWORDS.
+ * This means our biggest root signature uses 24 DWORDs total, well under the limit.
+ *
+ * The root parameter indices are created dynamically and stored in the D3D12GraphicsRootSignature struct.
+ */
+static D3D12GraphicsRootSignature *D3D12_INTERNAL_CreateGraphicsRootSignature(
+    D3D12Renderer *renderer,
+    D3D12Shader *vertexShader,
+    D3D12Shader *fragmentShader)
+{
+    // FIXME: I think the max can be smaller...
+    D3D12_ROOT_PARAMETER rootParameters[MAX_ROOT_SIGNATURE_PARAMETERS];
+    D3D12_DESCRIPTOR_RANGE descriptorRanges[MAX_ROOT_SIGNATURE_PARAMETERS];
+    Uint32 parameterCount = 0;
+    Uint32 rangeCount = 0;
+    D3D12_DESCRIPTOR_RANGE descriptorRange;
+    D3D12_ROOT_PARAMETER rootParameter;
+    D3D12GraphicsRootSignature *d3d12GraphicsRootSignature =
+        (D3D12GraphicsRootSignature *)SDL_calloc(1, sizeof(D3D12GraphicsRootSignature));
+    if (!d3d12GraphicsRootSignature) {
+        return NULL;
+    }
+
+    SDL_zeroa(rootParameters);
+    SDL_zeroa(descriptorRanges);
+    SDL_zero(rootParameter);
+
+    d3d12GraphicsRootSignature->vertexSamplerRootIndex = -1;
+    d3d12GraphicsRootSignature->vertexSamplerTextureRootIndex = -1;
+    d3d12GraphicsRootSignature->vertexStorageTextureRootIndex = -1;
+    d3d12GraphicsRootSignature->vertexStorageBufferRootIndex = -1;
+
+    d3d12GraphicsRootSignature->fragmentSamplerRootIndex = -1;
+    d3d12GraphicsRootSignature->fragmentSamplerTextureRootIndex = -1;
+    d3d12GraphicsRootSignature->fragmentStorageTextureRootIndex = -1;
+    d3d12GraphicsRootSignature->fragmentStorageBufferRootIndex = -1;
+
+    for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        d3d12GraphicsRootSignature->vertexUniformBufferRootIndex[i] = -1;
+        d3d12GraphicsRootSignature->fragmentUniformBufferRootIndex[i] = -1;
+    }
+
+    if (vertexShader->samplerCount > 0) {
+        // Vertex Samplers
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
+        descriptorRange.NumDescriptors = vertexShader->samplerCount;
+        descriptorRange.BaseShaderRegister = 0;
+        descriptorRange.RegisterSpace = 0;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
+        rootParameters[parameterCount] = rootParameter;
+        d3d12GraphicsRootSignature->vertexSamplerRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+        descriptorRange.NumDescriptors = vertexShader->samplerCount;
+        descriptorRange.BaseShaderRegister = 0;
+        descriptorRange.RegisterSpace = 0;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
+        rootParameters[parameterCount] = rootParameter;
+        d3d12GraphicsRootSignature->vertexSamplerTextureRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+    }
+
+    if (vertexShader->storageTextureCount) {
+        // Vertex storage textures
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+        descriptorRange.NumDescriptors = vertexShader->storageTextureCount;
+        descriptorRange.BaseShaderRegister = vertexShader->samplerCount;
+        descriptorRange.RegisterSpace = 0;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
+        rootParameters[parameterCount] = rootParameter;
+        d3d12GraphicsRootSignature->vertexStorageTextureRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+    }
+
+    if (vertexShader->storageBufferCount) {
+
+        // Vertex storage buffers
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+        descriptorRange.NumDescriptors = vertexShader->storageBufferCount;
+        descriptorRange.BaseShaderRegister = vertexShader->samplerCount + vertexShader->storageTextureCount;
+        descriptorRange.RegisterSpace = 0;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
+        rootParameters[parameterCount] = rootParameter;
+        d3d12GraphicsRootSignature->vertexStorageBufferRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+    }
+
+    // Vertex Uniforms
+    for (Uint32 i = 0; i < vertexShader->uniformBufferCount; i += 1) {
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+        rootParameter.Descriptor.ShaderRegister = i;
+        rootParameter.Descriptor.RegisterSpace = 1;
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
+        rootParameters[parameterCount] = rootParameter;
+        d3d12GraphicsRootSignature->vertexUniformBufferRootIndex[i] = parameterCount;
+        parameterCount += 1;
+    }
+
+    if (fragmentShader->samplerCount) {
+        // Fragment Samplers
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
+        descriptorRange.NumDescriptors = fragmentShader->samplerCount;
+        descriptorRange.BaseShaderRegister = 0;
+        descriptorRange.RegisterSpace = 2;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+        rootParameters[parameterCount] = rootParameter;
+        d3d12GraphicsRootSignature->fragmentSamplerRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+        descriptorRange.NumDescriptors = fragmentShader->samplerCount;
+        descriptorRange.BaseShaderRegister = 0;
+        descriptorRange.RegisterSpace = 2;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+        rootParameters[parameterCount] = rootParameter;
+        d3d12GraphicsRootSignature->fragmentSamplerTextureRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+    }
+
+    if (fragmentShader->storageTextureCount) {
+        // Fragment Storage Textures
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+        descriptorRange.NumDescriptors = fragmentShader->storageTextureCount;
+        descriptorRange.BaseShaderRegister = fragmentShader->samplerCount;
+        descriptorRange.RegisterSpace = 2;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+        rootParameters[parameterCount] = rootParameter;
+        d3d12GraphicsRootSignature->fragmentStorageTextureRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+    }
+
+    if (fragmentShader->storageBufferCount) {
+        // Fragment Storage Buffers
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+        descriptorRange.NumDescriptors = fragmentShader->storageBufferCount;
+        descriptorRange.BaseShaderRegister = fragmentShader->samplerCount + fragmentShader->storageTextureCount;
+        descriptorRange.RegisterSpace = 2;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+        rootParameters[parameterCount] = rootParameter;
+        d3d12GraphicsRootSignature->fragmentStorageBufferRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+    }
+
+    // Fragment Uniforms
+    for (Uint32 i = 0; i < fragmentShader->uniformBufferCount; i += 1) {
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+        rootParameter.Descriptor.ShaderRegister = i;
+        rootParameter.Descriptor.RegisterSpace = 3;
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+        rootParameters[parameterCount] = rootParameter;
+        d3d12GraphicsRootSignature->fragmentUniformBufferRootIndex[i] = parameterCount;
+        parameterCount += 1;
+    }
+
+    // FIXME: shouldn't have to assert here
+    SDL_assert(parameterCount <= MAX_ROOT_SIGNATURE_PARAMETERS);
+    SDL_assert(rangeCount <= MAX_ROOT_SIGNATURE_PARAMETERS);
+
+    // Create the root signature description
+    D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
+    rootSignatureDesc.NumParameters = parameterCount;
+    rootSignatureDesc.pParameters = rootParameters;
+    rootSignatureDesc.NumStaticSamplers = 0;
+    rootSignatureDesc.pStaticSamplers = NULL;
+    rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
+
+    // Serialize the root signature
+    ID3DBlob *serializedRootSignature;
+    ID3DBlob *errorBlob;
+    HRESULT res = renderer->D3D12SerializeRootSignature_func(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &serializedRootSignature, &errorBlob);
+
+    if (FAILED(res)) {
+        if (errorBlob) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to serialize RootSignature: %s", (const char *)ID3D10Blob_GetBufferPointer(errorBlob));
+            ID3D10Blob_Release(errorBlob);
+        }
+        D3D12_INTERNAL_DestroyGraphicsRootSignature(d3d12GraphicsRootSignature);
+        return NULL;
+    }
+
+    // Create the root signature
+    ID3D12RootSignature *rootSignature;
+
+    res = ID3D12Device_CreateRootSignature(
+        renderer->device,
+        0,
+        ID3D10Blob_GetBufferPointer(serializedRootSignature),
+        ID3D10Blob_GetBufferSize(serializedRootSignature),
+        D3D_GUID(D3D_IID_ID3D12RootSignature),
+        (void **)&rootSignature);
+
+    if (FAILED(res)) {
+        if (errorBlob) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create RootSignature");
+            ID3D10Blob_Release(errorBlob);
+        }
+        D3D12_INTERNAL_DestroyGraphicsRootSignature(d3d12GraphicsRootSignature);
+        return NULL;
+    }
+
+    d3d12GraphicsRootSignature->handle = rootSignature;
+    return d3d12GraphicsRootSignature;
+}
+
+static SDL_bool D3D12_INTERNAL_CreateShaderBytecode(
+    D3D12Renderer *renderer,
+    Uint32 stage,
+    SDL_GpuShaderFormat format,
+    const Uint8 *code,
+    size_t codeSize,
+    const char *entryPointName,
+    void **pBytecode,
+    size_t *pBytecodeSize)
+{
+    if (pBytecode != NULL) {
+        *pBytecode = SDL_malloc(codeSize);
+        if (!*pBytecode) {
+            return SDL_FALSE;
+        }
+        SDL_memcpy(*pBytecode, code, codeSize);
+        *pBytecodeSize = codeSize;
+    }
+
+    return SDL_TRUE;
+}
+
+static D3D12ComputeRootSignature *D3D12_INTERNAL_CreateComputeRootSignature(
+    D3D12Renderer *renderer,
+    SDL_GpuComputePipelineCreateInfo *createInfo)
+{
+    // FIXME: I think the max can be smaller...
+    D3D12_ROOT_PARAMETER rootParameters[MAX_ROOT_SIGNATURE_PARAMETERS];
+    D3D12_DESCRIPTOR_RANGE descriptorRanges[MAX_ROOT_SIGNATURE_PARAMETERS];
+    Uint32 parameterCount = 0;
+    Uint32 rangeCount = 0;
+    D3D12_DESCRIPTOR_RANGE descriptorRange;
+    D3D12_ROOT_PARAMETER rootParameter;
+    D3D12ComputeRootSignature *d3d12ComputeRootSignature =
+        (D3D12ComputeRootSignature *)SDL_calloc(1, sizeof(D3D12ComputeRootSignature));
+    if (!d3d12ComputeRootSignature) {
+        return NULL;
+    }
+
+    SDL_zeroa(rootParameters);
+    SDL_zeroa(descriptorRanges);
+    SDL_zero(rootParameter);
+
+    d3d12ComputeRootSignature->readOnlyStorageTextureRootIndex = -1;
+    d3d12ComputeRootSignature->readOnlyStorageBufferRootIndex = -1;
+    d3d12ComputeRootSignature->writeOnlyStorageTextureRootIndex = -1;
+    d3d12ComputeRootSignature->writeOnlyStorageBufferRootIndex = -1;
+
+    for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        d3d12ComputeRootSignature->uniformBufferRootIndex[i] = -1;
+    }
+
+    if (createInfo->readOnlyStorageTextureCount) {
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+        descriptorRange.NumDescriptors = createInfo->readOnlyStorageTextureCount;
+        descriptorRange.BaseShaderRegister = 0;
+        descriptorRange.RegisterSpace = 0;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
+        rootParameters[parameterCount] = rootParameter;
+        d3d12ComputeRootSignature->readOnlyStorageTextureRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+    }
+
+    if (createInfo->readOnlyStorageBufferCount) {
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+        descriptorRange.NumDescriptors = createInfo->readOnlyStorageBufferCount;
+        descriptorRange.BaseShaderRegister = createInfo->readOnlyStorageTextureCount;
+        descriptorRange.RegisterSpace = 0;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
+        rootParameters[parameterCount] = rootParameter;
+        d3d12ComputeRootSignature->readOnlyStorageBufferRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+    }
+
+    if (createInfo->writeOnlyStorageTextureCount) {
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
+        descriptorRange.NumDescriptors = createInfo->writeOnlyStorageTextureCount;
+        descriptorRange.BaseShaderRegister = 0;
+        descriptorRange.RegisterSpace = 1;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
+        rootParameters[parameterCount] = rootParameter;
+        d3d12ComputeRootSignature->writeOnlyStorageTextureRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+    }
+
+    if (createInfo->writeOnlyStorageBufferCount) {
+        descriptorRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
+        descriptorRange.NumDescriptors = createInfo->writeOnlyStorageBufferCount;
+        descriptorRange.BaseShaderRegister = createInfo->writeOnlyStorageTextureCount;
+        descriptorRange.RegisterSpace = 1;
+        descriptorRange.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+        descriptorRanges[rangeCount] = descriptorRange;
+
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+        rootParameter.DescriptorTable.NumDescriptorRanges = 1;
+        rootParameter.DescriptorTable.pDescriptorRanges = &descriptorRanges[rangeCount];
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
+        rootParameters[parameterCount] = rootParameter;
+        d3d12ComputeRootSignature->writeOnlyStorageBufferRootIndex = parameterCount;
+        rangeCount += 1;
+        parameterCount += 1;
+    }
+
+    for (Uint32 i = 0; i < createInfo->uniformBufferCount; i += 1) {
+        rootParameter.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+        rootParameter.Descriptor.ShaderRegister = i;
+        rootParameter.Descriptor.RegisterSpace = 2;
+        rootParameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; // ALL is used for compute
+        rootParameters[parameterCount] = rootParameter;
+        d3d12ComputeRootSignature->uniformBufferRootIndex[i] = parameterCount;
+        parameterCount += 1;
+    }
+
+    D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
+    rootSignatureDesc.NumParameters = parameterCount;
+    rootSignatureDesc.pParameters = rootParameters;
+    rootSignatureDesc.NumStaticSamplers = 0;
+    rootSignatureDesc.pStaticSamplers = NULL;
+    rootSignatureDesc.Flags = (D3D12_ROOT_SIGNATURE_FLAGS)0;
+
+    ID3DBlob *serializedRootSignature;
+    ID3DBlob *errorBlob;
+    HRESULT res = renderer->D3D12SerializeRootSignature_func(
+        &rootSignatureDesc,
+        D3D_ROOT_SIGNATURE_VERSION_1,
+        &serializedRootSignature,
+        &errorBlob);
+
+    if (FAILED(res)) {
+        if (errorBlob) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to serialize RootSignature: %s", (const char *)ID3D10Blob_GetBufferPointer(errorBlob));
+            ID3D10Blob_Release(errorBlob);
+        }
+        D3D12_INTERNAL_DestroyComputeRootSignature(d3d12ComputeRootSignature);
+        return NULL;
+    }
+
+    ID3D12RootSignature *rootSignature;
+
+    res = ID3D12Device_CreateRootSignature(
+        renderer->device,
+        0,
+        ID3D10Blob_GetBufferPointer(serializedRootSignature),
+        ID3D10Blob_GetBufferSize(serializedRootSignature),
+        D3D_GUID(D3D_IID_ID3D12RootSignature),
+        (void **)&rootSignature);
+
+    if (FAILED(res)) {
+        if (errorBlob) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create RootSignature");
+            ID3D10Blob_Release(errorBlob);
+        }
+        D3D12_INTERNAL_DestroyComputeRootSignature(d3d12ComputeRootSignature);
+        return NULL;
+    }
+
+    d3d12ComputeRootSignature->handle = rootSignature;
+    return d3d12ComputeRootSignature;
+}
+
+static SDL_GpuComputePipeline *D3D12_CreateComputePipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuComputePipelineCreateInfo *pipelineCreateInfo)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    void *bytecode;
+    size_t bytecodeSize;
+    ID3D12PipelineState *pipelineState;
+
+    if (!D3D12_INTERNAL_CreateShaderBytecode(
+            renderer,
+            SDL_GPU_SHADERSTAGE_COMPUTE,
+            pipelineCreateInfo->format,
+            pipelineCreateInfo->code,
+            pipelineCreateInfo->codeSize,
+            pipelineCreateInfo->entryPointName,
+            &bytecode,
+            &bytecodeSize)) {
+        return NULL;
+    }
+
+    D3D12ComputeRootSignature *rootSignature = D3D12_INTERNAL_CreateComputeRootSignature(
+        renderer,
+        pipelineCreateInfo);
+
+    if (rootSignature == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not create root signature!");
+        SDL_free(bytecode);
+        return NULL;
+    }
+
+    D3D12_COMPUTE_PIPELINE_STATE_DESC pipelineDesc;
+    pipelineDesc.CS.pShaderBytecode = bytecode;
+    pipelineDesc.CS.BytecodeLength = bytecodeSize;
+    pipelineDesc.pRootSignature = rootSignature->handle;
+    pipelineDesc.CachedPSO.CachedBlobSizeInBytes = 0;
+    pipelineDesc.CachedPSO.pCachedBlob = NULL;
+    pipelineDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
+    pipelineDesc.NodeMask = 0;
+
+    HRESULT res = ID3D12Device_CreateComputePipelineState(
+        renderer->device,
+        &pipelineDesc,
+        D3D_GUID(D3D_IID_ID3D12PipelineState),
+        (void **)&pipelineState);
+
+    if (FAILED(res)) {
+        D3D12_INTERNAL_LogError(renderer->device, "Could not create compute pipeline state", res);
+        SDL_free(bytecode);
+        return NULL;
+    }
+
+    D3D12ComputePipeline *computePipeline =
+        (D3D12ComputePipeline *)SDL_calloc(1, sizeof(D3D12ComputePipeline));
+
+    if (!computePipeline) {
+        ID3D12PipelineState_Release(pipelineState);
+        SDL_free(bytecode);
+        return NULL;
+    }
+
+    computePipeline->pipelineState = pipelineState;
+    computePipeline->rootSignature = rootSignature;
+    computePipeline->readOnlyStorageTextureCount = pipelineCreateInfo->readOnlyStorageTextureCount;
+    computePipeline->readOnlyStorageBufferCount = pipelineCreateInfo->readOnlyStorageBufferCount;
+    computePipeline->writeOnlyStorageTextureCount = pipelineCreateInfo->writeOnlyStorageTextureCount;
+    computePipeline->writeOnlyStorageBufferCount = pipelineCreateInfo->writeOnlyStorageBufferCount;
+    computePipeline->uniformBufferCount = pipelineCreateInfo->uniformBufferCount;
+    SDL_AtomicSet(&computePipeline->referenceCount, 0);
+
+    return (SDL_GpuComputePipeline *)computePipeline;
+}
+
+static SDL_bool D3D12_INTERNAL_ConvertRasterizerState(SDL_GpuRasterizerState rasterizerState, D3D12_RASTERIZER_DESC *desc)
+{
+    if (!desc) {
+        return SDL_FALSE;
+    }
+
+    desc->FillMode = SDLToD3D12_FillMode[rasterizerState.fillMode];
+    desc->CullMode = SDLToD3D12_CullMode[rasterizerState.cullMode];
+
+    switch (rasterizerState.frontFace) {
+    case SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE:
+        desc->FrontCounterClockwise = TRUE;
+        break;
+    case SDL_GPU_FRONTFACE_CLOCKWISE:
+        desc->FrontCounterClockwise = FALSE;
+        break;
+    default:
+        return SDL_FALSE;
+    }
+
+    if (rasterizerState.depthBiasEnable) {
+        desc->DepthBias = SDL_lroundf(rasterizerState.depthBiasConstantFactor);
+        desc->DepthBiasClamp = rasterizerState.depthBiasClamp;
+        desc->SlopeScaledDepthBias = rasterizerState.depthBiasSlopeFactor;
+    } else {
+        desc->DepthBias = 0;
+        desc->DepthBiasClamp = 0.0f;
+        desc->SlopeScaledDepthBias = 0.0f;
+    }
+
+    desc->DepthClipEnable = TRUE;
+    desc->MultisampleEnable = FALSE;
+    desc->AntialiasedLineEnable = FALSE;
+    desc->ForcedSampleCount = 0;
+    desc->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
+
+    return SDL_TRUE;
+}
+
+static SDL_bool D3D12_INTERNAL_ConvertBlendState(SDL_GpuGraphicsPipelineCreateInfo *pipelineInfo, D3D12_BLEND_DESC *blendDesc)
+{
+    if (!blendDesc) {
+        return SDL_FALSE;
+    }
+
+    SDL_zerop(blendDesc);
+    blendDesc->AlphaToCoverageEnable = FALSE;
+    blendDesc->IndependentBlendEnable = FALSE;
+
+    for (UINT i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
+        D3D12_RENDER_TARGET_BLEND_DESC rtBlendDesc;
+        rtBlendDesc.BlendEnable = FALSE;
+        rtBlendDesc.LogicOpEnable = FALSE;
+        rtBlendDesc.SrcBlend = D3D12_BLEND_ONE;
+        rtBlendDesc.DestBlend = D3D12_BLEND_ZERO;
+        rtBlendDesc.BlendOp = D3D12_BLEND_OP_ADD;
+        rtBlendDesc.SrcBlendAlpha = D3D12_BLEND_ONE;
+        rtBlendDesc.DestBlendAlpha = D3D12_BLEND_ZERO;
+        rtBlendDesc.BlendOpAlpha = D3D12_BLEND_OP_ADD;
+        rtBlendDesc.LogicOp = D3D12_LOGIC_OP_NOOP;
+        rtBlendDesc.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
+
+        // If attachmentInfo has more blend states, you can set IndependentBlendEnable to TRUE and assign different blend states to each render target slot
+        if (i < pipelineInfo->attachmentInfo.colorAttachmentCount) {
+
+            SDL_GpuColorAttachmentBlendState sdlBlendState = pipelineInfo->attachmentInfo.colorAttachmentDescriptions[i].blendState;
+
+            rtBlendDesc.BlendEnable = sdlBlendState.blendEnable;
+            rtBlendDesc.SrcBlend = SDLToD3D12_BlendFactor[sdlBlendState.srcColorBlendFactor];
+            rtBlendDesc.DestBlend = SDLToD3D12_BlendFactor[sdlBlendState.dstColorBlendFactor];
+            rtBlendDesc.BlendOp = SDLToD3D12_BlendOp[sdlBlendState.colorBlendOp];
+            rtBlendDesc.SrcBlendAlpha = SDLToD3D12_BlendFactorAlpha[sdlBlendState.srcAlphaBlendFactor];
+            rtBlendDesc.DestBlendAlpha = SDLToD3D12_BlendFactorAlpha[sdlBlendState.dstAlphaBlendFactor];
+            rtBlendDesc.BlendOpAlpha = SDLToD3D12_BlendOp[sdlBlendState.alphaBlendOp];
+            rtBlendDesc.RenderTargetWriteMask = sdlBlendState.colorWriteMask;
+
+            if (i > 0) {
+                blendDesc->IndependentBlendEnable = TRUE;
+            }
+        }
+
+        blendDesc->RenderTarget[i] = rtBlendDesc;
+    }
+
+    return SDL_TRUE;
+}
+
+static SDL_bool D3D12_INTERNAL_ConvertDepthStencilState(SDL_GpuDepthStencilState depthStencilState, D3D12_DEPTH_STENCIL_DESC *desc)
+{
+    if (desc == NULL) {
+        return SDL_FALSE;
+    }
+
+    desc->DepthEnable = depthStencilState.depthTestEnable == SDL_TRUE ? TRUE : FALSE;
+    desc->DepthWriteMask = depthStencilState.depthWriteEnable == SDL_TRUE ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO;
+    desc->DepthFunc = SDLToD3D12_CompareOp[depthStencilState.compareOp];
+    desc->StencilEnable = depthStencilState.stencilTestEnable == SDL_TRUE ? TRUE : FALSE;
+    desc->StencilReadMask = depthStencilState.compareMask;
+    desc->StencilWriteMask = depthStencilState.writeMask;
+
+    desc->FrontFace.StencilFailOp = SDLToD3D12_StencilOp[depthStencilState.frontStencilState.failOp];
+    desc->FrontFace.StencilDepthFailOp = SDLToD3D12_StencilOp[depthStencilState.frontStencilState.depthFailOp];
+    desc->FrontFace.StencilPassOp = SDLToD3D12_StencilOp[depthStencilState.frontStencilState.passOp];
+    desc->FrontFace.StencilFunc = SDLToD3D12_CompareOp[depthStencilState.frontStencilState.compareOp];
+
+    desc->BackFace.StencilFailOp = SDLToD3D12_StencilOp[depthStencilState.backStencilState.failOp];
+    desc->BackFace.StencilDepthFailOp = SDLToD3D12_StencilOp[depthStencilState.backStencilState.depthFailOp];
+    desc->BackFace.StencilPassOp = SDLToD3D12_StencilOp[depthStencilState.backStencilState.passOp];
+    desc->BackFace.StencilFunc = SDLToD3D12_CompareOp[depthStencilState.backStencilState.compareOp];
+
+    return SDL_TRUE;
+}
+
+static SDL_bool D3D12_INTERNAL_ConvertVertexInputState(SDL_GpuVertexInputState vertexInputState, D3D12_INPUT_ELEMENT_DESC *desc, const char *semantic)
+{
+    if (desc == NULL || vertexInputState.vertexAttributeCount == 0) {
+        return SDL_FALSE;
+    }
+
+    for (Uint32 i = 0; i < vertexInputState.vertexAttributeCount; i += 1) {
+        SDL_GpuVertexAttribute attribute = vertexInputState.vertexAttributes[i];
+
+        desc[i].SemanticName = semantic;
+        desc[i].SemanticIndex = attribute.location;
+        desc[i].Format = SDLToD3D12_VertexFormat[attribute.format];
+        desc[i].InputSlot = attribute.binding;
+        desc[i].AlignedByteOffset = attribute.offset;
+        desc[i].InputSlotClass = SDLToD3D12_InputRate[vertexInputState.vertexBindings[attribute.binding].inputRate];
+        desc[i].InstanceDataStepRate = (vertexInputState.vertexBindings[attribute.binding].inputRate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) ? vertexInputState.vertexBindings[attribute.binding].instanceStepRate : 0;
+    }
+
+    return SDL_TRUE;
+}
+
+static void D3D12_INTERNAL_AssignCpuDescriptorHandle(
+    D3D12Renderer *renderer,
+    D3D12_DESCRIPTOR_HEAP_TYPE heapType,
+    D3D12CPUDescriptor *cpuDescriptor)
+{
+    D3D12DescriptorHeap *heap = renderer->stagingDescriptorHeaps[heapType];
+    Uint32 descriptorIndex;
+
+    cpuDescriptor->heap = heap;
+
+    SDL_LockMutex(renderer->stagingDescriptorHeapLock);
+
+    if (heap->inactiveDescriptorCount > 0) {
+        descriptorIndex = heap->inactiveDescriptorIndices[heap->inactiveDescriptorCount - 1];
+        heap->inactiveDescriptorCount -= 1;
+    } else if (heap->currentDescriptorIndex < heap->maxDescriptors) {
+        descriptorIndex = heap->currentDescriptorIndex;
+        heap->currentDescriptorIndex += 1;
+    } else {
+        cpuDescriptor->cpuHandleIndex = SDL_MAX_UINT32;
+        cpuDescriptor->cpuHandle.ptr = 0;
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Out of CPU descriptor handles, many bad things are going to happen!");
+        SDL_UnlockMutex(renderer->stagingDescriptorHeapLock);
+        return;
+    }
+
+    SDL_UnlockMutex(renderer->stagingDescriptorHeapLock);
+
+    cpuDescriptor->cpuHandleIndex = descriptorIndex;
+    cpuDescriptor->cpuHandle.ptr = heap->descriptorHeapCPUStart.ptr + (descriptorIndex * heap->descriptorSize);
+}
+
+static SDL_GpuGraphicsPipeline *D3D12_CreateGraphicsPipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuGraphicsPipelineCreateInfo *pipelineCreateInfo)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12Shader *vertShader = (D3D12Shader *)pipelineCreateInfo->vertexShader;
+    D3D12Shader *fragShader = (D3D12Shader *)pipelineCreateInfo->fragmentShader;
+
+    D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc;
+    SDL_zero(psoDesc);
+    psoDesc.VS.pShaderBytecode = vertShader->bytecode;
+    psoDesc.VS.BytecodeLength = vertShader->bytecodeSize;
+    psoDesc.PS.pShaderBytecode = fragShader->bytecode;
+    psoDesc.PS.BytecodeLength = fragShader->bytecodeSize;
+
+    D3D12_INPUT_ELEMENT_DESC inputElementDescs[D3D12_IA_VERTEX_INPUT_STRUCTURE_ELEMENT_COUNT];
+    if (pipelineCreateInfo->vertexInputState.vertexAttributeCount > 0) {
+        psoDesc.InputLayout.pInputElementDescs = inputElementDescs;
+        psoDesc.InputLayout.NumElements = pipelineCreateInfo->vertexInputState.vertexAttributeCount;
+        D3D12_INTERNAL_ConvertVertexInputState(pipelineCreateInfo->vertexInputState, inputElementDescs, renderer->semantic);
+    }
+
+    psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
+
+    if (!D3D12_INTERNAL_ConvertRasterizerState(pipelineCreateInfo->rasterizerState, &psoDesc.RasterizerState)) {
+        return NULL;
+    }
+    if (!D3D12_INTERNAL_ConvertBlendState(pipelineCreateInfo, &psoDesc.BlendState)) {
+        return NULL;
+    }
+    if (!D3D12_INTERNAL_ConvertDepthStencilState(pipelineCreateInfo->depthStencilState, &psoDesc.DepthStencilState)) {
+        return NULL;
+    }
+
+    D3D12GraphicsPipeline *pipeline = (D3D12GraphicsPipeline *)SDL_calloc(1, sizeof(D3D12GraphicsPipeline));
+    if (!pipeline) {
+        return NULL;
+    }
+
+    psoDesc.SampleMask = UINT_MAX;
+    psoDesc.SampleDesc.Count = SDLToD3D12_SampleCount[pipelineCreateInfo->multisampleState.sampleCount];
+    psoDesc.SampleDesc.Quality = 0;
+
+    psoDesc.DSVFormat = SDLToD3D12_TextureFormat[pipelineCreateInfo->attachmentInfo.depthStencilFormat];
+    psoDesc.NumRenderTargets = pipelineCreateInfo->attachmentInfo.colorAttachmentCount;
+    for (uint32_t i = 0; i < pipelineCreateInfo->attachmentInfo.colorAttachmentCount; i += 1) {
+        psoDesc.RTVFormats[i] = SDLToD3D12_TextureFormat[pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].format];
+    }
+
+    // Assuming some default values or further initialization
+    psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
+    psoDesc.CachedPSO.CachedBlobSizeInBytes = 0;
+    psoDesc.CachedPSO.pCachedBlob = NULL;
+
+    psoDesc.NodeMask = 0;
+
+    D3D12GraphicsRootSignature *rootSignature = D3D12_INTERNAL_CreateGraphicsRootSignature(
+        renderer,
+        vertShader,
+        fragShader);
+
+    if (rootSignature == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not create root signature!");
+        D3D12_INTERNAL_DestroyGraphicsPipeline(pipeline);
+        return NULL;
+    }
+    pipeline->rootSignature = rootSignature;
+
+    psoDesc.pRootSignature = rootSignature->handle;
+    ID3D12PipelineState *pipelineState;
+
+    HRESULT res = ID3D12Device_CreateGraphicsPipelineState(
+        renderer->device,
+        &psoDesc,
+        D3D_GUID(D3D_IID_ID3D12PipelineState),
+        (void **)&pipelineState);
+    if (FAILED(res)) {
+        D3D12_INTERNAL_LogError(renderer->device, "Could not create graphics pipeline state", res);
+        D3D12_INTERNAL_DestroyGraphicsPipeline(pipeline);
+        return NULL;
+    }
+
+    pipeline->pipelineState = pipelineState;
+
+    for (Uint32 i = 0; i < pipelineCreateInfo->vertexInputState.vertexBindingCount; i += 1) {
+        pipeline->vertexStrides[i] = pipelineCreateInfo->vertexInputState.vertexBindings[i].stride;
+    }
+
+    pipeline->primitiveType = pipelineCreateInfo->primitiveType;
+    pipeline->blendConstants[0] = pipelineCreateInfo->blendConstants[0];
+    pipeline->blendConstants[1] = pipelineCreateInfo->blendConstants[1];
+    pipeline->blendConstants[2] = pipelineCreateInfo->blendConstants[2];
+    pipeline->blendConstants[3] = pipelineCreateInfo->blendConstants[3];
+    pipeline->stencilRef = pipelineCreateInfo->depthStencilState.reference;
+
+    pipeline->vertexSamplerCount = vertShader->samplerCount;
+    pipeline->vertexStorageTextureCount = vertShader->storageTextureCount;
+    pipeline->vertexStorageBufferCount = vertShader->storageBufferCount;
+    pipeline->vertexUniformBufferCount = vertShader->uniformBufferCount;
+
+    pipeline->fragmentSamplerCount = fragShader->samplerCount;
+    pipeline->fragmentStorageTextureCount = fragShader->storageTextureCount;
+    pipeline->fragmentStorageBufferCount = fragShader->storageBufferCount;
+    pipeline->fragmentUniformBufferCount = fragShader->uniformBufferCount;
+
+    SDL_AtomicSet(&pipeline->referenceCount, 0);
+    return (SDL_GpuGraphicsPipeline *)pipeline;
+}
+
+static SDL_GpuSampler *D3D12_CreateSampler(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuSamplerCreateInfo *samplerCreateInfo)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12Sampler *sampler = (D3D12Sampler *)SDL_calloc(1, sizeof(D3D12Sampler));
+    if (!sampler) {
+        return NULL;
+    }
+    D3D12_SAMPLER_DESC samplerDesc;
+
+    samplerDesc.Filter = SDLToD3D12_Filter(
+        samplerCreateInfo->minFilter,
+        samplerCreateInfo->magFilter,
+        samplerCreateInfo->mipmapMode,
+        samplerCreateInfo->compareEnable,
+        samplerCreateInfo->anisotropyEnable);
+    samplerDesc.AddressU = SDLToD3D12_SamplerAddressMode[samplerCreateInfo->addressModeU];
+    samplerDesc.AddressV = SDLToD3D12_SamplerAddressMode[samplerCreateInfo->addressModeV];
+    samplerDesc.AddressW = SDLToD3D12_SamplerAddressMode[samplerCreateInfo->addressModeW];
+    samplerDesc.MaxAnisotropy = (Uint32)samplerCreateInfo->maxAnisotropy;
+    samplerDesc.ComparisonFunc = SDLToD3D12_CompareOp[samplerCreateInfo->compareOp];
+    samplerDesc.MinLOD = samplerCreateInfo->minLod;
+    samplerDesc.MaxLOD = samplerCreateInfo->maxLod;
+    samplerDesc.MipLODBias = samplerCreateInfo->mipLodBias;
+    samplerDesc.BorderColor[0] = 0;
+    samplerDesc.BorderColor[1] = 0;
+    samplerDesc.BorderColor[2] = 0;
+    samplerDesc.BorderColor[3] = 0;
+
+    D3D12_INTERNAL_AssignCpuDescriptorHandle(
+        renderer,
+        D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
+        &sampler->handle);
+
+    ID3D12Device_CreateSampler(
+        renderer->device,
+        &samplerDesc,
+        sampler->handle.cpuHandle);
+
+    sampler->createInfo = *samplerCreateInfo;
+    SDL_AtomicSet(&sampler->referenceCount, 0);
+    return (SDL_GpuSampler *)sampler;
+}
+
+static SDL_GpuShader *D3D12_CreateShader(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuShaderCreateInfo *shaderCreateInfo)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    void *bytecode;
+    size_t bytecodeSize;
+    D3D12Shader *shader;
+
+    if (!D3D12_INTERNAL_CreateShaderBytecode(
+            renderer,
+            shaderCreateInfo->stage,
+            shaderCreateInfo->format,
+            shaderCreateInfo->code,
+            shaderCreateInfo->codeSize,
+            shaderCreateInfo->entryPointName,
+            &bytecode,
+            &bytecodeSize)) {
+        return NULL;
+    }
+    shader = (D3D12Shader *)SDL_calloc(1, sizeof(D3D12Shader));
+    if (!shader) {
+        SDL_free(bytecode);
+        return NULL;
+    }
+    shader->samplerCount = shaderCreateInfo->samplerCount;
+    shader->storageBufferCount = shaderCreateInfo->storageBufferCount;
+    shader->storageTextureCount = shaderCreateInfo->storageTextureCount;
+    shader->uniformBufferCount = shaderCreateInfo->uniformBufferCount;
+
+    shader->bytecode = bytecode;
+    shader->bytecodeSize = bytecodeSize;
+
+    return (SDL_GpuShader *)shader;
+}
+
+static D3D12Texture *D3D12_INTERNAL_CreateTexture(
+    D3D12Renderer *renderer,
+    SDL_GpuTextureCreateInfo *textureCreateInfo,
+    SDL_bool isSwapchainTexture)
+{
+    D3D12Texture *texture;
+    ID3D12Resource *handle;
+    D3D12_HEAP_PROPERTIES heapProperties;
+    D3D12_HEAP_FLAGS heapFlags = (D3D12_HEAP_FLAGS)0;
+    D3D12_RESOURCE_DESC desc;
+    D3D12_RESOURCE_FLAGS resourceFlags = (D3D12_RESOURCE_FLAGS)0;
+    D3D12_RESOURCE_STATES initialState = (D3D12_RESOURCE_STATES)0;
+    D3D12_CLEAR_VALUE clearValue;
+    SDL_bool useClearValue = SDL_FALSE;
+    HRESULT res;
+
+    texture = (D3D12Texture *)SDL_calloc(1, sizeof(D3D12Texture));
+    if (!texture) {
+        return NULL;
+    }
+
+    Uint32 layerCount = textureCreateInfo->type == SDL_GPU_TEXTURETYPE_3D ? 1 : textureCreateInfo->layerCountOrDepth;
+    Uint32 depth = textureCreateInfo->type == SDL_GPU_TEXTURETYPE_3D ? textureCreateInfo->layerCountOrDepth : 1;
+
+    if (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) {
+        resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
+        useClearValue = SDL_TRUE;
+        clearValue.Color[0] = SDL_GetFloatProperty(textureCreateInfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_R_FLOAT, 0);
+        clearValue.Color[1] = SDL_GetFloatProperty(textureCreateInfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_G_FLOAT, 0);
+        clearValue.Color[2] = SDL_GetFloatProperty(textureCreateInfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_B_FLOAT, 0);
+        clearValue.Color[3] = SDL_GetFloatProperty(textureCreateInfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_A_FLOAT, 0);
+    }
+
+    if (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) {
+        resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
+        useClearValue = SDL_TRUE;
+        clearValue.DepthStencil.Depth = SDL_GetFloatProperty(textureCreateInfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_DEPTH_FLOAT, 0);
+        clearValue.DepthStencil.Stencil = (UINT8)SDL_GetNumberProperty(textureCreateInfo->props, SDL_PROP_GPU_CREATETEXTURE_D3D12_CLEAR_STENCIL_UINT8, 0);
+    }
+
+    if (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+        resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+    }
+
+    heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
+    heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+    heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+    heapProperties.CreationNodeMask = 0; // We don't do multi-adapter operation
+    heapProperties.VisibleNodeMask = 0;  // We don't do multi-adapter operation
+
+    heapFlags = isSwapchainTexture ? D3D12_HEAP_FLAG_ALLOW_DISPLAY : D3D12_HEAP_FLAG_NONE;
+
+    if (textureCreateInfo->type != SDL_GPU_TEXTURETYPE_3D) {
+        desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
+        desc.Alignment = isSwapchainTexture ? 0 : D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+        desc.Width = textureCreateInfo->width;
+        desc.Height = textureCreateInfo->height;
+        desc.DepthOrArraySize = textureCreateInfo->layerCountOrDepth;
+        desc.MipLevels = textureCreateInfo->levelCount;
+        desc.Format = SDLToD3D12_TextureFormat[textureCreateInfo->format];
+        desc.SampleDesc.Count = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; // Apparently this is the most efficient choice
+        desc.Flags = resourceFlags;
+    } else {
+        desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
+        desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+        desc.Width = textureCreateInfo->width;
+        desc.Height = textureCreateInfo->height;
+        desc.DepthOrArraySize = textureCreateInfo->layerCountOrDepth;
+        desc.MipLevels = textureCreateInfo->levelCount;
+        desc.Format = SDLToD3D12_TextureFormat[textureCreateInfo->format];
+        desc.SampleDesc.Count = 1;
+        desc.SampleDesc.Quality = 0;
+        desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
+        desc.Flags = resourceFlags;
+    }
+
+    initialState = isSwapchainTexture ? D3D12_RESOURCE_STATE_PRESENT : D3D12_INTERNAL_DefaultTextureResourceState(textureCreateInfo->usageFlags);
+    clearValue.Format = desc.Format;
+
+    res = ID3D12Device_CreateCommittedResource(
+        renderer->device,
+        &heapProperties,
+        heapFlags,
+        &desc,
+        initialState,
+        useClearValue ? &clearValue : NULL,
+        D3D_GUID(D3D_IID_ID3D12Resource),
+        (void **)&handle);
+    if (FAILED(res)) {
+        D3D12_INTERNAL_LogError(renderer->device, "Failed to create texture!", res);
+        D3D12_INTERNAL_DestroyTexture(renderer, texture);
+        return NULL;
+    }
+
+    texture->resource = handle;
+
+    // Create the SRV if applicable
+    if ((textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) ||
+        (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT) ||
+        (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT)) {
+        D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
+
+        D3D12_INTERNAL_AssignCpuDescriptorHandle(
+            renderer,
+            D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+            &texture->srvHandle);
+
+        srvDesc.Format = SDLToD3D12_TextureFormat[textureCreateInfo->format];
+        srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+
+        if (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+            srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
+            srvDesc.TextureCube.MipLevels = textureCreateInfo->levelCount;
+            srvDesc.TextureCube.MostDetailedMip = 0;
+            srvDesc.TextureCube.ResourceMinLODClamp = 0;
+        } else if (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
+            srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
+            srvDesc.Texture2DArray.MipLevels = textureCreateInfo->levelCount;
+            srvDesc.Texture2DArray.MostDetailedMip = 0;
+            srvDesc.Texture2DArray.FirstArraySlice = 0;
+            srvDesc.Texture2DArray.ArraySize = layerCount;
+            srvDesc.Texture2DArray.ResourceMinLODClamp = 0;
+            srvDesc.Texture2DArray.PlaneSlice = 0;
+        } else if (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_3D) {
+            srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
+            srvDesc.Texture3D.MipLevels = textureCreateInfo->levelCount;
+            srvDesc.Texture3D.MostDetailedMip = 0;
+            srvDesc.Texture3D.ResourceMinLODClamp = 0; // default behavior
+        } else {
+            srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+            srvDesc.Texture2D.MipLevels = textureCreateInfo->levelCount;
+            srvDesc.Texture2D.MostDetailedMip = 0;
+            srvDesc.Texture2D.PlaneSlice = 0;
+            srvDesc.Texture2D.ResourceMinLODClamp = 0; // default behavior
+        }
+
+        ID3D12Device_CreateShaderResourceView(
+            renderer->device,
+            handle,
+            &srvDesc,
+            texture->srvHandle.cpuHandle);
+    }
+
+    SDL_AtomicSet(&texture->referenceCount, 0);
+
+    texture->subresourceCount = textureCreateInfo->levelCount * layerCount;
+    texture->subresources = (D3D12TextureSubresource *)SDL_calloc(
+        texture->subresourceCount, sizeof(D3D12TextureSubresource));
+    if (!texture->subresources) {
+        D3D12_INTERNAL_DestroyTexture(renderer, texture);
+        return NULL;
+    }
+    for (Uint32 layerIndex = 0; layerIndex < layerCount; layerIndex += 1) {
+        for (Uint32 levelIndex = 0; levelIndex < textureCreateInfo->levelCount; levelIndex += 1) {
+            Uint32 subresourceIndex = D3D12_INTERNAL_CalcSubresource(
+                levelIndex,
+                layerIndex,
+                textureCreateInfo->levelCount);
+
+            texture->subresources[subresourceIndex].parent = texture;
+            texture->subresources[subresourceIndex].layer = layerIndex;
+            texture->subresources[subresourceIndex].level = levelIndex;
+            texture->subresources[subresourceIndex].depth = depth;
+            texture->subresources[subresourceIndex].index = subresourceIndex;
+
+            texture->subresources[subresourceIndex].rtvHandles = NULL;
+            texture->subresources[subresourceIndex].uavHandle.heap = NULL;
+            texture->subresources[subresourceIndex].dsvHandle.heap = NULL;
+
+            // Create RTV if needed
+            if (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) {
+                texture->subresources[subresourceIndex].rtvHandles = (D3D12CPUDescriptor *)SDL_calloc(depth, sizeof(D3D12CPUDescriptor));
+
+                for (Uint32 depthIndex = 0; depthIndex < depth; depthIndex += 1) {
+                    D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
+
+                    D3D12_INTERNAL_AssignCpuDescriptorHandle(
+                        renderer,
+                        D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
+                        &texture->subresources[subresourceIndex].rtvHandles[depthIndex]);
+
+                    rtvDesc.Format = SDLToD3D12_TextureFormat[textureCreateInfo->format];
+
+                    if (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || textureCreateInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+                        rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
+                        rtvDesc.Texture2DArray.MipSlice = levelIndex;
+                        rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
+                        rtvDesc.Texture2DArray.ArraySize = 1;
+                        rtvDesc.Texture2DArray.PlaneSlice = 0;
+                    } else if (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_3D) {
+                        rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE3D;
+                        rtvDesc.Texture3D.MipSlice = levelIndex;
+                        rtvDesc.Texture3D.FirstWSlice = depthIndex;
+                        rtvDesc.Texture3D.WSize = 1;
+                    } else {
+                        rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
+                        rtvDesc.Texture2D.MipSlice = levelIndex;
+                        rtvDesc.Texture2D.PlaneSlice = 0;
+                    }
+
+                    ID3D12Device_CreateRenderTargetView(
+                        renderer->device,
+                        texture->resource,
+                        &rtvDesc,
+                        texture->subresources[subresourceIndex].rtvHandles[depthIndex].cpuHandle);
+                }
+            }
+
+            // Create DSV if needed
+            if (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) {
+                D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+
+                D3D12_INTERNAL_AssignCpuDescriptorHandle(
+                    renderer,
+                    D3D12_DESCRIPTOR_HEAP_TYPE_DSV,
+                    &texture->subresources[subresourceIndex].dsvHandle);
+
+                dsvDesc.Format = SDLToD3D12_TextureFormat[textureCreateInfo->format];
+                dsvDesc.Flags = (D3D12_DSV_FLAGS)0;
+                dsvDesc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
+                dsvDesc.Texture2D.MipSlice = levelIndex;
+
+                ID3D12Device_CreateDepthStencilView(
+                    renderer->device,
+                    texture->resource,
+                    &dsvDesc,
+                    texture->subresources[subresourceIndex].dsvHandle.cpuHandle);
+            }
+
+            // Create subresource UAV if necessary
+            if (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+                D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+
+                D3D12_INTERNAL_AssignCpuDescriptorHandle(
+                    renderer,
+                    D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+                    &texture->subresources[subresourceIndex].uavHandle);
+
+                uavDesc.Format = SDLToD3D12_TextureFormat[textureCreateInfo->format];
+
+                if (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || textureCreateInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+                    uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2DARRAY;
+                    uavDesc.Texture2DArray.MipSlice = levelIndex;
+                    uavDesc.Texture2DArray.FirstArraySlice = layerIndex;
+                    uavDesc.Texture2DArray.ArraySize = 1;
+                } else if (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_3D) {
+                    uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
+                    uavDesc.Texture3D.MipSlice = levelIndex;
+                    uavDesc.Texture3D.FirstWSlice = 0;
+                    uavDesc.Texture3D.WSize = depth;
+                } else {
+                    uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
+                    uavDesc.Texture2D.MipSlice = levelIndex;
+                    uavDesc.Texture2D.PlaneSlice = 0;
+                }
+
+                ID3D12Device_CreateUnorderedAccessView(
+                    renderer->device,
+                    texture->resource,
+                    NULL,
+                    &uavDesc,
+                    texture->subresources[subresourceIndex].uavHandle.cpuHandle);
+            }
+        }
+    }
+
+    return texture;
+}
+
+static SDL_GpuTexture *D3D12_CreateTexture(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureCreateInfo *textureCreateInfo)
+{
+    D3D12TextureContainer *container = (D3D12TextureContainer *)SDL_calloc(1, sizeof(D3D12TextureContainer));
+    if (!container) {
+        return NULL;
+    }
+
+    container->header.info = *textureCreateInfo;
+    container->textureCapacity = 1;
+    container->textureCount = 1;
+    container->textures = (D3D12Texture **)SDL_calloc(
+        container->textureCapacity, sizeof(D3D12Texture *));
+
+    if (!container->textures) {
+        SDL_free(container);
+        return NULL;
+    }
+
+    container->debugName = NULL;
+    container->canBeCycled = SDL_TRUE;
+
+    D3D12Texture *texture = D3D12_INTERNAL_CreateTexture(
+        (D3D12Renderer *)driverData,
+        textureCreateInfo,
+        SDL_FALSE);
+
+    if (!texture) {
+        SDL_free(container->textures);
+        SDL_free(container);
+        return NULL;
+    }
+
+    container->textures[0] = texture;
+    container->activeTexture = texture;
+
+    texture->container = container;
+    texture->containerIndex = 0;
+
+    return (SDL_GpuTexture *)container;
+}
+
+static D3D12Buffer *D3D12_INTERNAL_CreateBuffer(
+    D3D12Renderer *renderer,
+    SDL_GpuBufferUsageFlags usageFlags,
+    Uint32 sizeInBytes,
+    D3D12BufferType type)
+{
+    D3D12Buffer *buffer;
+    ID3D12Resource *handle;
+    D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+    D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
+    D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc;
+    D3D12_HEAP_PROPERTIES heapProperties;
+    D3D12_RESOURCE_DESC desc;
+    D3D12_HEAP_FLAGS heapFlags = (D3D12_HEAP_FLAGS)0;
+    D3D12_RESOURCE_FLAGS resourceFlags = (D3D12_RESOURCE_FLAGS)0;
+    D3D12_RESOURCE_STATES initialState = D3D12_RESOURCE_STATE_COMMON;
+    HRESULT res;
+
+    buffer = (D3D12Buffer *)SDL_calloc(1, sizeof(D3D12Buffer));
+
+    if (!buffer) {
+        return NULL;
+    }
+
+    if (usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+        resourceFlags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS;
+    }
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT_BIT) {
+        resourceFlags |= D3D12XBOX_RESOURCE_FLAG_ALLOW_INDIRECT_BUFFER;
+    }
+#endif
+
+    heapProperties.CreationNodeMask = 0; // We don't do multi-adapter operation
+    heapProperties.VisibleNodeMask = 0;  // We don't do multi-adapter operation
+
+    if (type == D3D12_BUFFER_TYPE_GPU) {
+        heapProperties.Type = D3D12_HEAP_TYPE_DEFAULT;
+        heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+        heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+        heapFlags = D3D12_HEAP_FLAG_NONE;
+    } else if (type == D3D12_BUFFER_TYPE_UPLOAD) {
+        heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
+        heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+        heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+        heapFlags = D3D12_HEAP_FLAG_NONE;
+        initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
+    } else if (type == D3D12_BUFFER_TYPE_DOWNLOAD) {
+        heapProperties.Type = D3D12_HEAP_TYPE_READBACK;
+        heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+        heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+        heapFlags = D3D12_HEAP_FLAG_NONE;
+        initialState = D3D12_RESOURCE_STATE_COPY_DEST;
+    } else if (type == D3D12_BUFFER_TYPE_UNIFORM) {
+        // D3D12 is badly designed, so we have to check if the fast path for uniform buffers is enabled
+        if (renderer->GPUUploadHeapSupported) {
+            heapProperties.Type = D3D12_HEAP_TYPE_GPU_UPLOAD;
+            heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+            heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+        } else {
+            heapProperties.Type = D3D12_HEAP_TYPE_UPLOAD;
+            heapProperties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+            heapProperties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+            initialState = D3D12_RESOURCE_STATE_GENERIC_READ;
+        }
+        heapFlags = D3D12_HEAP_FLAG_NONE;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized buffer type!");
+        return NULL;
+    }
+
+    desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+    desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
+    desc.Width = sizeInBytes;
+    desc.Height = 1;
+    desc.DepthOrArraySize = 1;
+    desc.MipLevels = 1;
+    desc.Format = DXGI_FORMAT_UNKNOWN;
+    desc.SampleDesc.Count = 1;
+    desc.SampleDesc.Quality = 0;
+    desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+    desc.Flags = resourceFlags;
+
+    res = ID3D12Device_CreateCommittedResource(
+        renderer->device,
+        &heapProperties,
+        heapFlags,
+        &desc,
+        initialState,
+        NULL,
+        D3D_GUID(D3D_IID_ID3D12Resource),
+        (void **)&handle);
+    if (FAILED(res)) {
+        D3D12_INTERNAL_LogError(renderer->device, "Could not create buffer!", res);
+        D3D12_INTERNAL_DestroyBuffer(renderer, buffer);
+        return NULL;
+    }
+
+    buffer->handle = handle;
+    SDL_AtomicSet(&buffer->referenceCount, 0);
+
+    buffer->uavDescriptor.heap = NULL;
+    buffer->srvDescriptor.heap = NULL;
+    buffer->cbvDescriptor.heap = NULL;
+
+    if (usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+        D3D12_INTERNAL_AssignCpuDescriptorHandle(
+            renderer,
+            D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+            &buffer->uavDescriptor);
+
+        uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
+        uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+        uavDesc.Buffer.FirstElement = 0;
+        uavDesc.Buffer.NumElements = sizeInBytes / sizeof(Uint32);
+        uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_RAW;
+        uavDesc.Buffer.CounterOffsetInBytes = 0; // TODO: support counters?
+        uavDesc.Buffer.StructureByteStride = 0;
+
+        // Create UAV
+        ID3D12Device_CreateUnorderedAccessView(
+            renderer->device,
+            handle,
+            NULL, // TODO: support counters?
+            &uavDesc,
+            buffer->uavDescriptor.cpuHandle);
+    }
+
+    if (
+        (usageFlags & SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT) ||
+        (usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ_BIT)) {
+        D3D12_INTERNAL_AssignCpuDescriptorHandle(
+            renderer,
+            D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+            &buffer->srvDescriptor);
+
+        srvDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+        srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+        srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
+        srvDesc.Buffer.FirstElement = 0;
+        srvDesc.Buffer.NumElements = sizeInBytes / sizeof(Uint32);
+        srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW;
+        srvDesc.Buffer.StructureByteStride = 0;
+
+        // Create SRV
+        ID3D12Device_CreateShaderResourceView(
+            renderer->device,
+            handle,
+            &srvDesc,
+            buffer->srvDescriptor.cpuHandle);
+    }
+
+    // FIXME: we may not need a CBV since we use root descriptors
+    if (type == D3D12_BUFFER_TYPE_UNIFORM) {
+        D3D12_INTERNAL_AssignCpuDescriptorHandle(
+            renderer,
+            D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+            &buffer->cbvDescriptor);
+
+        cbvDesc.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(handle);
+        cbvDesc.SizeInBytes = sizeInBytes;
+
+        // Create CBV
+        ID3D12Device_CreateConstantBufferView(
+            renderer->device,
+            &cbvDesc,
+            buffer->cbvDescriptor.cpuHandle);
+    }
+
+    buffer->virtualAddress = 0;
+    if (type == D3D12_BUFFER_TYPE_GPU || type == D3D12_BUFFER_TYPE_UNIFORM) {
+        buffer->virtualAddress = ID3D12Resource_GetGPUVirtualAddress(buffer->handle);
+    }
+
+    buffer->mapPointer = NULL;
+    // Persistently map upload buffers
+    if (type == D3D12_BUFFER_TYPE_UPLOAD) {
+        res = ID3D12Resource_Map(
+            buffer->handle,
+            0,
+            NULL,
+            (void **)&buffer->mapPointer);
+        if (FAILED(res)) {
+            D3D12_INTERNAL_LogError(renderer->device, "Failed to map upload buffer!", res);
+            D3D12_INTERNAL_DestroyBuffer(renderer, buffer);
+            return NULL;
+        }
+    }
+
+    buffer->container = NULL;
+    buffer->containerIndex = 0;
+
+    buffer->transitioned = initialState != D3D12_RESOURCE_STATE_COMMON;
+    SDL_AtomicSet(&buffer->referenceCount, 0);
+    return buffer;
+}
+
+static D3D12BufferContainer *D3D12_INTERNAL_CreateBufferContainer(
+    D3D12Renderer *renderer,
+    SDL_GpuBufferUsageFlags usageFlags,
+    Uint32 sizeInBytes,
+    D3D12BufferType type)
+{
+    D3D12BufferContainer *container;
+    D3D12Buffer *buffer;
+
+    container = (D3D12BufferContainer *)SDL_calloc(1, sizeof(D3D12BufferContainer));
+    if (!container) {
+        return NULL;
+    }
+
+    container->usageFlags = usageFlags;
+    container->size = sizeInBytes;
+    container->type = type;
+
+    container->bufferCapacity = 1;
+    container->bufferCount = 1;
+    container->buffers = (D3D12Buffer **)SDL_calloc(
+        container->bufferCapacity, sizeof(D3D12Buffer *));
+    if (!container->buffers) {
+        SDL_free(container);
+        return NULL;
+    }
+    container->debugName = NULL;
+
+    buffer = D3D12_INTERNAL_CreateBuffer(
+        renderer,
+        usageFlags,
+        sizeInBytes,
+        type);
+
+    if (buffer == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create buffer!");
+        SDL_free(container->buffers);
+        SDL_free(container);
+        return NULL;
+    }
+
+    container->activeBuffer = buffer;
+    container->buffers[0] = buffer;
+    buffer->container = container;
+    buffer->containerIndex = 0;
+
+    return container;
+}
+
+static SDL_GpuBuffer *D3D12_CreateBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBufferUsageFlags usageFlags,
+    Uint32 sizeInBytes)
+{
+    return (SDL_GpuBuffer *)D3D12_INTERNAL_CreateBufferContainer(
+        (D3D12Renderer *)driverData,
+        usageFlags,
+        sizeInBytes,
+        D3D12_BUFFER_TYPE_GPU);
+}
+
+static SDL_GpuTransferBuffer *D3D12_CreateTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBufferUsage usage,
+    Uint32 sizeInBytes)
+{
+    return (SDL_GpuTransferBuffer *)D3D12_INTERNAL_CreateBufferContainer(
+        (D3D12Renderer *)driverData,
+        0,
+        sizeInBytes,
+        usage == SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD ? D3D12_BUFFER_TYPE_UPLOAD : D3D12_BUFFER_TYPE_DOWNLOAD);
+}
+
+// Debug Naming
+
+static void D3D12_SetBufferName(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBuffer *buffer,
+    const char *text)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12BufferContainer *container = (D3D12BufferContainer *)buffer;
+    size_t textLength = SDL_strlen(text) + 1;
+
+    if (renderer->debugMode) {
+        container->debugName = (char *)SDL_realloc(
+            container->debugName,
+            textLength);
+
+        SDL_utf8strlcpy(
+            container->debugName,
+            text,
+            textLength);
+
+        for (Uint32 i = 0; i < container->bufferCount; i += 1) {
+            D3D12_INTERNAL_SetResourceName(
+                renderer,
+                container->buffers[i]->handle,
+                text);
+        }
+    }
+}
+
+static void D3D12_SetTextureName(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTexture *texture,
+    const char *text)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12TextureContainer *container = (D3D12TextureContainer *)texture;
+    size_t textLength = SDL_strlen(text) + 1;
+
+    if (renderer->debugMode) {
+        container->debugName = (char *)SDL_realloc(
+            container->debugName,
+            textLength);
+
+        SDL_utf8strlcpy(
+            container->debugName,
+            text,
+            textLength);
+
+        for (Uint32 i = 0; i < container->textureCount; i += 1) {
+            D3D12_INTERNAL_SetResourceName(
+                renderer,
+                container->textures[i]->resource,
+                text);
+        }
+    }
+}
+
+/* These debug functions are all marked as "for internal usage only"
+ * on D3D12... works on renderdoc!
+ */
+
+static SDL_bool D3D12_INTERNAL_StrToWStr(
+    D3D12Renderer *renderer,
+    const char *str,
+    wchar_t *wstr,
+    size_t wstr_size,
+    Uint32 *outSize)
+{
+    size_t inlen, result;
+    size_t outlen = wstr_size;
+
+    if (renderer->iconv == NULL) {
+        renderer->iconv = SDL_iconv_open("WCHAR_T", "UTF-8");
+        SDL_assert(renderer->iconv);
+    }
+
+    // Convert...
+    inlen = SDL_strlen(str) + 1;
+    result = SDL_iconv(
+        renderer->iconv,
+        &str,
+        &inlen,
+        (char **)&wstr,
+        &outlen);
+
+    *outSize = (Uint32)outlen;
+
+    // Check...
+    switch (result) {
+    case SDL_ICONV_ERROR:
+    case SDL_ICONV_E2BIG:
+    case SDL_ICONV_EILSEQ:
+    case SDL_ICONV_EINVAL:
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Failed to convert string to wchar_t!");
+        return SDL_FALSE;
+    default:
+        break;
+    }
+
+    return SDL_TRUE;
+}
+
+static void D3D12_InsertDebugLabel(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *text)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    wchar_t wstr[256];
+    Uint32 convSize;
+
+    if (!D3D12_INTERNAL_StrToWStr(
+            d3d12CommandBuffer->renderer,
+            text,
+            wstr,
+            sizeof(wstr),
+            &convSize)) {
+        return;
+    }
+
+    ID3D12GraphicsCommandList_SetMarker(
+        d3d12CommandBuffer->graphicsCommandList,
+        0,
+        wstr,
+        convSize);
+}
+
+static void D3D12_PushDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *name)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    wchar_t wstr[256];
+    Uint32 convSize;
+
+    if (!D3D12_INTERNAL_StrToWStr(
+            d3d12CommandBuffer->renderer,
+            name,
+            wstr,
+            sizeof(wstr),
+            &convSize)) {
+        return;
+    }
+
+    ID3D12GraphicsCommandList_BeginEvent(
+        d3d12CommandBuffer->graphicsCommandList,
+        0,
+        wstr,
+        convSize);
+}
+
+static void D3D12_PopDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    ID3D12GraphicsCommandList_EndEvent(d3d12CommandBuffer->graphicsCommandList);
+}
+
+// Disposal
+
+static void D3D12_ReleaseTexture(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTexture *texture)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12TextureContainer *container = (D3D12TextureContainer *)texture;
+
+    D3D12_INTERNAL_ReleaseTextureContainer(
+        renderer,
+        container);
+}
+
+static void D3D12_ReleaseSampler(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuSampler *sampler)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12Sampler *d3d12Sampler = (D3D12Sampler *)sampler;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->samplersToDestroy,
+        D3D12Sampler *,
+        renderer->samplersToDestroyCount + 1,
+        renderer->samplersToDestroyCapacity,
+        renderer->samplersToDestroyCapacity * 2)
+
+    renderer->samplersToDestroy[renderer->samplersToDestroyCount] = d3d12Sampler;
+    renderer->samplersToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void D3D12_ReleaseBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBuffer *buffer)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12BufferContainer *bufferContainer = (D3D12BufferContainer *)buffer;
+
+    D3D12_INTERNAL_ReleaseBufferContainer(
+        renderer,
+        bufferContainer);
+}
+
+static void D3D12_ReleaseTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12BufferContainer *transferBufferContainer = (D3D12BufferContainer *)transferBuffer;
+
+    D3D12_INTERNAL_ReleaseBufferContainer(
+        renderer,
+        transferBufferContainer);
+}
+
+static void D3D12_ReleaseShader(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuShader *shader)
+{
+    /* D3D12Renderer *renderer = (D3D12Renderer *)driverData; */
+    D3D12Shader *d3d12shader = (D3D12Shader *)shader;
+
+    if (d3d12shader->bytecode) {
+        SDL_free(d3d12shader->bytecode);
+        d3d12shader->bytecode = NULL;
+    }
+    SDL_free(d3d12shader);
+}
+
+static void D3D12_ReleaseComputePipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuComputePipeline *computePipeline)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12ComputePipeline *d3d12ComputePipeline = (D3D12ComputePipeline *)computePipeline;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->computePipelinesToDestroy,
+        D3D12ComputePipeline *,
+        renderer->computePipelinesToDestroyCount + 1,
+        renderer->computePipelinesToDestroyCapacity,
+        renderer->computePipelinesToDestroyCapacity * 2)
+
+    renderer->computePipelinesToDestroy[renderer->computePipelinesToDestroyCount] = d3d12ComputePipeline;
+    renderer->computePipelinesToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void D3D12_ReleaseGraphicsPipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuGraphicsPipeline *graphicsPipeline)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12GraphicsPipeline *d3d12GraphicsPipeline = (D3D12GraphicsPipeline *)graphicsPipeline;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->graphicsPipelinesToDestroy,
+        D3D12GraphicsPipeline *,
+        renderer->graphicsPipelinesToDestroyCount + 1,
+        renderer->graphicsPipelinesToDestroyCapacity,
+        renderer->graphicsPipelinesToDestroyCapacity * 2)
+
+    renderer->graphicsPipelinesToDestroy[renderer->graphicsPipelinesToDestroyCount] = d3d12GraphicsPipeline;
+    renderer->graphicsPipelinesToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void D3D12_INTERNAL_ReleaseBlitPipelines(SDL_GpuRenderer *driverData)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12_ReleaseSampler(driverData, renderer->blitLinearSampler);
+    D3D12_ReleaseSampler(driverData, renderer->blitNearestSampler);
+    D3D12_ReleaseShader(driverData, renderer->blitVertexShader);
+    D3D12_ReleaseShader(driverData, renderer->blitFrom2DShader);
+    D3D12_ReleaseShader(driverData, renderer->blitFrom2DArrayShader);
+    D3D12_ReleaseShader(driverData, renderer->blitFrom3DShader);
+    D3D12_ReleaseShader(driverData, renderer->blitFromCubeShader);
+
+    for (Uint32 i = 0; i < renderer->blitPipelineCount; i += 1) {
+        D3D12_ReleaseGraphicsPipeline(driverData, renderer->blitPipelines[i].pipeline);
+    }
+    SDL_free(renderer->blitPipelines);
+}
+
+// Render Pass
+
+static void D3D12_SetViewport(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuViewport *viewport)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12_VIEWPORT d3d12Viewport;
+    d3d12Viewport.TopLeftX = viewport->x;
+    d3d12Viewport.TopLeftY = viewport->y;
+    d3d12Viewport.Width = viewport->w;
+    d3d12Viewport.Height = viewport->h;
+    d3d12Viewport.MinDepth = viewport->minDepth;
+    d3d12Viewport.MaxDepth = viewport->maxDepth;
+    ID3D12GraphicsCommandList_RSSetViewports(d3d12CommandBuffer->graphicsCommandList, 1, &d3d12Viewport);
+}
+
+static void D3D12_SetScissor(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_Rect *scissor)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12_RECT scissorRect;
+    scissorRect.left = scissor->x;
+    scissorRect.top = scissor->y;
+    scissorRect.right = scissor->x + scissor->w;
+    scissorRect.bottom = scissor->y + scissor->h;
+    ID3D12GraphicsCommandList_RSSetScissorRects(d3d12CommandBuffer->graphicsCommandList, 1, &scissorRect);
+}
+
+static D3D12TextureSubresource *D3D12_INTERNAL_FetchTextureSubresource(
+    D3D12TextureContainer *container,
+    Uint32 layer,
+    Uint32 level)
+{
+    Uint32 index = D3D12_INTERNAL_CalcSubresource(
+        level,
+        layer,
+        container->header.info.levelCount);
+    return &container->activeTexture->subresources[index];
+}
+
+static void D3D12_INTERNAL_CycleActiveTexture(
+    D3D12Renderer *renderer,
+    D3D12TextureContainer *container)
+{
+    D3D12Texture *texture;
+
+    // If a previously-cycled texture is available, we can use that.
+    for (Uint32 i = 0; i < container->textureCount; i += 1) {
+        texture = container->textures[i];
+
+        if (SDL_AtomicGet(&texture->referenceCount) == 0) {
+            container->activeTexture = texture;
+            return;
+        }
+    }
+
+    // No texture is available, generate a new one.
+    texture = D3D12_INTERNAL_CreateTexture(
+        renderer,
+        &container->header.info,
+        SDL_FALSE);
+
+    if (!texture) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to cycle active texture!");
+        return;
+    }
+
+    EXPAND_ARRAY_IF_NEEDED(
+        container->textures,
+        D3D12Texture *,
+        container->textureCount + 1,
+        container->textureCapacity,
+        container->textureCapacity * 2);
+
+    container->textures[container->textureCount] = texture;
+    texture->container = container;
+    texture->containerIndex = container->textureCount;
+    container->textureCount += 1;
+
+    container->activeTexture = texture;
+
+    if (renderer->debugMode && container->debugName != NULL) {
+        D3D12_INTERNAL_SetResourceName(
+            renderer,
+            container->activeTexture->resource,
+            container->debugName);
+    }
+}
+
+static D3D12TextureSubresource *D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12TextureContainer *container,
+    Uint32 layer,
+    Uint32 level,
+    SDL_bool cycle,
+    D3D12_RESOURCE_STATES destinationUsageMode)
+{
+    D3D12TextureSubresource *subresource = D3D12_INTERNAL_FetchTextureSubresource(
+        container,
+        layer,
+        level);
+
+    if (
+        container->canBeCycled &&
+        cycle &&
+        SDL_AtomicGet(&subresource->parent->referenceCount) > 0) {
+        D3D12_INTERNAL_CycleActiveTexture(
+            commandBuffer->renderer,
+            container);
+
+        subresource = D3D12_INTERNAL_FetchTextureSubresource(
+            container,
+            layer,
+            level);
+    }
+
+    D3D12_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+        commandBuffer,
+        destinationUsageMode,
+        subresource);
+
+    return subresource;
+}
+
+static void D3D12_INTERNAL_CycleActiveBuffer(
+    D3D12Renderer *renderer,
+    D3D12BufferContainer *container)
+{
+    // If a previously-cycled buffer is available, we can use that.
+    for (Uint32 i = 0; i < container->bufferCount; i += 1) {
+        D3D12Buffer *buffer = container->buffers[i];
+        if (SDL_AtomicGet(&buffer->referenceCount) == 0) {
+            container->activeBuffer = buffer;
+            return;
+        }
+    }
+
+    // No buffer handle is available, create a new one.
+    D3D12Buffer *buffer = D3D12_INTERNAL_CreateBuffer(
+        renderer,
+        container->usageFlags,
+        container->size,
+        container->type);
+
+    if (!buffer) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to cycle active buffer!");
+        return;
+    }
+
+    EXPAND_ARRAY_IF_NEEDED(
+        container->buffers,
+        D3D12Buffer *,
+        container->bufferCount + 1,
+        container->bufferCapacity,
+        container->bufferCapacity * 2);
+
+    container->buffers[container->bufferCount] = buffer;
+    buffer->container = container;
+    buffer->containerIndex = container->bufferCount;
+    container->bufferCount += 1;
+
+    container->activeBuffer = buffer;
+
+    if (renderer->debugMode && container->debugName != NULL) {
+        D3D12_INTERNAL_SetResourceName(
+            renderer,
+            container->activeBuffer->handle,
+            container->debugName);
+    }
+}
+
+static D3D12Buffer *D3D12_INTERNAL_PrepareBufferForWrite(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12BufferContainer *container,
+    SDL_bool cycle,
+    D3D12_RESOURCE_STATES destinationState)
+{
+    if (
+        cycle &&
+        SDL_AtomicGet(&container->activeBuffer->referenceCount) > 0) {
+        D3D12_INTERNAL_CycleActiveBuffer(
+            commandBuffer->renderer,
+            container);
+    }
+
+    D3D12_INTERNAL_BufferTransitionFromDefaultUsage(
+        commandBuffer,
+        destinationState,
+        container->activeBuffer);
+
+    return container->activeBuffer;
+}
+
+static void D3D12_BeginRenderPass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuColorAttachmentInfo *colorAttachmentInfos,
+    Uint32 colorAttachmentCount,
+    SDL_GpuDepthStencilAttachmentInfo *depthStencilAttachmentInfo)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    /* D3D12Renderer *renderer = d3d12CommandBuffer->renderer; */
+
+    Uint32 framebufferWidth = SDL_MAX_UINT32;
+    Uint32 framebufferHeight = SDL_MAX_UINT32;
+
+    for (Uint32 i = 0; i < colorAttachmentCount; i += 1) {
+        D3D12TextureContainer *container = (D3D12TextureContainer *)colorAttachmentInfos[i].texture;
+        Uint32 h = container->header.info.height >> colorAttachmentInfos[i].mipLevel;
+        Uint32 w = container->header.info.width >> colorAttachmentInfos[i].mipLevel;
+
+        // The framebuffer cannot be larger than the smallest attachment.
+
+        if (w < framebufferWidth) {
+            framebufferWidth = w;
+        }
+
+        if (h < framebufferHeight) {
+            framebufferHeight = h;
+        }
+
+        if (!(container->header.info.usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT)) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Color attachment texture was not designated as a color target!");
+            return;
+        }
+    }
+
+    if (depthStencilAttachmentInfo != NULL) {
+        D3D12TextureContainer *container = (D3D12TextureContainer *)depthStencilAttachmentInfo->texture;
+
+        Uint32 h = container->header.info.height;
+        Uint32 w = container->header.info.width;
+
+        // The framebuffer cannot be larger than the smallest attachment.
+
+        if (w < framebufferWidth) {
+            framebufferWidth = w;
+        }
+
+        if (h < framebufferHeight) {
+            framebufferHeight = h;
+        }
+
+        // Fixme:
+        if (!(container->header.info.usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT)) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Depth stencil attachment texture was not designated as a depth target!");
+            return;
+        }
+    }
+
+    D3D12_CPU_DESCRIPTOR_HANDLE rtvs[MAX_COLOR_TARGET_BINDINGS];
+
+    for (Uint32 i = 0; i < colorAttachmentCount; i += 1) {
+        D3D12TextureContainer *container = (D3D12TextureContainer *)colorAttachmentInfos[i].texture;
+        D3D12TextureSubresource *subresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
+            d3d12CommandBuffer,
+            container,
+            container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorAttachmentInfos[i].layerOrDepthPlane,
+            colorAttachmentInfos[i].mipLevel,
+            colorAttachmentInfos[i].cycle,
+            D3D12_RESOURCE_STATE_RENDER_TARGET);
+
+        Uint32 rtvIndex = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorAttachmentInfos[i].layerOrDepthPlane : 0;
+        D3D12_CPU_DESCRIPTOR_HANDLE rtv =
+            subresource->rtvHandles[rtvIndex].cpuHandle;
+
+        if (colorAttachmentInfos[i].loadOp == SDL_GPU_LOADOP_CLEAR) {
+            float clearColor[4];
+            clearColor[0] = colorAttachmentInfos[i].clearColor.r;
+            clearColor[1] = colorAttachmentInfos[i].clearColor.g;
+            clearColor[2] = colorAttachmentInfos[i].clearColor.b;
+            clearColor[3] = colorAttachmentInfos[i].clearColor.a;
+
+            ID3D12GraphicsCommandList_ClearRenderTargetView(
+                d3d12CommandBuffer->graphicsCommandList,
+                rtv,
+                clearColor,
+                0,
+                NULL);
+        }
+
+        rtvs[i] = rtv;
+        d3d12CommandBuffer->colorAttachmentTextureSubresources[i] = subresource;
+
+        D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, subresource->parent);
+    }
+
+    d3d12CommandBuffer->colorAttachmentTextureSubresourceCount = colorAttachmentCount;
+
+    D3D12_CPU_DESCRIPTOR_HANDLE dsv;
+    if (depthStencilAttachmentInfo != NULL) {
+        D3D12TextureContainer *container = (D3D12TextureContainer *)depthStencilAttachmentInfo->texture;
+        D3D12TextureSubresource *subresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
+            d3d12CommandBuffer,
+            container,
+            0,
+            0,
+            depthStencilAttachmentInfo->cycle,
+            D3D12_RESOURCE_STATE_DEPTH_WRITE);
+
+        if (
+            depthStencilAttachmentInfo->loadOp == SDL_GPU_LOADOP_CLEAR ||
+            depthStencilAttachmentInfo->stencilLoadOp == SDL_GPU_LOADOP_CLEAR) {
+            D3D12_CLEAR_FLAGS clearFlags = (D3D12_CLEAR_FLAGS)0;
+            if (depthStencilAttachmentInfo->loadOp == SDL_GPU_LOADOP_CLEAR) {
+                clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
+            }
+            if (depthStencilAttachmentInfo->stencilLoadOp == SDL_GPU_LOADOP_CLEAR) {
+                clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
+            }
+
+            ID3D12GraphicsCommandList_ClearDepthStencilView(
+                d3d12CommandBuffer->graphicsCommandList,
+                subresource->dsvHandle.cpuHandle,
+                clearFlags,
+                depthStencilAttachmentInfo->depthStencilClearValue.depth,
+                depthStencilAttachmentInfo->depthStencilClearValue.stencil,
+                0,
+                NULL);
+        }
+
+        dsv = subresource->dsvHandle.cpuHandle;
+        d3d12CommandBuffer->depthStencilTextureSubresource = subresource;
+        D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, subresource->parent);
+    }
+
+    ID3D12GraphicsCommandList_OMSetRenderTargets(
+        d3d12CommandBuffer->graphicsCommandList,
+        colorAttachmentCount,
+        rtvs,
+        SDL_FALSE,
+        (depthStencilAttachmentInfo == NULL) ? NULL : &dsv);
+
+    // Set sensible default viewport state
+    SDL_GpuViewport defaultViewport;
+    defaultViewport.x = 0;
+    defaultViewport.y = 0;
+    defaultViewport.w = (float)framebufferWidth;
+    defaultViewport.h = (float)framebufferHeight;
+    defaultViewport.minDepth = 0;
+    defaultViewport.maxDepth = 1;
+
+    D3D12_SetViewport(
+        commandBuffer,
+        &defaultViewport);
+
+    SDL_Rect defaultScissor;
+    defaultScissor.x = 0;
+    defaultScissor.y = 0;
+    defaultScissor.w = (Sint32)framebufferWidth;
+    defaultScissor.h = (Sint32)framebufferHeight;
+
+    D3D12_SetScissor(
+        commandBuffer,
+        &defaultScissor);
+}
+
+static void D3D12_INTERNAL_TrackUniformBuffer(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12UniformBuffer *uniformBuffer)
+{
+    Uint32 i;
+    for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
+        if (commandBuffer->usedUniformBuffers[i] == uniformBuffer) {
+            return;
+        }
+    }
+
+    if (commandBuffer->usedUniformBufferCount == commandBuffer->usedUniformBufferCapacity) {
+        commandBuffer->usedUniformBufferCapacity += 1;
+        commandBuffer->usedUniformBuffers = (D3D12UniformBuffer **)SDL_realloc(
+            commandBuffer->usedUniformBuffers,
+            commandBuffer->usedUniformBufferCapacity * sizeof(D3D12UniformBuffer *));
+    }
+
+    commandBuffer->usedUniformBuffers[commandBuffer->usedUniformBufferCount] = uniformBuffer;
+    commandBuffer->usedUniformBufferCount += 1;
+
+    D3D12_INTERNAL_TrackBuffer(
+        commandBuffer,
+        uniformBuffer->buffer);
+}
+
+static D3D12UniformBuffer *D3D12_INTERNAL_AcquireUniformBufferFromPool(
+    D3D12CommandBuffer *commandBuffer)
+{
+    D3D12Renderer *renderer = commandBuffer->renderer;
+    D3D12UniformBuffer *uniformBuffer;
+
+    SDL_LockMutex(renderer->acquireUniformBufferLock);
+
+    if (renderer->uniformBufferPoolCount > 0) {
+        uniformBuffer = renderer->uniformBufferPool[renderer->uniformBufferPoolCount - 1];
+        renderer->uniformBufferPoolCount -= 1;
+    } else {
+        uniformBuffer = (D3D12UniformBuffer *)SDL_calloc(1, sizeof(D3D12UniformBuffer));
+        if (!uniformBuffer) {
+            SDL_UnlockMutex(renderer->acquireUniformBufferLock);
+            return NULL;
+        }
+
+        uniformBuffer->buffer = D3D12_INTERNAL_CreateBuffer(
+            renderer,
+            0,
+            UNIFORM_BUFFER_SIZE,
+            D3D12_BUFFER_TYPE_UNIFORM);
+        if (!uniformBuffer->buffer) {
+            SDL_UnlockMutex(renderer->acquireUniformBufferLock);
+            return NULL;
+        }
+    }
+
+    SDL_UnlockMutex(renderer->acquireUniformBufferLock);
+
+    uniformBuffer->currentBlockSize = 0;
+    uniformBuffer->drawOffset = 0;
+    uniformBuffer->writeOffset = 0;
+
+    HRESULT res = ID3D12Resource_Map(
+        uniformBuffer->buffer->handle,
+        0,
+        NULL,
+        (void **)&uniformBuffer->buffer->mapPointer);
+    ERROR_CHECK_RETURN("Failed to map buffer pool!", NULL);
+
+    D3D12_INTERNAL_TrackUniformBuffer(commandBuffer, uniformBuffer);
+
+    return uniformBuffer;
+}
+
+static void D3D12_INTERNAL_ReturnUniformBufferToPool(
+    D3D12Renderer *renderer,
+    D3D12UniformBuffer *uniformBuffer)
+{
+    if (renderer->uniformBufferPoolCount >= renderer->uniformBufferPoolCapacity) {
+        renderer->uniformBufferPoolCapacity *= 2;
+        renderer->uniformBufferPool = (D3D12UniformBuffer **)SDL_realloc(
+            renderer->uniformBufferPool,
+            renderer->uniformBufferPoolCapacity * sizeof(D3D12UniformBuffer *));
+    }
+
+    renderer->uniformBufferPool[renderer->uniformBufferPoolCount] = uniformBuffer;
+    renderer->uniformBufferPoolCount += 1;
+}
+
+static void D3D12_INTERNAL_PushUniformData(
+    D3D12CommandBuffer *commandBuffer,
+    SDL_GpuShaderStage shaderStage,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    D3D12UniformBuffer *uniformBuffer;
+
+    if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
+        if (commandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
+            commandBuffer->vertexUniformBuffers[slotIndex] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
+                commandBuffer);
+        }
+        uniformBuffer = commandBuffer->vertexUniformBuffers[slotIndex];
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
+        if (commandBuffer->fragmentUniformBuffers[slotIndex] == NULL) {
+            commandBuffer->fragmentUniformBuffers[slotIndex] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
+                commandBuffer);
+        }
+        uniformBuffer = commandBuffer->fragmentUniformBuffers[slotIndex];
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
+        if (commandBuffer->computeUniformBuffers[slotIndex] == NULL) {
+            commandBuffer->computeUniformBuffers[slotIndex] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
+                commandBuffer);
+        }
+        uniformBuffer = commandBuffer->computeUniformBuffers[slotIndex];
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+        return;
+    }
+
+    uniformBuffer->currentBlockSize =
+        D3D12_INTERNAL_Align(
+            dataLengthInBytes,
+            256);
+
+    // If there is no more room, acquire a new uniform buffer
+    if (uniformBuffer->writeOffset + uniformBuffer->currentBlockSize >= UNIFORM_BUFFER_SIZE) {
+        ID3D12Resource_Unmap(
+            uniformBuffer->buffer->handle,
+            0,
+            NULL);
+        uniformBuffer->buffer->mapPointer = NULL;
+
+        uniformBuffer = D3D12_INTERNAL_AcquireUniformBufferFromPool(commandBuffer);
+
+        uniformBuffer->drawOffset = 0;
+        uniformBuffer->writeOffset = 0;
+
+        if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
+            commandBuffer->vertexUniformBuffers[slotIndex] = uniformBuffer;
+        } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
+            commandBuffer->fragmentUniformBuffers[slotIndex] = uniformBuffer;
+        } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
+            commandBuffer->computeUniformBuffers[slotIndex] = uniformBuffer;
+        } else {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+        }
+    }
+
+    uniformBuffer->drawOffset = uniformBuffer->writeOffset;
+
+    SDL_memcpy(
+        (Uint8 *)uniformBuffer->buffer->mapPointer + uniformBuffer->writeOffset,
+        data,
+        dataLengthInBytes);
+
+    uniformBuffer->writeOffset += uniformBuffer->currentBlockSize;
+
+    if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
+        commandBuffer->needVertexUniformBufferBind[slotIndex] = SDL_TRUE;
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
+        commandBuffer->needFragmentUniformBufferBind[slotIndex] = SDL_TRUE;
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
+        commandBuffer->needComputeUniformBufferBind[slotIndex] = SDL_TRUE;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+    }
+}
+
+static void D3D12_BindGraphicsPipeline(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuGraphicsPipeline *graphicsPipeline)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12GraphicsPipeline *pipeline = (D3D12GraphicsPipeline *)graphicsPipeline;
+    Uint32 i;
+
+    d3d12CommandBuffer->currentGraphicsPipeline = pipeline;
+
+    // Set the pipeline state
+    ID3D12GraphicsCommandList_SetPipelineState(d3d12CommandBuffer->graphicsCommandList, pipeline->pipelineState);
+
+    ID3D12GraphicsCommandList_SetGraphicsRootSignature(d3d12CommandBuffer->graphicsCommandList, pipeline->rootSignature->handle);
+
+    ID3D12GraphicsCommandList_IASetPrimitiveTopology(d3d12CommandBuffer->graphicsCommandList, SDLToD3D12_PrimitiveType[pipeline->primitiveType]);
+
+    float blendFactor[4] = {
+        pipeline->blendConstants[0],
+        pipeline->blendConstants[1],
+        pipeline->blendConstants[2],
+        pipeline->blendConstants[3]
+    };
+    ID3D12GraphicsCommandList_OMSetBlendFactor(d3d12CommandBuffer->graphicsCommandList, blendFactor);
+
+    ID3D12GraphicsCommandList_OMSetStencilRef(d3d12CommandBuffer->graphicsCommandList, pipeline->stencilRef);
+
+    // Mark that bindings are needed
+    d3d12CommandBuffer->needVertexSamplerBind = SDL_TRUE;
+    d3d12CommandBuffer->needVertexStorageTextureBind = SDL_TRUE;
+    d3d12CommandBuffer->needVertexStorageBufferBind = SDL_TRUE;
+    d3d12CommandBuffer->needFragmentSamplerBind = SDL_TRUE;
+    d3d12CommandBuffer->needFragmentStorageTextureBind = SDL_TRUE;
+    d3d12CommandBuffer->needFragmentStorageBufferBind = SDL_TRUE;
+
+    for (i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        d3d12CommandBuffer->needVertexUniformBufferBind[i] = SDL_TRUE;
+        d3d12CommandBuffer->needFragmentUniformBufferBind[i] = SDL_TRUE;
+    }
+
+    for (i = 0; i < pipeline->vertexUniformBufferCount; i += 1) {
+        if (d3d12CommandBuffer->vertexUniformBuffers[i] == NULL) {
+            d3d12CommandBuffer->vertexUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
+                d3d12CommandBuffer);
+        }
+    }
+
+    for (i = 0; i < pipeline->fragmentUniformBufferCount; i += 1) {
+        if (d3d12CommandBuffer->fragmentUniformBuffers[i] == NULL) {
+            d3d12CommandBuffer->fragmentUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
+                d3d12CommandBuffer);
+        }
+    }
+
+    D3D12_INTERNAL_TrackGraphicsPipeline(d3d12CommandBuffer, pipeline);
+}
+
+static void D3D12_BindVertexBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstBinding,
+    SDL_GpuBufferBinding *pBindings,
+    Uint32 bindingCount)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D12Buffer *currentBuffer = ((D3D12BufferContainer *)pBindings[i].buffer)->activeBuffer;
+        d3d12CommandBuffer->vertexBuffers[firstBinding + i] = currentBuffer;
+        d3d12CommandBuffer->vertexBufferOffsets[firstBinding + i] = pBindings[i].offset;
+        D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, currentBuffer);
+    }
+
+    d3d12CommandBuffer->vertexBufferCount =
+        SDL_max(d3d12CommandBuffer->vertexBufferCount, firstBinding + bindingCount);
+
+    d3d12CommandBuffer->needVertexBufferBind = SDL_TRUE;
+}
+
+static void D3D12_BindIndexBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferBinding *pBinding,
+    SDL_GpuIndexElementSize indexElementSize)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12Buffer *buffer = ((D3D12BufferContainer *)pBinding->buffer)->activeBuffer;
+    D3D12_INDEX_BUFFER_VIEW view;
+
+    D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, buffer);
+
+    view.BufferLocation = buffer->virtualAddress + pBinding->offset;
+    view.SizeInBytes = buffer->container->size - pBinding->offset;
+    view.Format =
+        indexElementSize == SDL_GPU_INDEXELEMENTSIZE_16BIT ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
+
+    ID3D12GraphicsCommandList_IASetIndexBuffer(
+        d3d12CommandBuffer->graphicsCommandList,
+        &view);
+}
+
+static void D3D12_BindVertexSamplers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
+        D3D12Sampler *sampler = (D3D12Sampler *)textureSamplerBindings[i].sampler;
+
+        D3D12_INTERNAL_TrackTexture(
+            d3d12CommandBuffer,
+            container->activeTexture);
+
+        D3D12_INTERNAL_TrackSampler(
+            d3d12CommandBuffer,
+            sampler);
+
+        d3d12CommandBuffer->vertexSamplers[firstSlot + i] = sampler;
+        d3d12CommandBuffer->vertexSamplerTextures[firstSlot + i] = container->activeTexture;
+    }
+
+    d3d12CommandBuffer->needVertexSamplerBind = SDL_TRUE;
+}
+
+static void D3D12_BindVertexStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextures[i];
+        D3D12Texture *texture = container->activeTexture;
+
+        D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, texture);
+
+        d3d12CommandBuffer->vertexStorageTextures[firstSlot + i] = texture;
+    }
+
+    d3d12CommandBuffer->needVertexStorageTextureBind = SDL_TRUE;
+}
+
+static void D3D12_BindVertexStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D12BufferContainer *container = (D3D12BufferContainer *)storageBuffers[i];
+
+        D3D12_INTERNAL_TrackBuffer(
+            d3d12CommandBuffer,
+            container->activeBuffer);
+
+        d3d12CommandBuffer->vertexStorageBuffers[firstSlot + i] = container->activeBuffer;
+    }
+
+    d3d12CommandBuffer->needVertexStorageBufferBind = SDL_TRUE;
+}
+
+static void D3D12_BindFragmentSamplers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
+        D3D12Sampler *sampler = (D3D12Sampler *)textureSamplerBindings[i].sampler;
+
+        D3D12_INTERNAL_TrackTexture(
+            d3d12CommandBuffer,
+            container->activeTexture);
+
+        D3D12_INTERNAL_TrackSampler(
+            d3d12CommandBuffer,
+            sampler);
+
+        d3d12CommandBuffer->fragmentSamplers[firstSlot + i] = sampler;
+        d3d12CommandBuffer->fragmentSamplerTextures[firstSlot + i] = container->activeTexture;
+    }
+
+    d3d12CommandBuffer->needFragmentSamplerBind = SDL_TRUE;
+}
+
+static void D3D12_BindFragmentStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextures[i];
+        D3D12Texture *texture = container->activeTexture;
+
+        D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, texture);
+
+        d3d12CommandBuffer->fragmentStorageTextures[firstSlot + i] = texture;
+    }
+
+    d3d12CommandBuffer->needFragmentStorageTextureBind = SDL_TRUE;
+}
+
+static void D3D12_BindFragmentStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        D3D12BufferContainer *container = (D3D12BufferContainer *)storageBuffers[i];
+
+        D3D12_INTERNAL_TrackBuffer(
+            d3d12CommandBuffer,
+            container->activeBuffer);
+
+        d3d12CommandBuffer->fragmentStorageBuffers[firstSlot + i] = container->activeBuffer;
+    }
+
+    d3d12CommandBuffer->needFragmentStorageBufferBind = SDL_TRUE;
+}
+
+static void D3D12_PushVertexUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    D3D12_INTERNAL_PushUniformData(
+        d3d12CommandBuffer,
+        SDL_GPU_SHADERSTAGE_VERTEX,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+static void D3D12_PushFragmentUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    D3D12_INTERNAL_PushUniformData(
+        d3d12CommandBuffer,
+        SDL_GPU_SHADERSTAGE_FRAGMENT,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+static void D3D12_INTERNAL_WriteGPUDescriptors(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12_DESCRIPTOR_HEAP_TYPE heapType,
+    D3D12_CPU_DESCRIPTOR_HANDLE *resourceDescriptorHandles,
+    Uint32 resourceHandleCount,
+    D3D12_GPU_DESCRIPTOR_HANDLE *gpuBaseDescriptor)
+{
+    D3D12DescriptorHeap *heap = commandBuffer->gpuDescriptorHeaps[heapType];
+    D3D12_CPU_DESCRIPTOR_HANDLE gpuHeapCpuHandle;
+
+    // FIXME: need to error on overflow
+    gpuHeapCpuHandle.ptr = heap->descriptorHeapCPUStart.ptr + (heap->currentDescriptorIndex * heap->descriptorSize);
+    gpuBaseDescriptor->ptr = heap->descriptorHeapGPUStart.ptr + (heap->currentDescriptorIndex * heap->descriptorSize);
+
+    for (Uint32 i = 0; i < resourceHandleCount; i += 1) {
+        ID3D12Device_CopyDescriptorsSimple(
+            commandBuffer->renderer->device,
+            1,
+            gpuHeapCpuHandle,
+            resourceDescriptorHandles[i],
+            heapType);
+
+        heap->currentDescriptorIndex += 1;
+        gpuHeapCpuHandle.ptr += heap->descriptorSize;
+    }
+}
+
+static void D3D12_INTERNAL_BindGraphicsResources(
+    D3D12CommandBuffer *commandBuffer)
+{
+    D3D12GraphicsPipeline *graphicsPipeline = commandBuffer->currentGraphicsPipeline;
+
+    D3D12_CPU_DESCRIPTOR_HANDLE cpuHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptorHandle;
+    D3D12_VERTEX_BUFFER_VIEW vertexBufferViews[MAX_BUFFER_BINDINGS];
+
+    if (commandBuffer->needVertexBufferBind) {
+        for (Uint32 i = 0; i < commandBuffer->vertexBufferCount; i += 1) {
+            vertexBufferViews[i].BufferLocation = commandBuffer->vertexBuffers[i]->virtualAddress + commandBuffer->vertexBufferOffsets[i];
+            vertexBufferViews[i].SizeInBytes = commandBuffer->vertexBuffers[i]->container->size - commandBuffer->vertexBufferOffsets[i];
+            vertexBufferViews[i].StrideInBytes = graphicsPipeline->vertexStrides[i];
+        }
+
+        ID3D12GraphicsCommandList_IASetVertexBuffers(
+            commandBuffer->graphicsCommandList,
+            0,
+            commandBuffer->vertexBufferCount,
+            vertexBufferViews);
+    }
+
+    if (commandBuffer->needVertexSamplerBind) {
+        if (graphicsPipeline->vertexSamplerCount > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->vertexSamplerCount; i += 1) {
+                cpuHandles[i] = commandBuffer->vertexSamplers[i]->handle.cpuHandle;
+            }
+
+            D3D12_INTERNAL_WriteGPUDescriptors(
+                commandBuffer,
+                D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
+                cpuHandles,
+                graphicsPipeline->vertexSamplerCount,
+                &gpuDescriptorHandle);
+
+            ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
+                commandBuffer->graphicsCommandList,
+                graphicsPipeline->rootSignature->vertexSamplerRootIndex,
+                gpuDescriptorHandle);
+
+            for (Uint32 i = 0; i < graphicsPipeline->vertexSamplerCount; i += 1) {
+                cpuHandles[i] = commandBuffer->vertexSamplerTextures[i]->srvHandle.cpuHandle;
+            }
+
+            D3D12_INTERNAL_WriteGPUDescriptors(
+                commandBuffer,
+                D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+                cpuHandles,
+                graphicsPipeline->vertexSamplerCount,
+                &gpuDescriptorHandle);
+
+            ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
+                commandBuffer->graphicsCommandList,
+                graphicsPipeline->rootSignature->vertexSamplerTextureRootIndex,
+                gpuDescriptorHandle);
+        }
+        commandBuffer->needVertexSamplerBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needVertexStorageTextureBind) {
+        if (graphicsPipeline->vertexStorageTextureCount > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->vertexStorageTextureCount; i += 1) {
+                cpuHandles[i] = commandBuffer->vertexStorageTextures[i]->srvHandle.cpuHandle;
+            }
+
+            D3D12_INTERNAL_WriteGPUDescriptors(
+                commandBuffer,
+                D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+                cpuHandles,
+                graphicsPipeline->vertexStorageTextureCount,
+                &gpuDescriptorHandle);
+
+            ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
+                commandBuffer->graphicsCommandList,
+                graphicsPipeline->rootSignature->vertexStorageTextureRootIndex,
+                gpuDescriptorHandle);
+        }
+        commandBuffer->needVertexStorageTextureBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needVertexStorageBufferBind) {
+        if (graphicsPipeline->vertexStorageBufferCount > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->vertexStorageBufferCount; i += 1) {
+                cpuHandles[i] = commandBuffer->vertexStorageBuffers[i]->srvDescriptor.cpuHandle;
+            }
+
+            D3D12_INTERNAL_WriteGPUDescriptors(
+                commandBuffer,
+                D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+                cpuHandles,
+                graphicsPipeline->vertexStorageBufferCount,
+                &gpuDescriptorHandle);
+
+            ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
+                commandBuffer->graphicsCommandList,
+                graphicsPipeline->rootSignature->vertexStorageBufferRootIndex,
+                gpuDescriptorHandle);
+        }
+        commandBuffer->needVertexStorageBufferBind = SDL_FALSE;
+    }
+
+    for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        if (commandBuffer->needVertexUniformBufferBind[i]) {
+            if (graphicsPipeline->vertexUniformBufferCount > i) {
+                ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(
+                    commandBuffer->graphicsCommandList,
+                    graphicsPipeline->rootSignature->vertexUniformBufferRootIndex[i],
+                    commandBuffer->vertexUniformBuffers[i]->buffer->virtualAddress + commandBuffer->vertexUniformBuffers[i]->drawOffset);
+            }
+            commandBuffer->needVertexUniformBufferBind[i] = SDL_FALSE;
+        }
+    }
+
+    if (commandBuffer->needFragmentSamplerBind) {
+        if (graphicsPipeline->fragmentSamplerCount > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->fragmentSamplerCount; i += 1) {
+                cpuHandles[i] = commandBuffer->fragmentSamplers[i]->handle.cpuHandle;
+            }
+
+            D3D12_INTERNAL_WriteGPUDescriptors(
+                commandBuffer,
+                D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
+                cpuHandles,
+                graphicsPipeline->fragmentSamplerCount,
+                &gpuDescriptorHandle);
+
+            ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
+                commandBuffer->graphicsCommandList,
+                graphicsPipeline->rootSignature->fragmentSamplerRootIndex,
+                gpuDescriptorHandle);
+
+            for (Uint32 i = 0; i < graphicsPipeline->fragmentSamplerCount; i += 1) {
+                cpuHandles[i] = commandBuffer->fragmentSamplerTextures[i]->srvHandle.cpuHandle;
+            }
+
+            D3D12_INTERNAL_WriteGPUDescriptors(
+                commandBuffer,
+                D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+                cpuHandles,
+                graphicsPipeline->fragmentSamplerCount,
+                &gpuDescriptorHandle);
+
+            ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
+                commandBuffer->graphicsCommandList,
+                graphicsPipeline->rootSignature->fragmentSamplerTextureRootIndex,
+                gpuDescriptorHandle);
+        }
+        commandBuffer->needFragmentSamplerBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needFragmentStorageTextureBind) {
+        if (graphicsPipeline->fragmentStorageTextureCount > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageTextureCount; i += 1) {
+                cpuHandles[i] = commandBuffer->fragmentStorageTextures[i]->srvHandle.cpuHandle;
+            }
+
+            D3D12_INTERNAL_WriteGPUDescriptors(
+                commandBuffer,
+                D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+                cpuHandles,
+                graphicsPipeline->fragmentStorageTextureCount,
+                &gpuDescriptorHandle);
+
+            ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
+                commandBuffer->graphicsCommandList,
+                graphicsPipeline->rootSignature->fragmentStorageTextureRootIndex,
+                gpuDescriptorHandle);
+        }
+        commandBuffer->needFragmentStorageTextureBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needFragmentStorageBufferBind) {
+        if (graphicsPipeline->fragmentStorageBufferCount > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageBufferCount; i += 1) {
+                cpuHandles[i] = commandBuffer->fragmentStorageBuffers[i]->srvDescriptor.cpuHandle;
+            }
+
+            D3D12_INTERNAL_WriteGPUDescriptors(
+                commandBuffer,
+                D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+                cpuHandles,
+                graphicsPipeline->fragmentStorageBufferCount,
+                &gpuDescriptorHandle);
+
+            ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
+                commandBuffer->graphicsCommandList,
+                graphicsPipeline->rootSignature->fragmentStorageBufferRootIndex,
+                gpuDescriptorHandle);
+        }
+        commandBuffer->needFragmentStorageBufferBind = SDL_FALSE;
+    }
+
+    for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        if (commandBuffer->needFragmentUniformBufferBind[i]) {
+            if (graphicsPipeline->fragmentUniformBufferCount > i) {
+                ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(
+                    commandBuffer->graphicsCommandList,
+                    graphicsPipeline->rootSignature->fragmentUniformBufferRootIndex[i],
+                    commandBuffer->fragmentUniformBuffers[i]->buffer->virtualAddress + commandBuffer->fragmentUniformBuffers[i]->drawOffset);
+            }
+            commandBuffer->needFragmentUniformBufferBind[i] = SDL_FALSE;
+        }
+    }
+}
+
+static void D3D12_DrawIndexedPrimitives(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 indexCount,
+    Uint32 instanceCount,
+    Uint32 firstIndex,
+    Sint32 vertexOffset,
+    Uint32 firstInstance)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12_INTERNAL_BindGraphicsResources(d3d12CommandBuffer);
+
+    ID3D12GraphicsCommandList_DrawIndexedInstanced(
+        d3d12CommandBuffer->graphicsCommandList,
+        indexCount,
+        instanceCount,
+        firstIndex,
+        vertexOffset,
+        firstInstance);
+}
+
+static void D3D12_DrawPrimitives(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 vertexCount,
+    Uint32 instanceCount,
+    Uint32 firstVertex,
+    Uint32 firstInstance)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12_INTERNAL_BindGraphicsResources(d3d12CommandBuffer);
+
+    ID3D12GraphicsCommandList_DrawInstanced(
+        d3d12CommandBuffer->graphicsCommandList,
+        vertexCount,
+        instanceCount,
+        firstVertex,
+        firstInstance);
+}
+
+static void D3D12_DrawPrimitivesIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12Buffer *d3d12Buffer = ((D3D12BufferContainer *)buffer)->activeBuffer;
+
+    D3D12_INTERNAL_BindGraphicsResources(d3d12CommandBuffer);
+
+    if (stride == sizeof(SDL_GpuIndirectDrawCommand)) {
+        // Real multi-draw!
+        ID3D12GraphicsCommandList_ExecuteIndirect(
+            d3d12CommandBuffer->graphicsCommandList,
+            d3d12CommandBuffer->renderer->indirectDrawCommandSignature,
+            drawCount,
+            d3d12Buffer->handle,
+            offsetInBytes,
+            NULL,
+            0);
+    } else {
+        /* Fake multi-draw...
+         * FIXME: we could make this real multi-draw
+         * if we have a lookup to get command signature per stride value
+         */
+        for (Uint32 i = 0; i < drawCount; i += 1) {
+            ID3D12GraphicsCommandList_ExecuteIndirect(
+                d3d12CommandBuffer->graphicsCommandList,
+                d3d12CommandBuffer->renderer->indirectDrawCommandSignature,
+                1,
+                d3d12Buffer->handle,
+                offsetInBytes + (stride * i),
+                NULL,
+                0);
+        }
+    }
+}
+
+static void D3D12_DrawIndexedPrimitivesIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12Buffer *d3d12Buffer = ((D3D12BufferContainer *)buffer)->activeBuffer;
+
+    D3D12_INTERNAL_BindGraphicsResources(d3d12CommandBuffer);
+
+    if (stride == sizeof(SDL_GpuIndexedIndirectDrawCommand)) {
+        // Real multi-draw!
+        ID3D12GraphicsCommandList_ExecuteIndirect(
+            d3d12CommandBuffer->graphicsCommandList,
+            d3d12CommandBuffer->renderer->indirectIndexedDrawCommandSignature,
+            drawCount,
+            d3d12Buffer->handle,
+            offsetInBytes,
+            NULL,
+            0);
+    } else {
+        /* Fake multi-draw...
+         * FIXME: we could make this real multi-draw
+         * if we have a lookup to get command signature per stride value
+         */
+        for (Uint32 i = 0; i < drawCount; i += 1) {
+            ID3D12GraphicsCommandList_ExecuteIndirect(
+                d3d12CommandBuffer->graphicsCommandList,
+                d3d12CommandBuffer->renderer->indirectIndexedDrawCommandSignature,
+                1,
+                d3d12Buffer->handle,
+                offsetInBytes + (stride * i),
+                NULL,
+                0);
+        }
+    }
+}
+
+static void D3D12_EndRenderPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    Uint32 i;
+
+    for (i = 0; i < d3d12CommandBuffer->colorAttachmentTextureSubresourceCount; i += 1) {
+        D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+            d3d12CommandBuffer,
+            D3D12_RESOURCE_STATE_RENDER_TARGET,
+            d3d12CommandBuffer->colorAttachmentTextureSubresources[i]);
+
+        d3d12CommandBuffer->colorAttachmentTextureSubresources[i] = NULL;
+    }
+    d3d12CommandBuffer->colorAttachmentTextureSubresourceCount = 0;
+
+    if (d3d12CommandBuffer->depthStencilTextureSubresource != NULL) {
+        D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+            d3d12CommandBuffer,
+            D3D12_RESOURCE_STATE_DEPTH_WRITE,
+            d3d12CommandBuffer->depthStencilTextureSubresource);
+
+        d3d12CommandBuffer->depthStencilTextureSubresource = NULL;
+    }
+
+    d3d12CommandBuffer->currentGraphicsPipeline = NULL;
+
+    ID3D12GraphicsCommandList_OMSetRenderTargets(
+        d3d12CommandBuffer->graphicsCommandList,
+        0,
+        NULL,
+        SDL_FALSE,
+        NULL);
+
+    // Reset bind state
+    SDL_zeroa(d3d12CommandBuffer->colorAttachmentTextureSubresources);
+    d3d12CommandBuffer->depthStencilTextureSubresource = NULL;
+
+    SDL_zeroa(d3d12CommandBuffer->vertexBuffers);
+    SDL_zeroa(d3d12CommandBuffer->vertexBufferOffsets);
+    d3d12CommandBuffer->vertexBufferCount = 0;
+
+    SDL_zeroa(d3d12CommandBuffer->vertexSamplerTextures);
+    SDL_zeroa(d3d12CommandBuffer->vertexSamplers);
+    SDL_zeroa(d3d12CommandBuffer->vertexStorageTextures);
+    SDL_zeroa(d3d12CommandBuffer->vertexStorageBuffers);
+
+    SDL_zeroa(d3d12CommandBuffer->fragmentSamplerTextures);
+    SDL_zeroa(d3d12CommandBuffer->fragmentSamplers);
+    SDL_zeroa(d3d12CommandBuffer->fragmentStorageTextures);
+    SDL_zeroa(d3d12CommandBuffer->fragmentStorageBuffers);
+}
+
+// Compute Pass
+
+static void D3D12_BeginComputePass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuStorageTextureWriteOnlyBinding *storageTextureBindings,
+    Uint32 storageTextureBindingCount,
+    SDL_GpuStorageBufferWriteOnlyBinding *storageBufferBindings,
+    Uint32 storageBufferBindingCount)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    d3d12CommandBuffer->computeWriteOnlyStorageTextureSubresourceCount = storageTextureBindingCount;
+    d3d12CommandBuffer->computeWriteOnlyStorageBufferCount = storageBufferBindingCount;
+
+    /* Write-only resources will be actually bound in BindComputePipeline
+     * after the root signature is set.
+     * We also have to scan to see which barriers we actually need because depth slices aren't separate subresources
+     */
+    if (storageTextureBindingCount > 0) {
+        for (Uint32 i = 0; i < storageTextureBindingCount; i += 1) {
+            D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextureBindings[i].texture;
+            if (!(container->header.info.usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT)) {
+                SDL_LogError(SDL_LOG_CATEGORY_GPU, "Attempted to bind read-only texture as compute write texture");
+            }
+
+            D3D12TextureSubresource *subresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
+                d3d12CommandBuffer,
+                container,
+                storageTextureBindings[i].layer,
+                storageTextureBindings[i].mipLevel,
+                storageTextureBindings[i].cycle,
+                D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+
+            d3d12CommandBuffer->computeWriteOnlyStorageTextureSubresources[i] = subresource;
+
+            D3D12_INTERNAL_TrackTexture(
+                d3d12CommandBuffer,
+                subresource->parent);
+        }
+    }
+
+    if (storageBufferBindingCount > 0) {
+        for (Uint32 i = 0; i < storageBufferBindingCount; i += 1) {
+            D3D12BufferContainer *container = (D3D12BufferContainer *)storageBufferBindings[i].buffer;
+            if (!(container->usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT)) {
+                SDL_LogError(SDL_LOG_CATEGORY_GPU, "Attempted to bind read-only texture as compute write texture");
+            }
+            D3D12Buffer *buffer = D3D12_INTERNAL_PrepareBufferForWrite(
+                d3d12CommandBuffer,
+                container,
+                storageBufferBindings[i].cycle,
+                D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
+
+            d3d12CommandBuffer->computeWriteOnlyStorageBuffers[i] = buffer;
+
+            D3D12_INTERNAL_TrackBuffer(
+                d3d12CommandBuffer,
+                buffer);
+        }
+    }
+}
+
+static void D3D12_BindComputePipeline(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuComputePipeline *computePipeline)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12ComputePipeline *pipeline = (D3D12ComputePipeline *)computePipeline;
+    D3D12_CPU_DESCRIPTOR_HANDLE cpuHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptorHandle;
+
+    ID3D12GraphicsCommandList_SetPipelineState(
+        d3d12CommandBuffer->graphicsCommandList,
+        pipeline->pipelineState);
+
+    ID3D12GraphicsCommandList_SetComputeRootSignature(
+        d3d12CommandBuffer->graphicsCommandList,
+        pipeline->rootSignature->handle);
+
+    d3d12CommandBuffer->currentComputePipeline = pipeline;
+
+    d3d12CommandBuffer->needComputeReadOnlyStorageTextureBind = SDL_TRUE;
+    d3d12CommandBuffer->needComputeReadOnlyStorageBufferBind = SDL_TRUE;
+
+    for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        d3d12CommandBuffer->needComputeUniformBufferBind[i] = SDL_TRUE;
+    }
+
+    for (Uint32 i = 0; i < pipeline->uniformBufferCount; i += 1) {
+        if (d3d12CommandBuffer->computeUniformBuffers[i] == NULL) {
+            d3d12CommandBuffer->computeUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
+                d3d12CommandBuffer);
+        }
+    }
+
+    D3D12_INTERNAL_TrackComputePipeline(d3d12CommandBuffer, pipeline);
+
+    // Bind write-only resources after setting root signature
+    if (pipeline->writeOnlyStorageTextureCount > 0) {
+        for (Uint32 i = 0; i < pipeline->writeOnlyStorageTextureCount; i += 1) {
+            cpuHandles[i] = d3d12CommandBuffer->computeWriteOnlyStorageTextureSubresources[i]->uavHandle.cpuHandle;
+        }
+
+        D3D12_INTERNAL_WriteGPUDescriptors(
+            d3d12CommandBuffer,
+            D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+            cpuHandles,
+            d3d12CommandBuffer->computeWriteOnlyStorageTextureSubresourceCount,
+            &gpuDescriptorHandle);
+
+        ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
+            d3d12CommandBuffer->graphicsCommandList,
+            d3d12CommandBuffer->currentComputePipeline->rootSignature->writeOnlyStorageTextureRootIndex,
+            gpuDescriptorHandle);
+    }
+
+    if (pipeline->writeOnlyStorageBufferCount > 0) {
+        for (Uint32 i = 0; i < pipeline->writeOnlyStorageBufferCount; i += 1) {
+            cpuHandles[i] = d3d12CommandBuffer->computeWriteOnlyStorageBuffers[i]->uavDescriptor.cpuHandle;
+        }
+
+        D3D12_INTERNAL_WriteGPUDescriptors(
+            d3d12CommandBuffer,
+            D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+            cpuHandles,
+            d3d12CommandBuffer->computeWriteOnlyStorageBufferCount,
+            &gpuDescriptorHandle);
+
+        ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
+            d3d12CommandBuffer->graphicsCommandList,
+            d3d12CommandBuffer->currentComputePipeline->rootSignature->writeOnlyStorageBufferRootIndex,
+            gpuDescriptorHandle);
+    }
+}
+
+static void D3D12_BindComputeStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        if (d3d12CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i] != NULL) {
+            D3D12_INTERNAL_TextureTransitionToDefaultUsage(
+                d3d12CommandBuffer,
+                D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
+                d3d12CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i]);
+        }
+
+        D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextures[i];
+        d3d12CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i] = container->activeTexture;
+
+        D3D12_INTERNAL_TextureTransitionFromDefaultUsage(
+            d3d12CommandBuffer,
+            D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
+            container->activeTexture);
+
+        D3D12_INTERNAL_TrackTexture(
+            d3d12CommandBuffer,
+            container->activeTexture);
+    }
+
+    d3d12CommandBuffer->needComputeReadOnlyStorageTextureBind = SDL_TRUE;
+}
+
+static void D3D12_BindComputeStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        if (d3d12CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i] != NULL) {
+            D3D12_INTERNAL_BufferTransitionToDefaultUsage(
+                d3d12CommandBuffer,
+                D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
+                d3d12CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i]);
+        }
+
+        D3D12BufferContainer *container = (D3D12BufferContainer *)storageBuffers[i];
+        D3D12Buffer *buffer = container->activeBuffer;
+
+        d3d12CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i] = buffer;
+
+        D3D12_INTERNAL_BufferTransitionFromDefaultUsage(
+            d3d12CommandBuffer,
+            D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
+            buffer);
+
+        D3D12_INTERNAL_TrackBuffer(
+            d3d12CommandBuffer,
+            buffer);
+    }
+
+    d3d12CommandBuffer->needComputeReadOnlyStorageBufferBind = SDL_TRUE;
+}
+
+static void D3D12_PushComputeUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    D3D12_INTERNAL_PushUniformData(
+        d3d12CommandBuffer,
+        SDL_GPU_SHADERSTAGE_COMPUTE,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+static void D3D12_INTERNAL_BindComputeResources(
+    D3D12CommandBuffer *commandBuffer)
+{
+    D3D12ComputePipeline *computePipeline = commandBuffer->currentComputePipeline;
+
+    D3D12_CPU_DESCRIPTOR_HANDLE cpuHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptorHandle;
+
+    if (commandBuffer->needComputeReadOnlyStorageTextureBind) {
+        if (computePipeline->readOnlyStorageTextureCount > 0) {
+            for (Uint32 i = 0; i < computePipeline->readOnlyStorageTextureCount; i += 1) {
+                cpuHandles[i] = commandBuffer->computeReadOnlyStorageTextures[i]->srvHandle.cpuHandle;
+            }
+
+            D3D12_INTERNAL_WriteGPUDescriptors(
+                commandBuffer,
+                D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+                cpuHandles,
+                computePipeline->readOnlyStorageTextureCount,
+                &gpuDescriptorHandle);
+
+            ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
+                commandBuffer->graphicsCommandList,
+                computePipeline->rootSignature->readOnlyStorageTextureRootIndex,
+                gpuDescriptorHandle);
+        }
+        commandBuffer->needComputeReadOnlyStorageTextureBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needComputeReadOnlyStorageBufferBind) {
+        if (computePipeline->readOnlyStorageBufferCount > 0) {
+            for (Uint32 i = 0; i < computePipeline->readOnlyStorageBufferCount; i += 1) {
+                cpuHandles[i] = commandBuffer->computeReadOnlyStorageBuffers[i]->srvDescriptor.cpuHandle;
+            }
+
+            D3D12_INTERNAL_WriteGPUDescriptors(
+                commandBuffer,
+                D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+                cpuHandles,
+                computePipeline->readOnlyStorageBufferCount,
+                &gpuDescriptorHandle);
+
+            ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
+                commandBuffer->graphicsCommandList,
+                computePipeline->rootSignature->readOnlyStorageBufferRootIndex,
+                gpuDescriptorHandle);
+        }
+        commandBuffer->needComputeReadOnlyStorageBufferBind = SDL_FALSE;
+    }
+
+    for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        if (commandBuffer->needComputeUniformBufferBind[i]) {
+            if (computePipeline->uniformBufferCount > i) {
+                ID3D12GraphicsCommandList_SetComputeRootConstantBufferView(
+                    commandBuffer->graphicsCommandList,
+                    computePipeline->rootSignature->uniformBufferRootIndex[i],
+                    commandBuffer->computeUniformBuffers[i]->buffer->virtualAddress + commandBuffer->computeUniformBuffers[i]->drawOffset);
+            }
+        }
+        commandBuffer->needComputeUniformBufferBind[i] = SDL_FALSE;
+    }
+}
+
+static void D3D12_DispatchCompute(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 groupCountX,
+    Uint32 groupCountY,
+    Uint32 groupCountZ)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    D3D12_INTERNAL_BindComputeResources(d3d12CommandBuffer);
+    ID3D12GraphicsCommandList_Dispatch(
+        d3d12CommandBuffer->graphicsCommandList,
+        groupCountX,
+        groupCountY,
+        groupCountZ);
+}
+
+static void D3D12_DispatchComputeIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12Buffer *d3d12Buffer = ((D3D12BufferContainer *)buffer)->activeBuffer;
+
+    D3D12_INTERNAL_BindComputeResources(d3d12CommandBuffer);
+    ID3D12GraphicsCommandList_ExecuteIndirect(
+        d3d12CommandBuffer->graphicsCommandList,
+        d3d12CommandBuffer->renderer->indirectDispatchCommandSignature,
+        1,
+        d3d12Buffer->handle,
+        offsetInBytes,
+        NULL,
+        0);
+}
+
+static void D3D12_EndComputePass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < d3d12CommandBuffer->computeWriteOnlyStorageTextureSubresourceCount; i += 1) {
+        if (d3d12CommandBuffer->computeWriteOnlyStorageTextureSubresources[i]) {
+            D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+                d3d12CommandBuffer,
+                D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
+                d3d12CommandBuffer->computeWriteOnlyStorageTextureSubresources[i]);
+
+            d3d12CommandBuffer->computeWriteOnlyStorageTextureSubresources[i] = NULL;
+        }
+    }
+    d3d12CommandBuffer->computeWriteOnlyStorageTextureSubresourceCount = 0;
+
+    for (Uint32 i = 0; i < d3d12CommandBuffer->computeWriteOnlyStorageBufferCount; i += 1) {
+        if (d3d12CommandBuffer->computeWriteOnlyStorageBuffers[i]) {
+            D3D12_INTERNAL_BufferTransitionToDefaultUsage(
+                d3d12CommandBuffer,
+                D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
+                d3d12CommandBuffer->computeWriteOnlyStorageBuffers[i]);
+
+            d3d12CommandBuffer->computeWriteOnlyStorageBuffers[i] = NULL;
+        }
+    }
+    d3d12CommandBuffer->computeWriteOnlyStorageBufferCount = 0;
+
+    for (Uint32 i = 0; i < MAX_STORAGE_TEXTURES_PER_STAGE; i += 1) {
+        if (d3d12CommandBuffer->computeReadOnlyStorageTextures[i]) {
+            D3D12_INTERNAL_TextureTransitionToDefaultUsage(
+                d3d12CommandBuffer,
+                D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
+                d3d12CommandBuffer->computeReadOnlyStorageTextures[i]);
+
+            d3d12CommandBuffer->computeReadOnlyStorageTextures[i] = NULL;
+        }
+    }
+
+    for (Uint32 i = 0; i < MAX_STORAGE_BUFFERS_PER_STAGE; i += 1) {
+        if (d3d12CommandBuffer->computeReadOnlyStorageBuffers[i]) {
+            D3D12_INTERNAL_BufferTransitionToDefaultUsage(
+                d3d12CommandBuffer,
+                D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE,
+                d3d12CommandBuffer->computeReadOnlyStorageBuffers[i]);
+
+            d3d12CommandBuffer->computeReadOnlyStorageBuffers[i] = NULL;
+        }
+    }
+
+    d3d12CommandBuffer->currentComputePipeline = NULL;
+}
+
+// TransferBuffer Data
+
+static void *D3D12_MapTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer,
+    SDL_bool cycle)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12BufferContainer *container = (D3D12BufferContainer *)transferBuffer;
+    void *dataPointer;
+
+    if (
+        cycle &&
+        SDL_AtomicGet(&container->activeBuffer->referenceCount) > 0) {
+        D3D12_INTERNAL_CycleActiveBuffer(
+            renderer,
+            container);
+    }
+
+    // Upload buffers are persistently mapped, download buffers are not
+    if (container->type == D3D12_BUFFER_TYPE_UPLOAD) {
+        dataPointer = container->activeBuffer->mapPointer;
+    } else {
+        ID3D12Resource_Map(
+            container->activeBuffer->handle,
+            0,
+            NULL,
+            (void **)&dataPointer);
+    }
+
+    return dataPointer;
+}
+
+static void D3D12_UnmapTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer)
+{
+    (void)driverData;
+    D3D12BufferContainer *container = (D3D12BufferContainer *)transferBuffer;
+
+    // Upload buffers are persistently mapped, download buffers are not
+    if (container->type == D3D12_BUFFER_TYPE_DOWNLOAD) {
+        ID3D12Resource_Unmap(
+            container->activeBuffer->handle,
+            0,
+            NULL);
+    }
+}
+
+// Copy Pass
+
+static void D3D12_BeginCopyPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    // no-op
+    (void)commandBuffer;
+}
+
+static void D3D12_UploadToTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureTransferInfo *source,
+    SDL_GpuTextureRegion *destination,
+    SDL_bool cycle)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12BufferContainer *transferBufferContainer = (D3D12BufferContainer *)source->transferBuffer;
+    D3D12Buffer *temporaryBuffer = NULL;
+    D3D12_TEXTURE_COPY_LOCATION sourceLocation;
+    D3D12_TEXTURE_COPY_LOCATION destinationLocation;
+    Uint32 pixelsPerRow = source->imagePitch;
+    Uint32 rowPitch;
+    Uint32 alignedRowPitch;
+    Uint32 rowsPerSlice = source->imageHeight;
+    Uint32 bytesPerSlice;
+    SDL_bool needsRealignment;
+    SDL_bool needsPlacementCopy;
+
+    // Note that the transfer buffer does not need a barrier, as it is synced by the client.
+
+    D3D12TextureContainer *textureContainer = (D3D12TextureContainer *)destination->texture;
+    D3D12TextureSubresource *textureSubresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
+        d3d12CommandBuffer,
+        textureContainer,
+        destination->layer,
+        destination->mipLevel,
+        cycle,
+        D3D12_RESOURCE_STATE_COPY_DEST);
+
+    /* D3D12 requires texture data row pitch to be 256 byte aligned, which is obviously insane.
+     * Instead of exposing that restriction to the client, which is a huge rake to step on,
+     * and a restriction that no other backend requires, we're going to copy data to a temporary buffer,
+     * copy THAT data to the texture, and then get rid of the temporary buffer ASAP.
+     * If we're lucky and the row pitch and depth pitch are already aligned, we can skip all of that.
+     *
+     * D3D12 also requires offsets to be 512 byte aligned. We'll fix that for the client and warn them as well.
+     *
+     * And just for some extra fun, D3D12 doesn't actually support depth pitch, so we have to realign that too!
+     */
+
+    if (pixelsPerRow == 0) {
+        pixelsPerRow = destination->w;
+    }
+
+    rowPitch = BytesPerRow(pixelsPerRow, textureContainer->header.info.format);
+
+    if (rowsPerSlice == 0) {
+        rowsPerSlice = destination->h;
+    }
+
+    bytesPerSlice = rowsPerSlice * rowPitch;
+
+    alignedRowPitch = D3D12_INTERNAL_Align(rowPitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+    needsRealignment = rowsPerSlice != destination->h || rowPitch != alignedRowPitch;
+    needsPlacementCopy = source->offset % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT != 0;
+
+    sourceLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+    sourceLocation.PlacedFootprint.Footprint.Format = SDLToD3D12_TextureFormat[textureContainer->header.info.format];
+    sourceLocation.PlacedFootprint.Footprint.RowPitch = alignedRowPitch;
+
+    destinationLocation.pResource = textureContainer->activeTexture->resource;
+    destinationLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+    destinationLocation.SubresourceIndex = textureSubresource->index;
+
+    if (needsRealignment) {
+        temporaryBuffer = D3D12_INTERNAL_CreateBuffer(
+            d3d12CommandBuffer->renderer,
+            0,
+            alignedRowPitch * destination->h * destination->d,
+            D3D12_BUFFER_TYPE_UPLOAD);
+
+        if (!temporaryBuffer) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create temporary upload buffer.");
+            return;
+        }
+
+        sourceLocation.pResource = temporaryBuffer->handle;
+
+        for (Uint32 sliceIndex = 0; sliceIndex < destination->d; sliceIndex += 1) {
+            // copy row count minus one to avoid overread
+            for (Uint32 rowIndex = 0; rowIndex < rowsPerSlice - 1; rowIndex += 1) {
+                SDL_memcpy(
+                    temporaryBuffer->mapPointer + (sliceIndex * rowsPerSlice) + (rowIndex * alignedRowPitch),
+                    transferBufferContainer->activeBuffer->mapPointer + source->offset + (sliceIndex * bytesPerSlice) + (rowIndex * rowPitch),
+                    alignedRowPitch);
+            }
+            Uint32 offset = source->offset + (sliceIndex * bytesPerSlice) + ((rowsPerSlice - 1) * rowPitch);
+            SDL_memcpy(
+                temporaryBuffer->mapPointer + (sliceIndex * rowsPerSlice) + ((rowsPerSlice - 1) * alignedRowPitch),
+                transferBufferContainer->activeBuffer->mapPointer + offset,
+                SDL_min(alignedRowPitch, transferBufferContainer->size - offset));
+
+            sourceLocation.PlacedFootprint.Footprint.Width = destination->w;
+            sourceLocation.PlacedFootprint.Footprint.Height = rowsPerSlice;
+            sourceLocation.PlacedFootprint.Footprint.Depth = 1;
+            sourceLocation.PlacedFootprint.Offset = (sliceIndex * bytesPerSlice);
+
+            ID3D12GraphicsCommandList_CopyTextureRegion(
+                d3d12CommandBuffer->graphicsCommandList,
+                &destinationLocation,
+                destination->x,
+                destination->y,
+                sliceIndex,
+                &sourceLocation,
+                NULL);
+        }
+
+        D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, temporaryBuffer);
+        D3D12_INTERNAL_ReleaseBuffer(
+            d3d12CommandBuffer->renderer,
+            temporaryBuffer);
+    } else if (needsPlacementCopy) {
+        temporaryBuffer = D3D12_INTERNAL_CreateBuffer(
+            d3d12CommandBuffer->renderer,
+            0,
+            alignedRowPitch * destination->h * destination->d,
+            D3D12_BUFFER_TYPE_UPLOAD);
+
+        if (!temporaryBuffer) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create temporary upload buffer.");
+            return;
+        }
+
+        SDL_memcpy(
+            temporaryBuffer->mapPointer,
+            transferBufferContainer->activeBuffer->mapPointer + source->offset,
+            alignedRowPitch * destination->h * destination->d);
+
+        sourceLocation.pResource = temporaryBuffer->handle;
+        sourceLocation.PlacedFootprint.Offset = 0;
+        sourceLocation.PlacedFootprint.Footprint.Width = destination->w;
+        sourceLocation.PlacedFootprint.Footprint.Height = destination->h;
+        sourceLocation.PlacedFootprint.Footprint.Depth = 1;
+
+        ID3D12GraphicsCommandList_CopyTextureRegion(
+            d3d12CommandBuffer->graphicsCommandList,
+            &destinationLocation,
+            destination->x,
+            destination->y,
+            destination->z,
+            &sourceLocation,
+            NULL);
+
+        D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, temporaryBuffer);
+        D3D12_INTERNAL_ReleaseBuffer(
+            d3d12CommandBuffer->renderer,
+            temporaryBuffer);
+
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Texture upload offset not aligned to 512 bytes! This is suboptimal on D3D12!");
+    } else {
+        sourceLocation.pResource = transferBufferContainer->activeBuffer->handle;
+        sourceLocation.PlacedFootprint.Offset = source->offset;
+        sourceLocation.PlacedFootprint.Footprint.Width = destination->w;
+        sourceLocation.PlacedFootprint.Footprint.Height = destination->h;
+        sourceLocation.PlacedFootprint.Footprint.Depth = destination->d;
+
+        ID3D12GraphicsCommandList_CopyTextureRegion(
+            d3d12CommandBuffer->graphicsCommandList,
+            &destinationLocation,
+            destination->x,
+            destination->y,
+            destination->z,
+            &sourceLocation,
+            NULL);
+    }
+
+    D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_DEST,
+        textureSubresource);
+
+    D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, transferBufferContainer->activeBuffer);
+    D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, textureSubresource->parent);
+}
+
+static void D3D12_UploadToBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTransferBufferLocation *source,
+    SDL_GpuBufferRegion *destination,
+    SDL_bool cycle)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12BufferContainer *transferBufferContainer = (D3D12BufferContainer *)source->transferBuffer;
+    D3D12BufferContainer *bufferContainer = (D3D12BufferContainer *)destination->buffer;
+
+    // The transfer buffer does not need a barrier, it is synced by the client.
+
+    D3D12Buffer *buffer = D3D12_INTERNAL_PrepareBufferForWrite(
+        d3d12CommandBuffer,
+        bufferContainer,
+        cycle,
+        D3D12_RESOURCE_STATE_COPY_DEST);
+
+    ID3D12GraphicsCommandList_CopyBufferRegion(
+        d3d12CommandBuffer->graphicsCommandList,
+        buffer->handle,
+        destination->offset,
+        transferBufferContainer->activeBuffer->handle,
+        source->offset,
+        destination->size);
+
+    D3D12_INTERNAL_BufferTransitionToDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_DEST,
+        buffer);
+
+    D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, transferBufferContainer->activeBuffer);
+    D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, buffer);
+}
+
+static void D3D12_CopyTextureToTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureLocation *source,
+    SDL_GpuTextureLocation *destination,
+    Uint32 w,
+    Uint32 h,
+    Uint32 d,
+    SDL_bool cycle)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12_TEXTURE_COPY_LOCATION sourceLocation;
+    D3D12_TEXTURE_COPY_LOCATION destinationLocation;
+
+    D3D12TextureSubresource *sourceSubresource = D3D12_INTERNAL_FetchTextureSubresource(
+        (D3D12TextureContainer *)source->texture,
+        source->layer,
+        source->mipLevel);
+
+    D3D12TextureSubresource *destinationSubresource = D3D12_INTERNAL_PrepareTextureSubresourceForWrite(
+        d3d12CommandBuffer,
+        (D3D12TextureContainer *)destination->texture,
+        destination->layer,
+        destination->mipLevel,
+        cycle,
+        D3D12_RESOURCE_STATE_COPY_DEST);
+
+    D3D12_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_SOURCE,
+        sourceSubresource);
+
+    sourceLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+    sourceLocation.SubresourceIndex = sourceSubresource->index;
+    sourceLocation.pResource = sourceSubresource->parent->resource;
+
+    destinationLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+    destinationLocation.SubresourceIndex = destinationSubresource->index;
+    destinationLocation.pResource = destinationSubresource->parent->resource;
+
+    D3D12_BOX sourceBox = { source->x, source->y, source->z, source->x + w, source->y + h, source->z + d };
+
+    ID3D12GraphicsCommandList_CopyTextureRegion(
+        d3d12CommandBuffer->graphicsCommandList,
+        &destinationLocation,
+        destination->x,
+        destination->y,
+        destination->z,
+        &sourceLocation,
+        &sourceBox);
+
+    D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_SOURCE,
+        sourceSubresource);
+
+    D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_DEST,
+        destinationSubresource);
+
+    D3D12_INTERNAL_TrackTexture(
+        d3d12CommandBuffer,
+        sourceSubresource->parent);
+
+    D3D12_INTERNAL_TrackTexture(
+        d3d12CommandBuffer,
+        destinationSubresource->parent);
+}
+
+static void D3D12_CopyBufferToBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferLocation *source,
+    SDL_GpuBufferLocation *destination,
+    Uint32 size,
+    SDL_bool cycle)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12BufferContainer *sourceContainer = (D3D12BufferContainer *)source->buffer;
+    D3D12BufferContainer *destinationContainer = (D3D12BufferContainer *)destination->buffer;
+
+    D3D12Buffer *sourceBuffer = sourceContainer->activeBuffer;
+    D3D12Buffer *destinationBuffer = D3D12_INTERNAL_PrepareBufferForWrite(
+        d3d12CommandBuffer,
+        destinationContainer,
+        cycle,
+        D3D12_RESOURCE_STATE_COPY_DEST);
+
+    D3D12_INTERNAL_BufferTransitionFromDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_SOURCE,
+        sourceBuffer);
+
+    ID3D12GraphicsCommandList_CopyBufferRegion(
+        d3d12CommandBuffer->graphicsCommandList,
+        destinationBuffer->handle,
+        destination->offset,
+        sourceBuffer->handle,
+        source->offset,
+        size);
+
+    D3D12_INTERNAL_BufferTransitionToDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_SOURCE,
+        sourceBuffer);
+
+    D3D12_INTERNAL_BufferTransitionToDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_DEST,
+        destinationBuffer);
+
+    D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, sourceBuffer);
+    D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, destinationBuffer);
+}
+
+static void D3D12_DownloadFromTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureRegion *source,
+    SDL_GpuTextureTransferInfo *destination)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12_TEXTURE_COPY_LOCATION sourceLocation;
+    D3D12_TEXTURE_COPY_LOCATION destinationLocation;
+    Uint32 pixelsPerRow = destination->imagePitch;
+    Uint32 rowPitch;
+    Uint32 alignedRowPitch;
+    Uint32 rowsPerSlice = destination->imageHeight;
+    SDL_bool needsRealignment;
+    SDL_bool needsPlacementCopy;
+    D3D12TextureDownload *textureDownload = NULL;
+    D3D12TextureContainer *sourceContainer = (D3D12TextureContainer *)source->texture;
+    D3D12TextureSubresource *sourceSubresource = D3D12_INTERNAL_FetchTextureSubresource(
+        sourceContainer,
+        source->layer,
+        source->mipLevel);
+    D3D12BufferContainer *destinationContainer = (D3D12BufferContainer *)destination->transferBuffer;
+    D3D12Buffer *destinationBuffer = destinationContainer->activeBuffer;
+
+    /* D3D12 requires texture data row pitch to be 256 byte aligned, which is obviously insane.
+     * Instead of exposing that restriction to the client, which is a huge rake to step on,
+     * and a restriction that no other backend requires, we're going to copy data to a temporary buffer,
+     * copy THAT data to the texture, and then get rid of the temporary buffer ASAP.
+     * If we're lucky and the row pitch and depth pitch are already aligned, we can skip all of that.
+     *
+     * D3D12 also requires offsets to be 512 byte aligned. We'll fix that for the client and warn them as well.
+     *
+     * And just for some extra fun, D3D12 doesn't actually support depth pitch, so we have to realign that too!
+     *
+     * Since this is an async download we have to do all these fixups after the command is finished,
+     * so we'll cache the metadata similar to D3D11 and map and copy it when the command buffer is cleaned.
+     */
+
+    if (pixelsPerRow == 0) {
+        pixelsPerRow = source->w;
+    }
+
+    rowPitch = BytesPerRow(pixelsPerRow, sourceContainer->header.info.format);
+
+    if (rowsPerSlice == 0) {
+        rowsPerSlice = source->h;
+    }
+
+    alignedRowPitch = D3D12_INTERNAL_Align(rowPitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
+    needsRealignment = rowsPerSlice != source->h || rowPitch != alignedRowPitch;
+    needsPlacementCopy = destination->offset % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT != 0;
+
+    sourceLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
+    sourceLocation.SubresourceIndex = sourceSubresource->index;
+    sourceLocation.pResource = sourceSubresource->parent->resource;
+
+    D3D12_BOX sourceBox = { source->x, source->y, source->z, source->x + source->w, source->y + rowsPerSlice, source->z + source->d };
+
+    destinationLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
+    destinationLocation.PlacedFootprint.Footprint.Format = SDLToD3D12_TextureFormat[sourceContainer->header.info.format];
+    destinationLocation.PlacedFootprint.Footprint.Width = source->w;
+    destinationLocation.PlacedFootprint.Footprint.Height = rowsPerSlice;
+    destinationLocation.PlacedFootprint.Footprint.Depth = source->d;
+    destinationLocation.PlacedFootprint.Footprint.RowPitch = alignedRowPitch;
+
+    if (needsRealignment || needsPlacementCopy) {
+        textureDownload = (D3D12TextureDownload *)SDL_malloc(sizeof(D3D12TextureDownload));
+
+        if (!textureDownload) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create texture download structure!");
+            return;
+        }
+
+        textureDownload->temporaryBuffer = D3D12_INTERNAL_CreateBuffer(
+            d3d12CommandBuffer->renderer,
+            0,
+            alignedRowPitch * rowsPerSlice * source->d,
+            D3D12_BUFFER_TYPE_DOWNLOAD);
+
+        if (!textureDownload->temporaryBuffer) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create temporary download buffer!");
+            SDL_free(textureDownload);
+            return;
+        }
+
+        textureDownload->destinationBuffer = destinationBuffer;
+        textureDownload->bufferOffset = destination->offset;
+        textureDownload->width = source->w;
+        textureDownload->height = rowsPerSlice;
+        textureDownload->depth = source->d;
+        textureDownload->bytesPerRow = rowPitch;
+        textureDownload->bytesPerDepthSlice = rowPitch * rowsPerSlice;
+        textureDownload->alignedBytesPerRow = alignedRowPitch;
+
+        destinationLocation.pResource = textureDownload->temporaryBuffer->handle;
+        destinationLocation.PlacedFootprint.Offset = 0;
+    } else {
+        destinationLocation.pResource = destinationBuffer->handle;
+        destinationLocation.PlacedFootprint.Offset = destination->offset;
+    }
+
+    D3D12_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_SOURCE,
+        sourceSubresource);
+
+    ID3D12GraphicsCommandList_CopyTextureRegion(
+        d3d12CommandBuffer->graphicsCommandList,
+        &destinationLocation,
+        0,
+        0,
+        0,
+        &sourceLocation,
+        &sourceBox);
+
+    D3D12_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_SOURCE,
+        sourceSubresource);
+
+    D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, destinationBuffer);
+    D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, sourceSubresource->parent);
+
+    if (textureDownload != NULL) {
+        D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, textureDownload->temporaryBuffer);
+
+        if (d3d12CommandBuffer->textureDownloadCount >= d3d12CommandBuffer->textureDownloadCapacity) {
+            d3d12CommandBuffer->textureDownloadCapacity *= 2;
+            d3d12CommandBuffer->textureDownloads = (D3D12TextureDownload **)SDL_realloc(
+                d3d12CommandBuffer->textureDownloads,
+                d3d12CommandBuffer->textureDownloadCapacity * sizeof(D3D12TextureDownload *));
+        }
+
+        d3d12CommandBuffer->textureDownloads[d3d12CommandBuffer->textureDownloadCount] = textureDownload;
+        d3d12CommandBuffer->textureDownloadCount += 1;
+
+        D3D12_INTERNAL_ReleaseBuffer(d3d12CommandBuffer->renderer, textureDownload->temporaryBuffer);
+    }
+}
+
+static void D3D12_DownloadFromBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferRegion *source,
+    SDL_GpuTransferBufferLocation *destination)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12BufferContainer *sourceContainer = (D3D12BufferContainer *)source->buffer;
+    D3D12BufferContainer *destinationContainer = (D3D12BufferContainer *)destination->transferBuffer;
+
+    D3D12Buffer *sourceBuffer = sourceContainer->activeBuffer;
+    D3D12_INTERNAL_BufferTransitionFromDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_SOURCE,
+        sourceBuffer);
+
+    D3D12Buffer *destinationBuffer = destinationContainer->activeBuffer;
+
+    ID3D12GraphicsCommandList_CopyBufferRegion(
+        d3d12CommandBuffer->graphicsCommandList,
+        destinationBuffer->handle,
+        destination->offset,
+        sourceBuffer->handle,
+        source->offset,
+        source->size);
+
+    D3D12_INTERNAL_BufferTransitionToDefaultUsage(
+        d3d12CommandBuffer,
+        D3D12_RESOURCE_STATE_COPY_SOURCE,
+        sourceBuffer);
+
+    D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, sourceBuffer);
+    D3D12_INTERNAL_TrackBuffer(d3d12CommandBuffer, destinationBuffer);
+}
+
+static void D3D12_EndCopyPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    // no-op
+    (void)commandBuffer;
+}
+
+static void D3D12_GenerateMipmaps(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTexture *texture)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12Renderer *renderer = d3d12CommandBuffer->renderer;
+    D3D12TextureContainer *container = (D3D12TextureContainer *)texture;
+    SDL_GpuGraphicsPipeline *blitPipeline;
+    SDL_GpuBlitRegion srcRegion, dstRegion;
+
+    blitPipeline = SDL_Gpu_FetchBlitPipeline(
+        renderer->sdlGpuDevice,
+        container->header.info.type,
+        container->header.info.format,
+        renderer->blitVertexShader,
+        renderer->blitFrom2DShader,
+        renderer->blitFrom2DArrayShader,
+        renderer->blitFrom3DShader,
+        renderer->blitFromCubeShader,
+        &renderer->blitPipelines,
+        &renderer->blitPipelineCount,
+        &renderer->blitPipelineCapacity);
+
+    if (blitPipeline == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not fetch blit pipeline");
+        return;
+    }
+
+    // We have to do this one subresource at a time
+    for (Uint32 layerOrDepthIndex = 0; layerOrDepthIndex < container->header.info.layerCountOrDepth; layerOrDepthIndex += 1) {
+        for (Uint32 levelIndex = 1; levelIndex < container->header.info.levelCount; levelIndex += 1) {
+
+            srcRegion.texture = texture;
+            srcRegion.mipLevel = levelIndex - 1;
+            srcRegion.layerOrDepthPlane = layerOrDepthIndex;
+            srcRegion.x = 0;
+            srcRegion.y = 0;
+            srcRegion.w = container->header.info.width >> (levelIndex - 1);
+            srcRegion.h = container->header.info.height >> (levelIndex - 1);
+
+            dstRegion.texture = texture;
+            dstRegion.mipLevel = levelIndex;
+            dstRegion.layerOrDepthPlane = layerOrDepthIndex;
+            dstRegion.x = 0;
+            dstRegion.y = 0;
+            dstRegion.w = container->header.info.width >> levelIndex;
+            dstRegion.h = container->header.info.height >> levelIndex;
+
+            SDL_BlitGpu(
+                commandBuffer,
+                &srcRegion,
+                &dstRegion,
+                SDL_FLIP_NONE,
+                SDL_GPU_FILTER_LINEAR,
+                SDL_FALSE);
+        }
+    }
+
+    D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, container->activeTexture);
+}
+
+static void D3D12_Blit(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBlitRegion *source,
+    SDL_GpuBlitRegion *destination,
+    SDL_FlipMode flipMode,
+    SDL_GpuFilter filterMode,
+    SDL_bool cycle)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12Renderer *renderer = (D3D12Renderer *)d3d12CommandBuffer->renderer;
+
+    SDL_Gpu_BlitCommon(
+        commandBuffer,
+        source,
+        destination,
+        flipMode,
+        filterMode,
+        cycle,
+        renderer->blitLinearSampler,
+        renderer->blitNearestSampler,
+        renderer->blitVertexShader,
+        renderer->blitFrom2DShader,
+        renderer->blitFrom2DArrayShader,
+        renderer->blitFrom3DShader,
+        renderer->blitFromCubeShader,
+        &renderer->blitPipelines,
+        &renderer->blitPipelineCount,
+        &renderer->blitPipelineCapacity);
+}
+
+// Submission/Presentation
+
+static D3D12WindowData *D3D12_INTERNAL_FetchWindowData(
+    SDL_Window *window)
+{
+    SDL_PropertiesID properties = SDL_GetWindowProperties(window);
+    return (D3D12WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
+}
+
+static SDL_bool D3D12_SupportsSwapchainComposition(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition)
+{
+#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
+    // FIXME: HDR support would be nice to add, but it seems complicated...
+    return swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR ||
+           swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR;
+#else
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    DXGI_FORMAT format;
+    D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport;
+    Uint32 colorSpaceSupport;
+    HRESULT res;
+
+    format = SwapchainCompositionToTextureFormat[swapchainComposition];
+
+    formatSupport.Format = format;
+    res = ID3D12Device_CheckFeatureSupport(
+        renderer->device,
+        D3D12_FEATURE_FORMAT_SUPPORT,
+        &formatSupport,
+        sizeof(formatSupport));
+    if (FAILED(res)) {
+        // Format is apparently unknown
+        return SDL_FALSE;
+    }
+
+    if (!(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_DISPLAY)) {
+        return SDL_FALSE;
+    }
+
+    D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
+    if (windowData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Must claim window before querying swapchain composition support!");
+        return SDL_FALSE;
+    }
+
+    // Check the color space support if necessary
+    if (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR) {
+        IDXGISwapChain3_CheckColorSpaceSupport(
+            windowData->swapchain,
+            SwapchainCompositionToColorSpace[swapchainComposition],
+            &colorSpaceSupport);
+
+        if (!(colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) {
+            return SDL_FALSE;
+        }
+    }
+#endif
+
+    return SDL_TRUE;
+}
+
+static SDL_bool D3D12_SupportsPresentMode(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuPresentMode presentMode)
+{
+    (void)driverData;
+    (void)window;
+
+    switch (presentMode) {
+    case SDL_GPU_PRESENTMODE_IMMEDIATE:
+    case SDL_GPU_PRESENTMODE_VSYNC:
+        return SDL_TRUE;
+    case SDL_GPU_PRESENTMODE_MAILBOX:
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+        return SDL_FALSE;
+#else
+        return SDL_TRUE;
+#endif
+    default:
+        SDL_assert(!"Unrecognized present mode");
+        return SDL_FALSE;
+    }
+}
+
+#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
+static SDL_bool D3D12_INTERNAL_CreateSwapchain(
+    D3D12Renderer *renderer,
+    D3D12WindowData *windowData,
+    SDL_GpuSwapchainComposition swapchainComposition,
+    SDL_GpuPresentMode presentMode)
+{
+    int width, height;
+    SDL_GpuTextureCreateInfo createInfo;
+    D3D12Texture *texture;
+
+    // Get the swapchain size
+    SDL_GetWindowSize(windowData->window, &width, &height);
+
+    // Create the swapchain textures
+    SDL_zero(createInfo);
+    createInfo.type = SDL_GPU_TEXTURETYPE_2D;
+    createInfo.width = width;
+    createInfo.height = height;
+    createInfo.format = SwapchainCompositionToSDLTextureFormat[swapchainComposition];
+    createInfo.usageFlags = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT;
+    createInfo.layerCountOrDepth = 1;
+    createInfo.levelCount = 1;
+
+    for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+        texture = D3D12_INTERNAL_CreateTexture(renderer, &createInfo, SDL_TRUE);
+        texture->container = &windowData->textureContainers[i];
+        windowData->textureContainers[i].activeTexture = texture;
+        windowData->textureContainers[i].canBeCycled = SDL_FALSE;
+        windowData->textureContainers[i].header.info = createInfo;
+        windowData->textureContainers[i].textureCapacity = 1;
+        windowData->textureContainers[i].textureCount = 1;
+        windowData->textureContainers[i].textures = &windowData->textureContainers[i].activeTexture;
+    }
+
+    // Initialize the swapchain data
+    windowData->presentMode = presentMode;
+    windowData->swapchainComposition = swapchainComposition;
+    windowData->swapchainColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
+    windowData->frameCounter = 0;
+    windowData->swapchainWidth = width;
+    windowData->swapchainHeight = height;
+
+    // Precache blit pipelines for the swapchain format
+    for (Uint32 i = 0; i < 4; i += 1) {
+        SDL_Gpu_FetchBlitPipeline(
+            renderer->sdlGpuDevice,
+            (SDL_GpuTextureType)i,
+            createInfo.format,
+            renderer->blitVertexShader,
+            renderer->blitFrom2DShader,
+            renderer->blitFrom2DArrayShader,
+            renderer->blitFrom3DShader,
+            renderer->blitFromCubeShader,
+            &renderer->blitPipelines,
+            &renderer->blitPipelineCount,
+            &renderer->blitPipelineCapacity);
+    }
+
+    return SDL_TRUE;
+}
+
+static void D3D12_INTERNAL_DestroySwapchain(
+    D3D12Renderer *renderer,
+    D3D12WindowData *windowData)
+{
+    renderer->commandQueue->PresentX(0, NULL, NULL);
+    for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+        D3D12_INTERNAL_DestroyTexture(
+            renderer,
+            windowData->textureContainers[i].activeTexture);
+    }
+}
+
+static SDL_bool D3D12_INTERNAL_ResizeSwapchainIfNeeded(
+    D3D12Renderer *renderer,
+    D3D12WindowData *windowData)
+{
+    int w, h;
+    SDL_GetWindowSize(windowData->window, &w, &h);
+
+    if (w != windowData->swapchainWidth || h != windowData->swapchainHeight) {
+        // Wait so we don't release in-flight views
+        D3D12_Wait((SDL_GpuRenderer *)renderer);
+
+        // Present a black screen
+        renderer->commandQueue->PresentX(0, NULL, NULL);
+
+        // Clean up the previous swapchain textures
+        for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+            D3D12_INTERNAL_DestroyTexture(
+                renderer,
+                windowData->textureContainers[i].activeTexture);
+        }
+
+        // Create a new swapchain
+        D3D12_INTERNAL_CreateSwapchain(
+            renderer,
+            windowData,
+            windowData->swapchainComposition,
+            windowData->presentMode);
+    }
+
+    return SDL_TRUE;
+}
+#else
+static SDL_bool D3D12_INTERNAL_InitializeSwapchainTexture(
+    D3D12Renderer *renderer,
+    IDXGISwapChain3 *swapchain,
+    SDL_GpuSwapchainComposition composition,
+    Uint32 index,
+    D3D12TextureContainer *pTextureContainer)
+{
+    D3D12Texture *pTexture;
+    ID3D12Resource *swapchainTexture;
+    D3D12_RESOURCE_DESC textureDesc;
+    D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
+    D3D12_RENDER_TARGET_VIEW_DESC rtvDesc;
+    DXGI_FORMAT swapchainFormat = SwapchainCompositionToTextureFormat[composition];
+    HRESULT res;
+
+    res = IDXGISwapChain_GetBuffer(
+        swapchain,
+        index,
+        D3D_GUID(D3D_IID_ID3D12Resource),
+        (void **)&swapchainTexture);
+    ERROR_CHECK_RETURN("Could not get buffer from swapchain!", 0);
+
+    pTexture = (D3D12Texture *)SDL_calloc(1, sizeof(D3D12Texture));
+    if (!pTexture) {
+        ID3D12Resource_Release(swapchainTexture);
+        return SDL_FALSE;
+    }
+    pTexture->resource = NULL; // This will be set in AcquireSwapchainTexture
+    SDL_AtomicSet(&pTexture->referenceCount, 0);
+    pTexture->subresourceCount = 1;
+    pTexture->subresources = (D3D12TextureSubresource *)SDL_calloc(1, sizeof(D3D12TextureSubresource));
+    if (!pTexture->subresources) {
+        SDL_free(pTexture);
+        ID3D12Resource_Release(swapchainTexture);
+        return SDL_FALSE;
+    }
+    pTexture->subresources[0].rtvHandles = SDL_calloc(1, sizeof(D3D12CPUDescriptor));
+    pTexture->subresources[0].uavHandle.heap = NULL;
+    pTexture->subresources[0].dsvHandle.heap = NULL;
+    pTexture->subresources[0].parent = pTexture;
+    pTexture->subresources[0].index = 0;
+    pTexture->subresources[0].layer = 0;
+    pTexture->subresources[0].depth = 1;
+    pTexture->subresources[0].level = 0;
+
+    ID3D12Resource_GetDesc(swapchainTexture, &textureDesc);
+    pTextureContainer->header.info.width = (Uint32)textureDesc.Width;
+    pTextureContainer->header.info.height = (Uint32)textureDesc.Height;
+    pTextureContainer->header.info.layerCountOrDepth = 1;
+    pTextureContainer->header.info.levelCount = 1;
+    pTextureContainer->header.info.type = SDL_GPU_TEXTURETYPE_2D;
+    pTextureContainer->header.info.usageFlags = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT;
+    pTextureContainer->header.info.sampleCount = SDL_GPU_SAMPLECOUNT_1;
+    pTextureContainer->header.info.format = SwapchainCompositionToSDLTextureFormat[composition];
+
+    pTextureContainer->debugName = NULL;
+    pTextureContainer->textures = (D3D12Texture **)SDL_calloc(1, sizeof(D3D12Texture *));
+    if (!pTextureContainer->textures) {
+        SDL_free(pTexture->subresources);
+        SDL_free(pTexture);
+        ID3D12Resource_Release(swapchainTexture);
+        return SDL_FALSE;
+    }
+
+    pTextureContainer->textureCapacity = 1;
+    pTextureContainer->textureCount = 1;
+    pTextureContainer->textures[0] = pTexture;
+    pTextureContainer->activeTexture = pTexture;
+    pTextureContainer->canBeCycled = SDL_FALSE;
+
+    pTexture->container = pTextureContainer;
+    pTexture->containerIndex = 0;
+
+    // Create the SRV for the swapchain
+    D3D12_INTERNAL_AssignCpuDescriptorHandle(
+        renderer,
+        D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
+        &pTexture->srvHandle);
+
+    srvDesc.Format = SwapchainCompositionToTextureFormat[composition];
+    srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
+    srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
+    srvDesc.Texture2D.MipLevels = 1;
+    srvDesc.Texture2D.MostDetailedMip = 0;
+    srvDesc.Texture2D.ResourceMinLODClamp = 0;
+    srvDesc.Texture2D.PlaneSlice = 0;
+
+    ID3D12Device_CreateShaderResourceView(
+        renderer->device,
+        swapchainTexture,
+        &srvDesc,
+        pTexture->srvHandle.cpuHandle);
+
+    // Create the RTV for the swapchain
+    D3D12_INTERNAL_AssignCpuDescriptorHandle(
+        renderer,
+        D3D12_DESCRIPTOR_HEAP_TYPE_RTV,
+        &pTexture->subresources[0].rtvHandles[0]);
+
+    rtvDesc.Format = (composition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : swapchainFormat;
+    rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
+    rtvDesc.Texture2D.MipSlice = 0;
+    rtvDesc.Texture2D.PlaneSlice = 0;
+
+    ID3D12Device_CreateRenderTargetView(
+        renderer->device,
+        swapchainTexture,
+        &rtvDesc,
+        pTexture->subresources[0].rtvHandles[0].cpuHandle);
+
+    ID3D12Resource_Release(swapchainTexture);
+
+    return SDL_TRUE;
+}
+
+static SDL_bool D3D12_INTERNAL_ResizeSwapchainIfNeeded(
+    D3D12Renderer *renderer,
+    D3D12WindowData *windowData)
+{
+    DXGI_SWAP_CHAIN_DESC swapchainDesc;
+    int w, h;
+
+    IDXGISwapChain_GetDesc(windowData->swapchain, &swapchainDesc);
+    SDL_GetWindowSize(windowData->window, &w, &h);
+
+    if (w != swapchainDesc.BufferDesc.Width || h != swapchainDesc.BufferDesc.Height) {
+        // Wait so we don't release in-flight views
+        D3D12_Wait((SDL_GpuRenderer *)renderer);
+
+        // Release views and clean up
+        for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+            D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+                renderer,
+                &windowData->textureContainers[i].activeTexture->srvHandle);
+            D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+                renderer,
+                &windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles[0]);
+
+            SDL_free(windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles);
+            SDL_free(windowData->textureContainers[i].activeTexture->subresources);
+            SDL_free(windowData->textureContainers[i].activeTexture);
+            SDL_free(windowData->textureContainers[i].textures);
+        }
+
+        // Resize the swapchain
+        HRESULT res = IDXGISwapChain_ResizeBuffers(
+            windowData->swapchain,
+            0, // Keep buffer count the same
+            swapchainDesc.BufferDesc.Width,
+            swapchainDesc.BufferDesc.Height,
+            DXGI_FORMAT_UNKNOWN, // Keep the old format
+            renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
+        ERROR_CHECK_RETURN("Could not resize swapchain buffers", 0)
+
+        // Create texture object for the swapchain
+        for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+            if (!D3D12_INTERNAL_InitializeSwapchainTexture(
+                    renderer,
+                    windowData->swapchain,
+                    windowData->swapchainComposition,
+                    i,
+                    &windowData->textureContainers[i])) {
+                return SDL_FALSE;
+            }
+        }
+    }
+
+    return SDL_TRUE;
+}
+
+static void D3D12_INTERNAL_DestroySwapchain(
+    D3D12Renderer *renderer,
+    D3D12WindowData *windowData)
+{
+    // Release views and clean up
+    for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+        D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+            renderer,
+            &windowData->textureContainers[i].activeTexture->srvHandle);
+        D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
+            renderer,
+            &windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles[0]);
+
+        SDL_free(windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles);
+        SDL_free(windowData->textureContainers[i].activeTexture->subresources);
+        SDL_free(windowData->textureContainers[i].activeTexture);
+        SDL_free(windowData->textureContainers[i].textures);
+    }
+
+    IDXGISwapChain_Release(windowData->swapchain);
+    windowData->swapchain = NULL;
+}
+
+static SDL_bool D3D12_INTERNAL_CreateSwapchain(
+    D3D12Renderer *renderer,
+    D3D12WindowData *windowData,
+    SDL_GpuSwapchainComposition swapchainComposition,
+    SDL_GpuPresentMode presentMode)
+{
+    HWND dxgiHandle;
+    int width, height;
+    DXGI_SWAP_CHAIN_DESC1 swapchainDesc;
+    DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc;
+    DXGI_FORMAT swapchainFormat;
+    IDXGIFactory1 *pParent;
+    IDXGISwapChain1 *swapchain;
+    IDXGISwapChain3 *swapchain3;
+    HRESULT res;
+
+    // Get the DXGI handle
+#ifdef _WIN32
+    dxgiHandle = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(windowData->window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
+#else
+    dxgiHandle = (HWND)windowData->window;
+#endif
+
+    // Get the window size
+    SDL_GetWindowSize(windowData->window, &width, &height);
+
+    swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
+
+    // Initialize the swapchain buffer descriptor
+    swapchainDesc.Width = 0;
+    swapchainDesc.Height = 0;
+    swapchainDesc.Format = swapchainFormat;
+    swapchainDesc.SampleDesc.Count = 1;
+    swapchainDesc.SampleDesc.Quality = 0;
+    swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+    swapchainDesc.BufferCount = MAX_FRAMES_IN_FLIGHT;
+    swapchainDesc.Scaling = DXGI_SCALING_STRETCH;
+    swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
+    swapchainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
+    swapchainDesc.Flags = 0;
+    swapchainDesc.Stereo = 0;
+
+    // Initialize the fullscreen descriptor (if needed)
+    fullscreenDesc.RefreshRate.Numerator = 0;
+    fullscreenDesc.RefreshRate.Denominator = 0;
+    fullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+    fullscreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+    fullscreenDesc.Windowed = SDL_TRUE;
+
+    if (renderer->supportsTearing) {
+        swapchainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
+    } else {
+        swapchainDesc.Flags = 0;
+    }
+
+#ifndef SDL_PLATFORM_WINRT
+    if (!IsWindow(dxgiHandle)) {
+        return SDL_FALSE;
+    }
+#endif
+
+    // Create the swapchain!
+    res = IDXGIFactory4_CreateSwapChainForHwnd(
+        renderer->factory,
+        (IUnknown *)renderer->commandQueue,
+        dxgiHandle,
+        &swapchainDesc,
+        &fullscreenDesc,
+        NULL,
+        &swapchain);
+    ERROR_CHECK_RETURN("Could not create swapchain", 0);
+
+    res = IDXGISwapChain1_QueryInterface(
+        swapchain,
+        D3D_GUID(D3D_IID_IDXGISwapChain3),
+        (void **)&swapchain3);
+    IDXGISwapChain1_Release(swapchain);
+    ERROR_CHECK_RETURN("Could not create IDXGISwapChain3", 0);
+
+    if (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR) {
+        // Support already verified if we hit this block
+        IDXGISwapChain3_SetColorSpace1(
+            swapchain3,
+            SwapchainCompositionToColorSpace[swapchainComposition]);
+    }
+
+    /*
+     * The swapchain's parent is a separate factory from the factory that
+     * we used to create the swapchain, and only that parent can be used to
+     * set the window association. Trying to set an association on our factory
+     * will silently fail and doesn't even verify arguments or return errors.
+     * See https://gamedev.net/forums/topic/634235-dxgidisabling-altenter/4999955/
+     */
+    res = IDXGISwapChain3_GetParent(
+        swapchain3,
+        D3D_GUID(D3D_IID_IDXGIFactory1),
+        (void **)&pParent);
+    if (FAILED(res)) {
+        SDL_LogWarn(
+            SDL_LOG_CATEGORY_APPLICATION,
+            "Could not get swapchain parent! Error Code: " HRESULT_FMT,
+            res);
+    } else {
+        // Disable DXGI window crap
+        res = IDXGIFactory1_MakeWindowAssociation(
+            pParent,
+            dxgiHandle,
+            DXGI_MWA_NO_WINDOW_CHANGES);
+        if (FAILED(res)) {
+            SDL_LogWarn(
+                SDL_LOG_CATEGORY_APPLICATION,
+                "MakeWindowAssociation failed! Error Code: " HRESULT_FMT,
+                res);
+        }
+
+        // We're done with the parent now
+        IDXGIFactory1_Release(pParent);
+    }
+
+    // Initialize the swapchain data
+    windowData->swapchain = swapchain3;
+    windowData->presentMode = presentMode;
+    windowData->swapchainComposition = swapchainComposition;
+    windowData->swapchainColorSpace = SwapchainCompositionToColorSpace[swapchainComposition];
+    windowData->frameCounter = 0;
+
+    // Precache blit pipelines for the swapchain format
+    for (Uint32 i = 0; i < 4; i += 1) {
+        SDL_Gpu_FetchBlitPipeline(
+            renderer->sdlGpuDevice,
+            (SDL_GpuTextureType)i,
+            SwapchainCompositionToSDLTextureFormat[swapchainComposition],
+            renderer->blitVertexShader,
+            renderer->blitFrom2DShader,
+            renderer->blitFrom2DArrayShader,
+            renderer->blitFrom3DShader,
+            renderer->blitFromCubeShader,
+            &renderer->blitPipelines,
+            &renderer->blitPipelineCount,
+            &renderer->blitPipelineCapacity);
+    }
+
+    /* If a you are using a FLIP model format you can't create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM_SRGB.
+     * You have to create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM and then set the render target view's format to DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
+     */
+    for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+        if (!D3D12_INTERNAL_InitializeSwapchainTexture(
+                renderer,
+                swapchain3,
+                swapchainComposition,
+                i,
+                &windowData->textureContainers[i])) {
+            IDXGISwapChain3_Release(swapchain3);
+            return SDL_FALSE;
+        }
+    }
+
+    return SDL_TRUE;
+}
+#endif
+
+static SDL_bool D3D12_ClaimWindow(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        windowData = (D3D12WindowData *)SDL_calloc(1, sizeof(D3D12WindowData));
+        if (!windowData) {
+            return SDL_FALSE;
+        }
+        windowData->window = window;
+
+        if (D3D12_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
+            SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
+
+            SDL_LockMutex(renderer->windowLock);
+
+            if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
+                renderer->claimedWindowCapacity *= 2;
+                renderer->claimedWindows = (D3D12WindowData **)SDL_realloc(
+                    renderer->claimedWindows,
+                    renderer->claimedWindowCapacity * sizeof(D3D12WindowData *));
+            }
+            renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
+            renderer->claimedWindowCount += 1;
+
+            SDL_UnlockMutex(renderer->windowLock);
+
+            return SDL_TRUE;
+        } else {
+            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not create swapchain, failed to claim window!");
+            SDL_free(windowData);
+            return SDL_FALSE;
+        }
+    } else {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Window already claimed!");
+        return SDL_FALSE;
+    }
+}
+
+static void D3D12_UnclaimWindow(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Window already unclaimed!");
+        return;
+    }
+
+    D3D12_Wait(driverData);
+
+    for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+        if (windowData->inFlightFences[i] != NULL) {
+            D3D12_ReleaseFence(
+                driverData,
+                (SDL_GpuFence *)windowData->inFlightFences[i]);
+            windowData->inFlightFences[i] = NULL;
+        }
+    }
+
+    D3D12_INTERNAL_DestroySwapchain(renderer, windowData);
+
+    SDL_LockMutex(renderer->windowLock);
+    for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
+        if (renderer->claimedWindows[i]->window == window) {
+            renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1];
+            renderer->claimedWindowCount -= 1;
+            break;
+        }
+    }
+    SDL_UnlockMutex(renderer->windowLock);
+
+    SDL_free(windowData);
+    SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
+}
+
+static SDL_bool D3D12_SetSwapchainParameters(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition,
+    SDL_GpuPresentMode presentMode)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Cannot set swapchain parameters on unclaimed window!");
+        return SDL_FALSE;
+    }
+
+    if (!D3D12_SupportsSwapchainComposition(driverData, window, swapchainComposition)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Swapchain composition not supported!");
+        return SDL_FALSE;
+    }
+
+    if (!D3D12_SupportsPresentMode(driverData, window, presentMode)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Present mode not supported!");
+        return SDL_FALSE;
+    }
+
+    if (
+        swapchainComposition != windowData->swapchainComposition ||
+        presentMode != windowData->presentMode) {
+        D3D12_Wait(driverData);
+
+        // Recreate the swapchain
+        D3D12_INTERNAL_DestroySwapchain(
+            renderer,
+            windowData);
+
+        return D3D12_INTERNAL_CreateSwapchain(
+            renderer,
+            windowData,
+            swapchainComposition,
+            presentMode);
+    }
+
+    return SDL_TRUE;
+}
+
+static SDL_GpuTextureFormat D3D12_GetSwapchainTextureFormat(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Cannot get swapchain format, window has not been claimed!");
+        return SDL_GPU_TEXTUREFORMAT_INVALID;
+    }
+
+    return windowData->textureContainers[windowData->frameCounter].header.info.format;
+}
+
+static D3D12Fence *D3D12_INTERNAL_AcquireFence(
+    D3D12Renderer *renderer)
+{
+    D3D12Fence *fence;
+    ID3D12Fence *handle;
+    HRESULT res;
+
+    SDL_LockMutex(renderer->fenceLock);
+
+    if (renderer->availableFenceCount == 0) {
+        res = ID3D12Device_CreateFence(
+            renderer->device,
+            D3D12_FENCE_UNSIGNALED_VALUE,
+            D3D12_FENCE_FLAG_NONE,
+            D3D_GUID(D3D_IID_ID3D12Fence),
+            (void **)&handle);
+        if (FAILED(res)) {
+            D3D12_INTERNAL_LogError(renderer->device, "Failed to create fence!", res);
+            SDL_UnlockMutex(renderer->fenceLock);
+            return NULL;
+        }
+
+        fence = (D3D12Fence *)SDL_calloc(1, sizeof(D3D12Fence));
+        if (!fence) {
+            ID3D12Fence_Release(handle);
+            SDL_UnlockMutex(renderer->fenceLock);
+            return NULL;
+        }
+        fence->handle = handle;
+        fence->event = CreateEventEx(NULL, 0, 0, EVENT_ALL_ACCESS);
+        SDL_AtomicSet(&fence->referenceCount, 0);
+    } else {
+        fence = renderer->availableFences[renderer->availableFenceCount - 1];
+        renderer->availableFenceCount -= 1;
+        ID3D12Fence_Signal(fence->handle, D3D12_FENCE_UNSIGNALED_VALUE);
+    }
+
+    SDL_UnlockMutex(renderer->fenceLock);
+
+    (void)SDL_AtomicIncRef(&fence->referenceCount);
+    return fence;
+}
+
+static void D3D12_INTERNAL_AllocateCommandBuffer(
+    D3D12Renderer *renderer)
+{
+    D3D12CommandBuffer *commandBuffer;
+    HRESULT res;
+    ID3D12CommandAllocator *commandAllocator;
+    ID3D12GraphicsCommandList *commandList;
+
+    commandBuffer = (D3D12CommandBuffer *)SDL_calloc(1, sizeof(D3D12CommandBuffer));
+    if (!commandBuffer) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create ID3D12CommandList. Out of Memory");
+        return;
+    }
+
+    res = ID3D12Device_CreateCommandAllocator(
+        renderer->device,
+        D3D12_COMMAND_LIST_TYPE_DIRECT,
+        D3D_GUID(D3D_IID_ID3D12CommandAllocator),
+        (void **)&commandAllocator);
+    if (FAILED(res)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create ID3D12CommandAllocator");
+        D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
+        return;
+    }
+    commandBuffer->commandAllocator = commandAllocator;
+
+    res = ID3D12Device_CreateCommandList(
+        renderer->device,
+        0,
+        D3D12_COMMAND_LIST_TYPE_DIRECT,
+        commandAllocator,
+        NULL,
+        D3D_GUID(D3D_IID_ID3D12GraphicsCommandList),
+        (void **)&commandList);
+
+    if (FAILED(res)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create ID3D12CommandList");
+        D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
+        return;
+    }
+    commandBuffer->graphicsCommandList = commandList;
+
+    commandBuffer->renderer = renderer;
+    commandBuffer->inFlightFence = NULL;
+
+    // Window handling
+    commandBuffer->presentDataCapacity = 1;
+    commandBuffer->presentDataCount = 0;
+    commandBuffer->presentDatas = (D3D12PresentData *)SDL_calloc(
+        commandBuffer->presentDataCapacity, sizeof(D3D12PresentData));
+
+    // Resource tracking
+    commandBuffer->usedTextureCapacity = 4;
+    commandBuffer->usedTextureCount = 0;
+    commandBuffer->usedTextures = (D3D12Texture **)SDL_calloc(
+        commandBuffer->usedTextureCapacity, sizeof(D3D12Texture *));
+
+    commandBuffer->usedBufferCapacity = 4;
+    commandBuffer->usedBufferCount = 0;
+    commandBuffer->usedBuffers = (D3D12Buffer **)SDL_calloc(
+        commandBuffer->usedBufferCapacity, sizeof(D3D12Buffer *));
+
+    commandBuffer->usedSamplerCapacity = 4;
+    commandBuffer->usedSamplerCount = 0;
+    commandBuffer->usedSamplers = (D3D12Sampler **)SDL_calloc(
+        commandBuffer->usedSamplerCapacity, sizeof(D3D12Sampler *));
+
+    commandBuffer->usedGraphicsPipelineCapacity = 4;
+    commandBuffer->usedGraphicsPipelineCount = 0;
+    commandBuffer->usedGraphicsPipelines = (D3D12GraphicsPipeline **)SDL_calloc(
+        commandBuffer->usedGraphicsPipelineCapacity, sizeof(D3D12GraphicsPipeline *));
+
+    commandBuffer->usedComputePipelineCapacity = 4;
+    commandBuffer->usedComputePipelineCount = 0;
+    commandBuffer->usedComputePipelines = (D3D12ComputePipeline **)SDL_calloc(
+        commandBuffer->usedComputePipelineCapacity, sizeof(D3D12ComputePipeline *));
+
+    commandBuffer->usedUniformBufferCapacity = 4;
+    commandBuffer->usedUniformBufferCount = 0;
+    commandBuffer->usedUniformBuffers = (D3D12UniformBuffer **)SDL_calloc(
+        commandBuffer->usedUniformBufferCapacity, sizeof(D3D12UniformBuffer *));
+
+    commandBuffer->textureDownloadCapacity = 4;
+    commandBuffer->textureDownloadCount = 0;
+    commandBuffer->textureDownloads = (D3D12TextureDownload **)SDL_calloc(
+        commandBuffer->textureDownloadCapacity, sizeof(D3D12TextureDownload *));
+
+    if (
+        (!commandBuffer->presentDatas) ||
+        (!commandBuffer->usedTextures) ||
+        (!commandBuffer->usedBuffers) ||
+        (!commandBuffer->usedSamplers) ||
+        (!commandBuffer->usedGraphicsPipelines) ||
+        (!commandBuffer->usedComputePipelines) ||
+        (!commandBuffer->usedUniformBuffers) ||
+        (!commandBuffer->textureDownloads)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create ID3D12CommandList. Out of Memory");
+        D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
+        return;
+    }
+
+    D3D12CommandBuffer **resizedAvailableCommandBuffers = (D3D12CommandBuffer **)SDL_realloc(
+        renderer->availableCommandBuffers,
+        sizeof(D3D12CommandBuffer *) * (renderer->availableCommandBufferCapacity + 1));
+
+    if (!resizedAvailableCommandBuffers) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create ID3D12CommandList. Out of Memory");
+        D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
+        return;
+    }
+    // Add to inactive command buffer array
+    renderer->availableCommandBufferCapacity += 1;
+    renderer->availableCommandBuffers = resizedAvailableCommandBuffers;
+
+    renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
+    renderer->availableCommandBufferCount += 1;
+}
+
+static D3D12CommandBuffer *D3D12_INTERNAL_AcquireCommandBufferFromPool(
+    D3D12Renderer *renderer)
+{
+    D3D12CommandBuffer *commandBuffer;
+
+    if (renderer->availableCommandBufferCount == 0) {
+        D3D12_INTERNAL_AllocateCommandBuffer(renderer);
+    }
+
+    commandBuffer = renderer->availableCommandBuffers[renderer->availableCommandBufferCount - 1];
+    renderer->availableCommandBufferCount -= 1;
+
+    return commandBuffer;
+}
+
+static SDL_GpuCommandBuffer *D3D12_AcquireCommandBuffer(
+    SDL_GpuRenderer *driverData)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12CommandBuffer *commandBuffer;
+    ID3D12DescriptorHeap *heaps[2];
+    SDL_zeroa(heaps);
+
+    SDL_LockMutex(renderer->acquireCommandBufferLock);
+    commandBuffer = D3D12_INTERNAL_AcquireCommandBufferFromPool(renderer);
+    SDL_UnlockMutex(renderer->acquireCommandBufferLock);
+
+    if (commandBuffer == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to acquire command buffer!");
+        return NULL;
+    }
+
+    // Set the descriptor heaps!
+    commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV] =
+        D3D12_INTERNAL_AcquireDescriptorHeapFromPool(commandBuffer, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
+
+    if (!commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to acquire descriptor heap!");
+        D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
+        return NULL;
+    }
+
+    commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER] =
+        D3D12_INTERNAL_AcquireDescriptorHeapFromPool(commandBuffer, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
+
+    if (!commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to acquire descriptor heap!");
+        D3D12_INTERNAL_DestroyCommandBuffer(commandBuffer);
+        return NULL;
+    }
+
+    heaps[0] = commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]->handle;
+    heaps[1] = commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]->handle;
+
+    ID3D12GraphicsCommandList_SetDescriptorHeaps(
+        commandBuffer->graphicsCommandList,
+        2,
+        heaps);
+
+    // Set the bind state
+    commandBuffer->currentGraphicsPipeline = NULL;
+
+    SDL_zeroa(commandBuffer->colorAttachmentTextureSubresources);
+    commandBuffer->colorAttachmentTextureSubresourceCount = 0;
+    commandBuffer->depthStencilTextureSubresource = NULL;
+
+    SDL_zeroa(commandBuffer->vertexBuffers);
+    SDL_zeroa(commandBuffer->vertexBufferOffsets);
+    commandBuffer->vertexBufferCount = 0;
+
+    SDL_zeroa(commandBuffer->vertexSamplerTextures);
+    SDL_zeroa(commandBuffer->vertexSamplers);
+    SDL_zeroa(commandBuffer->vertexStorageTextures);
+    SDL_zeroa(commandBuffer->vertexStorageBuffers);
+    SDL_zeroa(commandBuffer->vertexUniformBuffers);
+
+    SDL_zeroa(commandBuffer->fragmentSamplerTextures);
+    SDL_zeroa(commandBuffer->fragmentSamplers);
+    SDL_zeroa(commandBuffer->fragmentStorageTextures);
+    SDL_zeroa(commandBuffer->fragmentStorageBuffers);
+    SDL_zeroa(commandBuffer->fragmentUniformBuffers);
+
+    SDL_zeroa(commandBuffer->computeReadOnlyStorageTextures);
+    SDL_zeroa(commandBuffer->computeReadOnlyStorageBuffers);
+    SDL_zeroa(commandBuffer->computeWriteOnlyStorageTextureSubresources);
+    SDL_zeroa(commandBuffer->computeWriteOnlyStorageBuffers);
+    SDL_zeroa(commandBuffer->computeUniformBuffers);
+
+    commandBuffer->autoReleaseFence = SDL_TRUE;
+
+    return (SDL_GpuCommandBuffer *)commandBuffer;
+}
+
+static SDL_GpuTexture *D3D12_AcquireSwapchainTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_Window *window,
+    Uint32 *pWidth,
+    Uint32 *pHeight)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12Renderer *renderer = d3d12CommandBuffer->renderer;
+    D3D12WindowData *windowData;
+    Uint32 swapchainIndex;
+    HRESULT res;
+
+    windowData = D3D12_INTERNAL_FetchWindowData(window);
+    if (windowData == NULL) {
+        return NULL;
+    }
+
+    res = D3D12_INTERNAL_ResizeSwapchainIfNeeded(
+        renderer,
+        windowData);
+    ERROR_CHECK_RETURN("Could not resize swapchain", NULL);
+
+    if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
+        if (windowData->presentMode == SDL_GPU_PRESENTMODE_VSYNC) {
+            // In VSYNC mode, block until the least recent presented frame is done
+            D3D12_WaitForFences(
+                (SDL_GpuRenderer *)renderer,
+                SDL_TRUE,
+                (SDL_GpuFence **)&windowData->inFlightFences[windowData->frameCounter],
+                1);
+        } else {
+            if (!D3D12_QueryFence(
+                    (SDL_GpuRenderer *)renderer,
+                    (SDL_GpuFence *)windowData->inFlightFences[windowData->frameCounter])) {
+                /*
+                 * In MAILBOX or IMMEDIATE mode, if the least recent fence is not signaled,
+                 * return NULL to indicate that rendering should be skipped
+                 */
+                return NULL;
+            }
+        }
+
+        D3D12_ReleaseFence(
+            (SDL_GpuRenderer *)renderer,
+            (SDL_GpuFence *)windowData->inFlightFences[windowData->frameCounter]);
+
+        windowData->inFlightFences[windowData->frameCounter] = NULL;
+    }
+
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    // FIXME: Should this happen before the inFlightFences stuff above?
+    windowData->frameToken = D3D12XBOX_FRAME_PIPELINE_TOKEN_NULL;
+    renderer->device->WaitFrameEventX(D3D12XBOX_FRAME_EVENT_ORIGIN, INFINITE, NULL, D3D12XBOX_WAIT_FRAME_EVENT_FLAG_NONE, &windowData->frameToken);
+    swapchainIndex = windowData->frameCounter;
+#else
+    swapchainIndex = IDXGISwapChain3_GetCurrentBackBufferIndex(windowData->swapchain);
+
+    // Set the handle on the windowData texture data.
+    res = IDXGISwapChain_GetBuffer(
+        windowData->swapchain,
+        swapchainIndex,
+        D3D_GUID(D3D_IID_ID3D12Resource),
+        (void **)&windowData->textureContainers[swapchainIndex].activeTexture->resource);
+    ERROR_CHECK_RETURN("Could not acquire swapchain!", NULL);
+#endif
+
+    // Send the dimensions to the out parameters.
+    *pWidth = windowData->textureContainers[swapchainIndex].header.info.width;
+    *pHeight = windowData->textureContainers[swapchainIndex].header.info.height;
+
+    // Set up presentation
+    if (d3d12CommandBuffer->presentDataCount == d3d12CommandBuffer->presentDataCapacity) {
+        d3d12CommandBuffer->presentDataCapacity += 1;
+        d3d12CommandBuffer->presentDatas = (D3D12PresentData *)SDL_realloc(
+            d3d12CommandBuffer->presentDatas,
+            d3d12CommandBuffer->presentDataCapacity * sizeof(D3D12PresentData));
+    }
+    d3d12CommandBuffer->presentDatas[d3d12CommandBuffer->presentDataCount].windowData = windowData;
+    d3d12CommandBuffer->presentDatas[d3d12CommandBuffer->presentDataCount].swapchainImageIndex = swapchainIndex;
+    d3d12CommandBuffer->presentDataCount += 1;
+
+    // Set up resource barrier
+    D3D12_RESOURCE_BARRIER barrierDesc;
+    barrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+    barrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+    barrierDesc.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
+    barrierDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
+    barrierDesc.Transition.pResource = windowData->textureContainers[swapchainIndex].activeTexture->resource;
+    barrierDesc.Transition.Subresource = 0;
+
+    ID3D12GraphicsCommandList_ResourceBarrier(
+        d3d12CommandBuffer->graphicsCommandList,
+        1,
+        &barrierDesc);
+
+    return (SDL_GpuTexture *)&windowData->textureContainers[swapchainIndex];
+}
+
+static void D3D12_INTERNAL_PerformPendingDestroys(D3D12Renderer *renderer)
+{
+    SDL_LockMutex(renderer->disposeLock);
+
+    for (Sint32 i = renderer->buffersToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->buffersToDestroy[i]->referenceCount) == 0) {
+            D3D12_INTERNAL_DestroyBuffer(
+                renderer,
+                renderer->buffersToDestroy[i]);
+
+            renderer->buffersToDestroy[i] = renderer->buffersToDestroy[renderer->buffersToDestroyCount - 1];
+            renderer->buffersToDestroyCount -= 1;
+        }
+    }
+
+    for (Sint32 i = renderer->texturesToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->texturesToDestroy[i]->referenceCount) == 0) {
+            D3D12_INTERNAL_DestroyTexture(
+                renderer,
+                renderer->texturesToDestroy[i]);
+
+            renderer->texturesToDestroy[i] = renderer->texturesToDestroy[renderer->texturesToDestroyCount - 1];
+            renderer->texturesToDestroyCount -= 1;
+        }
+    }
+
+    for (Sint32 i = renderer->samplersToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->samplersToDestroy[i]->referenceCount) == 0) {
+            D3D12_INTERNAL_DestroySampler(
+                renderer,
+                renderer->samplersToDestroy[i]);
+
+            renderer->samplersToDestroy[i] = renderer->samplersToDestroy[renderer->samplersToDestroyCount - 1];
+            renderer->samplersToDestroyCount -= 1;
+        }
+    }
+
+    for (Sint32 i = renderer->graphicsPipelinesToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->graphicsPipelinesToDestroy[i]->referenceCount) == 0) {
+            D3D12_INTERNAL_DestroyGraphicsPipeline(
+                renderer->graphicsPipelinesToDestroy[i]);
+
+            renderer->graphicsPipelinesToDestroy[i] = renderer->graphicsPipelinesToDestroy[renderer->graphicsPipelinesToDestroyCount - 1];
+            renderer->graphicsPipelinesToDestroyCount -= 1;
+        }
+    }
+
+    for (Sint32 i = renderer->computePipelinesToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->computePipelinesToDestroy[i]->referenceCount) == 0) {
+            D3D12_INTERNAL_DestroyComputePipeline(
+                renderer->computePipelinesToDestroy[i]);
+
+            renderer->computePipelinesToDestroy[i] = renderer->computePipelinesToDestroy[renderer->computePipelinesToDestroyCount - 1];
+            renderer->computePipelinesToDestroyCount -= 1;
+        }
+    }
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void D3D12_INTERNAL_CopyTextureDownload(
+    D3D12CommandBuffer *commandBuffer,
+    D3D12TextureDownload *download)
+{
+    Uint8 *sourcePtr;
+    Uint8 *destPtr;
+    HRESULT res;
+
+    res = ID3D12Resource_Map(
+        download->temporaryBuffer->handle,
+        0,
+        NULL,
+        (void **)&sourcePtr);
+
+    if (FAILED(res)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to map temporary buffer!");
+        return;
+    }
+
+    res = ID3D12Resource_Map(
+        download->destinationBuffer->handle,
+        0,
+        NULL,
+        (void **)&destPtr);
+
+    if (FAILED(res)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to map destination buffer!");
+        return;
+    }
+
+    for (Uint32 sliceIndex = 0; sliceIndex < download->depth; sliceIndex += 1) {
+        for (Uint32 rowIndex = 0; rowIndex < download->height; rowIndex += 1) {
+            SDL_memcpy(
+                destPtr + download->bufferOffset + (sliceIndex * download->bytesPerDepthSlice) + (rowIndex * download->bytesPerRow),
+                sourcePtr + (sliceIndex * download->height) + (rowIndex * download->alignedBytesPerRow),
+                download->bytesPerRow);
+        }
+    }
+
+    ID3D12Resource_Unmap(
+        download->temporaryBuffer->handle,
+        0,
+        NULL);
+
+    ID3D12Resource_Unmap(
+        download->destinationBuffer->handle,
+        0,
+        NULL);
+}
+
+static void D3D12_INTERNAL_CleanCommandBuffer(
+    D3D12Renderer *renderer,
+    D3D12CommandBuffer *commandBuffer)
+{
+    Uint32 i;
+    HRESULT res;
+
+    // Perform deferred texture data copies
+
+    for (i = 0; i < commandBuffer->textureDownloadCount; i += 1) {
+        D3D12_INTERNAL_CopyTextureDownload(
+            commandBuffer,
+            commandBuffer->textureDownloads[i]);
+        SDL_free(commandBuffer->textureDownloads[i]);
+    }
+    commandBuffer->textureDownloadCount = 0;
+
+    res = ID3D12CommandAllocator_Reset(commandBuffer->commandAllocator);
+    ERROR_CHECK("Could not reset command allocator")
+
+    res = ID3D12GraphicsCommandList_Reset(
+        commandBuffer->graphicsCommandList,
+        commandBuffer->commandAllocator,
+        NULL);
+    ERROR_CHECK("Could not reset graphicsCommandList")
+
+    // Return descriptor heaps to pool
+    D3D12_INTERNAL_ReturnDescriptorHeapToPool(
+        renderer,
+        commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV]);
+    D3D12_INTERNAL_ReturnDescriptorHeapToPool(
+        renderer,
+        commandBuffer->gpuDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER]);
+
+    // Uniform buffers are now available
+    SDL_LockMutex(renderer->acquireUniformBufferLock);
+
+    for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
+        D3D12_INTERNAL_ReturnUniformBufferToPool(
+            renderer,
+            commandBuffer->usedUniformBuffers[i]);
+    }
+    commandBuffer->usedUniformBufferCount = 0;
+
+    SDL_UnlockMutex(renderer->acquireUniformBufferLock);
+
+    // TODO: More reference counting
+
+    for (i = 0; i < commandBuffer->usedTextureCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
+    }
+    commandBuffer->usedTextureCount = 0;
+
+    for (i = 0; i < commandBuffer->usedBufferCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount);
+    }
+    commandBuffer->usedBufferCount = 0;
+
+    for (i = 0; i < commandBuffer->usedSamplerCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedSamplers[i]->referenceCount);
+    }
+    commandBuffer->usedSamplerCount = 0;
+
+    for (i = 0; i < commandBuffer->usedGraphicsPipelineCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedGraphicsPipelines[i]->referenceCount);
+    }
+    commandBuffer->usedGraphicsPipelineCount = 0;
+
+    for (i = 0; i < commandBuffer->usedComputePipelineCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedComputePipelines[i]->referenceCount);
+    }
+    commandBuffer->usedComputePipelineCount = 0;
+
+    // Reset presentation
+    commandBuffer->presentDataCount = 0;
+
+    // The fence is now available (unless SubmitAndAcquireFence was called)
+    if (commandBuffer->autoReleaseFence) {
+        D3D12_ReleaseFence(
+            (SDL_GpuRenderer *)renderer,
+            (SDL_GpuFence *)commandBuffer->inFlightFence);
+
+        commandBuffer->inFlightFence = NULL;
+    }
+
+    // Return command buffer to pool
+    SDL_LockMutex(renderer->acquireCommandBufferLock);
+
+    if (renderer->availableCommandBufferCount == renderer->availableCommandBufferCapacity) {
+        renderer->availableCommandBufferCapacity += 1;
+        renderer->availableCommandBuffers = (D3D12CommandBuffer **)SDL_realloc(
+            renderer->availableCommandBuffers,
+            renderer->availableCommandBufferCapacity * sizeof(D3D12CommandBuffer *));
+    }
+
+    renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
+    renderer->availableCommandBufferCount += 1;
+
+    SDL_UnlockMutex(renderer->acquireCommandBufferLock);
+
+    // Remove this command buffer from the submitted list
+    for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
+        if (renderer->submittedCommandBuffers[i] == commandBuffer) {
+            renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
+            renderer->submittedCommandBufferCount -= 1;
+        }
+    }
+}
+
+static void D3D12_Submit(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    D3D12Renderer *renderer = d3d12CommandBuffer->renderer;
+    ID3D12CommandList *commandLists[1];
+    HRESULT res;
+
+    SDL_LockMutex(renderer->submitLock);
+
+    // Unmap uniform buffers
+    for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        if (d3d12CommandBuffer->vertexUniformBuffers[i] != NULL) {
+            ID3D12Resource_Unmap(
+                d3d12CommandBuffer->vertexUniformBuffers[i]->buffer->handle,
+                0,
+                NULL);
+            d3d12CommandBuffer->vertexUniformBuffers[i]->buffer->mapPointer = NULL;
+        }
+
+        if (d3d12CommandBuffer->fragmentUniformBuffers[i] != NULL) {
+            ID3D12Resource_Unmap(
+                d3d12CommandBuffer->fragmentUniformBuffers[i]->buffer->handle,
+                0,
+                NULL);
+            d3d12CommandBuffer->fragmentUniformBuffers[i]->buffer->mapPointer = NULL;
+        }
+
+        // TODO: compute uniforms
+    }
+
+    // Transition present textures to present mode
+    for (Uint32 i = 0; i < d3d12CommandBuffer->presentDataCount; i += 1) {
+        Uint32 swapchainIndex = d3d12CommandBuffer->presentDatas[i].swapchainImageIndex;
+        D3D12TextureContainer *container = &d3d12CommandBuffer->presentDatas[i].windowData->textureContainers[swapchainIndex];
+        D3D12TextureSubresource *subresource = D3D12_INTERNAL_FetchTextureSubresource(container, 0, 0);
+
+        D3D12_RESOURCE_BARRIER barrierDesc;
+        barrierDesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
+        barrierDesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
+        barrierDesc.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
+        barrierDesc.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
+        barrierDesc.Transition.pResource = subresource->parent->resource;
+        barrierDesc.Transition.Subresource = subresource->index;
+
+        ID3D12GraphicsCommandList_ResourceBarrier(
+            d3d12CommandBuffer->graphicsCommandList,
+            1,
+            &barrierDesc);
+    }
+
+    // Notify the command buffer that we have completed recording
+    res = ID3D12GraphicsCommandList_Close(d3d12CommandBuffer->graphicsCommandList);
+    ERROR_CHECK("Failed to close command list!");
+
+    res = ID3D12GraphicsCommandList_QueryInterface(
+        d3d12CommandBuffer->graphicsCommandList,
+        D3D_GUID(D3D_IID_ID3D12CommandList),
+        (void **)&commandLists[0]);
+    ERROR_CHECK("Failed to convert command list!")
+
+    // Submit the command list to the queue
+    ID3D12CommandQueue_ExecuteCommandLists(
+        renderer->commandQueue,
+        1,
+        commandLists);
+
+    ID3D12CommandList_Release(commandLists[0]);
+
+    // Acquire a fence and set it to the in-flight fence
+    d3d12CommandBuffer->inFlightFence = D3D12_INTERNAL_AcquireFence(renderer);
+    if (!d3d12CommandBuffer->inFlightFence) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to acquire fence.");
+    }
+
+    // Mark that a fence should be signaled after command list execution
+    res = ID3D12CommandQueue_Signal(
+        renderer->commandQueue,
+        d3d12CommandBuffer->inFlightFence->handle,
+        D3D12_FENCE_SIGNAL_VALUE);
+    ERROR_CHECK("Failed to enqueue fence signal!");
+
+    // Mark the command buffer as submitted
+    if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) {
+        renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1;
+
+        renderer->submittedCommandBuffers = (D3D12CommandBuffer **)SDL_realloc(
+            renderer->submittedCommandBuffers,
+            sizeof(D3D12CommandBuffer *) * renderer->submittedCommandBufferCapacity);
+    }
+
+    renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = d3d12CommandBuffer;
+    renderer->submittedCommandBufferCount += 1;
+
+    // Present, if applicable
+    for (Uint32 i = 0; i < d3d12CommandBuffer->presentDataCount; i += 1) {
+        D3D12PresentData *presentData = &d3d12CommandBuffer->presentDatas[i];
+        D3D12WindowData *windowData = presentData->windowData;
+
+#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
+        D3D12XBOX_PRESENT_PLANE_PARAMETERS planeParams;
+        SDL_zero(planeParams);
+        planeParams.Token = windowData->frameToken;
+        planeParams.ResourceCount = 1;
+        planeParams.ppResources = &windowData->textureContainers[windowData->frameCounter].activeTexture->resource;
+        planeParams.ColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; // FIXME
+
+        D3D12XBOX_PRESENT_PARAMETERS presentParams;
+        SDL_zero(presentParams);
+        presentParams.Flags = (windowData->presentMode == SDL_GPU_PRESENTMODE_IMMEDIATE) ? D3D12XBOX_PRESENT_FLAG_IMMEDIATE : D3D12XBOX_PRESENT_FLAG_NONE;
+
+        renderer->commandQueue->PresentX(1, &planeParams, &presentParams);
+#else
+        // NOTE: flip discard always supported since DXGI 1.4 is required
+        Uint32 syncInterval = 1;
+        if (windowData->presentMode == SDL_GPU_PRESENTMODE_IMMEDIATE ||
+            windowData->presentMode == SDL_GPU_PRESENTMODE_MAILBOX) {
+            syncInterval = 0;
+        }
+
+        Uint32 presentFlags = 0;
+        if (renderer->supportsTearing &&
+            windowData->presentMode == SDL_GPU_PRESENTMODE_IMMEDIATE) {
+            presentFlags = DXGI_PRESENT_ALLOW_TEARING;
+        }
+
+        IDXGISwapChain_Present(
+            windowData->swapchain,
+            syncInterval,
+            presentFlags);
+
+        ID3D12Resource_Release(windowData->textureContainers[presentData->swapchainImageIndex].activeTexture->resource);
+#endif
+
+        windowData->inFlightFences[windowData->frameCounter] = d3d12CommandBuffer->inFlightFence;
+        (void)SDL_AtomicIncRef(&d3d12CommandBuffer->inFlightFence->referenceCount);
+        windowData->frameCounter = (windowData->frameCounter + 1) % MAX_FRAMES_IN_FLIGHT;
+    }
+
+    // Check for cleanups
+    for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+        Uint64 fenceValue = ID3D12Fence_GetCompletedValue(
+            renderer->submittedCommandBuffers[i]->inFlightFence->handle);
+
+        if (fenceValue == D3D12_FENCE_SIGNAL_VALUE) {
+            D3D12_INTERNAL_CleanCommandBuffer(
+                renderer,
+                renderer->submittedCommandBuffers[i]);
+        }
+    }
+
+    D3D12_INTERNAL_PerformPendingDestroys(renderer);
+
+    SDL_UnlockMutex(renderer->submitLock);
+}
+
+static SDL_GpuFence *D3D12_SubmitAndAcquireFence(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    D3D12CommandBuffer *d3d12CommandBuffer = (D3D12CommandBuffer *)commandBuffer;
+    d3d12CommandBuffer->autoReleaseFence = SDL_FALSE;
+    D3D12_Submit(commandBuffer);
+    return (SDL_GpuFence *)d3d12CommandBuffer->inFlightFence;
+}
+
+static void D3D12_Wait(
+    SDL_GpuRenderer *driverData)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12Fence *fence = D3D12_INTERNAL_AcquireFence(renderer);
+    if (!fence) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to acquire fence.");
+        return;
+    }
+    HRESULT res;
+
+    SDL_LockMutex(renderer->submitLock);
+
+    if (renderer->commandQueue) {
+        // Insert a signal into the end of the command queue...
+        ID3D12CommandQueue_Signal(
+            renderer->commandQueue,
+            fence->handle,
+            D3D12_FENCE_SIGNAL_VALUE);
+
+        // ...and then block on it.
+        if (ID3D12Fence_GetCompletedValue(fence->handle) != D3D12_FENCE_SIGNAL_VALUE) {
+            res = ID3D12Fence_SetEventOnCompletion(
+                fence->handle,
+                D3D12_FENCE_SIGNAL_VALUE,
+                fence->event);
+            ERROR_CHECK_RETURN("Setting fence event failed", )
+
+            WaitForSingleObject(fence->event, INFINITE);
+        }
+    }
+
+    D3D12_ReleaseFence(
+        (SDL_GpuRenderer *)renderer,
+        (SDL_GpuFence *)fence);
+
+    // Clean up
+    for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+        D3D12_INTERNAL_CleanCommandBuffer(renderer, renderer->submittedCommandBuffers[i]);
+    }
+
+    D3D12_INTERNAL_PerformPendingDestroys(renderer);
+
+    SDL_UnlockMutex(renderer->submitLock);
+}
+
+static void D3D12_WaitForFences(
+    SDL_GpuRenderer *driverData,
+    SDL_bool waitAll,
+    SDL_GpuFence **pFences,
+    Uint32 fenceCount)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12Fence *fence;
+    HANDLE *events = SDL_stack_alloc(HANDLE, fenceCount);
+    HRESULT res;
+
+    SDL_LockMutex(renderer->submitLock);
+
+    for (Uint32 i = 0; i < fenceCount; i += 1) {
+        fence = (D3D12Fence *)pFences[i];
+
+        res = ID3D12Fence_SetEventOnCompletion(
+            fence->handle,
+            D3D12_FENCE_SIGNAL_VALUE,
+            fence->event);
+        ERROR_CHECK_RETURN("Setting fence event failed", )
+
+        events[i] = fence->event;
+    }
+
+    WaitForMultipleObjects(
+        fenceCount,
+        events,
+        waitAll,
+        INFINITE);
+
+    // Check for cleanups
+    for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+        Uint64 fenceValue = ID3D12Fence_GetCompletedValue(
+            renderer->submittedCommandBuffers[i]->inFlightFence->handle);
+
+        if (fenceValue == D3D12_FENCE_SIGNAL_VALUE) {
+            D3D12_INTERNAL_CleanCommandBuffer(
+                renderer,
+                renderer->submittedCommandBuffers[i]);
+        }
+    }
+
+    D3D12_INTERNAL_PerformPendingDestroys(renderer);
+
+    SDL_stack_free(events);
+
+    SDL_UnlockMutex(renderer->submitLock);
+}
+
+// Feature Queries
+
+static SDL_bool D3D12_SupportsTextureFormat(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureFormat format,
+    SDL_GpuTextureType type,
+    SDL_GpuTextureUsageFlags usage)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    DXGI_FORMAT dxgiFormat = SDLToD3D12_TextureFormat[format];
+    D3D12_FEATURE_DATA_FORMAT_SUPPORT formatSupport = { dxgiFormat, D3D12_FORMAT_SUPPORT1_NONE, D3D12_FORMAT_SUPPORT2_NONE };
+    HRESULT res;
+
+    res = ID3D12Device_CheckFeatureSupport(
+        renderer->device,
+        D3D12_FEATURE_FORMAT_SUPPORT,
+        &formatSupport,
+        sizeof(formatSupport));
+    if (FAILED(res)) {
+        // Format is apparently unknown
+        return SDL_FALSE;
+    }
+
+    // Is the texture type supported?
+    if (type == SDL_GPU_TEXTURETYPE_2D && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D)) {
+        return SDL_FALSE;
+    }
+    if (type == SDL_GPU_TEXTURETYPE_2D_ARRAY && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE2D)) {
+        return SDL_FALSE;
+    }
+    if (type == SDL_GPU_TEXTURETYPE_3D && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURE3D)) {
+        return SDL_FALSE;
+    }
+    if (type == SDL_GPU_TEXTURETYPE_CUBE && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_TEXTURECUBE)) {
+        return SDL_FALSE;
+    }
+
+    // Are the usage flags supported?
+    if ((usage & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE)) {
+        return SDL_FALSE;
+    }
+    if ((usage & (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT)) && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_SHADER_LOAD)) {
+        return SDL_FALSE;
+    }
+    if ((usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT) && !(formatSupport.Support2 & D3D12_FORMAT_SUPPORT2_UAV_TYPED_STORE)) {
+        return SDL_FALSE;
+    }
+    if ((usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_RENDER_TARGET)) {
+        return SDL_FALSE;
+    }
+    if ((usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) && !(formatSupport.Support1 & D3D12_FORMAT_SUPPORT1_DEPTH_STENCIL)) {
+        return SDL_FALSE;
+    }
+
+    return SDL_TRUE;
+}
+
+static SDL_bool D3D12_SupportsSampleCount(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureFormat format,
+    SDL_GpuSampleCount sampleCount)
+{
+    D3D12Renderer *renderer = (D3D12Renderer *)driverData;
+    D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS featureData;
+    HRESULT res;
+
+#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
+    featureData.Flags = (D3D12_MULTISAMPLE_QUALITY_LEVELS_FLAG)0;
+#else
+    featureData.Flags = (D3D12_MULTISAMPLE_QUALITY_LEVEL_FLAGS)0;
+#endif
+    featureData.Format = SDLToD3D12_TextureFormat[format];
+    featureData.SampleCount = SDLToD3D12_SampleCount[sampleCount];
+    res = ID3D12Device_CheckFeatureSupport(
+        renderer->device,
+        D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS,
+        &featureData,
+        sizeof(featureData));
+
+    return SUCCEEDED(res) && featureData.NumQualityLevels > 0;
+}
+
+static void D3D12_INTERNAL_InitBlitResources(
+    D3D12Renderer *renderer)
+{
+    SDL_GpuShaderCreateInfo shaderCreateInfo;
+    SDL_GpuSamplerCreateInfo samplerCreateInfo;
+
+    renderer->blitPipelineCapacity = 2;
+    renderer->blitPipelineCount = 0;
+    renderer->blitPipelines = (BlitPipelineCacheEntry *)SDL_malloc(
+        renderer->blitPipelineCapacity * sizeof(BlitPipelineCacheEntry));
+
+    // Fullscreen vertex shader
+    SDL_zero(shaderCreateInfo);
+    shaderCreateInfo.code = (Uint8 *)D3D12_FullscreenVert;
+    shaderCreateInfo.codeSize = sizeof(D3D12_FullscreenVert);
+    shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_VERTEX;
+    shaderCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC;
+    shaderCreateInfo.entryPointName = "main";
+
+    renderer->blitVertexShader = D3D12_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (renderer->blitVertexShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile vertex shader for blit!");
+    }
+
+    // BlitFrom2D pixel shader
+    shaderCreateInfo.code = (Uint8 *)D3D12_BlitFrom2D;
+    shaderCreateInfo.codeSize = sizeof(D3D12_BlitFrom2D);
+    shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_FRAGMENT;
+    shaderCreateInfo.samplerCount = 1;
+    shaderCreateInfo.uniformBufferCount = 1;
+
+    renderer->blitFrom2DShader = D3D12_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (renderer->blitFrom2DShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2D pixel shader!");
+    }
+
+    // BlitFrom2DArray pixel shader
+    shaderCreateInfo.code = (Uint8 *)D3D12_BlitFrom2DArray;
+    shaderCreateInfo.codeSize = sizeof(D3D12_BlitFrom2DArray);
+
+    renderer->blitFrom2DArrayShader = D3D12_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (renderer->blitFrom2DArrayShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2DArray pixel shader!");
+    }
+
+    // BlitFrom3D pixel shader
+    shaderCreateInfo.code = (Uint8 *)D3D12_BlitFrom3D;
+    shaderCreateInfo.codeSize = sizeof(D3D12_BlitFrom3D);
+
+    renderer->blitFrom3DShader = D3D12_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (renderer->blitFrom3DShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom3D pixel shader!");
+    }
+
+    // BlitFromCube pixel shader
+    shaderCreateInfo.code = (Uint8 *)D3D12_BlitFromCube;
+    shaderCreateInfo.codeSize = sizeof(D3D12_BlitFromCube);
+
+    renderer->blitFromCubeShader = D3D12_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (renderer->blitFromCubeShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCube pixel shader!");
+    }
+
+    // Create samplers
+    samplerCreateInfo.addressModeU = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.addressModeV = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.addressModeW = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.anisotropyEnable = 0;
+    samplerCreateInfo.compareEnable = 0;
+    samplerCreateInfo.magFilter = SDL_GPU_FILTER_NEAREST;
+    samplerCreateInfo.minFilter = SDL_GPU_FILTER_NEAREST;
+    samplerCreateInfo.mipmapMode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
+    samplerCreateInfo.mipLodBias = 0.0f;
+    samplerCreateInfo.minLod = 0;
+    samplerCreateInfo.maxLod = 1000;
+    samplerCreateInfo.maxAnisotropy = 1.0f;
+    samplerCreateInfo.compareOp = SDL_GPU_COMPAREOP_ALWAYS;
+
+    renderer->blitNearestSampler = D3D12_CreateSampler(
+        (SDL_GpuRenderer *)renderer,
+        &samplerCreateInfo);
+
+    if (renderer->blitNearestSampler == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit nearest sampler!");
+    }
+
+    samplerCreateInfo.magFilter = SDL_GPU_FILTER_LINEAR;
+    samplerCreateInfo.minFilter = SDL_GPU_FILTER_LINEAR;
+    samplerCreateInfo.mipmapMode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR;
+
+    renderer->blitLinearSampler = D3D12_CreateSampler(
+        (SDL_GpuRenderer *)renderer,
+        &samplerCreateInfo);
+
+    if (renderer->blitLinearSampler == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit linear sampler!");
+    }
+}
+
+static SDL_bool D3D12_PrepareDriver(SDL_VideoDevice *_this)
+{
+#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
+    return SDL_TRUE;
+#else
+    void *d3d12_dll;
+    void *dxgi_dll;
+    PFN_D3D12_CREATE_DEVICE D3D12CreateDeviceFunc;
+    PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc;
+    HRESULT res;
+    ID3D12Device *device;
+    IDXGIFactory1 *factory;
+    IDXGIFactory4 *factory4;
+    IDXGIFactory6 *factory6;
+    IDXGIAdapter1 *adapter;
+
+    // Can we load D3D12?
+
+    d3d12_dll = SDL_LoadObject(D3D12_DLL);
+    if (d3d12_dll == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "D3D12: Could not find " D3D12_DLL);
+        return SDL_FALSE;
+    }
+
+    D3D12CreateDeviceFunc = (PFN_D3D12_CREATE_DEVICE)SDL_LoadFunction(
+        d3d12_dll,
+        D3D12_CREATE_DEVICE_FUNC);
+    if (D3D12CreateDeviceFunc == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "D3D12: Could not find function " D3D12_CREATE_DEVICE_FUNC " in " D3D12_DLL);
+        SDL_UnloadObject(d3d12_dll);
+        return SDL_FALSE;
+    }
+
+    // Can we load DXGI?
+
+    dxgi_dll = SDL_LoadObject(DXGI_DLL);
+    if (dxgi_dll == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "D3D12: Could not find " DXGI_DLL);
+        return SDL_FALSE;
+    }
+
+    CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY1)SDL_LoadFunction(
+        dxgi_dll,
+        CREATE_DXGI_FACTORY1_FUNC);
+    if (CreateDXGIFactoryFunc == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "D3D12: Could not find function " CREATE_DXGI_FACTORY1_FUNC " in " DXGI_DLL);
+        SDL_UnloadObject(dxgi_dll);
+        return SDL_FALSE;
+    }
+
+    // Can we create a device?
+
+    // Create the DXGI factory
+    res = CreateDXGIFactoryFunc(
+        &D3D_IID_IDXGIFactory1,
+        (void **)&factory);
+    if (FAILED(res)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "D3D12: Could not create DXGIFactory");
+        SDL_UnloadObject(d3d12_dll);
+        SDL_UnloadObject(dxgi_dll);
+        return SDL_FALSE;
+    }
+
+    // Check for DXGI 1.4 support
+    res = IDXGIFactory1_QueryInterface(
+        factory,
+        D3D_GUID(D3D_IID_IDXGIFactory4),
+        (void **)&factory4);
+    if (FAILED(res)) {
+        IDXGIFactory1_Release(factory);
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "D3D12: Failed to find DXGI1.4 support, required for DX12");
+        SDL_UnloadObject(d3d12_dll);
+        SDL_UnloadObject(dxgi_dll);
+        return SDL_FALSE;
+    }
+    IDXGIFactory4_Release(factory4);
+
+    res = IDXGIFactory1_QueryInterface(
+        factory,
+        D3D_GUID(D3D_IID_IDXGIFactory6),
+        (void **)&factory6);
+    if (SUCCEEDED(res)) {
+        res = IDXGIFactory6_EnumAdapterByGpuPreference(
+            factory6,
+            0,
+            DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
+            D3D_GUID(D3D_IID_IDXGIAdapter1),
+            (void **)&adapter);
+        IDXGIFactory6_Release(factory6);
+    } else {
+        res = IDXGIFactory1_EnumAdapters1(
+            factory,
+            0,
+            &adapter);
+    }
+    if (FAILED(res)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "D3D12: Failed to find adapter for D3D12Device");
+        IDXGIFactory1_Release(factory);
+        SDL_UnloadObject(d3d12_dll);
+        SDL_UnloadObject(dxgi_dll);
+        return SDL_FALSE;
+    }
+
+    res = D3D12CreateDeviceFunc(
+        (IUnknown *)adapter,
+        D3D_FEATURE_LEVEL_CHOICE,
+        D3D_GUID(D3D_IID_ID3D12Device),
+        (void **)&device);
+
+    if (SUCCEEDED(res)) {
+        ID3D12Device_Release(device);
+    }
+    IDXGIAdapter1_Release(adapter);
+    IDXGIFactory1_Release(factory);
+
+    SDL_UnloadObject(d3d12_dll);
+    SDL_UnloadObject(dxgi_dll);
+
+    if (FAILED(res)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "D3D12: Could not create D3D12Device with feature level " D3D_FEATURE_LEVEL_CHOICE_STR);
+        return SDL_FALSE;
+    }
+
+    return SDL_TRUE;
+#endif
+}
+
+#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+static void D3D12_INTERNAL_TryInitializeDXGIDebug(D3D12Renderer *renderer)
+{
+    PFN_DXGI_GET_DEBUG_INTERFACE DXGIGetDebugInterfaceFunc;
+    HRESULT res;
+
+    renderer->dxgidebug_dll = SDL_LoadObject(DXGIDEBUG_DLL);
+    if (renderer->dxgidebug_dll == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Could not find " DXGIDEBUG_DLL);
+        return;
+    }
+
+    DXGIGetDebugInterfaceFunc = (PFN_DXGI_GET_DEBUG_INTERFACE)SDL_LoadFunction(
+        renderer->dxgidebug_dll,
+        DXGI_GET_DEBUG_INTERFACE_FUNC);
+    if (DXGIGetDebugInterfaceFunc == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Could not load function: " DXGI_GET_DEBUG_INTERFACE_FUNC);
+        return;
+    }
+
+    res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIDebug, (void **)&renderer->dxgiDebug);
+    if (FAILED(res)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Could not get IDXGIDebug interface");
+    }
+
+    res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, (void **)&renderer->dxgiInfoQueue);
+    if (FAILED(res)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Could not get IDXGIInfoQueue interface");
+    }
+}
+#endif
+
+static void D3D12_INTERNAL_TryInitializeD3D12Debug(D3D12Renderer *renderer)
+{
+    PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterfaceFunc;
+    HRESULT res;
+
+    D3D12GetDebugInterfaceFunc = (PFN_D3D12_GET_DEBUG_INTERFACE)SDL_LoadFunction(
+        renderer->d3d12_dll,
+        D3D12_GET_DEBUG_INTERFACE_FUNC);
+    if (D3D12GetDebugInterfaceFunc == NULL) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not load function: " D3D12_GET_DEBUG_INTERFACE_FUNC);
+        return;
+    }
+
+    res = D3D12GetDebugInterfaceFunc(D3D_GUID(D3D_IID_ID3D12Debug), (void **)&renderer->d3d12Debug);
+    if (FAILED(res)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Could not get ID3D12Debug interface");
+        return;
+    }
+
+    ID3D12Debug_EnableDebugLayer(renderer->d3d12Debug);
+}
+
+#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+static void D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(D3D12Renderer *renderer)
+{
+    ID3D12InfoQueue *infoQueue = NULL;
+    D3D12_MESSAGE_SEVERITY severities[] = { D3D12_MESSAGE_SEVERITY_INFO };
+    D3D12_INFO_QUEUE_FILTER filter;
+    HRESULT res;
+
+    res = ID3D12Device_QueryInterface(
+        renderer->device,
+        D3D_GUID(D3D_IID_ID3D12InfoQueue),
+        (void **)&infoQueue);
+    if (FAILED(res)) {
+        ERROR_CHECK_RETURN("Failed to convert ID3D12Device to ID3D12InfoQueue", );
+    }
+
+    SDL_zero(filter);
+    filter.DenyList.NumSeverities = 1;
+    filter.DenyList.pSeverityList = severities;
+    ID3D12InfoQueue_PushStorageFilter(
+        infoQueue,
+        &filter);
+
+    ID3D12InfoQueue_SetBreakOnSeverity(
+        infoQueue,
+        D3D12_MESSAGE_SEVERITY_ERROR,
+        SDL_TRUE);
+
+    ID3D12InfoQueue_SetBreakOnSeverity(
+        infoQueue,
+        D3D12_MESSAGE_SEVERITY_CORRUPTION,
+        SDL_TRUE);
+
+    ID3D12InfoQueue_Release(infoQueue);
+}
+#endif
+
+static SDL_GpuDevice *D3D12_CreateDevice(SDL_bool debugMode, SDL_bool preferLowPower, SDL_PropertiesID props)
+{
+    SDL_GpuDevice *result;
+    D3D12Renderer *renderer;
+    HRESULT res;
+
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    PFN_D3D12_XBOX_CREATE_DEVICE D3D12XboxCreateDeviceFunc;
+    D3D12XBOX_CREATE_DEVICE_PARAMETERS createDeviceParams;
+#else
+    PFN_CREATE_DXGI_FACTORY1 CreateDXGIFactoryFunc;
+    IDXGIFactory1 *factory1;
+    IDXGIFactory5 *factory5;
+    IDXGIFactory6 *factory6;
+    DXGI_ADAPTER_DESC1 adapterDesc;
+    PFN_D3D12_CREATE_DEVICE D3D12CreateDeviceFunc;
+#endif
+    D3D12_FEATURE_DATA_ARCHITECTURE architecture;
+    D3D12_COMMAND_QUEUE_DESC queueDesc;
+
+    renderer = (D3D12Renderer *)SDL_calloc(1, sizeof(D3D12Renderer));
+
+#if !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    // Load the DXGI library
+    renderer->dxgi_dll = SDL_LoadObject(DXGI_DLL);
+    if (renderer->dxgi_dll == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not find " DXGI_DLL);
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    // Initialize the DXGI debug layer, if applicable
+    if (debugMode) {
+        D3D12_INTERNAL_TryInitializeDXGIDebug(renderer);
+    }
+
+    // Load the CreateDXGIFactory1 function
+    CreateDXGIFactoryFunc = (PFN_CREATE_DXGI_FACTORY1)SDL_LoadFunction(
+        renderer->dxgi_dll,
+        CREATE_DXGI_FACTORY1_FUNC);
+    if (CreateDXGIFactoryFunc == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not load function: " CREATE_DXGI_FACTORY1_FUNC);
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    // Create the DXGI factory
+    res = CreateDXGIFactoryFunc(
+        &D3D_IID_IDXGIFactory1,
+        (void **)&factory1);
+    if (FAILED(res)) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        ERROR_CHECK_RETURN("Could not create DXGIFactory", NULL);
+    }
+
+    // Check for DXGI 1.4 support
+    res = IDXGIFactory1_QueryInterface(
+        factory1,
+        D3D_GUID(D3D_IID_IDXGIFactory4),
+        (void **)&renderer->factory);
+    if (FAILED(res)) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        ERROR_CHECK_RETURN("DXGI1.4 support not found, required for DX12", NULL);
+    }
+    IDXGIFactory1_Release(factory1);
+
+    // Check for explicit tearing support
+    res = IDXGIFactory4_QueryInterface(
+        renderer->factory,
+        D3D_GUID(D3D_IID_IDXGIFactory5),
+        (void **)&factory5);
+    if (SUCCEEDED(res)) {
+        res = IDXGIFactory5_CheckFeatureSupport(
+            factory5,
+            DXGI_FEATURE_PRESENT_ALLOW_TEARING,
+            &renderer->supportsTearing,
+            sizeof(renderer->supportsTearing));
+        if (FAILED(res)) {
+            renderer->supportsTearing = SDL_FALSE;
+        }
+        IDXGIFactory5_Release(factory5);
+    }
+
+    // Select the appropriate device for rendering
+    res = IDXGIFactory4_QueryInterface(
+        renderer->factory,
+        D3D_GUID(D3D_IID_IDXGIFactory6),
+        (void **)&factory6);
+    if (SUCCEEDED(res)) {
+        res = IDXGIFactory6_EnumAdapterByGpuPreference(
+            factory6,
+            0,
+            preferLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER : DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
+            D3D_GUID(D3D_IID_IDXGIAdapter1),
+            (void **)&renderer->adapter);
+        IDXGIFactory6_Release(factory6);
+    } else {
+        res = IDXGIFactory4_EnumAdapters1(
+            renderer->factory,
+            0,
+            &renderer->adapter);
+    }
+
+    if (FAILED(res)) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        ERROR_CHECK_RETURN("Could not find adapter for D3D12Device", NULL);
+    }
+
+    // Get information about the selected adapter. Used for logging info.
+    res = IDXGIAdapter1_GetDesc1(renderer->adapter, &adapterDesc);
+    if (FAILED(res)) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        ERROR_CHECK_RETURN("Could not get adapter description", NULL);
+    }
+
+    SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_Gpu Driver: D3D12");
+    SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "D3D12 Adapter: %S", adapterDesc.Description);
+#endif
+
+    // Load the D3D library
+    renderer->d3d12_dll = SDL_LoadObject(D3D12_DLL);
+    if (renderer->d3d12_dll == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not find " D3D12_DLL);
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    // Load the CreateDevice function
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    D3D12XboxCreateDeviceFunc = (PFN_D3D12_XBOX_CREATE_DEVICE)SDL_LoadFunction(
+        renderer->d3d12_dll,
+        "D3D12XboxCreateDevice");
+    if (D3D12XboxCreateDeviceFunc == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not load function: D3D12XboxCreateDevice");
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+#else
+    D3D12CreateDeviceFunc = (PFN_D3D12_CREATE_DEVICE)SDL_LoadFunction(
+        renderer->d3d12_dll,
+        D3D12_CREATE_DEVICE_FUNC);
+    if (D3D12CreateDeviceFunc == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not load function: " D3D12_CREATE_DEVICE_FUNC);
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+#endif
+
+    renderer->D3D12SerializeRootSignature_func = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)SDL_LoadFunction(
+        renderer->d3d12_dll,
+        D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC);
+    if (renderer->D3D12SerializeRootSignature_func == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not load function: " D3D12_SERIALIZE_ROOT_SIGNATURE_FUNC);
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    // Initialize the D3D12 debug layer, if applicable
+    if (debugMode) {
+        D3D12_INTERNAL_TryInitializeD3D12Debug(renderer);
+    }
+
+    // Create the D3D12Device
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    if (s_Device != NULL) {
+        renderer->device = s_Device;
+    } else {
+        SDL_zero(createDeviceParams);
+        createDeviceParams.Version = D3D12_SDK_VERSION;
+        createDeviceParams.GraphicsCommandQueueRingSizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
+        createDeviceParams.GraphicsScratchMemorySizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
+        createDeviceParams.ComputeScratchMemorySizeBytes = D3D12XBOX_DEFAULT_SIZE_BYTES;
+        createDeviceParams.DisableGeometryShaderAllocations = TRUE;
+        createDeviceParams.DisableTessellationShaderAllocations = TRUE;
+#if defined(SDL_PLATFORM_XBOXSERIES)
+        createDeviceParams.DisableDXR = TRUE;
+#endif
+        if (debugMode) {
+            createDeviceParams.ProcessDebugFlags = D3D12XBOX_PROCESS_DEBUG_FLAG_DEBUG;
+        }
+
+        res = D3D12XboxCreateDeviceFunc(
+            NULL,
+            &createDeviceParams,
+            IID_GRAPHICS_PPV_ARGS(&renderer->device));
+        if (FAILED(res)) {
+            D3D12_INTERNAL_DestroyRenderer(renderer);
+            ERROR_CHECK_RETURN("Could not create D3D12Device", NULL);
+        }
+
+        res = renderer->device->SetFrameIntervalX(
+            NULL,
+            D3D12XBOX_FRAME_INTERVAL_60_HZ,
+            MAX_FRAMES_IN_FLIGHT - 1,
+            D3D12XBOX_FRAME_INTERVAL_FLAG_NONE);
+        if (FAILED(res)) {
+            D3D12_INTERNAL_DestroyRenderer(renderer);
+            ERROR_CHECK_RETURN("Could not get set frame interval", NULL);
+        }
+
+        res = renderer->device->ScheduleFrameEventX(
+            D3D12XBOX_FRAME_EVENT_ORIGIN,
+            0,
+            NULL,
+            D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE);
+        if (FAILED(res)) {
+            D3D12_INTERNAL_DestroyRenderer(renderer);
+            ERROR_CHECK_RETURN("Could not schedule frame events", NULL);
+        }
+
+        s_Device = renderer->device;
+    }
+#else
+    res = D3D12CreateDeviceFunc(
+        (IUnknown *)renderer->adapter,
+        D3D_FEATURE_LEVEL_CHOICE,
+        D3D_GUID(D3D_IID_ID3D12Device),
+        (void **)&renderer->device);
+
+    if (FAILED(res)) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        ERROR_CHECK_RETURN("Could not create D3D12Device", NULL);
+    }
+
+    // Initialize the D3D12 debug info queue, if applicable
+    if (debugMode) {
+        D3D12_INTERNAL_TryInitializeD3D12DebugInfoQueue(renderer);
+    }
+#endif
+
+    // Check UMA
+    architecture.NodeIndex = 0;
+    res = ID3D12Device_CheckFeatureSupport(
+        renderer->device,
+        D3D12_FEATURE_ARCHITECTURE,
+        &architecture,
+        sizeof(D3D12_FEATURE_DATA_ARCHITECTURE));
+    if (FAILED(res)) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        ERROR_CHECK_RETURN("Could not get device architecture", NULL);
+    }
+
+    renderer->UMA = (SDL_bool)architecture.UMA;
+    renderer->UMACacheCoherent = (SDL_bool)architecture.CacheCoherentUMA;
+
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    renderer->GPUUploadHeapSupported = SDL_FALSE;
+#else
+    // Check "GPU Upload Heap" support (for fast uniform buffers)
+    D3D12_FEATURE_DATA_D3D12_OPTIONS16 options16; // 15 wasn't enough, huh?
+    renderer->GPUUploadHeapSupported = SDL_FALSE;
+    res = ID3D12Device_CheckFeatureSupport(
+        renderer->device,
+        D3D12_FEATURE_D3D12_OPTIONS16,
+        &options16,
+        sizeof(options16));
+
+    if (SUCCEEDED(res)) {
+        renderer->GPUUploadHeapSupported = options16.GPUUploadHeapSupported;
+    }
+#endif
+
+    // Create command queue
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    if (s_CommandQueue != NULL) {
+        renderer->commandQueue = s_CommandQueue;
+    } else {
+#endif
+        queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
+        queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+        queueDesc.NodeMask = 0;
+        queueDesc.Priority = 0;
+
+        res = ID3D12Device_CreateCommandQueue(
+            renderer->device,
+            &queueDesc,
+            D3D_GUID(D3D_IID_ID3D12CommandQueue),
+            (void **)&renderer->commandQueue);
+
+        if (FAILED(res)) {
+            D3D12_INTERNAL_DestroyRenderer(renderer);
+            ERROR_CHECK_RETURN("Could not create D3D12CommandQueue", NULL);
+        }
+#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+        s_CommandQueue = renderer->commandQueue;
+    }
+#endif
+
+    // Create indirect command signatures
+
+    D3D12_COMMAND_SIGNATURE_DESC commandSignatureDesc;
+    D3D12_INDIRECT_ARGUMENT_DESC indirectArgumentDesc;
+    SDL_zero(indirectArgumentDesc);
+
+    indirectArgumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;
+    commandSignatureDesc.NodeMask = 0;
+    commandSignatureDesc.ByteStride = sizeof(SDL_GpuIndirectDrawCommand);
+    commandSignatureDesc.NumArgumentDescs = 1;
+    commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
+
+    res = ID3D12Device_CreateCommandSignature(
+        renderer->device,
+        &commandSignatureDesc,
+        NULL,
+        D3D_GUID(D3D_IID_ID3D12CommandSignature),
+        (void **)&renderer->indirectDrawCommandSignature);
+    if (FAILED(res)) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        ERROR_CHECK_RETURN("Could not create indirect draw command signature", NULL)
+    }
+
+    indirectArgumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;
+    commandSignatureDesc.ByteStride = sizeof(SDL_GpuIndexedIndirectDrawCommand);
+    commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
+
+    res = ID3D12Device_CreateCommandSignature(
+        renderer->device,
+        &commandSignatureDesc,
+        NULL,
+        D3D_GUID(D3D_IID_ID3D12CommandSignature),
+        (void **)&renderer->indirectIndexedDrawCommandSignature);
+    if (FAILED(res)) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        ERROR_CHECK_RETURN("Could not create indirect indexed draw command signature", NULL)
+    }
+
+    indirectArgumentDesc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_DISPATCH;
+    commandSignatureDesc.ByteStride = sizeof(SDL_GpuIndirectDispatchCommand);
+    commandSignatureDesc.pArgumentDescs = &indirectArgumentDesc;
+
+    res = ID3D12Device_CreateCommandSignature(
+        renderer->device,
+        &commandSignatureDesc,
+        NULL,
+        D3D_GUID(D3D_IID_ID3D12CommandSignature),
+        (void **)&renderer->indirectDispatchCommandSignature);
+    if (FAILED(res)) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        ERROR_CHECK_RETURN("Could not create indirect dispatch command signature", NULL)
+    }
+
+    // Initialize pools
+
+    renderer->submittedCommandBufferCapacity = 4;
+    renderer->submittedCommandBufferCount = 0;
+    renderer->submittedCommandBuffers = (D3D12CommandBuffer **)SDL_calloc(
+        renderer->submittedCommandBufferCapacity, sizeof(D3D12CommandBuffer *));
+    if (!renderer->submittedCommandBuffers) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    renderer->uniformBufferPoolCapacity = 4;
+    renderer->uniformBufferPoolCount = 0;
+    renderer->uniformBufferPool = (D3D12UniformBuffer **)SDL_calloc(
+        renderer->uniformBufferPoolCapacity, sizeof(D3D12UniformBuffer *));
+    if (!renderer->uniformBufferPool) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    renderer->claimedWindowCapacity = 4;
+    renderer->claimedWindowCount = 0;
+    renderer->claimedWindows = (D3D12WindowData **)SDL_calloc(
+        renderer->claimedWindowCapacity, sizeof(D3D12WindowData *));
+    if (!renderer->claimedWindows) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    renderer->availableFenceCapacity = 4;
+    renderer->availableFenceCount = 0;
+    renderer->availableFences = (D3D12Fence **)SDL_calloc(
+        renderer->availableFenceCapacity, sizeof(D3D12Fence *));
+    if (!renderer->availableFences) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    // Initialize CPU descriptor heaps
+    for (Uint32 i = 0; i < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; i += 1) {
+        renderer->stagingDescriptorHeaps[i] = D3D12_INTERNAL_CreateDescriptorHeap(
+            renderer,
+            (D3D12_DESCRIPTOR_HEAP_TYPE)i,
+            (i <= D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER) ? VIEW_SAMPLER_STAGING_DESCRIPTOR_COUNT : TARGET_STAGING_DESCRIPTOR_COUNT,
+            SDL_TRUE);
+    }
+
+    // Initialize GPU descriptor heaps
+    for (Uint32 i = 0; i < 2; i += 1) {
+        renderer->descriptorHeapPools[i].lock = SDL_CreateMutex();
+        renderer->descriptorHeapPools[i].capacity = 4;
+        renderer->descriptorHeapPools[i].count = 4;
+        renderer->descriptorHeapPools[i].heaps = (D3D12DescriptorHeap **)SDL_calloc(
+            renderer->descriptorHeapPools[i].capacity, sizeof(D3D12DescriptorHeap *));
+
+        for (Uint32 j = 0; j < renderer->descriptorHeapPools[i].capacity; j += 1) {
+            renderer->descriptorHeapPools[i].heaps[j] = D3D12_INTERNAL_CreateDescriptorHeap(
+                renderer,
+                (D3D12_DESCRIPTOR_HEAP_TYPE)i,
+                i == D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV ? VIEW_GPU_DESCRIPTOR_COUNT : SAMPLER_GPU_DESCRIPTOR_COUNT,
+                SDL_FALSE);
+        }
+    }
+
+    // Deferred resource releasing
+
+    renderer->buffersToDestroyCapacity = 4;
+    renderer->buffersToDestroyCount = 0;
+    renderer->buffersToDestroy = (D3D12Buffer **)SDL_calloc(
+        renderer->buffersToDestroyCapacity, sizeof(D3D12Buffer *));
+    if (!renderer->buffersToDestroy) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    renderer->texturesToDestroyCapacity = 4;
+    renderer->texturesToDestroyCount = 0;
+    renderer->texturesToDestroy = (D3D12Texture **)SDL_calloc(
+        renderer->texturesToDestroyCapacity, sizeof(D3D12Texture *));
+    if (!renderer->texturesToDestroy) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    renderer->samplersToDestroyCapacity = 4;
+    renderer->samplersToDestroyCount = 0;
+    renderer->samplersToDestroy = (D3D12Sampler **)SDL_calloc(
+        renderer->samplersToDestroyCapacity, sizeof(D3D12Sampler *));
+    if (!renderer->samplersToDestroy) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    renderer->graphicsPipelinesToDestroyCapacity = 4;
+    renderer->graphicsPipelinesToDestroyCount = 0;
+    renderer->graphicsPipelinesToDestroy = (D3D12GraphicsPipeline **)SDL_calloc(
+        renderer->graphicsPipelinesToDestroyCapacity, sizeof(D3D12GraphicsPipeline *));
+    if (!renderer->graphicsPipelinesToDestroy) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    renderer->computePipelinesToDestroyCapacity = 4;
+    renderer->computePipelinesToDestroyCount = 0;
+    renderer->computePipelinesToDestroy = (D3D12ComputePipeline **)SDL_calloc(
+        renderer->computePipelinesToDestroyCapacity, sizeof(D3D12ComputePipeline *));
+    if (!renderer->computePipelinesToDestroy) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    // Locks
+    renderer->stagingDescriptorHeapLock = SDL_CreateMutex();
+    renderer->acquireCommandBufferLock = SDL_CreateMutex();
+    renderer->acquireUniformBufferLock = SDL_CreateMutex();
+    renderer->submitLock = SDL_CreateMutex();
+    renderer->windowLock = SDL_CreateMutex();
+    renderer->fenceLock = SDL_CreateMutex();
+    renderer->disposeLock = SDL_CreateMutex();
+
+    renderer->debugMode = debugMode;
+
+    renderer->semantic = SDL_GetStringProperty(props, SDL_PROP_GPU_CREATEDEVICE_D3D12_SEMANTIC_NAME_STRING, "TEXCOORD");
+
+    // Blit resources
+    D3D12_INTERNAL_InitBlitResources(renderer);
+
+    // Create the SDL_Gpu Device
+    result = (SDL_GpuDevice *)SDL_calloc(1, sizeof(SDL_GpuDevice));
+
+    if (!result) {
+        D3D12_INTERNAL_DestroyRenderer(renderer);
+        return NULL;
+    }
+
+    ASSIGN_DRIVER(D3D12)
+    result->driverData = (SDL_GpuRenderer *)renderer;
+    result->debugMode = debugMode;
+    renderer->sdlGpuDevice = result;
+
+    return result;
+}
+
+SDL_GpuBootstrap D3D12Driver = {
+    "D3D12",
+    SDL_GPU_DRIVER_D3D12,
+    SDL_GPU_SHADERFORMAT_DXIL,
+    D3D12_PrepareDriver,
+    D3D12_CreateDevice
+};
+
+#endif // SDL_GPU_D3D12
+
+// GDK-specific APIs
+
+#ifdef SDL_PLATFORM_GDK
+
+void SDL_GDKSuspendGpu(SDL_GpuDevice *device)
+{
+#if defined(SDL_GPU_D3D12) && (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    D3D12Renderer *renderer = (D3D12Renderer *)device->driverData;
+    HRESULT res;
+    if (device == NULL) {
+        SDL_SetError("Invalid GPU device");
+        return;
+    }
+
+    SDL_LockMutex(renderer->submitLock);
+    res = renderer->commandQueue->SuspendX(0);
+    if (FAILED(res)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "SuspendX failed: %X", res);
+    }
+    SDL_UnlockMutex(renderer->submitLock);
+#endif
+}
+
+void SDL_GDKResumeGpu(SDL_GpuDevice *device)
+{
+#if defined(SDL_GPU_D3D12) && (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
+    D3D12Renderer *renderer = (D3D12Renderer *)device->driverData;
+    HRESULT res;
+    if (device == NULL) {
+        SDL_SetError("Invalid GPU device");
+        return;
+    }
+
+    SDL_LockMutex(renderer->submitLock);
+    res = renderer->commandQueue->ResumeX();
+    if (FAILED(res)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "ResumeX failed: %X", res);
+    }
+    SDL_UnlockMutex(renderer->submitLock);
+
+    res = renderer->device->SetFrameIntervalX(
+        NULL,
+        D3D12XBOX_FRAME_INTERVAL_60_HZ,
+        MAX_FRAMES_IN_FLIGHT - 1,
+        D3D12XBOX_FRAME_INTERVAL_FLAG_NONE);
+    if (FAILED(res)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not set frame interval: %X", res);
+    }
+
+    res = renderer->device->ScheduleFrameEventX(
+        D3D12XBOX_FRAME_EVENT_ORIGIN,
+        0,
+        NULL,
+        D3D12XBOX_SCHEDULE_FRAME_EVENT_FLAG_NONE);
+    if (FAILED(res)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not schedule frame events: %X", res);
+    }
+#endif
+}
+
+#endif // SDL_PLATFORM_GDK

+ 17 - 0
src/gpu/d3d12/compile_shaders.bat

@@ -0,0 +1,17 @@
+rem This script runs for the Windows build, but also via the _xbox variant with these vars set.
+rem Make sure to default to building for Windows if they're not set.
+if %DXC%.==. set DXC=dxc
+if %SUFFIX%.==. set SUFFIX=.h
+
+echo Building with %DXC%
+echo Suffix %SUFFIX%
+
+cd "%~dp0"
+
+%DXC% -E FullscreenVert -T vs_6_0 -Fh D3D12_FullscreenVert.h ..\d3dcommon\D3D_Blit.hlsl /D D3D12=1
+%DXC% -E BlitFrom2D -T ps_6_0 -Fh D3D12_BlitFrom2D.h ..\d3dcommon\D3D_Blit.hlsl /D D3D12=1
+%DXC% -E BlitFrom2DArray -T ps_6_0 -Fh D3D12_BlitFrom2DArray.h ..\d3dcommon\D3D_Blit.hlsl /D D3D12=1
+%DXC% -E BlitFrom3D -T ps_6_0 -Fh D3D12_BlitFrom3D.h ..\d3dcommon\D3D_Blit.hlsl /D D3D12=1
+%DXC% -E BlitFromCube -T ps_6_0  -Fh D3D12_BlitFromCube.h ..\d3dcommon\D3D_Blit.hlsl /D D3D12=1
+copy /b D3D12_FullscreenVert.h+D3D12_BlitFrom2D.h+D3D12_BlitFrom2DArray.h+D3D12_BlitFrom3D.h+D3D12_BlitFromCube.h D3D12_Blit%SUFFIX%
+del D3D12_FullscreenVert.h D3D12_BlitFrom2D.h D3D12_BlitFrom2DArray.h D3D12_BlitFrom3D.h D3D12_BlitFromCube.h

+ 13 - 0
src/gpu/d3d12/compile_shaders_xbox.bat

@@ -0,0 +1,13 @@
+if %2.==one. goto setxboxone
+rem Xbox Series compile
+set DXC="%GameDKLatest%\GXDK\bin\Scarlett\DXC.exe"
+set SUFFIX=_Series.h
+goto startbuild
+
+:setxboxone
+set DXC="%GameDKLatest%\GXDK\bin\XboxOne\DXC.exe"
+set SUFFIX=_One.h
+
+:startbuild
+
+call "%~dp0\compile_shaders.bat"

+ 91 - 0
src/gpu/d3dcommon/D3D_Blit.hlsl

@@ -0,0 +1,91 @@
+#if D3D12
+#define BlitRS \
+    "DescriptorTable ( Sampler(s0, space=2), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "DescriptorTable ( SRV(t0, space=2), visibility = SHADER_VISIBILITY_PIXEL ),"\
+    "CBV(b0, space=3, visibility = SHADER_VISIBILITY_PIXEL),"\
+
+#define REG(reg, space) register(reg, space)
+#else
+#define REG(reg, space) register(reg)
+#endif
+
+struct VertexToPixel
+{
+    float2 tex : TEXCOORD0;
+    float4 pos : SV_POSITION;
+};
+
+cbuffer SourceRegionBuffer : REG(b0, space3)
+{
+    float2 UVLeftTop;
+    float2 UVDimensions;
+    uint MipLevel;
+    float LayerOrDepth;
+};
+
+Texture2D SourceTexture2D : REG(t0, space2);
+Texture2DArray SourceTexture2DArray : REG(t0, space2);
+Texture3D SourceTexture3D : REG(t0, space2);
+TextureCube SourceTextureCube : REG(t0, space2);
+sampler SourceSampler : REG(s0, space2);
+
+#if D3D12
+[RootSignature(BlitRS)]
+#endif
+VertexToPixel FullscreenVert(uint vI : SV_VERTEXID)
+{
+    float2 inTex = float2((vI << 1) & 2, vI & 2);
+    VertexToPixel Out = (VertexToPixel)0;
+    Out.tex = inTex;
+    Out.pos = float4(inTex * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
+    return Out;
+}
+
+#if D3D12
+[RootSignature(BlitRS)]
+#endif
+float4 BlitFrom2D(VertexToPixel input) : SV_Target0
+{
+    float2 newCoord = UVLeftTop + UVDimensions * input.tex;
+    return SourceTexture2D.SampleLevel(SourceSampler, newCoord, MipLevel);
+}
+
+#if D3D12
+[RootSignature(BlitRS)]
+#endif
+float4 BlitFrom2DArray(VertexToPixel input) : SV_Target0
+{
+    float3 newCoord = float3(UVLeftTop + UVDimensions * input.tex, (uint)LayerOrDepth);
+    return SourceTexture2DArray.SampleLevel(SourceSampler, newCoord, MipLevel);
+}
+
+#if D3D12
+[RootSignature(BlitRS)]
+#endif
+float4 BlitFrom3D(VertexToPixel input) : SV_Target0
+{
+    float3 newCoord = float3(UVLeftTop + UVDimensions * input.tex, LayerOrDepth);
+    return SourceTexture3D.SampleLevel(SourceSampler, newCoord, MipLevel);
+}
+
+#if D3D12
+[RootSignature(BlitRS)]
+#endif
+float4 BlitFromCube(VertexToPixel input) : SV_Target0
+{
+    // Thanks, Wikipedia! https://en.wikipedia.org/wiki/Cube_mapping
+    float3 newCoord;
+    float2 scaledUV = UVLeftTop + UVDimensions * input.tex;
+    float u = 2.0 * scaledUV.x - 1.0;
+    float v = 2.0 * scaledUV.y - 1.0;
+    switch ((uint)LayerOrDepth) {
+        case 0: newCoord = float3(1.0, -v, -u); break; // POSITIVE X
+        case 1: newCoord = float3(-1.0, -v, u); break; // NEGATIVE X
+        case 2: newCoord = float3(u, -1.0, -v); break; // POSITIVE Y
+        case 3: newCoord = float3(u, 1.0, v); break; // NEGATIVE Y
+        case 4: newCoord = float3(u, -v, 1.0); break; // POSITIVE Z
+        case 5: newCoord = float3(-u, -v, -1.0); break; // NEGATIVE Z
+        default: newCoord = float3(0, 0, 0); break; // silences warning
+    }
+    return SourceTextureCube.SampleLevel(SourceSampler, newCoord, MipLevel);
+}

+ 7969 - 0
src/gpu/metal/Metal_Blit.h

@@ -0,0 +1,7969 @@
+#if defined(SDL_PLATFORM_IOS)
+#if TARGET_OS_SIMULATOR
+const unsigned char FullscreenVert_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x84, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0f, 0x00, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63,
+  0x72, 0x65, 0x65, 0x6e, 0x56, 0x65, 0x72, 0x74, 0x00, 0x54, 0x59, 0x50,
+  0x45, 0x01, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x16, 0x94,
+  0x3c, 0x5e, 0x18, 0xfb, 0x8a, 0x87, 0x81, 0x7e, 0xbc, 0x13, 0x64, 0x43,
+  0x3c, 0x97, 0xd9, 0x63, 0xd2, 0x8c, 0xed, 0x05, 0x40, 0xf4, 0xa2, 0xb6,
+  0x86, 0x25, 0x73, 0x2f, 0xe4, 0xb1, 0x4d, 0x44, 0x53, 0x5a, 0x08, 0x00,
+  0x90, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x46, 0x46, 0x54,
+  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x02, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x45, 0x4e, 0x44, 0x54,
+  0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x74, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x42, 0x43, 0xc0, 0xde, 0x35, 0x14, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x62, 0x0c, 0x30, 0x24, 0x80, 0x10, 0x05, 0xc8, 0x14, 0x00, 0x00, 0x00,
+  0x21, 0x0c, 0x00, 0x00, 0x96, 0x02, 0x00, 0x00, 0x0b, 0x02, 0x21, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91,
+  0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c,
+  0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02,
+  0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b,
+  0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5,
+  0x00, 0x19, 0x32, 0x42, 0x04, 0x49, 0x0e, 0x90, 0x11, 0x22, 0xc4, 0x50,
+  0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, 0x06,
+  0x51, 0x18, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x1b, 0x7a, 0x24, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0x01, 0x90, 0x00, 0x8a, 0x08, 0x07, 0x78, 0x80,
+  0x07, 0x79, 0x78, 0x07, 0x7c, 0x68, 0x03, 0x73, 0xa8, 0x07, 0x77, 0x18,
+  0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40,
+  0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xda, 0x21, 0x1d,
+  0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d,
+  0xec, 0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e,
+  0xd2, 0x81, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x38, 0x00, 0x06, 0x77, 0x78,
+  0x87, 0x36, 0x10, 0x87, 0x7a, 0x48, 0x07, 0x76, 0xa0, 0x87, 0x74, 0x70,
+  0x87, 0x79, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30, 0x07, 0x79, 0x08,
+  0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48, 0x07, 0x77, 0xa0,
+  0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48, 0x87, 0x76, 0x00,
+  0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d,
+  0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d, 0xca, 0xa1, 0x0d, 0xe0, 0xe1, 0x1d,
+  0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xca, 0x81, 0x1d,
+  0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d, 0xde, 0xc1, 0x1d, 0xda, 0x80, 0x1d,
+  0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00,
+  0x08, 0x77, 0x78, 0x87, 0x36, 0x48, 0x07, 0x77, 0x30, 0x87, 0x79, 0x68,
+  0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00,
+  0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d,
+  0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d,
+  0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28,
+  0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83, 0x79, 0x48, 0x87, 0x73, 0x70,
+  0x87, 0x72, 0x20, 0x87, 0x36, 0xd0, 0x87, 0x72, 0x90, 0x87, 0x77, 0x98,
+  0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40,
+  0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d,
+  0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c, 0xe0, 0x01, 0x1e, 0xd2, 0xc1, 0x1d,
+  0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90,
+  0x87, 0x7a, 0x28, 0x07, 0x80, 0x98, 0x07, 0x7a, 0x08, 0x87, 0x71, 0x58,
+  0x87, 0x36, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7a, 0x28, 0x87, 0x71, 0xa0,
+  0x87, 0x77, 0x90, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x30, 0x07, 0x73, 0x28,
+  0x07, 0x79, 0x68, 0x83, 0x79, 0x48, 0x07, 0x7d, 0x28, 0x07, 0x00, 0x0f,
+  0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e, 0xc2, 0xc1, 0x1c, 0xca, 0xa1, 0x0d,
+  0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0,
+  0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x36, 0x18, 0xc2, 0xff, 0xff, 0xff,
+  0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b, 0x8c, 0xe1, 0xff, 0xff, 0xff, 0xff,
+  0x07, 0x40, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06,
+  0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84,
+  0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c,
+  0x0b, 0x84, 0x84, 0x4c, 0x10, 0x38, 0x33, 0x00, 0xc3, 0x08, 0x02, 0x30,
+  0x8c, 0x40, 0x00, 0x56, 0x08, 0x99, 0x23, 0x00, 0x83, 0x22, 0x0c, 0x51,
+  0x15, 0x01, 0x88, 0x6e, 0x20, 0x20, 0x05, 0x68, 0x8e, 0x00, 0x14, 0x86,
+  0x11, 0x08, 0x62, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0xbe, 0x70, 0x48,
+  0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60,
+  0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0x88, 0x83, 0x39, 0x70,
+  0x03, 0x38, 0x70, 0x03, 0x38, 0x68, 0x83, 0x79, 0x48, 0x87, 0x76, 0xa8,
+  0x07, 0x76, 0x08, 0x07, 0x7a, 0x78, 0x07, 0x79, 0xd8, 0x70, 0x1b, 0xe5,
+  0xd0, 0x06, 0xf0, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x78,
+  0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x7a,
+  0x80, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x90, 0x0e, 0x73, 0x20, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76,
+  0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d,
+  0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x60, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x60, 0x07, 0x7a,
+  0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72,
+  0x40, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x60, 0x0f, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x60, 0x0f, 0x74, 0x80, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x79,
+  0x60, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72,
+  0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71,
+  0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6,
+  0x10, 0x07, 0x79, 0x20, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a,
+  0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x50, 0x07, 0x76,
+  0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76,
+  0xd0, 0x06, 0xf6, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71,
+  0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x71,
+  0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74,
+  0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78,
+  0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x11, 0xc2,
+  0x90, 0xce, 0x47, 0x2d, 0x8b, 0x24, 0x44, 0x04, 0xd1, 0xbc, 0x44, 0x34,
+  0x0d, 0x89, 0x00, 0xa7, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00,
+  0x00, 0x00, 0x80, 0x21, 0x91, 0x73, 0x1d, 0x40, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0xb1, 0x41, 0xa0, 0x28, 0xa6, 0x00,
+  0x00, 0x40, 0x16, 0x08, 0x07, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x0c,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0xa2,
+  0x22, 0x28, 0x81, 0x42, 0x18, 0x01, 0x20, 0x1d, 0x4b, 0x88, 0x04, 0x00,
+  0xb1, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c,
+  0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3,
+  0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6,
+  0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03,
+  0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48,
+  0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20,
+  0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e,
+  0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d,
+  0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89,
+  0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83,
+  0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78,
+  0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98,
+  0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5,
+  0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c,
+  0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43,
+  0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82,
+  0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58,
+  0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18,
+  0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2,
+  0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec,
+  0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e,
+  0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d,
+  0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83,
+  0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60,
+  0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0,
+  0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d,
+  0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d,
+  0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43,
+  0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3,
+  0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18,
+  0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3,
+  0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1,
+  0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e,
+  0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3,
+  0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3,
+  0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60,
+  0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec,
+  0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5,
+  0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5,
+  0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8,
+  0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17,
+  0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d,
+  0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03,
+  0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78,
+  0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce,
+  0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef,
+  0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08,
+  0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0,
+  0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8,
+  0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00, 0x00,
+  0x82, 0x00, 0x00, 0x00, 0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c, 0x27,
+  0x46, 0x46, 0xc8, 0x11, 0x32, 0x64, 0xd4, 0x26, 0xe8, 0x4c, 0x00, 0x00,
+  0x8b, 0xf2, 0x06, 0xc5, 0xc6, 0x91, 0x41, 0x44, 0x45, 0x06, 0x33, 0x30,
+  0xc6, 0xd0, 0x10, 0x02, 0x53, 0x44, 0x4b, 0x20, 0x56, 0x65, 0x72, 0x73,
+  0x69, 0x6f, 0x6e, 0x77, 0x63, 0x68, 0x61, 0x72, 0x5f, 0x73, 0x69, 0x7a,
+  0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c,
+  0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x32, 0x30,
+  0x32, 0x33, 0x2e, 0x39, 0x38, 0x20, 0x28, 0x6d, 0x65, 0x74, 0x61, 0x6c,
+  0x66, 0x65, 0x2d, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x29,
+  0x4d, 0x65, 0x74, 0x61, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
+  0x70, 0x69, 0x6c, 0x65, 0x2e, 0x64, 0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x73,
+  0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e,
+  0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74,
+  0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e,
+  0x66, 0x72, 0x61, 0x6d, 0x65, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f,
+  0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x6f,
+  0x75, 0x74, 0x70, 0x75, 0x74, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
+  0x65, 0x64, 0x28, 0x33, 0x74, 0x65, 0x78, 0x44, 0x76, 0x32, 0x5f, 0x66,
+  0x29, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70,
+  0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32,
+  0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+  0x74, 0x65, 0x78, 0x61, 0x69, 0x72, 0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74,
+  0x69, 0x6f, 0x6e, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x70, 0x6f, 0x73,
+  0x61, 0x69, 0x72, 0x2e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x69,
+  0x64, 0x75, 0x69, 0x6e, 0x74, 0x76, 0x49, 0x00, 0x23, 0x08, 0x84, 0x30,
+  0x82, 0xa0, 0x18, 0x23, 0x08, 0xc4, 0x30, 0x82, 0x40, 0x10, 0x23, 0x08,
+  0x44, 0x31, 0x82, 0x60, 0x00, 0x33, 0x0c, 0x54, 0x50, 0xcd, 0x30, 0x58,
+  0xc2, 0x35, 0x43, 0x30, 0xcc, 0x30, 0x50, 0x14, 0x36, 0x03, 0x41, 0x58,
+  0x16, 0x36, 0x43, 0x50, 0xcc, 0x10, 0x18, 0x33, 0x04, 0xc7, 0x0c, 0x06,
+  0x92, 0x28, 0x0b, 0xd3, 0xcc, 0x50, 0x38, 0xca, 0xc3, 0x40, 0x33, 0x08,
+  0x62, 0x30, 0x06, 0x33, 0x18, 0x58, 0xa4, 0x48, 0xcc, 0x34, 0x43, 0x50,
+  0x06, 0x33, 0x0c, 0x19, 0x19, 0x98, 0x81, 0x8c, 0x04, 0x26, 0xe8, 0x22,
+  0x36, 0x36, 0xbb, 0x36, 0x97, 0xb6, 0x37, 0xb2, 0x3a, 0xb6, 0x32, 0x17,
+  0x33, 0xb6, 0xb0, 0xb3, 0xb9, 0x51, 0x84, 0x4c, 0x3b, 0x85, 0x8d, 0xcd,
+  0xae, 0xcd, 0x25, 0x8d, 0xac, 0xcc, 0x8d, 0x6e, 0x94, 0x60, 0xbb, 0x25,
+  0x2c, 0x4d, 0xce, 0xc5, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x6d, 0x94,
+  0x80, 0x3b, 0x2a, 0x2c, 0x4d, 0xce, 0x85, 0x2d, 0xcc, 0xed, 0xac, 0x2e,
+  0xec, 0xac, 0xec, 0xcb, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x6d, 0x94,
+  0xa0, 0xbb, 0x29, 0x2c, 0x4d, 0xce, 0x65, 0xec, 0xad, 0x0d, 0x2e, 0x8d,
+  0xad, 0xec, 0xeb, 0x0d, 0x8e, 0x2e, 0xed, 0xcd, 0x6d, 0x6e, 0x94, 0xc1,
+  0xfb, 0xc0, 0xe0, 0x94, 0xb0, 0x34, 0x39, 0x17, 0xbb, 0x32, 0x39, 0xba,
+  0x32, 0xbc, 0x51, 0x02, 0x33, 0x00, 0x00, 0x00, 0xa9, 0x18, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x72, 0x28, 0x87, 0x77, 0x80, 0x07,
+  0x7a, 0x58, 0x70, 0x98, 0x43, 0x3d, 0xb8, 0xc3, 0x38, 0xb0, 0x43, 0x39,
+  0xd0, 0xc3, 0x82, 0xe6, 0x1c, 0xc6, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2,
+  0xc1, 0x1d, 0xe6, 0x21, 0x1d, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x16,
+  0x34, 0xe3, 0x60, 0x0e, 0xe7, 0x50, 0x0f, 0xe1, 0x20, 0x0f, 0xe4, 0x40,
+  0x0f, 0xe1, 0x20, 0x0f, 0xe7, 0x50, 0x0e, 0xf4, 0xb0, 0x80, 0x81, 0x07,
+  0x79, 0x28, 0x87, 0x70, 0x60, 0x07, 0x76, 0x78, 0x87, 0x71, 0x08, 0x07,
+  0x7a, 0x28, 0x07, 0x72, 0x58, 0x70, 0x9c, 0xc3, 0x38, 0xb4, 0x01, 0x3b,
+  0xa4, 0x83, 0x3d, 0x94, 0xc3, 0x02, 0x6b, 0x1c, 0xd8, 0x21, 0x1c, 0xdc,
+  0xe1, 0x1c, 0xdc, 0x20, 0x1c, 0xe4, 0x61, 0x1c, 0xdc, 0x20, 0x1c, 0xe8,
+  0x81, 0x1e, 0xc2, 0x61, 0x1c, 0xd0, 0xa1, 0x1c, 0xc8, 0x61, 0x1c, 0xc2,
+  0x81, 0x1d, 0xd8, 0x61, 0xc1, 0x01, 0x0f, 0xf4, 0x20, 0x0f, 0xe1, 0x50,
+  0x0f, 0xf4, 0x80, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x10, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x07, 0xcc, 0x3c, 0xa4, 0x83, 0x3b, 0x9c, 0x03,
+  0x3b, 0x94, 0x03, 0x3d, 0xa0, 0x83, 0x3c, 0x94, 0x43, 0x38, 0x90, 0xc3,
+  0x01, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x44, 0x33, 0x00, 0xb4, 0x23, 0x00, 0x25, 0x40, 0x3c, 0x07, 0x51, 0x0c,
+  0x08, 0x32, 0x16, 0x01, 0x04, 0xc6, 0x41, 0x30, 0x03, 0x30, 0x02, 0x30,
+  0x46, 0x00, 0x82, 0x20, 0x88, 0x7f, 0x14, 0x33, 0x00, 0x63, 0x09, 0x20,
+  0x08, 0x82, 0x20, 0x18, 0x80, 0x20, 0x08, 0x82, 0xe0, 0x30, 0x96, 0x00,
+  0x82, 0x20, 0x88, 0xff, 0x02, 0x08, 0x82, 0x20, 0xfe, 0xcd, 0x00, 0x90,
+  0xcc, 0x41, 0x34, 0x8d, 0xf3, 0xd0, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf5, 0x4c, 0x57, 0x41, 0xa5, 0x23, 0x06, 0xc6, 0x10, 0x82, 0x60, 0xe1,
+  0x1f, 0xc7, 0x15, 0xcc, 0x31, 0x24, 0x01, 0x54, 0x13, 0xa6, 0x23, 0x06,
+  0xc6, 0x10, 0x82, 0x60, 0xe1, 0x1f, 0x87, 0x16, 0xcc, 0x31, 0x0c, 0x81,
+  0x64, 0x01, 0x23, 0xfe, 0x16, 0x30, 0xe0, 0x3f, 0xc8, 0x10, 0x30, 0xd4,
+  0x20, 0x43, 0xc0, 0x50, 0xb3, 0x0d, 0x4c, 0x01, 0xcc, 0x36, 0x04, 0x42,
+  0x90, 0x01, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x32, 0x0e, 0x10, 0x22, 0x84, 0x00, 0xf1, 0x04, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x65, 0x0c, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x12, 0x03, 0x94, 0x28, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x24, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x5d, 0x0c, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x12, 0x03, 0x94, 0xac, 0x00, 0x00, 0x00, 0x00, 0x46, 0x75, 0x6c, 0x6c,
+  0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x56, 0x65, 0x72, 0x74, 0x61, 0x69,
+  0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2e, 0x66, 0x2e,
+  0x66, 0x33, 0x32, 0x2e, 0x75, 0x2e, 0x69, 0x33, 0x32, 0x33, 0x32, 0x30,
+  0x32, 0x33, 0x2e, 0x39, 0x38, 0x61, 0x69, 0x72, 0x36, 0x34, 0x2d, 0x61,
+  0x70, 0x70, 0x6c, 0x65, 0x2d, 0x69, 0x6f, 0x73, 0x31, 0x33, 0x2e, 0x30,
+  0x2e, 0x30, 0x2d, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 0x72,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int FullscreenVert_metallib_len = 3204;
+const unsigned char BlitFrom2D_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0b, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x32, 0x44, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01,
+  0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0xfc, 0x1b, 0x83, 0xbd, 0xe8, 0x47,
+  0xb7, 0x89, 0xbe, 0x0b, 0x20, 0x31, 0x4b, 0x78, 0x90, 0xba, 0x6f, 0xf4,
+  0xce, 0xe6, 0x39, 0x7c, 0xf5, 0x0b, 0x54, 0x34, 0x6b, 0x31, 0xf4, 0xe6,
+  0x0b, 0x40, 0x4d, 0x44, 0x53, 0x5a, 0x08, 0x00, 0x90, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45,
+  0x52, 0x53, 0x08, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54,
+  0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x70, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde,
+  0x35, 0x14, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x0c, 0x30, 0x24,
+  0x80, 0x10, 0x05, 0xc8, 0x14, 0x00, 0x00, 0x00, 0x21, 0x0c, 0x00, 0x00,
+  0x89, 0x03, 0x00, 0x00, 0x0b, 0x02, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88,
+  0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42,
+  0x04, 0x49, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c,
+  0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00,
+  0x83, 0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff,
+  0x01, 0x58, 0x03, 0x40, 0x02, 0x2a, 0x22, 0x1c, 0xe0, 0x01, 0x1e, 0xe4,
+  0xe1, 0x1d, 0xf0, 0xa1, 0x0d, 0xcc, 0xa1, 0x1e, 0xdc, 0x61, 0x1c, 0xda,
+  0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x68, 0x87, 0x74, 0x70, 0x87,
+  0x36, 0x60, 0x87, 0x72, 0x38, 0x87, 0x70, 0x60, 0x87, 0x36, 0xb0, 0x87,
+  0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x83, 0x7b, 0x48, 0x07,
+  0x72, 0xa0, 0x07, 0x74, 0x00, 0xe2, 0x40, 0x0e, 0xf0, 0x00, 0x18, 0xdc,
+  0xe1, 0x1d, 0xda, 0x40, 0x1c, 0xea, 0x21, 0x1d, 0xd8, 0x81, 0x1e, 0xd2,
+  0xc1, 0x1d, 0xe6, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4,
+  0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc,
+  0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87,
+  0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07,
+  0x76, 0x48, 0x87, 0x76, 0x68, 0x03, 0x77, 0x78, 0x07, 0x77, 0x68, 0x03,
+  0x76, 0x28, 0x87, 0x70, 0x30, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x20, 0x1d, 0xdc, 0xc1, 0x1c, 0xe6,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x70, 0x87, 0x70, 0x70, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xce,
+  0xc1, 0x1d, 0xca, 0x81, 0x1c, 0xda, 0x40, 0x1f, 0xca, 0x41, 0x1e, 0xde,
+  0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8,
+  0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87,
+  0x77, 0x68, 0x03, 0x7a, 0x90, 0x87, 0x70, 0x80, 0x07, 0x78, 0x48, 0x07,
+  0x77, 0x38, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8,
+  0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0x62, 0x1e, 0xe8, 0x21, 0x1c, 0xc6,
+  0x61, 0x1d, 0xda, 0x00, 0x1e, 0xe4, 0xe1, 0x1d, 0xe8, 0xa1, 0x1c, 0xc6,
+  0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0x40, 0x1c, 0xea, 0xc1, 0x1c, 0xcc,
+  0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xf4, 0xa1, 0x1c, 0x00,
+  0x3c, 0x00, 0x88, 0x7a, 0x70, 0x87, 0x79, 0x08, 0x07, 0x73, 0x28, 0x87,
+  0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07,
+  0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0xd8, 0xe0, 0x09, 0x03, 0xb0,
+  0x00, 0x55, 0x90, 0x06, 0xd8, 0x10, 0x0e, 0xe9, 0x20, 0x0f, 0x6d, 0x20,
+  0x0e, 0xf5, 0x60, 0x0e, 0xe6, 0x50, 0x0e, 0xf2, 0xd0, 0x06, 0xee, 0xf0,
+  0x0e, 0x6d, 0x10, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0xc0, 0x06,
+  0x63, 0x28, 0x80, 0x05, 0xa8, 0x36, 0x28, 0xc4, 0xff, 0xff, 0xff, 0xff,
+  0x0f, 0x40, 0x1b, 0x00, 0x6b, 0x00, 0x48, 0x40, 0xb5, 0xc1, 0x28, 0x02,
+  0x60, 0x01, 0xaa, 0x0d, 0x86, 0x21, 0x00, 0x0b, 0x50, 0x6d, 0x30, 0x8e,
+  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa0, 0x36, 0x18, 0xc8, 0xff,
+  0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b, 0x94, 0xe4, 0xff, 0xff,
+  0xff, 0xff, 0x07, 0xa0, 0x0d, 0x80, 0x35, 0x00, 0x24, 0xa0, 0x02, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18,
+  0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48,
+  0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x68, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30,
+  0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30,
+  0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10,
+  0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4a, 0x9a, 0x22, 0x4a, 0x98, 0xfc,
+  0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0xdf, 0x1e, 0xfe, 0x69, 0x8c, 0x00,
+  0x18, 0x44, 0x30, 0x82, 0x8b, 0xa4, 0x29, 0xa2, 0x84, 0xc9, 0xff, 0x25,
+  0x80, 0x79, 0x16, 0x22, 0xfa, 0xa7, 0x31, 0x02, 0x60, 0x10, 0x01, 0x11,
+  0x8a, 0x11, 0x44, 0x28, 0x27, 0x91, 0x9a, 0x23, 0x40, 0x8c, 0x10, 0xd8,
+  0x1c, 0x41, 0x30, 0x8c, 0x20, 0x0c, 0x45, 0x69, 0x27, 0x09, 0xf7, 0x1c,
+  0x00, 0x83, 0x60, 0x11, 0xc0, 0x20, 0x39, 0x10, 0x90, 0x02, 0x63, 0x8e,
+  0x00, 0x14, 0x06, 0x11, 0x04, 0x61, 0x10, 0x61, 0x10, 0x46, 0x00, 0x00,
+  0x13, 0xbe, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70,
+  0x80, 0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79,
+  0x88, 0x83, 0x39, 0x70, 0x03, 0x38, 0x70, 0x03, 0x38, 0x68, 0x83, 0x79,
+  0x48, 0x87, 0x76, 0xa8, 0x07, 0x76, 0x08, 0x07, 0x7a, 0x78, 0x07, 0x79,
+  0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06, 0xf0, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x90, 0x0e,
+  0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9, 0x80, 0x07,
+  0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07,
+  0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x90, 0x0e,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f,
+  0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07,
+  0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x74, 0x80, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07,
+  0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x20, 0x07,
+  0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07,
+  0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x79, 0x20, 0x07, 0x7a, 0x20, 0x07,
+  0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f,
+  0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07,
+  0x72, 0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x50, 0x07, 0x71, 0x20, 0x07,
+  0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07,
+  0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10, 0x07,
+  0x70, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07,
+  0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x11, 0xc2, 0x90, 0xca, 0xb6, 0x20, 0xd3, 0x17, 0x39, 0x8c,
+  0xdd, 0x0d, 0x89, 0x00, 0x45, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x80, 0x21, 0x91, 0xb2, 0x41, 0x40, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x30, 0x24, 0x2a, 0x83, 0x4b, 0x02,
+  0x02, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x89, 0x0d,
+  0x02, 0x45, 0x17, 0x07, 0x00, 0x00, 0xb2, 0x40, 0x0b, 0x00, 0x00, 0x00,
+  0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47,
+  0xc6, 0x04, 0x43, 0x1a, 0x45, 0x50, 0x02, 0x85, 0x30, 0x02, 0x50, 0x30,
+  0x05, 0x51, 0x20, 0x85, 0x52, 0x06, 0x64, 0x47, 0x00, 0x0a, 0xa2, 0x40,
+  0x0a, 0x85, 0xea, 0x58, 0x42, 0x24, 0x00, 0x00, 0xb1, 0x18, 0x00, 0x00,
+  0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66,
+  0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10,
+  0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce,
+  0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b,
+  0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c,
+  0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07,
+  0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11,
+  0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0,
+  0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8,
+  0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b,
+  0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b,
+  0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87,
+  0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07,
+  0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87,
+  0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81,
+  0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30,
+  0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca,
+  0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b,
+  0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b,
+  0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83,
+  0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87,
+  0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90,
+  0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20,
+  0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc,
+  0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66,
+  0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24,
+  0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07,
+  0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e,
+  0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e,
+  0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54,
+  0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39,
+  0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c,
+  0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07,
+  0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0,
+  0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4,
+  0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b,
+  0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39,
+  0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c,
+  0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87,
+  0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0,
+  0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50,
+  0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0,
+  0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec,
+  0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6,
+  0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66,
+  0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39,
+  0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07,
+  0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10,
+  0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90,
+  0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07,
+  0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07,
+  0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+  0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c, 0x27, 0x46, 0x46, 0xc8, 0x11,
+  0x32, 0x64, 0xd4, 0xd4, 0x80, 0x0c, 0xee, 0x09, 0x8b, 0xf2, 0x06, 0xc5,
+  0xc6, 0x91, 0x41, 0x14, 0x19, 0x12, 0xa5, 0x3c, 0x06, 0x33, 0x30, 0xd2,
+  0xa0, 0x3c, 0x12, 0x42, 0x25, 0x0c, 0x81, 0x14, 0x4c, 0x74, 0x31, 0xcc,
+  0xa2, 0x60, 0xcd, 0x72, 0x34, 0x00, 0x00, 0x00, 0x53, 0x44, 0x4b, 0x20,
+  0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x77, 0x63, 0x68, 0x61, 0x72,
+  0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x6d,
+  0x65, 0x74, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+  0x20, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x20, 0x28, 0x6d,
+  0x65, 0x74, 0x61, 0x6c, 0x66, 0x65, 0x2d, 0x33, 0x32, 0x30, 0x32, 0x33,
+  0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65, 0x74, 0x61, 0x6c, 0x61, 0x69, 0x72,
+  0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x64, 0x65, 0x6e,
+  0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e,
+  0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e,
+  0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70,
+  0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x62, 0x75, 0x66,
+  0x66, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x65, 0x6e,
+  0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x6e, 0x64,
+  0x65, 0x72, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x61, 0x69, 0x72,
+  0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61,
+  0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x61, 0x69, 0x72, 0x2e,
+  0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x70,
+  0x75, 0x74, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x28,
+  0x33, 0x74, 0x65, 0x78, 0x44, 0x76, 0x32, 0x5f, 0x66, 0x29, 0x61, 0x69,
+  0x72, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e,
+  0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67,
+  0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x78, 0x61, 0x69, 0x72, 0x2e,
+  0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x69, 0x72, 0x2e,
+  0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69,
+  0x76, 0x65, 0x70, 0x6f, 0x73, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66,
+  0x66, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65,
+  0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x6c, 0x6f,
+  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78,
+  0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x61, 0x64, 0x61, 0x69, 0x72, 0x2e,
+  0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f,
+  0x69, 0x6e, 0x66, 0x6f, 0x55, 0x56, 0x4c, 0x65, 0x66, 0x74, 0x54, 0x6f,
+  0x70, 0x55, 0x56, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+  0x73, 0x75, 0x69, 0x6e, 0x74, 0x4d, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65,
+  0x6c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x4f,
+  0x72, 0x44, 0x65, 0x70, 0x74, 0x68, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72,
+  0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61,
+  0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f,
+  0x61, 0x6c, 0x69, 0x67, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x53, 0x6f,
+  0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x6f,
+  0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x61, 0x69,
+  0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x61, 0x69, 0x72,
+  0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x78, 0x74, 0x75,
+  0x72, 0x65, 0x32, 0x64, 0x3c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x2c, 0x20,
+  0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3e, 0x73, 0x6f, 0x75, 0x72, 0x63,
+  0x65, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x61, 0x69, 0x72, 0x2e,
+  0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x61, 0x6d, 0x70, 0x6c,
+  0x65, 0x72, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70,
+  0x6c, 0x65, 0x72, 0x00, 0xc4, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x30, 0x82, 0x30, 0x0c, 0x23, 0x08, 0x15, 0x34, 0x82, 0x30, 0x10, 0x23,
+  0x08, 0x43, 0x31, 0x82, 0x30, 0x18, 0x23, 0x08, 0x0b, 0x30, 0x82, 0x30,
+  0x1c, 0x23, 0x08, 0x03, 0x32, 0x82, 0x30, 0x24, 0x23, 0x08, 0x83, 0x32,
+  0x82, 0x30, 0x2c, 0x33, 0x0c, 0x6b, 0x10, 0xb0, 0xc1, 0x0c, 0x43, 0x1b,
+  0x08, 0x6e, 0x30, 0x43, 0x30, 0xcc, 0x30, 0xac, 0xc1, 0x1a, 0xbc, 0xc1,
+  0x0c, 0x04, 0xd1, 0x06, 0x6d, 0xf0, 0x06, 0x33, 0x04, 0xc5, 0x0c, 0x81,
+  0x31, 0x43, 0x70, 0xcc, 0x50, 0x20, 0x6f, 0xf0, 0x06, 0x89, 0x32, 0x43,
+  0xe0, 0x07, 0x33, 0x24, 0x6f, 0xb0, 0x30, 0x8d, 0x93, 0x3c, 0x50, 0x34,
+  0x03, 0xd2, 0x06, 0x52, 0x33, 0x25, 0x0a, 0x44, 0xcd, 0x40, 0xbd, 0x81,
+  0x1c, 0xbc, 0xc1, 0xa3, 0xc9, 0x81, 0x1c, 0xbc, 0xc1, 0xb3, 0xcd, 0x81,
+  0x1b, 0xbc, 0x01, 0xd7, 0xd1, 0x81, 0x1b, 0xbc, 0x81, 0xf7, 0xcd, 0x20,
+  0xad, 0x41, 0x65, 0xc5, 0xc1, 0xf5, 0x06, 0x6d, 0x80, 0x65, 0xa2, 0x00,
+  0x06, 0x71, 0x10, 0x06, 0x72, 0x90, 0x88, 0x01, 0x34, 0x06, 0x33, 0x28,
+  0x75, 0x40, 0x06, 0xd7, 0x1b, 0xb4, 0x41, 0x19, 0x24, 0x66, 0x00, 0x9d,
+  0xc1, 0x0c, 0x89, 0x1b, 0xa0, 0xc1, 0xf5, 0x06, 0x6d, 0x90, 0xa4, 0x01,
+  0xa4, 0x06, 0x33, 0x14, 0xa0, 0x10, 0x0a, 0xa3, 0x40, 0x0a, 0xa5, 0x30,
+  0xc3, 0x00, 0x07, 0x7f, 0x60, 0x0a, 0xd5, 0x01, 0x1c, 0xc7, 0x71, 0x1c,
+  0xc7, 0x71, 0x1c, 0xc7, 0xb9, 0x81, 0x1b, 0x58, 0x74, 0xa0, 0x07, 0x96,
+  0x65, 0xe9, 0x01, 0xc7, 0x0a, 0xa6, 0x00, 0x1b, 0x7e, 0x61, 0x0f, 0xea,
+  0xc0, 0x0a, 0x32, 0x12, 0x98, 0xa0, 0x8b, 0xd8, 0xd8, 0xec, 0xda, 0x5c,
+  0xda, 0xde, 0xc8, 0xea, 0xd8, 0xca, 0x5c, 0xcc, 0xd8, 0xc2, 0xce, 0xe6,
+  0x46, 0x11, 0xea, 0xc0, 0x0e, 0x4e, 0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49,
+  0x23, 0x2b, 0x73, 0xa3, 0x1b, 0x25, 0xb8, 0x83, 0x5b, 0xc2, 0xd2, 0xe4,
+  0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2, 0xde, 0xdc, 0x46, 0x09, 0xf0, 0xe0,
+  0xa8, 0xb0, 0x34, 0x39, 0x17, 0xb6, 0x30, 0xb7, 0xb3, 0xba, 0xb0, 0xb3,
+  0xb2, 0x2f, 0xbb, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x51, 0x82, 0x3c,
+  0xb8, 0x29, 0x2c, 0x4d, 0xce, 0x65, 0xec, 0xad, 0x0d, 0x2e, 0x8d, 0xad,
+  0xec, 0xeb, 0x0d, 0x8e, 0x2e, 0xed, 0xcd, 0x6d, 0x6e, 0x94, 0x41, 0x0f,
+  0xf6, 0x80, 0x0f, 0x8e, 0x09, 0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b,
+  0x6b, 0x2b, 0x73, 0xa3, 0x1b, 0x25, 0x30, 0x05, 0x00, 0x00, 0x00, 0x00,
+  0xa9, 0x18, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x72, 0x28,
+  0x87, 0x77, 0x80, 0x07, 0x7a, 0x58, 0x70, 0x98, 0x43, 0x3d, 0xb8, 0xc3,
+  0x38, 0xb0, 0x43, 0x39, 0xd0, 0xc3, 0x82, 0xe6, 0x1c, 0xc6, 0xa1, 0x0d,
+  0xe8, 0x41, 0x1e, 0xc2, 0xc1, 0x1d, 0xe6, 0x21, 0x1d, 0xe8, 0x21, 0x1d,
+  0xde, 0xc1, 0x1d, 0x16, 0x34, 0xe3, 0x60, 0x0e, 0xe7, 0x50, 0x0f, 0xe1,
+  0x20, 0x0f, 0xe4, 0x40, 0x0f, 0xe1, 0x20, 0x0f, 0xe7, 0x50, 0x0e, 0xf4,
+  0xb0, 0x80, 0x81, 0x07, 0x79, 0x28, 0x87, 0x70, 0x60, 0x07, 0x76, 0x78,
+  0x87, 0x71, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x58, 0x70, 0x9c, 0xc3,
+  0x38, 0xb4, 0x01, 0x3b, 0xa4, 0x83, 0x3d, 0x94, 0xc3, 0x02, 0x6b, 0x1c,
+  0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c, 0xdc, 0x20, 0x1c, 0xe4, 0x61, 0x1c,
+  0xdc, 0x20, 0x1c, 0xe8, 0x81, 0x1e, 0xc2, 0x61, 0x1c, 0xd0, 0xa1, 0x1c,
+  0xc8, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0x61, 0xc1, 0x01, 0x0f, 0xf4,
+  0x20, 0x0f, 0xe1, 0x50, 0x0f, 0xf4, 0x80, 0x0e, 0x00, 0x00, 0x00, 0x00,
+  0xd1, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0xcc, 0x3c, 0xa4,
+  0x83, 0x3b, 0x9c, 0x03, 0x3b, 0x94, 0x03, 0x3d, 0xa0, 0x83, 0x3c, 0x94,
+  0x43, 0x38, 0x90, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00,
+  0x65, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0xe4, 0x6a, 0x80, 0xde, 0x08, 0x00, 0x81, 0x11,
+  0x00, 0x00, 0x00, 0x00, 0xf1, 0x30, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
+  0x22, 0x47, 0xc8, 0x90, 0x51, 0x22, 0x48, 0x4f, 0x00, 0x00, 0x00, 0x00,
+  0xcf, 0xc3, 0x59, 0x18, 0x26, 0x0d, 0x00, 0x00, 0x6f, 0x6d, 0x6e, 0x69,
+  0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x53,
+  0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x54, 0x42,
+  0x41, 0x41, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d,
+  0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x28, 0x42, 0x6c, 0x69, 0x74, 0x46,
+  0x72, 0x6f, 0x6d, 0x32, 0x44, 0x29, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c,
+  0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x61, 0x72,
+  0x67, 0x28, 0x32, 0x29, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61,
+  0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x73, 0x61, 0x6d, 0x70,
+  0x6c, 0x65, 0x72, 0x73, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61,
+  0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x74, 0x65, 0x78, 0x74,
+  0x75, 0x72, 0x65, 0x73, 0x5f, 0x5a, 0x54, 0x53, 0x31, 0x32, 0x53, 0x6f,
+  0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x69, 0x6e,
+  0x74, 0x00, 0x00, 0x00, 0x13, 0x04, 0x8b, 0x99, 0x20, 0x58, 0xcd, 0x04,
+  0xc1, 0x72, 0x26, 0x08, 0xd6, 0xb3, 0x42, 0xa0, 0x05, 0x55, 0x58, 0x31,
+  0xd4, 0x02, 0x2d, 0xac, 0xc2, 0x8a, 0xc1, 0x16, 0x68, 0x81, 0x15, 0x56,
+  0x0c, 0xb7, 0x40, 0x0b, 0xad, 0xb0, 0x21, 0x48, 0x85, 0x0d, 0x03, 0x2a,
+  0xe0, 0x02, 0x2c, 0x6c, 0x18, 0x72, 0x21, 0x17, 0x60, 0x61, 0x43, 0x50,
+  0x0b, 0x1b, 0x84, 0x5b, 0xb0, 0x85, 0x0d, 0xc3, 0x2b, 0xe4, 0x02, 0x2c,
+  0x6c, 0x18, 0xbc, 0x5c, 0x80, 0x85, 0x0d, 0x89, 0x2b, 0xe4, 0x02, 0x2c,
+  0xe4, 0x42, 0x2c, 0xf4, 0x82, 0x2c, 0xf8, 0xc2, 0x2c, 0x6c, 0x18, 0x7e,
+  0xa1, 0x17, 0x64, 0x01, 0x9b, 0x0c, 0x46, 0x33, 0x51, 0x20, 0xc8, 0x26,
+  0x03, 0xf2, 0x5c, 0x14, 0x08, 0x62, 0x01, 0x23, 0xfe, 0x16, 0x10, 0xe0,
+  0xbf, 0xc9, 0xc0, 0x4c, 0x1c, 0x05, 0x83, 0x8c, 0x18, 0x18, 0x44, 0x08,
+  0x82, 0x85, 0x7f, 0x48, 0x5f, 0x30, 0x62, 0xd0, 0x14, 0x21, 0x08, 0x06,
+  0x50, 0x18, 0x38, 0x0d, 0xc1, 0x2c, 0x4c, 0xa0, 0x70, 0xa3, 0x09, 0x01,
+  0x90, 0x41, 0x40, 0x0c, 0x09, 0x00, 0x00, 0x00, 0x5b, 0x8e, 0x20, 0xc8,
+  0x85, 0x43, 0x17, 0x90, 0x5d, 0xd8, 0x72, 0x0c, 0x41, 0x2e, 0x1c, 0xba,
+  0x80, 0xec, 0xc2, 0x96, 0xe3, 0x08, 0x7e, 0xe1, 0xd0, 0x05, 0x64, 0x17,
+  0xb6, 0x14, 0xc9, 0xb1, 0x0b, 0x88, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x32, 0x0e, 0x10, 0x22,
+  0x84, 0x00, 0xa4, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x65, 0x0c, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0x60,
+  0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x44, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x24, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x1b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x5d, 0x0c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0xe3,
+  0x00, 0x00, 0x00, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d,
+  0x32, 0x44, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+  0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x32, 0x64, 0x2e,
+  0x76, 0x34, 0x66, 0x33, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6e,
+  0x76, 0x65, 0x72, 0x74, 0x2e, 0x66, 0x2e, 0x66, 0x33, 0x32, 0x2e, 0x75,
+  0x2e, 0x69, 0x33, 0x32, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38,
+  0x61, 0x69, 0x72, 0x36, 0x34, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2d,
+  0x69, 0x6f, 0x73, 0x31, 0x33, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x73, 0x69,
+  0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom2D_metallib_len = 4224;
+const unsigned char BlitFrom2DArray_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x15, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x10, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x32, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79, 0x00, 0x54, 0x59,
+  0x50, 0x45, 0x01, 0x00, 0x01, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x54,
+  0x9d, 0x09, 0x99, 0x02, 0xf1, 0xc1, 0x26, 0x9f, 0xe1, 0x6b, 0xd4, 0xdb,
+  0x12, 0x7d, 0x68, 0xef, 0x7a, 0xbf, 0xd2, 0xe0, 0x0e, 0x03, 0x34, 0x46,
+  0xd1, 0x1d, 0x32, 0x1e, 0x93, 0x7c, 0x18, 0x4d, 0x44, 0x53, 0x5a, 0x08,
+  0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x46, 0x46,
+  0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x02, 0x00, 0x02,
+  0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x45, 0x4e, 0x44,
+  0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00,
+  0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00,
+  0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0x42, 0x43, 0xc0, 0xde, 0x35, 0x14, 0x00, 0x00, 0x03, 0x00, 0x00,
+  0x00, 0x62, 0x0c, 0x30, 0x24, 0x80, 0x10, 0x05, 0xc8, 0x14, 0x00, 0x00,
+  0x00, 0x21, 0x0c, 0x00, 0x00, 0x9e, 0x03, 0x00, 0x00, 0x0b, 0x02, 0x21,
+  0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23,
+  0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84,
+  0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45,
+  0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18,
+  0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88,
+  0xa5, 0x00, 0x19, 0x32, 0x42, 0x04, 0x49, 0x0e, 0x90, 0x91, 0x22, 0xc4,
+  0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46,
+  0x06, 0x51, 0x18, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24,
+  0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x58, 0x03, 0x40, 0x02, 0x2a, 0x22,
+  0x1c, 0xe0, 0x01, 0x1e, 0xe4, 0xe1, 0x1d, 0xf0, 0xa1, 0x0d, 0xcc, 0xa1,
+  0x1e, 0xdc, 0x61, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21,
+  0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80,
+  0x68, 0x87, 0x74, 0x70, 0x87, 0x36, 0x60, 0x87, 0x72, 0x38, 0x87, 0x70,
+  0x60, 0x87, 0x36, 0xb0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79,
+  0x68, 0x83, 0x7b, 0x48, 0x07, 0x72, 0xa0, 0x07, 0x74, 0x00, 0xe2, 0x40,
+  0x0e, 0xf0, 0x00, 0x18, 0xdc, 0xe1, 0x1d, 0xda, 0x40, 0x1c, 0xea, 0x21,
+  0x1d, 0xd8, 0x81, 0x1e, 0xd2, 0xc1, 0x1d, 0xe6, 0x01, 0x20, 0xdc, 0xe1,
+  0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00,
+  0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0,
+  0x1c, 0xd8, 0x21, 0x1d, 0xda, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72,
+  0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76,
+  0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72,
+  0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48, 0x87, 0x76, 0x68, 0x03, 0x77,
+  0x78, 0x07, 0x77, 0x68, 0x03, 0x76, 0x28, 0x87, 0x70, 0x30, 0x07, 0x80,
+  0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x20,
+  0x1d, 0xdc, 0xc1, 0x1c, 0xe6, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0,
+  0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72,
+  0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x70, 0x87, 0x70, 0x70, 0x87, 0x79,
+  0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74,
+  0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1,
+  0x0d, 0xe6, 0x21, 0x1d, 0xce, 0xc1, 0x1d, 0xca, 0x81, 0x1c, 0xda, 0x40,
+  0x1f, 0xca, 0x41, 0x1e, 0xde, 0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0, 0xa1,
+  0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a,
+  0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x03, 0x7a, 0x90, 0x87, 0x70,
+  0x80, 0x07, 0x78, 0x48, 0x07, 0x77, 0x38, 0x87, 0x36, 0x68, 0x87, 0x70,
+  0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0x62,
+  0x1e, 0xe8, 0x21, 0x1c, 0xc6, 0x61, 0x1d, 0xda, 0x00, 0x1e, 0xe4, 0xe1,
+  0x1d, 0xe8, 0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0x40,
+  0x1c, 0xea, 0xc1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xe6, 0x21,
+  0x1d, 0xf4, 0xa1, 0x1c, 0x00, 0x3c, 0x00, 0x88, 0x7a, 0x70, 0x87, 0x79,
+  0x08, 0x07, 0x73, 0x28, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76,
+  0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01,
+  0xd8, 0xe0, 0x09, 0x03, 0xb0, 0x00, 0x55, 0x90, 0x06, 0xd8, 0x10, 0x0e,
+  0xe9, 0x20, 0x0f, 0x6d, 0x20, 0x0e, 0xf5, 0x60, 0x0e, 0xe6, 0x50, 0x0e,
+  0xf2, 0xd0, 0x06, 0xee, 0xf0, 0x0e, 0x6d, 0x10, 0x0e, 0xec, 0x90, 0x0e,
+  0xe1, 0x30, 0x0f, 0xc0, 0x06, 0x63, 0x28, 0x80, 0x05, 0xa8, 0x36, 0x28,
+  0xc4, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x40, 0x1b, 0x00, 0x6b, 0x00, 0x48,
+  0x40, 0xb5, 0xc1, 0x28, 0x02, 0x60, 0x01, 0xaa, 0x0d, 0x86, 0x21, 0x00,
+  0x0b, 0x50, 0x6d, 0x30, 0x8e, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09,
+  0xa0, 0x36, 0x18, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50,
+  0x1b, 0x94, 0xe4, 0xff, 0xff, 0xff, 0xff, 0x07, 0xa0, 0x0d, 0x80, 0x35,
+  0x00, 0x24, 0xa0, 0x02, 0x00, 0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00,
+  0x00, 0x13, 0x86, 0x40, 0x18, 0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e,
+  0x09, 0x01, 0x32, 0x61, 0x48, 0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00,
+  0x00, 0x2a, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85,
+  0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90,
+  0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x74, 0x33,
+  0x00, 0xc3, 0x08, 0x04, 0x30, 0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70,
+  0x93, 0x34, 0x45, 0x94, 0x30, 0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12,
+  0x06, 0xe2, 0x34, 0x88, 0x10, 0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4d,
+  0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0xdf,
+  0x1e, 0x7e, 0x20, 0x8a, 0x00, 0xec, 0x9f, 0xc6, 0x08, 0x80, 0x41, 0x04,
+  0x23, 0xb8, 0x48, 0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x5f, 0x02, 0x98, 0x67,
+  0x21, 0xa2, 0x7f, 0x1a, 0x23, 0x00, 0x06, 0x11, 0x10, 0xa1, 0x18, 0x41,
+  0x84, 0x72, 0x12, 0xa9, 0x39, 0x02, 0xc4, 0x08, 0x81, 0xcd, 0x11, 0x04,
+  0xc3, 0x08, 0xc2, 0x50, 0x96, 0x76, 0x92, 0x18, 0xee, 0x39, 0x00, 0x06,
+  0xc1, 0x22, 0x80, 0x41, 0xb2, 0x08, 0x03, 0x10, 0x1d, 0x08, 0x48, 0x81,
+  0x31, 0x47, 0x00, 0x0a, 0x83, 0x08, 0x82, 0x30, 0x88, 0x00, 0x08, 0x83,
+  0x08, 0x83, 0x30, 0x02, 0x00, 0x13, 0xbe, 0x70, 0x48, 0x07, 0x79, 0xb0,
+  0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72, 0x68,
+  0x83, 0x74, 0x78, 0x87, 0x79, 0x88, 0x83, 0x39, 0x70, 0x03, 0x38, 0x70,
+  0x03, 0x38, 0x68, 0x83, 0x79, 0x48, 0x87, 0x76, 0xa8, 0x07, 0x76, 0x08,
+  0x07, 0x7a, 0x78, 0x07, 0x79, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06, 0xf0,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78,
+  0xd0, 0x06, 0xe9, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d,
+  0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71,
+  0x60, 0x07, 0x6d, 0x90, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x60, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x60, 0x0f, 0x74, 0x80, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x6d, 0x60, 0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07, 0x7a,
+  0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d,
+  0x60, 0x0f, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78,
+  0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x79,
+  0x20, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75,
+  0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72,
+  0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6,
+  0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a,
+  0x50, 0x07, 0x71, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07, 0x72,
+  0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x71,
+  0x00, 0x07, 0x72, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71,
+  0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x11, 0xc2, 0x90, 0xcf, 0xb6,
+  0x20, 0xd3, 0x17, 0x39, 0x8c, 0xdd, 0x69, 0x51, 0x04, 0x60, 0x43, 0x22,
+  0xe0, 0x51, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x60, 0x48, 0xf4, 0x84, 0x01, 0x04, 0x04, 0x80, 0x00, 0x00, 0x00, 0x20,
+  0x00, 0x00, 0x00, 0x00, 0x43, 0x22, 0x38, 0xb8, 0x24, 0x20, 0x00, 0x06,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x12, 0x9d, 0xc2, 0x45,
+  0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0xc4,
+  0x06, 0x81, 0xa2, 0xa0, 0x03, 0x00, 0x00, 0x59, 0x20, 0x0b, 0x00, 0x00,
+  0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26,
+  0x47, 0xc6, 0x04, 0x43, 0x1a, 0x45, 0x50, 0x02, 0x85, 0x30, 0x02, 0x50,
+  0x30, 0x05, 0x51, 0x20, 0x85, 0x52, 0x06, 0x84, 0x47, 0x00, 0x0a, 0xa2,
+  0x40, 0x0a, 0x85, 0xee, 0x58, 0x42, 0x24, 0x00, 0x00, 0xb1, 0x18, 0x00,
+  0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c,
+  0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80,
+  0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed,
+  0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d,
+  0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83,
+  0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78,
+  0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70,
+  0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc,
+  0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3,
+  0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c,
+  0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83,
+  0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03,
+  0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68,
+  0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60,
+  0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80,
+  0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98,
+  0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec,
+  0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d,
+  0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43,
+  0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03,
+  0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03,
+  0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70,
+  0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0,
+  0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4,
+  0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33,
+  0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c,
+  0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e,
+  0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50,
+  0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78,
+  0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33,
+  0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d,
+  0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06,
+  0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43,
+  0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3,
+  0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08,
+  0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec,
+  0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e,
+  0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19,
+  0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43,
+  0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03,
+  0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08,
+  0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed,
+  0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6,
+  0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3,
+  0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2,
+  0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d,
+  0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f,
+  0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83,
+  0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08,
+  0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5,
+  0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3,
+  0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90,
+  0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78,
+  0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
+  0x00, 0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c, 0x27, 0x46, 0x46, 0xc8,
+  0x11, 0x32, 0x64, 0xd4, 0xd4, 0x80, 0x0c, 0xfa, 0x09, 0x8b, 0xf2, 0x06,
+  0xc5, 0xc6, 0x91, 0x41, 0x14, 0x19, 0x12, 0xa5, 0x3c, 0x06, 0x33, 0x30,
+  0xd2, 0xa0, 0x3c, 0x12, 0x42, 0x25, 0x0c, 0x81, 0x14, 0x4c, 0x74, 0x31,
+  0xcc, 0xa2, 0x78, 0xcd, 0x72, 0x34, 0x00, 0x00, 0x00, 0x53, 0x44, 0x4b,
+  0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x77, 0x63, 0x68, 0x61,
+  0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20,
+  0x6d, 0x65, 0x74, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
+  0x6e, 0x20, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x20, 0x28,
+  0x6d, 0x65, 0x74, 0x61, 0x6c, 0x66, 0x65, 0x2d, 0x33, 0x32, 0x30, 0x32,
+  0x33, 0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65, 0x74, 0x61, 0x6c, 0x61, 0x69,
+  0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x64, 0x65,
+  0x6e, 0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
+  0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+  0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65,
+  0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
+  0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x62, 0x75,
+  0x66, 0x66, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x65,
+  0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x6e,
+  0x64, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x61, 0x69,
+  0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e,
+  0x61, 0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x61, 0x69, 0x72,
+  0x2e, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e,
+  0x70, 0x75, 0x74, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64,
+  0x28, 0x33, 0x74, 0x65, 0x78, 0x44, 0x76, 0x32, 0x5f, 0x66, 0x29, 0x61,
+  0x69, 0x72, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x69, 0x72,
+  0x2e, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65,
+  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72,
+  0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x78, 0x61, 0x69, 0x72,
+  0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x69, 0x72,
+  0x2e, 0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74,
+  0x69, 0x76, 0x65, 0x70, 0x6f, 0x73, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75,
+  0x66, 0x66, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66,
+  0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x6c,
+  0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65,
+  0x78, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x61, 0x64, 0x61, 0x69, 0x72,
+  0x2e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65,
+  0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x55, 0x56, 0x4c, 0x65, 0x66, 0x74, 0x54,
+  0x6f, 0x70, 0x55, 0x56, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f,
+  0x6e, 0x73, 0x75, 0x69, 0x6e, 0x74, 0x4d, 0x69, 0x70, 0x4c, 0x65, 0x76,
+  0x65, 0x6c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72,
+  0x4f, 0x72, 0x44, 0x65, 0x70, 0x74, 0x68, 0x61, 0x69, 0x72, 0x2e, 0x61,
+  0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65,
+  0x5f, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x53,
+  0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73,
+  0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x61,
+  0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x61, 0x69,
+  0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x78, 0x74,
+  0x75, 0x72, 0x65, 0x32, 0x64, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x3c,
+  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x2c, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c,
+  0x65, 0x3e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x65, 0x78, 0x74,
+  0x75, 0x72, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c,
+  0x65, 0x72, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x6f, 0x75,
+  0x72, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x00, 0x00,
+  0x00, 0xc4, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x82, 0x30,
+  0x10, 0x23, 0x08, 0x57, 0x34, 0x82, 0x30, 0x14, 0x23, 0x08, 0x83, 0x31,
+  0x82, 0x30, 0x1c, 0x23, 0x08, 0x0b, 0x30, 0x82, 0x30, 0x20, 0x23, 0x08,
+  0x43, 0x32, 0x82, 0x30, 0x28, 0x23, 0x08, 0xc3, 0x32, 0x82, 0x30, 0x30,
+  0x33, 0x0c, 0x6b, 0x10, 0xb0, 0xc1, 0x0c, 0x43, 0x1b, 0x08, 0x6e, 0x30,
+  0x43, 0x30, 0xcc, 0x30, 0xac, 0xc1, 0x1a, 0xbc, 0xc1, 0x0c, 0x04, 0xd1,
+  0x06, 0x6d, 0xf0, 0x06, 0x33, 0x04, 0xc5, 0x0c, 0x81, 0x31, 0x43, 0x70,
+  0xcc, 0x50, 0x20, 0x6f, 0xf0, 0x06, 0x89, 0x32, 0x43, 0xe0, 0x07, 0x33,
+  0x24, 0x6f, 0xb0, 0x30, 0x8d, 0x93, 0x3c, 0x50, 0x34, 0x03, 0xd2, 0x06,
+  0x52, 0x33, 0x25, 0x0a, 0x44, 0xcd, 0x40, 0xbd, 0x81, 0x1c, 0xbc, 0xc1,
+  0xa3, 0xc9, 0x81, 0x1c, 0xbc, 0xc1, 0xb3, 0xcd, 0x81, 0x1b, 0xbc, 0x01,
+  0xd7, 0xd1, 0x81, 0x1b, 0xbc, 0x81, 0xf7, 0xcd, 0x20, 0xad, 0x41, 0x65,
+  0xc5, 0xc1, 0xf5, 0x06, 0x6d, 0x80, 0x65, 0xa2, 0x00, 0x06, 0x71, 0x10,
+  0x06, 0x72, 0x90, 0x88, 0x01, 0x34, 0x06, 0x33, 0x28, 0x75, 0x40, 0x06,
+  0xd7, 0x1b, 0xb4, 0x41, 0x19, 0x24, 0x66, 0x00, 0x9d, 0xc1, 0x0c, 0x89,
+  0x1b, 0xa0, 0xc1, 0xf5, 0x06, 0x6d, 0x90, 0xa4, 0x01, 0xa4, 0x06, 0x33,
+  0x14, 0xa0, 0x10, 0x0a, 0xa3, 0x40, 0x0a, 0xa5, 0x30, 0xc3, 0x00, 0x07,
+  0x7f, 0x60, 0x0a, 0xd5, 0x01, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, 0x1c,
+  0xc7, 0xb9, 0x81, 0x1b, 0x58, 0x74, 0xa0, 0x07, 0x96, 0x65, 0xe9, 0x01,
+  0xc7, 0x0a, 0xa6, 0x00, 0x1b, 0x7e, 0x61, 0x0f, 0xea, 0xc0, 0x0a, 0x32,
+  0x12, 0x98, 0xa0, 0x8b, 0xd8, 0xd8, 0xec, 0xda, 0x5c, 0xda, 0xde, 0xc8,
+  0xea, 0xd8, 0xca, 0x5c, 0xcc, 0xd8, 0xc2, 0xce, 0xe6, 0x46, 0x11, 0xea,
+  0xc0, 0x0e, 0x4e, 0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73,
+  0xa3, 0x1b, 0x25, 0xb8, 0x83, 0x5b, 0xc2, 0xd2, 0xe4, 0x5c, 0xec, 0xca,
+  0xe4, 0xe6, 0xd2, 0xde, 0xdc, 0x46, 0x09, 0xf0, 0xe0, 0xa8, 0xb0, 0x34,
+  0x39, 0x17, 0xb6, 0x30, 0xb7, 0xb3, 0xba, 0xb0, 0xb3, 0xb2, 0x2f, 0xbb,
+  0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x51, 0x82, 0x3c, 0xb8, 0x29, 0x2c,
+  0x4d, 0xce, 0x65, 0xec, 0xad, 0x0d, 0x2e, 0x8d, 0xad, 0xec, 0xeb, 0x0d,
+  0x8e, 0x2e, 0xed, 0xcd, 0x6d, 0x6e, 0x94, 0x41, 0x0f, 0xf6, 0x80, 0x0f,
+  0x8e, 0x09, 0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73,
+  0xa3, 0x1b, 0x25, 0x30, 0x05, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x18, 0x00,
+  0x00, 0x25, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x72, 0x28, 0x87, 0x77, 0x80,
+  0x07, 0x7a, 0x58, 0x70, 0x98, 0x43, 0x3d, 0xb8, 0xc3, 0x38, 0xb0, 0x43,
+  0x39, 0xd0, 0xc3, 0x82, 0xe6, 0x1c, 0xc6, 0xa1, 0x0d, 0xe8, 0x41, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xe6, 0x21, 0x1d, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d,
+  0x16, 0x34, 0xe3, 0x60, 0x0e, 0xe7, 0x50, 0x0f, 0xe1, 0x20, 0x0f, 0xe4,
+  0x40, 0x0f, 0xe1, 0x20, 0x0f, 0xe7, 0x50, 0x0e, 0xf4, 0xb0, 0x80, 0x81,
+  0x07, 0x79, 0x28, 0x87, 0x70, 0x60, 0x07, 0x76, 0x78, 0x87, 0x71, 0x08,
+  0x07, 0x7a, 0x28, 0x07, 0x72, 0x58, 0x70, 0x9c, 0xc3, 0x38, 0xb4, 0x01,
+  0x3b, 0xa4, 0x83, 0x3d, 0x94, 0xc3, 0x02, 0x6b, 0x1c, 0xd8, 0x21, 0x1c,
+  0xdc, 0xe1, 0x1c, 0xdc, 0x20, 0x1c, 0xe4, 0x61, 0x1c, 0xdc, 0x20, 0x1c,
+  0xe8, 0x81, 0x1e, 0xc2, 0x61, 0x1c, 0xd0, 0xa1, 0x1c, 0xc8, 0x61, 0x1c,
+  0xc2, 0x81, 0x1d, 0xd8, 0x61, 0xc1, 0x01, 0x0f, 0xf4, 0x20, 0x0f, 0xe1,
+  0x50, 0x0f, 0xf4, 0x80, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x10, 0x00,
+  0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0xcc, 0x3c, 0xa4, 0x83, 0x3b, 0x9c,
+  0x03, 0x3b, 0x94, 0x03, 0x3d, 0xa0, 0x83, 0x3c, 0x94, 0x43, 0x38, 0x90,
+  0xc3, 0x01, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x70, 0x00, 0x00,
+  0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+  0x00, 0xe4, 0x6a, 0x80, 0xde, 0x08, 0x00, 0x81, 0x11, 0x00, 0x00, 0x00,
+  0x00, 0xf1, 0x30, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x22, 0x47, 0xc8,
+  0x90, 0x51, 0x22, 0x88, 0x58, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x13, 0x06,
+  0x16, 0x86, 0x49, 0x03, 0x00, 0x6f, 0x6d, 0x6e, 0x69, 0x70, 0x6f, 0x74,
+  0x65, 0x6e, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x53, 0x69, 0x6d, 0x70,
+  0x6c, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x54, 0x42, 0x41, 0x41, 0x61,
+  0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f,
+  0x70, 0x65, 0x73, 0x28, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d,
+  0x32, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79, 0x29, 0x61, 0x69, 0x72, 0x2d,
+  0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d,
+  0x61, 0x72, 0x67, 0x28, 0x32, 0x29, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c,
+  0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x73, 0x61,
+  0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c,
+  0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x74, 0x65,
+  0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5f, 0x5a, 0x54, 0x53, 0x31, 0x32,
+  0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e,
+  0x69, 0x6e, 0x74, 0x00, 0x00, 0x13, 0x04, 0xac, 0x99, 0x20, 0x60, 0xce,
+  0x04, 0x01, 0x7b, 0x26, 0x08, 0x18, 0xb4, 0x42, 0xa0, 0x05, 0x55, 0x58,
+  0x31, 0xd4, 0x02, 0x2d, 0xac, 0xc2, 0x8a, 0xc1, 0x16, 0x68, 0x81, 0x15,
+  0x56, 0x0c, 0xb7, 0x40, 0x0b, 0xad, 0xb0, 0x21, 0x48, 0x85, 0x0d, 0x03,
+  0x2a, 0xe0, 0x02, 0x2c, 0x6c, 0x18, 0x72, 0x21, 0x17, 0x60, 0x61, 0x43,
+  0x50, 0x0b, 0x1b, 0x84, 0x5b, 0xb0, 0x85, 0x0d, 0xc3, 0x2b, 0xe4, 0x02,
+  0x2c, 0x6c, 0x18, 0xbc, 0x5c, 0x80, 0x85, 0x0d, 0x89, 0x2b, 0xe4, 0x02,
+  0x2c, 0xe4, 0x42, 0x2c, 0xf4, 0x82, 0x2c, 0xf8, 0xc2, 0x2c, 0x6c, 0x18,
+  0x7e, 0xc1, 0x17, 0x66, 0x61, 0xc3, 0xf0, 0x0b, 0xbd, 0x20, 0x0b, 0x00,
+  0x00, 0x9b, 0x0c, 0x46, 0x33, 0x51, 0x20, 0xc8, 0x26, 0x03, 0xf2, 0x5c,
+  0x14, 0x08, 0x62, 0x01, 0x23, 0xfe, 0x16, 0x10, 0xe0, 0xbf, 0xc9, 0xc0,
+  0x4c, 0x14, 0x05, 0x60, 0x8c, 0x18, 0x14, 0x44, 0x08, 0x82, 0x01, 0xf5,
+  0x05, 0x9b, 0x0c, 0x8f, 0xf5, 0x51, 0x30, 0xc8, 0x88, 0x81, 0x41, 0x84,
+  0x20, 0x58, 0xf8, 0x87, 0x34, 0x06, 0xc1, 0x88, 0x81, 0x53, 0x84, 0x20,
+  0x18, 0x40, 0x65, 0x10, 0x41, 0x07, 0xf1, 0x38, 0x4f, 0xd0, 0x7c, 0xa3,
+  0x09, 0x01, 0x90, 0x41, 0x40, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
+  0x00, 0x5b, 0x8e, 0x20, 0xc8, 0x85, 0x43, 0x17, 0x90, 0x5d, 0xd8, 0x72,
+  0x0c, 0x41, 0x2e, 0x1c, 0xba, 0x80, 0xec, 0xc2, 0x96, 0xe3, 0x08, 0x7e,
+  0xe1, 0xd0, 0x05, 0x64, 0x17, 0xb6, 0x1c, 0x4a, 0x00, 0x0e, 0x87, 0x2e,
+  0x20, 0xbb, 0xb0, 0xa5, 0x60, 0x8e, 0x5d, 0x40, 0x74, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00,
+  0x00, 0x32, 0x0e, 0x10, 0x22, 0x84, 0x00, 0xae, 0x06, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x0c, 0x00, 0x00, 0x31, 0x00, 0x00,
+  0x00, 0x12, 0x03, 0x94, 0x78, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+  0x00, 0x5e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x58, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x24, 0x00,
+  0x00, 0x0f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
+  0x00, 0x21, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00,
+  0x00, 0x30, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+  0x00, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00,
+  0x00, 0x47, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00,
+  0x00, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x0c, 0x00, 0x00, 0x25, 0x00, 0x00,
+  0x00, 0x12, 0x03, 0x94, 0x25, 0x01, 0x00, 0x00, 0x00, 0x42, 0x6c, 0x69,
+  0x74, 0x46, 0x72, 0x6f, 0x6d, 0x32, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79,
+  0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x74,
+  0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x32, 0x64, 0x5f, 0x61, 0x72,
+  0x72, 0x61, 0x79, 0x2e, 0x76, 0x34, 0x66, 0x33, 0x32, 0x61, 0x69, 0x72,
+  0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2e, 0x66, 0x2e, 0x66,
+  0x33, 0x32, 0x2e, 0x75, 0x2e, 0x69, 0x33, 0x32, 0x61, 0x69, 0x72, 0x2e,
+  0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2e, 0x75, 0x2e, 0x69, 0x33,
+  0x32, 0x2e, 0x66, 0x2e, 0x66, 0x33, 0x32, 0x33, 0x32, 0x30, 0x32, 0x33,
+  0x2e, 0x39, 0x38, 0x61, 0x69, 0x72, 0x36, 0x34, 0x2d, 0x61, 0x70, 0x70,
+  0x6c, 0x65, 0x2d, 0x69, 0x6f, 0x73, 0x31, 0x33, 0x2e, 0x30, 0x2e, 0x30,
+  0x2d, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom2DArray_metallib_len = 4373;
+const unsigned char BlitFrom3D_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xb0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0b, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x33, 0x44, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01,
+  0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0xe4, 0xde, 0x19, 0x24, 0x29, 0x84,
+  0x73, 0x4a, 0xa8, 0x6c, 0xb6, 0x3f, 0x08, 0xfc, 0x66, 0xba, 0x11, 0xcd,
+  0x32, 0xb8, 0xeb, 0x7d, 0x9d, 0x59, 0xb3, 0x17, 0xa3, 0x8c, 0x03, 0xd3,
+  0x1a, 0x15, 0x4d, 0x44, 0x53, 0x5a, 0x08, 0x00, 0xc0, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45,
+  0x52, 0x53, 0x08, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54,
+  0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0xac, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde,
+  0x35, 0x14, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x0c, 0x30, 0x24,
+  0x80, 0x10, 0x05, 0xc8, 0x14, 0x00, 0x00, 0x00, 0x21, 0x0c, 0x00, 0x00,
+  0x98, 0x03, 0x00, 0x00, 0x0b, 0x02, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88,
+  0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42,
+  0x04, 0x49, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c,
+  0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00,
+  0x83, 0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff,
+  0x01, 0x58, 0x03, 0x40, 0x02, 0x2a, 0x22, 0x1c, 0xe0, 0x01, 0x1e, 0xe4,
+  0xe1, 0x1d, 0xf0, 0xa1, 0x0d, 0xcc, 0xa1, 0x1e, 0xdc, 0x61, 0x1c, 0xda,
+  0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x68, 0x87, 0x74, 0x70, 0x87,
+  0x36, 0x60, 0x87, 0x72, 0x38, 0x87, 0x70, 0x60, 0x87, 0x36, 0xb0, 0x87,
+  0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x83, 0x7b, 0x48, 0x07,
+  0x72, 0xa0, 0x07, 0x74, 0x00, 0xe2, 0x40, 0x0e, 0xf0, 0x00, 0x18, 0xdc,
+  0xe1, 0x1d, 0xda, 0x40, 0x1c, 0xea, 0x21, 0x1d, 0xd8, 0x81, 0x1e, 0xd2,
+  0xc1, 0x1d, 0xe6, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4,
+  0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc,
+  0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87,
+  0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07,
+  0x76, 0x48, 0x87, 0x76, 0x68, 0x03, 0x77, 0x78, 0x07, 0x77, 0x68, 0x03,
+  0x76, 0x28, 0x87, 0x70, 0x30, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x20, 0x1d, 0xdc, 0xc1, 0x1c, 0xe6,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x70, 0x87, 0x70, 0x70, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xce,
+  0xc1, 0x1d, 0xca, 0x81, 0x1c, 0xda, 0x40, 0x1f, 0xca, 0x41, 0x1e, 0xde,
+  0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8,
+  0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87,
+  0x77, 0x68, 0x03, 0x7a, 0x90, 0x87, 0x70, 0x80, 0x07, 0x78, 0x48, 0x07,
+  0x77, 0x38, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8,
+  0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0x62, 0x1e, 0xe8, 0x21, 0x1c, 0xc6,
+  0x61, 0x1d, 0xda, 0x00, 0x1e, 0xe4, 0xe1, 0x1d, 0xe8, 0xa1, 0x1c, 0xc6,
+  0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0x40, 0x1c, 0xea, 0xc1, 0x1c, 0xcc,
+  0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xf4, 0xa1, 0x1c, 0x00,
+  0x3c, 0x00, 0x88, 0x7a, 0x70, 0x87, 0x79, 0x08, 0x07, 0x73, 0x28, 0x87,
+  0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07,
+  0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0xd8, 0xe0, 0x09, 0x03, 0xb0,
+  0x00, 0x55, 0x90, 0x06, 0xd8, 0x10, 0x0e, 0xe9, 0x20, 0x0f, 0x6d, 0x20,
+  0x0e, 0xf5, 0x60, 0x0e, 0xe6, 0x50, 0x0e, 0xf2, 0xd0, 0x06, 0xee, 0xf0,
+  0x0e, 0x6d, 0x10, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0xc0, 0x06,
+  0x63, 0x28, 0x80, 0x05, 0xa8, 0x36, 0x28, 0xc4, 0xff, 0xff, 0xff, 0xff,
+  0x0f, 0x40, 0x1b, 0x00, 0x6b, 0x00, 0x48, 0x40, 0xb5, 0xc1, 0x28, 0x02,
+  0x60, 0x01, 0xaa, 0x0d, 0x86, 0x21, 0x00, 0x0b, 0x50, 0x6d, 0x30, 0x8e,
+  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa0, 0x36, 0x18, 0xc8, 0xff,
+  0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b, 0x94, 0xe4, 0xff, 0xff,
+  0xff, 0xff, 0x07, 0xa0, 0x0d, 0x80, 0x35, 0x00, 0x24, 0xa0, 0x02, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18,
+  0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48,
+  0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x70, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30,
+  0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30,
+  0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10,
+  0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4a, 0x9a, 0x22, 0x4a, 0x98, 0xfc,
+  0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0xff, 0x1e, 0xfe, 0x69, 0x8c, 0x00,
+  0x18, 0x44, 0x30, 0x82, 0x8b, 0xa4, 0x29, 0xa2, 0x84, 0xc9, 0xff, 0x25,
+  0x80, 0x79, 0x16, 0x22, 0xfa, 0xa7, 0x31, 0x02, 0x60, 0x10, 0x01, 0x11,
+  0x8a, 0x11, 0x44, 0x28, 0x27, 0x91, 0x9a, 0x23, 0x40, 0x8c, 0x10, 0xd8,
+  0x30, 0xc2, 0x00, 0xcc, 0x11, 0x04, 0xc3, 0x08, 0xc3, 0x50, 0x94, 0x76,
+  0x92, 0x7b, 0xf0, 0x01, 0x30, 0x28, 0x16, 0x01, 0x0c, 0x9a, 0x03, 0x01,
+  0x29, 0x30, 0xe6, 0x08, 0x40, 0x61, 0x10, 0x41, 0x10, 0x06, 0x11, 0x00,
+  0x61, 0x10, 0x61, 0x10, 0x46, 0x00, 0x00, 0x00, 0x13, 0xbe, 0x70, 0x48,
+  0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60,
+  0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0x88, 0x83, 0x39, 0x70,
+  0x03, 0x38, 0x70, 0x03, 0x38, 0x68, 0x83, 0x79, 0x48, 0x87, 0x76, 0xa8,
+  0x07, 0x76, 0x08, 0x07, 0x7a, 0x78, 0x07, 0x79, 0xd8, 0x70, 0x1b, 0xe5,
+  0xd0, 0x06, 0xf0, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x78,
+  0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x7a,
+  0x80, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x90, 0x0e, 0x73, 0x20, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76,
+  0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d,
+  0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x60, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x60, 0x07, 0x7a,
+  0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72,
+  0x40, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x60, 0x0f, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x60, 0x0f, 0x74, 0x80, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x79,
+  0x60, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72,
+  0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71,
+  0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6,
+  0x10, 0x07, 0x79, 0x20, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a,
+  0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x50, 0x07, 0x76,
+  0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76,
+  0xd0, 0x06, 0xf6, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71,
+  0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x71,
+  0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74,
+  0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78,
+  0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x11, 0xc2,
+  0x90, 0xca, 0xb6, 0x20, 0xd3, 0x17, 0x39, 0xcc, 0xdd, 0x0d, 0x89, 0x00,
+  0x45, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80,
+  0x21, 0x91, 0xb2, 0x45, 0x40, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00,
+  0x00, 0x00, 0x30, 0x24, 0x2a, 0x83, 0x6b, 0x02, 0x02, 0x60, 0x00, 0x00,
+  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x89, 0x0d, 0x02, 0x45, 0x35, 0x07,
+  0x00, 0x00, 0xb2, 0x40, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a,
+  0x45, 0x50, 0x02, 0x85, 0x30, 0x02, 0x50, 0x30, 0x05, 0x51, 0x20, 0x85,
+  0x52, 0x06, 0x74, 0x47, 0x00, 0x0a, 0xa2, 0x40, 0x0a, 0x85, 0xec, 0x58,
+  0x42, 0x24, 0x00, 0x00, 0xb1, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
+  0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88,
+  0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73,
+  0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e,
+  0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30,
+  0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8,
+  0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b,
+  0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76,
+  0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e,
+  0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e,
+  0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61,
+  0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4,
+  0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37,
+  0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76,
+  0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71,
+  0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e,
+  0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61,
+  0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8,
+  0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc,
+  0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7,
+  0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78,
+  0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f,
+  0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f,
+  0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1,
+  0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0,
+  0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0,
+  0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b,
+  0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c,
+  0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61,
+  0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1,
+  0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc,
+  0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4,
+  0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79,
+  0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72,
+  0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e,
+  0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1,
+  0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4,
+  0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8,
+  0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71,
+  0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19,
+  0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f,
+  0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e,
+  0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e,
+  0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81,
+  0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21,
+  0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc,
+  0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70,
+  0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77,
+  0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e,
+  0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e,
+  0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a,
+  0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73,
+  0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x79, 0x20, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x32, 0x9a, 0x08, 0x14,
+  0x02, 0x85, 0x8c, 0x27, 0x46, 0x46, 0xc8, 0x11, 0x32, 0x64, 0xd4, 0xd4,
+  0x80, 0x0c, 0xee, 0x09, 0x8b, 0xf2, 0x06, 0xc5, 0xc6, 0x91, 0x41, 0x14,
+  0x19, 0x12, 0xa5, 0x3c, 0x06, 0x33, 0x30, 0xd2, 0xa0, 0x3c, 0x12, 0x42,
+  0x25, 0x0c, 0x81, 0x14, 0x4c, 0x74, 0x31, 0xcc, 0xa2, 0x60, 0xcd, 0x72,
+  0x34, 0x00, 0x00, 0x00, 0x53, 0x44, 0x4b, 0x20, 0x56, 0x65, 0x72, 0x73,
+  0x69, 0x6f, 0x6e, 0x77, 0x63, 0x68, 0x61, 0x72, 0x5f, 0x73, 0x69, 0x7a,
+  0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c,
+  0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x32, 0x30,
+  0x32, 0x33, 0x2e, 0x39, 0x38, 0x20, 0x28, 0x6d, 0x65, 0x74, 0x61, 0x6c,
+  0x66, 0x65, 0x2d, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x29,
+  0x4d, 0x65, 0x74, 0x61, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
+  0x70, 0x69, 0x6c, 0x65, 0x2e, 0x64, 0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x73,
+  0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e,
+  0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74,
+  0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e,
+  0x66, 0x72, 0x61, 0x6d, 0x65, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f,
+  0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x74,
+  0x61, 0x72, 0x67, 0x65, 0x74, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67,
+  0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x66, 0x6c,
+  0x6f, 0x61, 0x74, 0x34, 0x61, 0x69, 0x72, 0x2e, 0x66, 0x72, 0x61, 0x67,
+  0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x67, 0x65,
+  0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x28, 0x33, 0x74, 0x65, 0x78,
+  0x44, 0x76, 0x32, 0x5f, 0x66, 0x29, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x65,
+  0x6e, 0x74, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x70, 0x65, 0x72, 0x73,
+  0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d,
+  0x65, 0x74, 0x65, 0x78, 0x61, 0x69, 0x72, 0x2e, 0x70, 0x6f, 0x73, 0x69,
+  0x74, 0x69, 0x6f, 0x6e, 0x61, 0x69, 0x72, 0x2e, 0x6e, 0x6f, 0x5f, 0x70,
+  0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x70, 0x6f,
+  0x73, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x61,
+  0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69,
+  0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+  0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x61, 0x69, 0x72, 0x2e,
+  0x72, 0x65, 0x61, 0x64, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x74, 0x72, 0x75,
+  0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f,
+  0x55, 0x56, 0x4c, 0x65, 0x66, 0x74, 0x54, 0x6f, 0x70, 0x55, 0x56, 0x44,
+  0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x75, 0x69, 0x6e,
+  0x74, 0x4d, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x66, 0x6c, 0x6f,
+  0x61, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x4f, 0x72, 0x44, 0x65, 0x70,
+  0x74, 0x68, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79,
+  0x70, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x61,
+  0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x67,
+  0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
+  0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+  0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x61, 0x69, 0x72, 0x2e, 0x74, 0x65,
+  0x78, 0x74, 0x75, 0x72, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d,
+  0x70, 0x6c, 0x65, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x33, 0x64,
+  0x3c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x2c, 0x20, 0x73, 0x61, 0x6d, 0x70,
+  0x6c, 0x65, 0x3e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x65, 0x78,
+  0x74, 0x75, 0x72, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70,
+  0x6c, 0x65, 0x72, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x6f,
+  0x75, 0x72, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x00,
+  0xc4, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x82, 0x30, 0x0c,
+  0x23, 0x08, 0x16, 0x34, 0x82, 0x30, 0x10, 0x23, 0x08, 0x43, 0x31, 0x82,
+  0x30, 0x18, 0x23, 0x08, 0x0b, 0x30, 0x82, 0x30, 0x1c, 0x23, 0x08, 0x03,
+  0x32, 0x82, 0x30, 0x24, 0x23, 0x08, 0x83, 0x32, 0x82, 0x30, 0x2c, 0x33,
+  0x0c, 0x6b, 0x10, 0xb0, 0xc1, 0x0c, 0x43, 0x1b, 0x08, 0x6e, 0x30, 0x43,
+  0x30, 0xcc, 0x30, 0xac, 0xc1, 0x1a, 0xbc, 0xc1, 0x0c, 0x04, 0xd1, 0x06,
+  0x6d, 0xf0, 0x06, 0x33, 0x04, 0xc5, 0x0c, 0x81, 0x31, 0x43, 0x70, 0xcc,
+  0x50, 0x20, 0x6f, 0xf0, 0x06, 0x89, 0x32, 0x43, 0xe0, 0x07, 0x33, 0x24,
+  0x6f, 0xb0, 0x30, 0x8d, 0x93, 0x3c, 0x50, 0x34, 0x03, 0xd2, 0x06, 0x52,
+  0x33, 0x25, 0x0a, 0x44, 0xcd, 0x40, 0xbd, 0x81, 0x1c, 0xbc, 0xc1, 0xa3,
+  0xc9, 0x81, 0x1c, 0xbc, 0xc1, 0xb3, 0xcd, 0x81, 0x1b, 0xbc, 0x01, 0xd7,
+  0xd1, 0x81, 0x1b, 0xbc, 0x81, 0xf7, 0xcd, 0x20, 0xad, 0x41, 0x65, 0xc5,
+  0xc1, 0xf5, 0x06, 0x6d, 0x80, 0x65, 0xa2, 0x00, 0x06, 0x71, 0x10, 0x06,
+  0x72, 0x90, 0x88, 0x01, 0x34, 0x06, 0x33, 0x28, 0x75, 0x40, 0x06, 0xd7,
+  0x1b, 0xb4, 0x41, 0x19, 0x24, 0x66, 0x00, 0x9d, 0xc1, 0x0c, 0x89, 0x1b,
+  0xa0, 0xc1, 0xf5, 0x06, 0x6d, 0x90, 0xa4, 0x01, 0xa4, 0x06, 0x33, 0x14,
+  0xa0, 0x10, 0x0a, 0xa3, 0x40, 0x0a, 0xa5, 0x30, 0xc3, 0x00, 0x07, 0x7f,
+  0x60, 0x0a, 0xd5, 0x01, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, 0x1c, 0xc7,
+  0xb9, 0x81, 0x1b, 0x58, 0x74, 0xa0, 0x07, 0x96, 0x65, 0xe9, 0x01, 0xc7,
+  0x0a, 0xa6, 0x00, 0x1b, 0x7e, 0x61, 0x0f, 0xea, 0xc0, 0x0a, 0x32, 0x12,
+  0x98, 0xa0, 0x8b, 0xd8, 0xd8, 0xec, 0xda, 0x5c, 0xda, 0xde, 0xc8, 0xea,
+  0xd8, 0xca, 0x5c, 0xcc, 0xd8, 0xc2, 0xce, 0xe6, 0x46, 0x11, 0xea, 0xc0,
+  0x0e, 0x4e, 0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3,
+  0x1b, 0x25, 0xb8, 0x83, 0x5b, 0xc2, 0xd2, 0xe4, 0x5c, 0xec, 0xca, 0xe4,
+  0xe6, 0xd2, 0xde, 0xdc, 0x46, 0x09, 0xf0, 0xe0, 0xa8, 0xb0, 0x34, 0x39,
+  0x17, 0xb6, 0x30, 0xb7, 0xb3, 0xba, 0xb0, 0xb3, 0xb2, 0x2f, 0xbb, 0x32,
+  0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x51, 0x82, 0x3c, 0xb8, 0x29, 0x2c, 0x4d,
+  0xce, 0x65, 0xec, 0xad, 0x0d, 0x2e, 0x8d, 0xad, 0xec, 0xeb, 0x0d, 0x8e,
+  0x2e, 0xed, 0xcd, 0x6d, 0x6e, 0x94, 0x41, 0x0f, 0xf6, 0x80, 0x0f, 0x8e,
+  0x09, 0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3,
+  0x1b, 0x25, 0x30, 0x05, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x18, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x72, 0x28, 0x87, 0x77, 0x80, 0x07,
+  0x7a, 0x58, 0x70, 0x98, 0x43, 0x3d, 0xb8, 0xc3, 0x38, 0xb0, 0x43, 0x39,
+  0xd0, 0xc3, 0x82, 0xe6, 0x1c, 0xc6, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2,
+  0xc1, 0x1d, 0xe6, 0x21, 0x1d, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x16,
+  0x34, 0xe3, 0x60, 0x0e, 0xe7, 0x50, 0x0f, 0xe1, 0x20, 0x0f, 0xe4, 0x40,
+  0x0f, 0xe1, 0x20, 0x0f, 0xe7, 0x50, 0x0e, 0xf4, 0xb0, 0x80, 0x81, 0x07,
+  0x79, 0x28, 0x87, 0x70, 0x60, 0x07, 0x76, 0x78, 0x87, 0x71, 0x08, 0x07,
+  0x7a, 0x28, 0x07, 0x72, 0x58, 0x70, 0x9c, 0xc3, 0x38, 0xb4, 0x01, 0x3b,
+  0xa4, 0x83, 0x3d, 0x94, 0xc3, 0x02, 0x6b, 0x1c, 0xd8, 0x21, 0x1c, 0xdc,
+  0xe1, 0x1c, 0xdc, 0x20, 0x1c, 0xe4, 0x61, 0x1c, 0xdc, 0x20, 0x1c, 0xe8,
+  0x81, 0x1e, 0xc2, 0x61, 0x1c, 0xd0, 0xa1, 0x1c, 0xc8, 0x61, 0x1c, 0xc2,
+  0x81, 0x1d, 0xd8, 0x61, 0xc1, 0x01, 0x0f, 0xf4, 0x20, 0x0f, 0xe1, 0x50,
+  0x0f, 0xf4, 0x80, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x10, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x07, 0xcc, 0x3c, 0xa4, 0x83, 0x3b, 0x9c, 0x03,
+  0x3b, 0x94, 0x03, 0x3d, 0xa0, 0x83, 0x3c, 0x94, 0x43, 0x38, 0x90, 0xc3,
+  0x01, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x34, 0x66, 0x00, 0xe8, 0xd5, 0x00, 0xc1, 0x39, 0x06, 0x83, 0xb0, 0x46,
+  0x00, 0xe8, 0x16, 0x01, 0x81, 0x11, 0x00, 0x12, 0x33, 0x00, 0x00, 0x00,
+  0xf1, 0x30, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x22, 0x47, 0xc8, 0x90,
+  0x51, 0x22, 0x48, 0x4f, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xc3, 0x59, 0x18,
+  0x26, 0x0d, 0x00, 0x00, 0x6f, 0x6d, 0x6e, 0x69, 0x70, 0x6f, 0x74, 0x65,
+  0x6e, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x53, 0x69, 0x6d, 0x70, 0x6c,
+  0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x54, 0x42, 0x41, 0x41, 0x61, 0x69,
+  0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70,
+  0x65, 0x73, 0x28, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x33,
+  0x44, 0x29, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d,
+  0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x61, 0x72, 0x67, 0x28, 0x32, 0x29,
+  0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63,
+  0x6f, 0x70, 0x65, 0x2d, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73,
+  0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63,
+  0x6f, 0x70, 0x65, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73,
+  0x5f, 0x5a, 0x54, 0x53, 0x31, 0x32, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
+  0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x74, 0x00, 0x00, 0x00,
+  0x13, 0x84, 0x8b, 0x99, 0x20, 0x5c, 0xcd, 0x04, 0xe1, 0x72, 0x26, 0x08,
+  0xd7, 0xb3, 0x42, 0xa0, 0x05, 0x55, 0x58, 0x31, 0xd4, 0x02, 0x2d, 0xac,
+  0xc2, 0x8a, 0xc1, 0x16, 0x68, 0x81, 0x15, 0x56, 0x0c, 0xb7, 0x40, 0x0b,
+  0xad, 0xb0, 0x21, 0x48, 0x85, 0x0d, 0x03, 0x2a, 0xe0, 0x02, 0x2c, 0x6c,
+  0x18, 0x72, 0x21, 0x17, 0x60, 0x61, 0x43, 0x50, 0x0b, 0x1b, 0x84, 0x5b,
+  0xb0, 0x85, 0x0d, 0xc3, 0x2b, 0xe4, 0x02, 0x2c, 0x6c, 0x18, 0xbc, 0x5c,
+  0x80, 0x85, 0x0d, 0x89, 0x2b, 0xe4, 0x02, 0x2c, 0xe4, 0x42, 0x2c, 0xf4,
+  0x82, 0x2c, 0xf8, 0xc2, 0x2c, 0x6c, 0x18, 0x7e, 0xc1, 0x17, 0x66, 0x61,
+  0xc3, 0xf0, 0x0b, 0xbd, 0x20, 0x0b, 0x00, 0x00, 0x9b, 0x0c, 0x4a, 0x74,
+  0x51, 0x20, 0xc8, 0x26, 0x03, 0x33, 0x6d, 0x14, 0x08, 0x62, 0x01, 0x24,
+  0xfe, 0x16, 0x10, 0xe0, 0x3f, 0xc8, 0x10, 0x1c, 0xcb, 0x26, 0x43, 0x84,
+  0x65, 0x14, 0x80, 0x31, 0xc7, 0x30, 0x04, 0xcc, 0x26, 0x03, 0xb5, 0x91,
+  0x01, 0x05, 0x83, 0x8c, 0x18, 0x18, 0x44, 0x08, 0x82, 0x85, 0x7f, 0x4c,
+  0x67, 0x10, 0x8c, 0x18, 0x34, 0x45, 0x08, 0x82, 0x41, 0x94, 0x06, 0x56,
+  0x45, 0x4c, 0xd1, 0x14, 0x3c, 0x64, 0x30, 0x9a, 0x10, 0x00, 0x19, 0x04,
+  0xc4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x5b, 0x8e, 0x20, 0xc8,
+  0x85, 0x43, 0x17, 0x90, 0x5d, 0xd8, 0x72, 0x0c, 0x41, 0x2e, 0x1c, 0xba,
+  0x80, 0xec, 0xc2, 0x96, 0x03, 0x09, 0x7e, 0xe1, 0xd0, 0x05, 0x64, 0x17,
+  0xb6, 0x1c, 0x4b, 0x00, 0x0e, 0x87, 0x2e, 0x20, 0xbb, 0xb0, 0xa5, 0x68,
+  0x8e, 0x5d, 0x40, 0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x32, 0x0e, 0x10, 0x22,
+  0x84, 0x00, 0xa6, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x65, 0x0c, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0x60,
+  0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x44, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x24, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x1b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x5d, 0x0c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0xe3,
+  0x00, 0x00, 0x00, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d,
+  0x33, 0x44, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+  0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x33, 0x64, 0x2e,
+  0x76, 0x34, 0x66, 0x33, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6e,
+  0x76, 0x65, 0x72, 0x74, 0x2e, 0x66, 0x2e, 0x66, 0x33, 0x32, 0x2e, 0x75,
+  0x2e, 0x69, 0x33, 0x32, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38,
+  0x61, 0x69, 0x72, 0x36, 0x34, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2d,
+  0x69, 0x6f, 0x73, 0x31, 0x33, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x73, 0x69,
+  0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom3D_metallib_len = 4272;
+const unsigned char BlitFromCube_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0d, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x43, 0x75, 0x62, 0x65, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01,
+  0x00, 0x01, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x32, 0xbf, 0xae, 0x86,
+  0xd6, 0xb8, 0x7b, 0x2e, 0x00, 0x92, 0x3e, 0x24, 0xf3, 0xaa, 0xc1, 0x76,
+  0x58, 0x9e, 0x55, 0xe6, 0x00, 0xdc, 0xdd, 0x0a, 0x70, 0xe0, 0x87, 0xa9,
+  0xdd, 0xc5, 0x24, 0x4c, 0x4d, 0x44, 0x53, 0x5a, 0x08, 0x00, 0x10, 0x11,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00,
+  0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00,
+  0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00,
+  0x00, 0x00, 0xf0, 0x10, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43,
+  0xc0, 0xde, 0x35, 0x14, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x0c,
+  0x30, 0x24, 0x80, 0x10, 0x05, 0xc8, 0x14, 0x00, 0x00, 0x00, 0x21, 0x0c,
+  0x00, 0x00, 0xdc, 0x03, 0x00, 0x00, 0x0b, 0x02, 0x21, 0x00, 0x02, 0x00,
+  0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8,
+  0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05,
+  0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92,
+  0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32,
+  0x52, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19,
+  0x32, 0x42, 0x04, 0x49, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51,
+  0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18,
+  0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff,
+  0xff, 0xff, 0x01, 0x58, 0x03, 0x40, 0x02, 0x2a, 0x22, 0x1c, 0xe0, 0x01,
+  0x1e, 0xe4, 0xe1, 0x1d, 0xf0, 0xa1, 0x0d, 0xcc, 0xa1, 0x1e, 0xdc, 0x61,
+  0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01,
+  0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x68, 0x87, 0x74,
+  0x70, 0x87, 0x36, 0x60, 0x87, 0x72, 0x38, 0x87, 0x70, 0x60, 0x87, 0x36,
+  0xb0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x83, 0x7b,
+  0x48, 0x07, 0x72, 0xa0, 0x07, 0x74, 0x00, 0xe2, 0x40, 0x0e, 0xf0, 0x00,
+  0x18, 0xdc, 0xe1, 0x1d, 0xda, 0x40, 0x1c, 0xea, 0x21, 0x1d, 0xd8, 0x81,
+  0x1e, 0xd2, 0xc1, 0x1d, 0xe6, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0,
+  0x1c, 0xe4, 0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21,
+  0x1d, 0xdc, 0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21,
+  0x1d, 0xda, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77,
+  0x78, 0x87, 0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36,
+  0x80, 0x87, 0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36,
+  0x28, 0x07, 0x76, 0x48, 0x87, 0x76, 0x68, 0x03, 0x77, 0x78, 0x07, 0x77,
+  0x68, 0x03, 0x76, 0x28, 0x87, 0x70, 0x30, 0x07, 0x80, 0x1e, 0xe4, 0xa1,
+  0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x20, 0x1d, 0xdc, 0xc1,
+  0x1c, 0xe6, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81,
+  0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77,
+  0x78, 0x87, 0x36, 0x70, 0x87, 0x70, 0x70, 0x87, 0x79, 0x68, 0x03, 0x73,
+  0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41,
+  0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe6, 0x21,
+  0x1d, 0xce, 0xc1, 0x1d, 0xca, 0x81, 0x1c, 0xda, 0x40, 0x1f, 0xca, 0x41,
+  0x1e, 0xde, 0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21,
+  0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80,
+  0x70, 0x87, 0x77, 0x68, 0x03, 0x7a, 0x90, 0x87, 0x70, 0x80, 0x07, 0x78,
+  0x48, 0x07, 0x77, 0x38, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74,
+  0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0x62, 0x1e, 0xe8, 0x21,
+  0x1c, 0xc6, 0x61, 0x1d, 0xda, 0x00, 0x1e, 0xe4, 0xe1, 0x1d, 0xe8, 0xa1,
+  0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0x40, 0x1c, 0xea, 0xc1,
+  0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xf4, 0xa1,
+  0x1c, 0x00, 0x3c, 0x00, 0x88, 0x7a, 0x70, 0x87, 0x79, 0x08, 0x07, 0x73,
+  0x28, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a,
+  0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0xd8, 0xe0, 0x09,
+  0x03, 0xb0, 0x00, 0x55, 0x90, 0x06, 0xd8, 0x10, 0x0e, 0xe9, 0x20, 0x0f,
+  0x6d, 0x20, 0x0e, 0xf5, 0x60, 0x0e, 0xe6, 0x50, 0x0e, 0xf2, 0xd0, 0x06,
+  0xee, 0xf0, 0x0e, 0x6d, 0x10, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f,
+  0xc0, 0x06, 0x63, 0x28, 0x80, 0x05, 0xa8, 0x36, 0x28, 0xc4, 0xff, 0xff,
+  0xff, 0xff, 0x0f, 0x40, 0x1b, 0x00, 0x6b, 0x00, 0x48, 0x40, 0xb5, 0xc1,
+  0x28, 0x02, 0x60, 0x01, 0xaa, 0x0d, 0x86, 0x21, 0x00, 0x0b, 0x50, 0x6d,
+  0x30, 0x8e, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa0, 0x36, 0x18,
+  0xc8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b, 0x94, 0xe4,
+  0xff, 0xff, 0xff, 0xff, 0x07, 0xa0, 0x0d, 0x80, 0x35, 0x00, 0x24, 0xa0,
+  0x02, 0x00, 0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86,
+  0x40, 0x18, 0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32,
+  0x61, 0x48, 0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x2b, 0x00,
+  0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22,
+  0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c,
+  0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x7c, 0x33, 0x00, 0xc3, 0x08,
+  0x04, 0x30, 0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45,
+  0x94, 0x30, 0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34,
+  0x88, 0x10, 0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4b, 0x9a, 0x22, 0x4a,
+  0x98, 0xfc, 0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0x5f, 0xa0, 0x02, 0xe2,
+  0x9f, 0xc6, 0x08, 0x80, 0x41, 0x04, 0x23, 0xb8, 0x48, 0x9a, 0x22, 0x4a,
+  0x98, 0xfc, 0x5f, 0x02, 0x98, 0x67, 0x21, 0xa2, 0x7f, 0x1a, 0x23, 0x00,
+  0x06, 0x11, 0x10, 0xa1, 0x18, 0x41, 0x84, 0x72, 0x12, 0xa9, 0x39, 0x02,
+  0xc4, 0x08, 0x81, 0x0d, 0x23, 0x0c, 0xc0, 0x1c, 0x41, 0x50, 0x90, 0x76,
+  0x92, 0x7b, 0x00, 0x0c, 0x82, 0x45, 0x00, 0x83, 0x64, 0x11, 0x06, 0x20,
+  0x3a, 0x10, 0x90, 0x02, 0x63, 0x8e, 0x00, 0x14, 0x06, 0x11, 0x04, 0x61,
+  0x10, 0x01, 0x10, 0xa6, 0x00, 0x46, 0x00, 0x86, 0x11, 0x86, 0x61, 0x10,
+  0x61, 0x10, 0x00, 0x00, 0x00, 0x00, 0x13, 0xbe, 0x70, 0x48, 0x07, 0x79,
+  0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72,
+  0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0x88, 0x83, 0x39, 0x70, 0x03, 0x38,
+  0x70, 0x03, 0x38, 0x68, 0x83, 0x79, 0x48, 0x87, 0x76, 0xa8, 0x07, 0x76,
+  0x08, 0x07, 0x7a, 0x78, 0x07, 0x79, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06,
+  0xf0, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07,
+  0x78, 0xd0, 0x06, 0xe9, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07,
+  0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x6d, 0x90, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x60, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x60, 0x0f, 0x74, 0x80, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07,
+  0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07,
+  0x6d, 0x60, 0x0f, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07,
+  0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07,
+  0x79, 0x20, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07,
+  0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07,
+  0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06,
+  0xf6, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07,
+  0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07,
+  0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07,
+  0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x11, 0xc2, 0x90, 0xcc,
+  0xb6, 0x20, 0xd3, 0x17, 0x39, 0x0c, 0x47, 0x05, 0xc4, 0x90, 0x08, 0x60,
+  0x14, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18,
+  0x12, 0x31, 0x1d, 0x04, 0x04, 0x80, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+  0x00, 0x00, 0x43, 0xa2, 0x34, 0xb8, 0x24, 0x20, 0x00, 0x06, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x12, 0x81, 0xc2, 0x45, 0x01, 0x01,
+  0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0xc4, 0x06, 0x81,
+  0xa2, 0xde, 0x03, 0x00, 0x00, 0x59, 0x20, 0x00, 0x00, 0x00, 0x0b, 0x00,
+  0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09,
+  0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a, 0x45, 0x50, 0x02, 0x85, 0x30, 0x02,
+  0x50, 0x30, 0x05, 0x51, 0x20, 0x85, 0x52, 0x06, 0x84, 0x47, 0x00, 0x0a,
+  0xa2, 0x40, 0x0a, 0x85, 0xee, 0x58, 0x42, 0x24, 0x00, 0x00, 0xb1, 0x18,
+  0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1,
+  0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42,
+  0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f,
+  0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1,
+  0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84,
+  0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc,
+  0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70,
+  0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19,
+  0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f,
+  0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21,
+  0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc,
+  0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84,
+  0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37,
+  0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70,
+  0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77,
+  0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79,
+  0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e,
+  0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81,
+  0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88,
+  0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4,
+  0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72,
+  0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74,
+  0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e,
+  0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e,
+  0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21,
+  0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01,
+  0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc,
+  0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77,
+  0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e,
+  0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1,
+  0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61,
+  0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0,
+  0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0,
+  0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74,
+  0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e,
+  0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41,
+  0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48,
+  0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c,
+  0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4,
+  0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71,
+  0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f,
+  0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f,
+  0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f,
+  0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23,
+  0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21,
+  0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21,
+  0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94,
+  0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a,
+  0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e,
+  0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e,
+  0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74,
+  0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74,
+  0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78,
+  0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c, 0x27, 0x46, 0x46,
+  0xc8, 0x11, 0x32, 0x64, 0xd4, 0xd4, 0x80, 0x0c, 0xf2, 0x09, 0x8b, 0xf2,
+  0x06, 0xc5, 0xc6, 0x91, 0x41, 0x14, 0x19, 0x12, 0xa5, 0x3c, 0x06, 0x33,
+  0x30, 0xd2, 0xa0, 0x3c, 0x12, 0x42, 0x25, 0x0c, 0x81, 0x14, 0x4c, 0x74,
+  0x31, 0xcc, 0xa2, 0x68, 0xcd, 0x72, 0x34, 0x00, 0x00, 0x00, 0x53, 0x44,
+  0x4b, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x77, 0x63, 0x68,
+  0x61, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65,
+  0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
+  0x6f, 0x6e, 0x20, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x20,
+  0x28, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x66, 0x65, 0x2d, 0x33, 0x32, 0x30,
+  0x32, 0x33, 0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65, 0x74, 0x61, 0x6c, 0x61,
+  0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x64,
+  0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62,
+  0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c,
+  0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f,
+  0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f,
+  0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x62,
+  0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f,
+  0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65,
+  0x6e, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x61,
+  0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f,
+  0x6e, 0x61, 0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x61, 0x69,
+  0x72, 0x2e, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69,
+  0x6e, 0x70, 0x75, 0x74, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
+  0x64, 0x28, 0x33, 0x74, 0x65, 0x78, 0x44, 0x76, 0x32, 0x5f, 0x66, 0x29,
+  0x61, 0x69, 0x72, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x69,
+  0x72, 0x2e, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76,
+  0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61,
+  0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x78, 0x61, 0x69,
+  0x72, 0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x69,
+  0x72, 0x2e, 0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63,
+  0x74, 0x69, 0x76, 0x65, 0x70, 0x6f, 0x73, 0x61, 0x69, 0x72, 0x2e, 0x62,
+  0x75, 0x66, 0x66, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66,
+  0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e,
+  0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64,
+  0x65, 0x78, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x61, 0x64, 0x61, 0x69,
+  0x72, 0x2e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70,
+  0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x55, 0x56, 0x4c, 0x65, 0x66, 0x74,
+  0x54, 0x6f, 0x70, 0x55, 0x56, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69,
+  0x6f, 0x6e, 0x73, 0x75, 0x69, 0x6e, 0x74, 0x4d, 0x69, 0x70, 0x4c, 0x65,
+  0x76, 0x65, 0x6c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x4c, 0x61, 0x79, 0x65,
+  0x72, 0x4f, 0x72, 0x44, 0x65, 0x70, 0x74, 0x68, 0x61, 0x69, 0x72, 0x2e,
+  0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x69, 0x7a,
+  0x65, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70,
+  0x65, 0x5f, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65,
+  0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e,
+  0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e,
+  0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x61,
+  0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x78,
+  0x74, 0x75, 0x72, 0x65, 0x63, 0x75, 0x62, 0x65, 0x3c, 0x66, 0x6c, 0x6f,
+  0x61, 0x74, 0x2c, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3e, 0x73,
+  0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73,
+  0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+  0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00, 0xc4, 0x62,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x82, 0x30, 0x10, 0x23, 0x08,
+  0x57, 0x34, 0x82, 0x30, 0x14, 0x23, 0x08, 0x83, 0x31, 0x82, 0x30, 0x1c,
+  0x23, 0x08, 0x0b, 0x30, 0x82, 0x30, 0x20, 0x23, 0x08, 0x43, 0x32, 0x82,
+  0x30, 0x28, 0x23, 0x08, 0xc3, 0x32, 0x82, 0x30, 0x30, 0x33, 0x0c, 0x6b,
+  0x10, 0xb0, 0xc1, 0x0c, 0x43, 0x1b, 0x08, 0x6e, 0x30, 0x43, 0x30, 0xcc,
+  0x30, 0xac, 0xc1, 0x1a, 0xbc, 0xc1, 0x0c, 0x04, 0xd1, 0x06, 0x6d, 0xf0,
+  0x06, 0x33, 0x04, 0xc5, 0x0c, 0x81, 0x31, 0x43, 0x70, 0xcc, 0x50, 0x20,
+  0x6f, 0xf0, 0x06, 0x89, 0x32, 0x43, 0xe0, 0x07, 0x33, 0x24, 0x6f, 0xb0,
+  0x30, 0x8d, 0x93, 0x3c, 0x50, 0x34, 0x03, 0xd2, 0x06, 0x52, 0x33, 0x25,
+  0x0a, 0x44, 0xcd, 0x40, 0xbd, 0x81, 0x1c, 0xbc, 0xc1, 0xa3, 0xc9, 0x81,
+  0x1c, 0xbc, 0xc1, 0xb3, 0xcd, 0x81, 0x1b, 0xbc, 0x01, 0xd7, 0xd1, 0x81,
+  0x1b, 0xbc, 0x81, 0xf7, 0xcd, 0x20, 0xad, 0x41, 0x65, 0xc5, 0xc1, 0xf5,
+  0x06, 0x6d, 0x80, 0x65, 0xa2, 0x00, 0x06, 0x71, 0x10, 0x06, 0x72, 0x90,
+  0x88, 0x01, 0x34, 0x06, 0x33, 0x28, 0x75, 0x40, 0x06, 0xd7, 0x1b, 0xb4,
+  0x41, 0x19, 0x24, 0x66, 0x00, 0x9d, 0xc1, 0x0c, 0x89, 0x1b, 0xa0, 0xc1,
+  0xf5, 0x06, 0x6d, 0x90, 0xa4, 0x01, 0xa4, 0x06, 0x33, 0x14, 0xa0, 0x10,
+  0x0a, 0xa3, 0x40, 0x0a, 0xa5, 0x30, 0xc3, 0x00, 0x07, 0x7f, 0x60, 0x0a,
+  0xd5, 0x01, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0xb9, 0x81,
+  0x1b, 0x58, 0x74, 0xa0, 0x07, 0x96, 0x65, 0xe9, 0x01, 0xc7, 0x0a, 0xa6,
+  0x00, 0x1b, 0x7e, 0x61, 0x0f, 0xea, 0xc0, 0x0a, 0x32, 0x12, 0x98, 0xa0,
+  0x8b, 0xd8, 0xd8, 0xec, 0xda, 0x5c, 0xda, 0xde, 0xc8, 0xea, 0xd8, 0xca,
+  0x5c, 0xcc, 0xd8, 0xc2, 0xce, 0xe6, 0x46, 0x11, 0xea, 0xc0, 0x0e, 0x4e,
+  0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3, 0x1b, 0x25,
+  0xb8, 0x83, 0x5b, 0xc2, 0xd2, 0xe4, 0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2,
+  0xde, 0xdc, 0x46, 0x09, 0xf0, 0xe0, 0xa8, 0xb0, 0x34, 0x39, 0x17, 0xb6,
+  0x30, 0xb7, 0xb3, 0xba, 0xb0, 0xb3, 0xb2, 0x2f, 0xbb, 0x32, 0xb9, 0xb9,
+  0xb4, 0x37, 0xb7, 0x51, 0x82, 0x3c, 0xb8, 0x29, 0x2c, 0x4d, 0xce, 0x65,
+  0xec, 0xad, 0x0d, 0x2e, 0x8d, 0xad, 0xec, 0xeb, 0x0d, 0x8e, 0x2e, 0xed,
+  0xcd, 0x6d, 0x6e, 0x94, 0x41, 0x0f, 0xf6, 0x80, 0x0f, 0x8e, 0x09, 0x4b,
+  0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0x1b, 0x25,
+  0x30, 0x05, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x18, 0x00, 0x00, 0x25, 0x00,
+  0x00, 0x00, 0x0b, 0x0a, 0x72, 0x28, 0x87, 0x77, 0x80, 0x07, 0x7a, 0x58,
+  0x70, 0x98, 0x43, 0x3d, 0xb8, 0xc3, 0x38, 0xb0, 0x43, 0x39, 0xd0, 0xc3,
+  0x82, 0xe6, 0x1c, 0xc6, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2, 0xc1, 0x1d,
+  0xe6, 0x21, 0x1d, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x16, 0x34, 0xe3,
+  0x60, 0x0e, 0xe7, 0x50, 0x0f, 0xe1, 0x20, 0x0f, 0xe4, 0x40, 0x0f, 0xe1,
+  0x20, 0x0f, 0xe7, 0x50, 0x0e, 0xf4, 0xb0, 0x80, 0x81, 0x07, 0x79, 0x28,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x78, 0x87, 0x71, 0x08, 0x07, 0x7a, 0x28,
+  0x07, 0x72, 0x58, 0x70, 0x9c, 0xc3, 0x38, 0xb4, 0x01, 0x3b, 0xa4, 0x83,
+  0x3d, 0x94, 0xc3, 0x02, 0x6b, 0x1c, 0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c,
+  0xdc, 0x20, 0x1c, 0xe4, 0x61, 0x1c, 0xdc, 0x20, 0x1c, 0xe8, 0x81, 0x1e,
+  0xc2, 0x61, 0x1c, 0xd0, 0xa1, 0x1c, 0xc8, 0x61, 0x1c, 0xc2, 0x81, 0x1d,
+  0xd8, 0x61, 0xc1, 0x01, 0x0f, 0xf4, 0x20, 0x0f, 0xe1, 0x50, 0x0f, 0xf4,
+  0x80, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x10, 0x00, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0x07, 0xcc, 0x3c, 0xa4, 0x83, 0x3b, 0x9c, 0x03, 0x3b, 0x94,
+  0x03, 0x3d, 0xa0, 0x83, 0x3c, 0x94, 0x43, 0x38, 0x90, 0xc3, 0x01, 0x00,
+  0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x13, 0x04,
+  0x48, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x34, 0x4a,
+  0x81, 0x5e, 0x0d, 0x10, 0x2e, 0x81, 0x22, 0xa0, 0x3e, 0xd6, 0x00, 0x04,
+  0x02, 0x81, 0x19, 0x80, 0x31, 0x02, 0x10, 0x04, 0x41, 0x10, 0x14, 0x66,
+  0x00, 0xc6, 0x08, 0x40, 0x10, 0x04, 0xf1, 0x5f, 0x18, 0x01, 0x18, 0x23,
+  0x00, 0x41, 0x10, 0xc4, 0xbf, 0x31, 0x02, 0x10, 0x04, 0x41, 0x10, 0x0c,
+  0x28, 0xcc, 0x41, 0x84, 0x01, 0xc7, 0x79, 0x73, 0x10, 0x1f, 0xc7, 0x79,
+  0x73, 0x10, 0xdc, 0xc7, 0x79, 0x73, 0x10, 0x5c, 0x18, 0x70, 0xde, 0x1c,
+  0x04, 0xc7, 0x85, 0x81, 0x37, 0x07, 0xc1, 0x71, 0x9f, 0x37, 0x07, 0x01,
+  0x06, 0x60, 0x00, 0x06, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x30,
+  0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x22, 0x47, 0xc8, 0x90, 0x51, 0x22,
+  0xc8, 0x4f, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xe3, 0x59, 0x18, 0x26, 0x0d,
+  0x00, 0x00, 0x6f, 0x6d, 0x6e, 0x69, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74,
+  0x20, 0x63, 0x68, 0x61, 0x72, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20,
+  0x43, 0x2b, 0x2b, 0x20, 0x54, 0x42, 0x41, 0x41, 0x61, 0x69, 0x72, 0x2d,
+  0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73,
+  0x28, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x75, 0x62,
+  0x65, 0x29, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d,
+  0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x61, 0x72, 0x67, 0x28, 0x32, 0x29,
+  0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63,
+  0x6f, 0x70, 0x65, 0x2d, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73,
+  0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63,
+  0x6f, 0x70, 0x65, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73,
+  0x5f, 0x5a, 0x54, 0x53, 0x31, 0x32, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
+  0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x74, 0x00, 0x13, 0x04,
+  0xac, 0x99, 0x20, 0x60, 0xce, 0x04, 0x01, 0x7b, 0x26, 0x08, 0x18, 0xb4,
+  0x42, 0xa0, 0x05, 0x55, 0x58, 0x31, 0xd4, 0x02, 0x2d, 0xac, 0xc2, 0x8a,
+  0xc1, 0x16, 0x68, 0x81, 0x15, 0x56, 0x0c, 0xb7, 0x40, 0x0b, 0xad, 0xb0,
+  0x21, 0x48, 0x85, 0x0d, 0x03, 0x2a, 0xe0, 0x02, 0x2c, 0x6c, 0x18, 0x72,
+  0x21, 0x17, 0x60, 0x61, 0x43, 0x50, 0x0b, 0x1b, 0x84, 0x5b, 0xb0, 0x85,
+  0x0d, 0xc3, 0x2b, 0xe4, 0x02, 0x2c, 0x6c, 0x18, 0xbc, 0x5c, 0x80, 0x85,
+  0x0d, 0x89, 0x2b, 0xe4, 0x02, 0x2c, 0xe4, 0x42, 0x2c, 0xf4, 0x82, 0x2c,
+  0xf8, 0xc2, 0x2c, 0x6c, 0x18, 0x7e, 0xc1, 0x17, 0x66, 0x61, 0xc3, 0xf0,
+  0x0b, 0xbd, 0x20, 0x0b, 0x00, 0x00, 0x9b, 0x0c, 0x97, 0x47, 0x06, 0x14,
+  0x08, 0xb2, 0xc9, 0x90, 0x81, 0x01, 0x1a, 0x50, 0x20, 0x88, 0x05, 0x9d,
+  0xf8, 0x5b, 0x40, 0x80, 0xff, 0x18, 0x42, 0x40, 0x06, 0x16, 0x40, 0xe2,
+  0x6f, 0x01, 0x05, 0xfe, 0x63, 0x08, 0xc4, 0x66, 0xc1, 0x24, 0xfe, 0x16,
+  0x5c, 0xe0, 0xbf, 0xc9, 0x30, 0x06, 0x6a, 0xb0, 0x06, 0x14, 0x80, 0x31,
+  0x62, 0x50, 0x10, 0x21, 0x08, 0x06, 0x94, 0x1d, 0x04, 0xc3, 0x3c, 0x43,
+  0x70, 0x1c, 0x41, 0x21, 0x10, 0x03, 0x43, 0x18, 0xc5, 0x65, 0x58, 0x47,
+  0x84, 0xff, 0x1c, 0x03, 0x16, 0x88, 0x81, 0x7d, 0x49, 0xf8, 0xcf, 0x31,
+  0x08, 0xc1, 0x18, 0xcc, 0x12, 0x1c, 0x16, 0x06, 0x48, 0xf8, 0xcf, 0x31,
+  0x6c, 0x81, 0x19, 0xcc, 0x31, 0x04, 0x8d, 0x19, 0xcc, 0x12, 0x1c, 0x73,
+  0x0c, 0x9c, 0x43, 0x07, 0x56, 0x06, 0x4c, 0xf8, 0xcf, 0x31, 0x08, 0x41,
+  0x1a, 0xcc, 0x12, 0x1c, 0x73, 0x0c, 0x5e, 0x74, 0x07, 0x73, 0x0c, 0xc1,
+  0xb3, 0x06, 0xb3, 0x04, 0x87, 0xa5, 0x01, 0x14, 0xfe, 0x73, 0x0c, 0x60,
+  0x40, 0xe9, 0xc1, 0x1c, 0x43, 0x20, 0xbc, 0xc1, 0x2c, 0xc1, 0x61, 0x6c,
+  0x60, 0x85, 0xbf, 0xb5, 0x01, 0x15, 0xfe, 0x73, 0x0c, 0x63, 0x20, 0xf8,
+  0xc1, 0x1c, 0x43, 0x20, 0xcc, 0xc1, 0x2c, 0xc1, 0x31, 0xd0, 0x13, 0x08,
+  0x86, 0x52, 0x40, 0x04, 0x35, 0x68, 0x02, 0x18, 0x04, 0xa8, 0x00, 0x0c,
+  0x32, 0x04, 0x64, 0x30, 0x07, 0x9b, 0x0c, 0x7b, 0x20, 0x0a, 0xab, 0x40,
+  0xc1, 0x20, 0x23, 0x06, 0x06, 0x11, 0x82, 0x60, 0xe1, 0x1f, 0xd2, 0x2b,
+  0x04, 0x23, 0x06, 0x4b, 0x11, 0x82, 0x60, 0x00, 0xc5, 0x42, 0x1f, 0xf0,
+  0x01, 0xa1, 0x07, 0x81, 0x1c, 0xac, 0xc2, 0x68, 0x42, 0x00, 0x64, 0x10,
+  0x10, 0x03, 0x0c, 0x00, 0x00, 0x00, 0x5b, 0x8e, 0x20, 0xc8, 0x85, 0x43,
+  0x17, 0x90, 0x5d, 0xd8, 0x72, 0x0c, 0x41, 0x2e, 0x1c, 0xba, 0x80, 0xec,
+  0xc2, 0x96, 0xa3, 0x09, 0x7e, 0xe1, 0xd0, 0x05, 0x64, 0x17, 0xb6, 0x1c,
+  0x6c, 0x10, 0x80, 0xc3, 0xa1, 0x0b, 0xc8, 0x2e, 0x6c, 0x29, 0xdc, 0xe0,
+  0xd8, 0x05, 0x44, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x32, 0x0e, 0x10, 0x22, 0x84, 0x00,
+  0xae, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x0c,
+  0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0x78, 0x01, 0x00,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00,
+  0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+  0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x00, 0x24, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1d, 0x00,
+  0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x17, 0x00,
+  0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x17, 0x00,
+  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x0c,
+  0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0xfe, 0x00, 0x00,
+  0x00, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x75,
+  0x62, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+  0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x75, 0x62,
+  0x65, 0x2e, 0x76, 0x34, 0x66, 0x33, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x63,
+  0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2e, 0x66, 0x2e, 0x66, 0x33, 0x32,
+  0x2e, 0x75, 0x2e, 0x69, 0x33, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f,
+  0x6e, 0x76, 0x65, 0x72, 0x74, 0x2e, 0x75, 0x2e, 0x69, 0x33, 0x32, 0x2e,
+  0x66, 0x2e, 0x66, 0x33, 0x32, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39,
+  0x38, 0x61, 0x69, 0x72, 0x36, 0x34, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65,
+  0x2d, 0x69, 0x6f, 0x73, 0x31, 0x33, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x73,
+  0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00
+};
+const unsigned int BlitFromCube_metallib_len = 4610;
+#else
+const unsigned char FullscreenVert_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa2, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0f, 0x00, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63,
+  0x72, 0x65, 0x65, 0x6e, 0x56, 0x65, 0x72, 0x74, 0x00, 0x54, 0x59, 0x50,
+  0x45, 0x01, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x09, 0x3f,
+  0x09, 0xcf, 0x14, 0xb2, 0xfb, 0xb5, 0xe2, 0x14, 0x3b, 0xbe, 0x99, 0x33,
+  0x7a, 0x9f, 0x6b, 0x94, 0xd6, 0x41, 0x46, 0xd3, 0xa9, 0x59, 0xe0, 0x34,
+  0xbf, 0xca, 0x49, 0x0d, 0xfb, 0x05, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
+  0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0,
+  0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa8, 0x09,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c,
+  0x00, 0x00, 0x67, 0x02, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00,
+  0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8,
+  0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05,
+  0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92,
+  0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32,
+  0x44, 0x24, 0x48, 0x0a, 0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19,
+  0x21, 0x72, 0x24, 0x07, 0xc8, 0x08, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40,
+  0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x6c, 0x00,
+  0x00, 0x00, 0x1b, 0x7a, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x90,
+  0x00, 0x8a, 0x08, 0x07, 0x78, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7c, 0x68,
+  0x03, 0x73, 0xa8, 0x07, 0x77, 0x18, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68,
+  0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e,
+  0xca, 0x01, 0x20, 0xda, 0x21, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c,
+  0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d, 0xec, 0xa1, 0x1c, 0xc6, 0x81, 0x1e,
+  0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e, 0xd2, 0x81, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x38, 0x00, 0x06, 0x77, 0x78, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x48,
+  0x07, 0x76, 0xa0, 0x87, 0x74, 0x70, 0x87, 0x79, 0x00, 0x08, 0x77, 0x78,
+  0x87, 0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80,
+  0x87, 0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28,
+  0x07, 0x76, 0x48, 0x87, 0x76, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c,
+  0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d,
+  0xca, 0xa1, 0x0d, 0xe0, 0xe1, 0x1d, 0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x0d, 0xca, 0x81, 0x1d, 0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d,
+  0xde, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0,
+  0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x48,
+  0x07, 0x77, 0x30, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68,
+  0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c,
+  0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e,
+  0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68,
+  0x83, 0x79, 0x48, 0x87, 0x73, 0x70, 0x87, 0x72, 0x20, 0x87, 0x36, 0xd0,
+  0x87, 0x72, 0x90, 0x87, 0x77, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68,
+  0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e,
+  0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c,
+  0xe0, 0x01, 0x1e, 0xd2, 0xc1, 0x1d, 0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c,
+  0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x98,
+  0x07, 0x7a, 0x08, 0x87, 0x71, 0x58, 0x87, 0x36, 0x80, 0x07, 0x79, 0x78,
+  0x07, 0x7a, 0x28, 0x87, 0x71, 0xa0, 0x87, 0x77, 0x90, 0x87, 0x36, 0x10,
+  0x87, 0x7a, 0x30, 0x07, 0x73, 0x28, 0x07, 0x79, 0x68, 0x83, 0x79, 0x48,
+  0x07, 0x7d, 0x28, 0x07, 0x00, 0x0f, 0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e,
+  0xc2, 0xc1, 0x1c, 0xca, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d,
+  0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00,
+  0x36, 0x18, 0xc2, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b,
+  0x8c, 0xe1, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0x28, 0x00, 0x00,
+  0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82,
+  0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20,
+  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, 0x20, 0x64,
+  0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1,
+  0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x34,
+  0x33, 0x00, 0xc3, 0x08, 0x02, 0x30, 0x8c, 0x40, 0x00, 0x56, 0x08, 0x99,
+  0x23, 0x00, 0x83, 0x22, 0x0c, 0x51, 0x15, 0x01, 0x88, 0x6e, 0x20, 0x20,
+  0x05, 0x68, 0x18, 0x81, 0x20, 0x46, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa8,
+  0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07,
+  0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8, 0x03,
+  0x37, 0x80, 0x03, 0x37, 0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d, 0x00,
+  0x0f, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80,
+  0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0,
+  0x06, 0xe9, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10,
+  0x07, 0x76, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xf6, 0x40, 0x07, 0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76, 0xa0,
+  0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0,
+  0x06, 0xf6, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80,
+  0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x90,
+  0x07, 0x72, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50,
+  0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20,
+  0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60,
+  0x0f, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xa0,
+  0x07, 0x75, 0x10, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70, 0x20,
+  0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10,
+  0x07, 0x70, 0x20, 0x07, 0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a, 0x10,
+  0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x43, 0x18, 0x03, 0x00, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0x0c, 0x02, 0x04, 0x80, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x40, 0x16, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x32, 0x1e, 0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09,
+  0x26, 0x47, 0xc6, 0x04, 0x43, 0xa2, 0x12, 0x18, 0x01, 0x28, 0x82, 0x42,
+  0x28, 0x08, 0xd2, 0xb1, 0x84, 0x48, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18,
+  0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29,
+  0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x21, 0x06,
+  0x41, 0x24, 0x80, 0x72, 0x50, 0xb9, 0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a,
+  0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x10, 0x42, 0x22, 0x10, 0x05, 0xdf, 0x20,
+  0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4, 0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4,
+  0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x0d, 0x64, 0x46, 0x06, 0x46, 0x66,
+  0xc6, 0x25, 0x07, 0x07, 0x04, 0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac,
+  0xac, 0x65, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x27, 0x65, 0x88,
+  0x90, 0x10, 0x43, 0x0c, 0x42, 0x20, 0x0c, 0x62, 0x60, 0xd1, 0x54, 0x46,
+  0x17, 0xc6, 0x36, 0x04, 0x49, 0x0e, 0x42, 0x20, 0x04, 0x62, 0xe0, 0x16,
+  0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42,
+  0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26,
+  0xc6, 0x56, 0x36, 0x44, 0x48, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63,
+  0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f,
+  0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43,
+  0x84, 0x64, 0x21, 0x19, 0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1,
+  0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99,
+  0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x95, 0xb9,
+  0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11, 0x92, 0x86, 0x51, 0x58, 0x9a, 0x9c,
+  0x8b, 0x5d, 0x99, 0x1c, 0x5d, 0x19, 0xde, 0xd7, 0x5b, 0x1d, 0x1d, 0x5c,
+  0x1d, 0x1d, 0xa9, 0xb3, 0x32, 0xb7, 0x32, 0xb9, 0x30, 0xba, 0x32, 0x32,
+  0x94, 0x19, 0xba, 0x32, 0x3c, 0x22, 0x3b, 0x99, 0x2f, 0xb3, 0x14, 0x46,
+  0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65,
+  0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x34, 0xcc, 0xd8, 0xde, 0xc2, 0xe8, 0x64,
+  0xc8, 0x84, 0xa5, 0xc9, 0xb9, 0x84, 0xc9, 0x9d, 0x7d, 0xb9, 0x85, 0xb5,
+  0x95, 0x71, 0xa0, 0x2b, 0xc3, 0x1b, 0xc2, 0x24, 0x4f, 0x02, 0x25, 0x51,
+  0x22, 0x25, 0x53, 0x42, 0x91, 0x09, 0x4b, 0x93, 0x73, 0x81, 0x7b, 0x9b,
+  0x4b, 0xa3, 0x4b, 0x7b, 0x73, 0xa3, 0x61, 0xc6, 0xf6, 0x16, 0x46, 0x47,
+  0xc3, 0x01, 0xee, 0x6d, 0x6e, 0x88, 0x92, 0x58, 0x49, 0x94, 0x5c, 0xc9,
+  0x94, 0x60, 0x43, 0x88, 0xa4, 0x4a, 0x32, 0x36, 0x61, 0x69, 0x72, 0x2e,
+  0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x64, 0x24, 0xea, 0xd2,
+  0xdc, 0xe8, 0x28, 0xd8, 0x25, 0x0d, 0x61, 0x88, 0x21, 0xd9, 0x92, 0x28,
+  0xe1, 0x92, 0x29, 0xe9, 0x86, 0x08, 0x89, 0x37, 0xc4, 0x30, 0x80, 0x44,
+  0x4b, 0xbe, 0x11, 0x11, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0xb4,
+  0xc3, 0x3b, 0x90, 0x43, 0x3d, 0xb0, 0x43, 0x39, 0xb8, 0x81, 0x39, 0xb0,
+  0x43, 0x38, 0x9c, 0xc3, 0x3c, 0x4c, 0x11, 0x82, 0x61, 0x84, 0xc2, 0x0e,
+  0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xe9, 0x40, 0x0e, 0xe5, 0xe0, 0x0e,
+  0xf4, 0x30, 0x25, 0x28, 0x46, 0x2c, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06,
+  0xf6, 0x50, 0x0e, 0xf2, 0x30, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x25,
+  0x30, 0x46, 0x50, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xec, 0x10, 0x0e,
+  0xee, 0x70, 0x0e, 0xf5, 0x10, 0x0e, 0xe7, 0x50, 0x0e, 0xbf, 0x60, 0x0f,
+  0xe5, 0x20, 0x0f, 0xf3, 0x90, 0x0e, 0xef, 0xe0, 0x0e, 0x53, 0x02, 0x64,
+  0xc4, 0x14, 0x0e, 0xe9, 0x20, 0x0f, 0x6e, 0x30, 0x0e, 0xef, 0xd0, 0x0e,
+  0xf0, 0x90, 0x0e, 0xec, 0x50, 0x0e, 0xbf, 0xf0, 0x0e, 0xf0, 0x40, 0x0f,
+  0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x0f, 0x53, 0x06, 0x85, 0x71, 0x46, 0x28,
+  0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e, 0xf2, 0x40, 0x0f,
+  0xe5, 0x80, 0x0f, 0x53, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18,
+  0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1,
+  0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42,
+  0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f,
+  0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1,
+  0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84,
+  0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc,
+  0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70,
+  0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19,
+  0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f,
+  0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21,
+  0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc,
+  0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84,
+  0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37,
+  0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70,
+  0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77,
+  0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79,
+  0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e,
+  0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81,
+  0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88,
+  0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4,
+  0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72,
+  0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74,
+  0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e,
+  0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e,
+  0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21,
+  0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01,
+  0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc,
+  0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77,
+  0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e,
+  0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1,
+  0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61,
+  0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0,
+  0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0,
+  0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74,
+  0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e,
+  0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41,
+  0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48,
+  0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c,
+  0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4,
+  0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71,
+  0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f,
+  0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f,
+  0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f,
+  0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23,
+  0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21,
+  0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21,
+  0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94,
+  0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a,
+  0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e,
+  0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e,
+  0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74,
+  0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74,
+  0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78,
+  0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x09, 0x00,
+  0x00, 0x00, 0x06, 0xe0, 0x7c, 0xd4, 0xb2, 0x48, 0x42, 0x44, 0x10, 0xcd,
+  0x4b, 0x44, 0x93, 0x05, 0x5c, 0x00, 0x12, 0xf9, 0x82, 0xd3, 0x54, 0x44,
+  0x34, 0xf9, 0x85, 0x5f, 0xdc, 0xb6, 0x4f, 0xf9, 0xc8, 0x6d, 0x03, 0x00,
+  0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x13, 0x04,
+  0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xb4, 0x63,
+  0x11, 0x40, 0x60, 0x1c, 0x73, 0x10, 0x83, 0xb0, 0x2c, 0x44, 0x33, 0x00,
+  0x14, 0x33, 0x00, 0x63, 0x09, 0x20, 0x08, 0x82, 0x20, 0x18, 0x80, 0x20,
+  0x08, 0x82, 0xe0, 0x30, 0x96, 0x00, 0x82, 0x20, 0x88, 0xff, 0x02, 0x08,
+  0x82, 0x20, 0xfe, 0xcd, 0x00, 0x90, 0xcc, 0x41, 0x50, 0xd4, 0x24, 0xd1,
+  0xcc, 0x00, 0x10, 0x8c, 0x11, 0x80, 0x20, 0x08, 0xe2, 0xdf, 0x08, 0xc0,
+  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x4c, 0x57, 0x81, 0xa4, 0x23,
+  0x06, 0xc4, 0x10, 0x58, 0xc1, 0x1c, 0x03, 0x13, 0x54, 0x15, 0x55, 0x3a,
+  0x62, 0x40, 0x0c, 0x41, 0x16, 0xcc, 0x31, 0x0c, 0x41, 0x66, 0xc1, 0x23,
+  0x1f, 0x0b, 0x1e, 0xf8, 0x0c, 0x32, 0x04, 0x0f, 0x35, 0xc8, 0x10, 0x3c,
+  0xd6, 0x6c, 0xc3, 0x53, 0x00, 0xb3, 0x0d, 0x81, 0x10, 0x64, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int FullscreenVert_metallib_len = 2722;
+const unsigned char BlitFrom2D_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x3e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0b, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x32, 0x44, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01,
+  0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x8e, 0xc1, 0x03, 0x5e, 0x12, 0x72,
+  0x1f, 0x9e, 0x32, 0x93, 0x48, 0x9e, 0xbb, 0x7b, 0xe5, 0xaf, 0x2a, 0x2b,
+  0x49, 0x9f, 0x09, 0x1b, 0x0e, 0x1e, 0xec, 0x02, 0xbd, 0x97, 0xa6, 0x39,
+  0xcf, 0xb8, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53,
+  0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00,
+  0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x48, 0x0d, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x4f, 0x03,
+  0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00,
+  0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10,
+  0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04,
+  0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10,
+  0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a,
+  0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07,
+  0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00,
+  0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x1b, 0xc2,
+  0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x60, 0x00, 0x09, 0xa8, 0x88,
+  0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77, 0xc0, 0x87, 0x36, 0x30, 0x87,
+  0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87,
+  0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00,
+  0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0xe1, 0x1c, 0xc2,
+  0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4,
+  0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81, 0x1e, 0xd0, 0x01, 0x88, 0x03,
+  0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77, 0x68, 0x03, 0x71, 0xa8, 0x87,
+  0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77, 0x98, 0x07, 0x80, 0x70, 0x87,
+  0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70, 0x68, 0x87, 0x72, 0x68, 0x03,
+  0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a, 0x28, 0x07, 0x79, 0x68, 0x83,
+  0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c, 0xda,
+  0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e, 0xca,
+  0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0xa1, 0x0d, 0xdc,
+  0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xc2, 0xc1, 0x1c, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83,
+  0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83,
+  0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1d, 0xc2, 0xc1, 0x1d, 0xe6,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77, 0x28, 0x07, 0x72, 0x68, 0x03,
+  0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2,
+  0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1, 0x1c, 0xda, 0xa0, 0x1d, 0xc2,
+  0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x88,
+  0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75, 0x68, 0x03, 0x78, 0x90, 0x87,
+  0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x03,
+  0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72, 0x90, 0x87, 0x36, 0x98, 0x87,
+  0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00, 0x20, 0xea, 0xc1, 0x1d, 0xe6,
+  0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda,
+  0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07,
+  0x60, 0xc3, 0x26, 0x0c, 0xc0, 0x02, 0x54, 0x43, 0x38, 0xa4, 0x83, 0x3c,
+  0xb4, 0x81, 0x38, 0xd4, 0x83, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x1b,
+  0xb8, 0xc3, 0x3b, 0xb4, 0x41, 0x38, 0xb0, 0x43, 0x3a, 0x84, 0xc3, 0x3c,
+  0x00, 0x1b, 0x8c, 0xa1, 0x00, 0x16, 0xa0, 0xda, 0x80, 0x10, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x0c, 0x20, 0x01, 0xd5, 0x06, 0xa3, 0x08, 0x80,
+  0x05, 0xa8, 0x36, 0x18, 0x86, 0x00, 0x2c, 0x40, 0xb5, 0xc1, 0x38, 0xfe,
+  0xff, 0xff, 0xff, 0x7f, 0x00, 0x24, 0x80, 0xda, 0x60, 0x20, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x12, 0x40, 0x6d, 0x40, 0x92, 0xff, 0xff, 0xff,
+  0xff, 0x1f, 0x00, 0x06, 0x90, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x49, 0x18,
+  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18, 0x26, 0x0c,
+  0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48, 0x0a, 0x03,
+  0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x32, 0x22,
+  0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93,
+  0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84,
+  0xa4, 0x4c, 0x10, 0x60, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30, 0x8c, 0x20,
+  0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30, 0xf9, 0xac,
+  0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10, 0x62, 0x80,
+  0x41, 0x04, 0x42, 0x38, 0x4a, 0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x7f, 0x22,
+  0xae, 0x89, 0x8a, 0x88, 0xdf, 0x1e, 0xfe, 0x69, 0x8c, 0x00, 0x18, 0x44,
+  0x30, 0x82, 0x8b, 0xa4, 0x29, 0xa2, 0x84, 0xc9, 0xff, 0x25, 0x80, 0x79,
+  0x16, 0x22, 0xfa, 0xa7, 0x31, 0x02, 0x60, 0x10, 0x01, 0x11, 0x8a, 0x11,
+  0x44, 0x28, 0x27, 0x91, 0x9a, 0x23, 0x08, 0x86, 0x11, 0x84, 0xa1, 0x20,
+  0xe1, 0x24, 0xc1, 0x1a, 0x03, 0xe4, 0x8a, 0x00, 0x06, 0xc1, 0x81, 0x80,
+  0x14, 0x18, 0x73, 0x04, 0xa0, 0x30, 0x88, 0x20, 0x08, 0x83, 0x08, 0x83,
+  0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa8, 0x70, 0x48, 0x07, 0x79,
+  0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72,
+  0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8, 0x03, 0x37, 0x80, 0x03, 0x37,
+  0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06,
+  0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d, 0x90, 0x0e,
+  0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06,
+  0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06,
+  0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07,
+  0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x40, 0x07,
+  0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06,
+  0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07,
+  0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x20, 0x07,
+  0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07,
+  0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07,
+  0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x90, 0x07, 0x72, 0xa0, 0x07,
+  0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06,
+  0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07,
+  0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x75, 0x10, 0x07,
+  0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07,
+  0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07,
+  0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07,
+  0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x43, 0x98, 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0x21, 0xcc, 0x03, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc0, 0x10, 0x26, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+  0x0b, 0x04, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11,
+  0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a, 0x23, 0x00,
+  0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05, 0x53, 0x20, 0x85, 0x52, 0x06,
+  0x44, 0x0b, 0x65, 0x04, 0xa0, 0x40, 0x0a, 0x82, 0xe6, 0x58, 0x42, 0x24,
+  0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0x1a, 0x03,
+  0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9, 0xb9, 0xb4,
+  0x37, 0xb7, 0x21, 0xc6, 0x70, 0x48, 0xc0, 0x04, 0x51, 0xb9, 0x1b, 0x43,
+  0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x0c, 0x84, 0x24,
+  0x0c, 0x06, 0xdf, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4, 0xad, 0x8c,
+  0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x0d, 0x64,
+  0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x07, 0x04, 0xa5, 0xad, 0x8c,
+  0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25,
+  0x07, 0x27, 0x65, 0x88, 0x20, 0x11, 0x43, 0x8c, 0x81, 0x18, 0x8a, 0x61,
+  0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04, 0x91, 0x8e, 0x81, 0x18,
+  0x88, 0x61, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6, 0x06, 0x97,
+  0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36, 0xf7, 0x45,
+  0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44, 0x90, 0x12, 0x72, 0x61,
+  0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66,
+  0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61,
+  0x62, 0x6c, 0x65, 0x43, 0x04, 0x69, 0x21, 0x19, 0x84, 0xa5, 0xc9, 0xb9,
+  0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9, 0x85, 0xb5,
+  0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95, 0xd1, 0x8d,
+  0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11, 0xa4, 0x86,
+  0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99, 0x1b, 0x59, 0x99, 0xdc, 0x17,
+  0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3, 0xb0, 0x34, 0x39, 0x97, 0x30,
+  0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0x2f, 0xb7, 0xb0, 0xb6, 0x32,
+  0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x43, 0x10, 0xe9, 0x19, 0x06,
+  0x09, 0x92, 0xa2, 0x21, 0x82, 0x24, 0x51, 0x0a, 0x4b, 0x93, 0x73, 0x31,
+  0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0xfb, 0x4a, 0x73, 0x83, 0xab,
+  0xa3, 0x23, 0x75, 0x56, 0xe6, 0x56, 0x26, 0x17, 0x46, 0x57, 0x46, 0x86,
+  0x32, 0x43, 0x57, 0x86, 0x47, 0x64, 0x27, 0xf3, 0x65, 0x96, 0x42, 0x25,
+  0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d, 0xae, 0x4c, 0x8e, 0x4f, 0x58,
+  0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9, 0x18, 0x5d, 0x9a,
+  0x5d, 0x19, 0x0d, 0x33, 0xb6, 0xb7, 0x30, 0x3a, 0x19, 0x32, 0x61, 0x69,
+  0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x1c, 0xe8,
+  0xca, 0xf0, 0x86, 0x48, 0xc3, 0x20, 0x51, 0x52, 0x25, 0x59, 0xd2, 0x25,
+  0x41, 0x12, 0x26, 0x65, 0x92, 0x46, 0x26, 0x2c, 0x4d, 0xce, 0x05, 0xee,
+  0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x8d, 0x52, 0x58, 0x9a, 0x9c, 0x8b,
+  0xdb, 0xdb, 0x17, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9, 0x18, 0x5d, 0x9a,
+  0x5d, 0x19, 0x07, 0xb8, 0xb7, 0xb9, 0x21, 0xd0, 0x40, 0x48, 0x9c, 0x64,
+  0x49, 0x9d, 0x04, 0x49, 0x91, 0x94, 0x49, 0x1e, 0x95, 0xb0, 0x34, 0x39,
+  0x17, 0xb1, 0x3a, 0x33, 0xb3, 0x32, 0x39, 0x3e, 0x61, 0x69, 0x72, 0x2e,
+  0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x94,
+  0xc2, 0xd2, 0xe4, 0x5c, 0xd8, 0xde, 0xc6, 0xc2, 0xe8, 0xd2, 0xde, 0xdc,
+  0xbe, 0xd2, 0xdc, 0xc8, 0xca, 0xf0, 0x88, 0x84, 0xa5, 0xc9, 0xb9, 0xc8,
+  0x95, 0x85, 0x91, 0x91, 0x0a, 0x4b, 0x93, 0x73, 0x99, 0xa3, 0x93, 0xab,
+  0x1b, 0xa3, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb, 0x4a, 0x73, 0x33, 0x7b,
+  0x63, 0x52, 0x65, 0xc5, 0x54, 0x66, 0x46, 0x47, 0xf5, 0x06, 0x47, 0xa6,
+  0xca, 0x8a, 0x28, 0xad, 0xad, 0xcc, 0x6d, 0x2e, 0xed, 0xcd, 0x6d, 0x8e,
+  0x44, 0x5d, 0x9a, 0x1b, 0x1d, 0x91, 0xa6, 0x34, 0x38, 0xa6, 0x32, 0xbb,
+  0x32, 0x36, 0x16, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x64, 0x98, 0xc2, 0xf2,
+  0xca, 0xe4, 0x9e, 0xe4, 0x88, 0xca, 0xe0, 0xe8, 0xd0, 0x86, 0xa0, 0xc1,
+  0x30, 0x0c, 0xc5, 0x30, 0x48, 0x98, 0x54, 0x06, 0x43, 0x31, 0x14, 0xc3,
+  0x20, 0x61, 0x92, 0x19, 0x0c, 0xc9, 0x60, 0x0c, 0x83, 0x74, 0x06, 0x12,
+  0x1a, 0x0c, 0xca, 0x60, 0x0c, 0x83, 0x94, 0x06, 0x92, 0x1a, 0x30, 0x0a,
+  0x4b, 0x93, 0x73, 0x09, 0x93, 0x3b, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb,
+  0x9a, 0x4b, 0xd3, 0x2b, 0xe3, 0x15, 0x96, 0x26, 0xe7, 0x12, 0x26, 0x77,
+  0xf6, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x15, 0xc6, 0x96, 0x76, 0xe6, 0xf6,
+  0x35, 0x97, 0xa6, 0x57, 0x46, 0x66, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x4c,
+  0xaa, 0xec, 0x2c, 0xed, 0xcd, 0x8d, 0xcc, 0xdc, 0x5b, 0x9d, 0xdc, 0x58,
+  0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0xdb, 0x10, 0x32, 0x18, 0x0e, 0x09,
+  0x0c, 0xa4, 0x30, 0x18, 0x10, 0x49, 0x0c, 0x86, 0x61, 0x20, 0xa4, 0x31,
+  0x90, 0xc8, 0x40, 0x5a, 0x03, 0x89, 0x0d, 0x06, 0x44, 0x6a, 0x83, 0xa1,
+  0x90, 0x20, 0xc9, 0x0d, 0xa4, 0x4c, 0x7a, 0x03, 0x2e, 0x61, 0x69, 0x72,
+  0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x54, 0xc2, 0xd2, 0xe4,
+  0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0x88, 0xd1, 0x95, 0xe1, 0xd1,
+  0xd5, 0xc9, 0x95, 0xc9, 0x90, 0xf1, 0x98, 0xb1, 0xbd, 0x85, 0xd1, 0xb1,
+  0x80, 0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xf9, 0xb0, 0x99, 0x7b, 0xab,
+  0x93, 0x1b, 0x2b, 0xa3, 0x2a, 0xc3, 0xa3, 0xab, 0x93, 0x2b, 0x1b, 0x42,
+  0x0d, 0x8b, 0x14, 0x07, 0x92, 0x18, 0x0c, 0xc3, 0x40, 0x48, 0x72, 0x20,
+  0x41, 0xd2, 0x1c, 0x48, 0x99, 0x44, 0x07, 0x5c, 0xc2, 0xd2, 0xe4, 0x5c,
+  0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x78, 0xcc, 0x85, 0xb5, 0xc1,
+  0xb1, 0x95, 0xc9, 0xb1, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0x9b, 0x0a,
+  0x6b, 0x83, 0x63, 0x2b, 0x93, 0x1b, 0x22, 0x0d, 0x86, 0x64, 0x07, 0x92,
+  0x18, 0x0c, 0xc3, 0x40, 0x48, 0x90, 0x74, 0x07, 0x52, 0x26, 0xe1, 0xc1,
+  0x10, 0x45, 0xda, 0xa4, 0x4f, 0x82, 0x03, 0xa9, 0x0e, 0xa4, 0x3c, 0x18,
+  0x62, 0x2c, 0x80, 0x34, 0x49, 0x7a, 0xc0, 0xe7, 0xad, 0xcd, 0x2d, 0x0d,
+  0xee, 0x8d, 0xae, 0xcc, 0x8d, 0x0e, 0x64, 0x0c, 0x2d, 0x4c, 0x8e, 0xcf,
+  0x54, 0x5a, 0x1b, 0x1c, 0x5b, 0x19, 0xc8, 0xd0, 0xca, 0x0a, 0x08, 0x95,
+  0x50, 0x50, 0xd0, 0x10, 0x41, 0xea, 0x83, 0x21, 0x86, 0xc4, 0x07, 0x92,
+  0x1f, 0x50, 0xcd, 0x10, 0x43, 0xfa, 0x03, 0xe9, 0x0f, 0xa8, 0x86, 0x5c,
+  0x58, 0x9a, 0x5c, 0x4b, 0x18, 0x5b, 0x5a, 0xd8, 0x5c, 0xcb, 0xdc, 0xd8,
+  0x1b, 0x5c, 0xd9, 0x1c, 0x8a, 0x10, 0x5b, 0x1a, 0x9d, 0x91, 0xdc, 0x5b,
+  0x9b, 0x0c, 0x51, 0xca, 0x10, 0x42, 0x12, 0x05, 0x29, 0x14, 0x68, 0x85,
+  0xa5, 0xc9, 0xb5, 0x84, 0xb1, 0xa5, 0x85, 0xcd, 0xb5, 0xcc, 0x8d, 0xbd,
+  0xc1, 0x95, 0xb5, 0x84, 0xc9, 0x9d, 0xa1, 0xc8, 0xa4, 0x0c, 0x31, 0x24,
+  0x52, 0x90, 0x44, 0x41, 0x1a, 0x85, 0x21, 0x82, 0x44, 0x0a, 0xc4, 0xc2,
+  0xd2, 0xe4, 0x5a, 0xc2, 0xd8, 0xd2, 0xc2, 0xe6, 0x5a, 0xe6, 0xc6, 0xde,
+  0xe0, 0xca, 0x5a, 0xe8, 0xca, 0xf0, 0xe8, 0xea, 0xe4, 0xca, 0xe6, 0x86,
+  0x18, 0xd2, 0x29, 0x48, 0xa2, 0x20, 0x99, 0x02, 0xb1, 0xb0, 0x34, 0xb9,
+  0x96, 0x30, 0xb6, 0xb4, 0xb0, 0xb9, 0x96, 0xb9, 0xb1, 0x37, 0xb8, 0xb2,
+  0x96, 0xb9, 0xb0, 0x36, 0x38, 0xb6, 0x32, 0xb9, 0xb9, 0x21, 0x86, 0x94,
+  0x0a, 0x92, 0x28, 0x48, 0xa8, 0x30, 0x84, 0x90, 0x4e, 0x41, 0x4a, 0x05,
+  0x4a, 0x5f, 0x5a, 0x54, 0x53, 0x31, 0x32, 0x53, 0x6f, 0x75, 0x72, 0x63,
+  0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x1c, 0xd2, 0xdc, 0xe8, 0x86,
+  0x18, 0x12, 0x2b, 0x48, 0x7f, 0x40, 0x35, 0x43, 0x0c, 0x29, 0x0d, 0xa4,
+  0x3f, 0xa0, 0x9a, 0x21, 0x92, 0xb4, 0x0a, 0xd2, 0x1f, 0x50, 0x8d, 0xf4,
+  0x07, 0xd4, 0x23, 0xb5, 0x02, 0xe5, 0x48, 0xae, 0x40, 0x31, 0x43, 0x0c,
+  0xe9, 0x15, 0xa4, 0x56, 0xa0, 0x9c, 0x11, 0x11, 0x3b, 0xb0, 0x83, 0x3d,
+  0xb4, 0x83, 0x1b, 0xb4, 0xc3, 0x3b, 0x90, 0x43, 0x3d, 0xb0, 0x43, 0x39,
+  0xb8, 0x81, 0x39, 0xb0, 0x43, 0x38, 0x9c, 0xc3, 0x3c, 0x4c, 0x11, 0x82,
+  0x61, 0x84, 0xc2, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xe9, 0x40,
+  0x0e, 0xe5, 0xe0, 0x0e, 0xf4, 0x30, 0x25, 0x28, 0x46, 0x2c, 0xe1, 0x90,
+  0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e, 0xf2, 0x30, 0x0f, 0xe9, 0xf0,
+  0x0e, 0xee, 0x30, 0x25, 0x30, 0x46, 0x50, 0xe1, 0x90, 0x0e, 0xf2, 0xe0,
+  0x06, 0xec, 0x10, 0x0e, 0xee, 0x70, 0x0e, 0xf5, 0x10, 0x0e, 0xe7, 0x50,
+  0x0e, 0xbf, 0x60, 0x0f, 0xe5, 0x20, 0x0f, 0xf3, 0x90, 0x0e, 0xef, 0xe0,
+  0x0e, 0x53, 0x02, 0x64, 0xc4, 0x14, 0x0e, 0xe9, 0x20, 0x0f, 0x6e, 0x30,
+  0x0e, 0xef, 0xd0, 0x0e, 0xf0, 0x90, 0x0e, 0xec, 0x50, 0x0e, 0xbf, 0xf0,
+  0x0e, 0xf0, 0x40, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x0f, 0x53, 0x06,
+  0x85, 0x71, 0x46, 0x30, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xe6, 0x20,
+  0x0f, 0xe1, 0x70, 0x0e, 0xed, 0x50, 0x0e, 0xee, 0x40, 0x0f, 0x53, 0x82,
+  0x3d, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08,
+  0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38,
+  0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71,
+  0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c,
+  0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d,
+  0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d,
+  0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07,
+  0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87,
+  0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30,
+  0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10,
+  0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66,
+  0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c,
+  0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07,
+  0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87,
+  0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05,
+  0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87,
+  0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0,
+  0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca,
+  0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38,
+  0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c,
+  0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87,
+  0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87,
+  0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00,
+  0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20,
+  0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2,
+  0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4,
+  0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a,
+  0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07,
+  0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90,
+  0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8,
+  0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc,
+  0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b,
+  0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b,
+  0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87,
+  0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81,
+  0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30,
+  0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde,
+  0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b,
+  0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39,
+  0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07,
+  0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6,
+  0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30,
+  0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30,
+  0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50,
+  0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8,
+  0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8,
+  0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d,
+  0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07,
+  0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87,
+  0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0,
+  0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28,
+  0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87,
+  0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87,
+  0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20,
+  0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x16, 0xb0, 0x01, 0x48, 0xe4, 0x4b,
+  0x00, 0xf3, 0x2c, 0xc4, 0x3f, 0x11, 0xd7, 0x44, 0x45, 0xc4, 0x6f, 0x0f,
+  0x7e, 0x85, 0x17, 0xb7, 0x6d, 0x00, 0xca, 0xb6, 0x20, 0xd3, 0x17, 0x39,
+  0x8c, 0xdd, 0x99, 0xc0, 0x05, 0x20, 0x91, 0x2f, 0x38, 0x4d, 0x45, 0x44,
+  0x93, 0x5f, 0xf8, 0xc5, 0x6d, 0xfb, 0x94, 0x8f, 0xdc, 0x36, 0x00, 0x00,
+  0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x13, 0x04,
+  0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc4, 0x6a,
+  0x80, 0xda, 0x08, 0x00, 0x00, 0x00, 0xe3, 0x0d, 0xc5, 0x52, 0x51, 0x40,
+  0xc6, 0x1b, 0x8e, 0xc6, 0xa2, 0x80, 0x58, 0xb0, 0xc8, 0xc7, 0x02, 0x02,
+  0x3e, 0xe3, 0x0d, 0x4b, 0x74, 0x51, 0x40, 0x46, 0x0c, 0x08, 0x22, 0xf0,
+  0x82, 0x11, 0x03, 0xa5, 0x08, 0xc0, 0xa0, 0x61, 0x88, 0x45, 0x59, 0x82,
+  0x0c, 0x02, 0x62, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5b, 0x8e,
+  0x20, 0x00, 0x85, 0xa3, 0x14, 0x10, 0x55, 0xd8, 0x72, 0x0c, 0x01, 0x28,
+  0x1c, 0xa5, 0x80, 0xa8, 0xc2, 0x96, 0xe3, 0x08, 0x60, 0xe1, 0x28, 0x05,
+  0x44, 0x15, 0xb6, 0x14, 0xc9, 0xa1, 0x0a, 0x48, 0x29, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom2D_metallib_len = 3646;
+const unsigned char BlitFrom2DArray_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x10, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x32, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79, 0x00, 0x54, 0x59,
+  0x50, 0x45, 0x01, 0x00, 0x01, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x55,
+  0x4c, 0xff, 0xde, 0xd2, 0x71, 0x33, 0x89, 0x2c, 0xf4, 0xc8, 0xd4, 0x34,
+  0x23, 0x27, 0x12, 0x5f, 0x96, 0x0f, 0xc8, 0x4c, 0x26, 0xda, 0x7d, 0x82,
+  0xf5, 0xbd, 0x20, 0x44, 0x17, 0x29, 0x47, 0x4f, 0x46, 0x46, 0x54, 0x18,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01,
+  0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45,
+  0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde,
+  0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa8,
+  0x0d, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21,
+  0x0c, 0x00, 0x00, 0x67, 0x03, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41,
+  0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25,
+  0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42,
+  0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a,
+  0x32, 0x44, 0x24, 0x48, 0x0a, 0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c,
+  0x19, 0x21, 0x72, 0x24, 0x07, 0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8,
+  0x40, 0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x81,
+  0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x60, 0x00, 0x09, 0xa8, 0x88, 0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77,
+  0xc0, 0x87, 0x36, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73,
+  0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41,
+  0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80,
+  0x1d, 0xca, 0xe1, 0x1c, 0xc2, 0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61,
+  0x1c, 0xe8, 0xe1, 0x1d, 0xe4, 0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81,
+  0x1e, 0xd0, 0x01, 0x88, 0x03, 0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77,
+  0x68, 0x03, 0x71, 0xa8, 0x87, 0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77,
+  0x98, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70,
+  0x68, 0x87, 0x72, 0x68, 0x03, 0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a,
+  0x28, 0x07, 0x79, 0x68, 0x83, 0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80,
+  0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0,
+  0x1c, 0xe4, 0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21,
+  0x1d, 0xdc, 0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21,
+  0x1d, 0xda, 0xa1, 0x0d, 0xdc, 0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1,
+  0x1c, 0xc2, 0xc1, 0x1c, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80,
+  0x70, 0x87, 0x77, 0x68, 0x83, 0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36,
+  0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80,
+  0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0,
+  0x1d, 0xc2, 0xc1, 0x1d, 0xe6, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0,
+  0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72,
+  0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77,
+  0x28, 0x07, 0x72, 0x68, 0x03, 0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79,
+  0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74,
+  0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1,
+  0x0d, 0xe8, 0x41, 0x1e, 0xc2, 0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1,
+  0x1c, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79,
+  0xa8, 0x87, 0x72, 0x00, 0x88, 0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75,
+  0x68, 0x03, 0x78, 0x90, 0x87, 0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a,
+  0x78, 0x07, 0x79, 0x68, 0x03, 0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72,
+  0x90, 0x87, 0x36, 0x98, 0x87, 0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00,
+  0x20, 0xea, 0xc1, 0x1d, 0xe6, 0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0,
+  0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a,
+  0x90, 0x87, 0x7a, 0x28, 0x07, 0x60, 0xc3, 0x26, 0x0c, 0xc0, 0x02, 0x54,
+  0x43, 0x38, 0xa4, 0x83, 0x3c, 0xb4, 0x81, 0x38, 0xd4, 0x83, 0x39, 0x98,
+  0x43, 0x39, 0xc8, 0x43, 0x1b, 0xb8, 0xc3, 0x3b, 0xb4, 0x41, 0x38, 0xb0,
+  0x43, 0x3a, 0x84, 0xc3, 0x3c, 0x00, 0x1b, 0x8c, 0xa1, 0x00, 0x16, 0xa0,
+  0xda, 0x80, 0x10, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x0c, 0x20, 0x01,
+  0xd5, 0x06, 0xa3, 0x08, 0x80, 0x05, 0xa8, 0x36, 0x18, 0x86, 0x00, 0x2c,
+  0x40, 0xb5, 0xc1, 0x38, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x24, 0x80,
+  0xda, 0x60, 0x20, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x12, 0x40, 0x6d,
+  0x40, 0x92, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x06, 0x90, 0x80, 0x0a,
+  0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13,
+  0x86, 0x40, 0x18, 0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01,
+  0x32, 0x61, 0x48, 0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x29,
+  0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93,
+  0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12,
+  0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x6c, 0x33, 0x00, 0xc3,
+  0x08, 0x04, 0x30, 0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34,
+  0x45, 0x94, 0x30, 0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2,
+  0x34, 0x88, 0x10, 0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4d, 0x9a, 0x22,
+  0x4a, 0x98, 0xfc, 0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0xdf, 0x1e, 0x7e,
+  0x20, 0x8a, 0x00, 0xec, 0x9f, 0xc6, 0x08, 0x80, 0x41, 0x04, 0x23, 0xb8,
+  0x48, 0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x5f, 0x02, 0x98, 0x67, 0x21, 0xa2,
+  0x7f, 0x1a, 0x23, 0x00, 0x06, 0x11, 0x10, 0xa1, 0x18, 0x41, 0x84, 0x72,
+  0x12, 0xa9, 0x39, 0x82, 0x60, 0x18, 0x41, 0x18, 0x4a, 0x12, 0x4e, 0x12,
+  0x83, 0x35, 0x06, 0xc8, 0x15, 0x01, 0x0c, 0x82, 0x45, 0x18, 0x80, 0xe4,
+  0x40, 0x40, 0x0a, 0x8c, 0x39, 0x02, 0x50, 0x18, 0x44, 0x10, 0x84, 0x41,
+  0x04, 0x40, 0x18, 0x44, 0x18, 0x84, 0x11, 0x00, 0x00, 0x00, 0x00, 0x13,
+  0xa8, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80,
+  0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8,
+  0x03, 0x37, 0x80, 0x03, 0x37, 0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d,
+  0x00, 0x0f, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a,
+  0x80, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78,
+  0xd0, 0x06, 0xe9, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a,
+  0x10, 0x07, 0x76, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6,
+  0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71,
+  0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6,
+  0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xd0, 0x06, 0xf6, 0x40, 0x07, 0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76,
+  0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78,
+  0xd0, 0x06, 0xf6, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72,
+  0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71,
+  0x90, 0x07, 0x72, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72,
+  0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a,
+  0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d,
+  0x60, 0x0f, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72,
+  0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70,
+  0x20, 0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a,
+  0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a,
+  0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x43, 0x98, 0x05, 0x00,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0xcc, 0x03, 0x04, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x10, 0x26, 0x02, 0x02, 0x60, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x33, 0x01, 0x01, 0x30, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x90, 0x05, 0x02, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x32,
+  0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6,
+  0x04, 0x43, 0x1a, 0x23, 0x00, 0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05,
+  0x53, 0x20, 0x85, 0x52, 0x06, 0x64, 0x0b, 0x62, 0x04, 0xa0, 0x40, 0x0a,
+  0x85, 0xea, 0x58, 0x42, 0x24, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x47,
+  0x01, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10,
+  0xab, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x80, 0x50, 0x40,
+  0x15, 0x51, 0xb9, 0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b,
+  0x1b, 0x62, 0x0c, 0x05, 0x25, 0x0c, 0x07, 0xdf, 0x20, 0x08, 0x0e, 0x8e,
+  0xad, 0x0c, 0xa4, 0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e,
+  0x2e, 0xed, 0xcd, 0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07,
+  0x07, 0x04, 0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46,
+  0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x27, 0x65, 0x88, 0x40, 0x11, 0x43,
+  0x8c, 0xa1, 0x18, 0x8c, 0x81, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36,
+  0x04, 0xa1, 0x8e, 0xa1, 0x18, 0x8a, 0x81, 0xe0, 0x16, 0x96, 0x26, 0xe7,
+  0x32, 0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6,
+  0x26, 0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36,
+  0x44, 0xa0, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70,
+  0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74,
+  0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x6a, 0x21,
+  0x19, 0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95,
+  0xb9, 0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9,
+  0x7d, 0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1,
+  0x95, 0x0d, 0x11, 0xa8, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99,
+  0x1b, 0x59, 0x99, 0xdc, 0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3,
+  0xb0, 0x34, 0x39, 0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2,
+  0x2f, 0xb7, 0xb0, 0xb6, 0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
+  0x43, 0x10, 0xea, 0x19, 0x08, 0x0a, 0xa2, 0xa2, 0x21, 0x02, 0x25, 0x51,
+  0x0a, 0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3,
+  0xfb, 0x4a, 0x73, 0x83, 0xab, 0xa3, 0x23, 0x75, 0x56, 0xe6, 0x56, 0x26,
+  0x17, 0x46, 0x57, 0x46, 0x86, 0x32, 0x43, 0x57, 0x86, 0x47, 0x64, 0x27,
+  0xf3, 0x65, 0x96, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d,
+  0xae, 0x4c, 0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c,
+  0x5c, 0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x0d, 0x33, 0xb6, 0xb7, 0x30,
+  0x3a, 0x19, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e,
+  0x61, 0x6d, 0x65, 0x1c, 0xe8, 0xca, 0xf0, 0x86, 0x48, 0x03, 0x41, 0x51,
+  0x54, 0x45, 0x59, 0xd4, 0x45, 0x41, 0x14, 0x46, 0x65, 0x94, 0x46, 0x26,
+  0x2c, 0x4d, 0xce, 0x05, 0xee, 0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x8d,
+  0x52, 0x58, 0x9a, 0x9c, 0x8b, 0xdb, 0xdb, 0x17, 0x5c, 0x99, 0xdc, 0x1c,
+  0x5c, 0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x07, 0xb8, 0xb7, 0xb9, 0x21,
+  0xd0, 0x50, 0x50, 0x1c, 0x65, 0x51, 0x1d, 0x05, 0x51, 0x11, 0x95, 0x51,
+  0x1e, 0x95, 0xb0, 0x34, 0x39, 0x17, 0xb1, 0x3a, 0x33, 0xb3, 0x32, 0x39,
+  0x3e, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f,
+  0x73, 0x69, 0x7a, 0x65, 0x94, 0xc2, 0xd2, 0xe4, 0x5c, 0xd8, 0xde, 0xc6,
+  0xc2, 0xe8, 0xd2, 0xde, 0xdc, 0xbe, 0xd2, 0xdc, 0xc8, 0xca, 0xf0, 0x88,
+  0x84, 0xa5, 0xc9, 0xb9, 0xc8, 0x95, 0x85, 0x91, 0x91, 0x0a, 0x4b, 0x93,
+  0x73, 0x99, 0xa3, 0x93, 0xab, 0x1b, 0xa3, 0xfb, 0xa2, 0xcb, 0x83, 0x2b,
+  0xfb, 0x4a, 0x73, 0x33, 0x7b, 0x63, 0x52, 0x65, 0xc5, 0x54, 0x66, 0x46,
+  0x47, 0xf5, 0x06, 0x47, 0xa6, 0xca, 0x8a, 0x28, 0xad, 0xad, 0xcc, 0x6d,
+  0x2e, 0xed, 0xcd, 0x6d, 0x8e, 0x44, 0x5d, 0x9a, 0x1b, 0x1d, 0x91, 0xa6,
+  0x34, 0x38, 0xa6, 0x32, 0xbb, 0x32, 0x36, 0x16, 0x66, 0x6c, 0x6f, 0x61,
+  0x74, 0x64, 0x98, 0xc2, 0xf2, 0xca, 0xe4, 0x9e, 0xe4, 0x88, 0xca, 0xe0,
+  0xe8, 0xd0, 0x86, 0xa0, 0xc1, 0x40, 0x0c, 0xc6, 0x40, 0x50, 0x18, 0x55,
+  0x06, 0x83, 0x31, 0x18, 0x03, 0x41, 0x61, 0x94, 0x19, 0x0c, 0xca, 0x70,
+  0x0c, 0x04, 0x75, 0x06, 0x14, 0x1a, 0x0c, 0xcb, 0x70, 0x0c, 0x04, 0x95,
+  0x06, 0x94, 0x1a, 0x30, 0x0a, 0x4b, 0x93, 0x73, 0x09, 0x93, 0x3b, 0xfb,
+  0xa2, 0xcb, 0x83, 0x2b, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0xe3, 0x15, 0x96,
+  0x26, 0xe7, 0x12, 0x26, 0x77, 0xf6, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x15,
+  0xc6, 0x96, 0x76, 0xe6, 0xf6, 0x35, 0x97, 0xa6, 0x57, 0x46, 0x66, 0xea,
+  0xad, 0x4e, 0x6e, 0xac, 0x4c, 0xaa, 0xec, 0x2c, 0xed, 0xcd, 0x8d, 0xcc,
+  0xdc, 0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0xdb,
+  0x10, 0x32, 0x18, 0x10, 0x0a, 0x0c, 0xa8, 0x30, 0x18, 0x12, 0x4a, 0x0c,
+  0x06, 0x62, 0x28, 0xa8, 0x31, 0xa0, 0xc8, 0x80, 0x5a, 0x03, 0x8a, 0x0d,
+  0x86, 0x84, 0x6a, 0x83, 0xc1, 0xa0, 0x20, 0xca, 0x0d, 0xa8, 0x8c, 0x7a,
+  0x03, 0x2e, 0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
+  0x65, 0x54, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca,
+  0xe8, 0xd1, 0x95, 0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0xc9, 0x90, 0x7d, 0x85,
+  0xc9, 0xc9, 0x85, 0xe5, 0xf1, 0x98, 0xb1, 0xbd, 0x85, 0xd1, 0xb1, 0x80,
+  0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xf9, 0xb0, 0x99, 0x7b, 0xab, 0x93,
+  0x1b, 0x2b, 0xa3, 0x2a, 0xc3, 0xa3, 0xab, 0x93, 0x2b, 0x1b, 0x42, 0x0d,
+  0x0c, 0x15, 0x07, 0x94, 0x18, 0x0c, 0xc4, 0x50, 0x50, 0x72, 0x40, 0x41,
+  0xd4, 0x1c, 0x50, 0x19, 0x45, 0x07, 0x5c, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6,
+  0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x78, 0xcc, 0x85, 0xb5, 0xc1, 0xb1,
+  0x95, 0xc9, 0xb1, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0x9b, 0x0a, 0x6b,
+  0x83, 0x63, 0x2b, 0x93, 0x1b, 0x22, 0x0d, 0x07, 0x65, 0x07, 0x94, 0x18,
+  0x0c, 0xc4, 0x50, 0x50, 0x10, 0x75, 0x07, 0x54, 0x46, 0xe1, 0xc1, 0x10,
+  0x85, 0xda, 0xa8, 0x8f, 0x82, 0x03, 0xaa, 0x0e, 0xa8, 0x3c, 0x18, 0x62,
+  0x2c, 0x00, 0x35, 0x51, 0x7a, 0xc0, 0xe7, 0xad, 0xcd, 0x2d, 0x0d, 0xee,
+  0x8d, 0xae, 0xcc, 0x8d, 0x0e, 0x64, 0x0c, 0x2d, 0x4c, 0x8e, 0xcf, 0x54,
+  0x5a, 0x1b, 0x1c, 0x5b, 0x19, 0xc8, 0xd0, 0xca, 0x0a, 0x08, 0x95, 0x50,
+  0x50, 0xd0, 0x10, 0x81, 0xea, 0x83, 0x21, 0x06, 0xc5, 0x07, 0x94, 0x1f,
+  0x58, 0xce, 0x10, 0x83, 0xfa, 0x03, 0xea, 0x0f, 0x2c, 0x87, 0x61, 0x10,
+  0x96, 0x26, 0xd7, 0x12, 0xc6, 0x96, 0x16, 0x36, 0xd7, 0x32, 0x37, 0xf6,
+  0x06, 0x57, 0x36, 0x87, 0x22, 0xc4, 0x96, 0x46, 0x67, 0x24, 0xf7, 0xd6,
+  0x26, 0x43, 0x14, 0x24, 0x27, 0x17, 0x96, 0x97, 0x32, 0x84, 0xa0, 0x44,
+  0x81, 0x0a, 0x05, 0x5a, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61,
+  0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x61, 0x72, 0x67, 0x28,
+  0x32, 0x29, 0x43, 0x0c, 0x8a, 0x14, 0x28, 0x51, 0xa0, 0x46, 0x61, 0x88,
+  0x40, 0x91, 0x02, 0xb1, 0xb0, 0x34, 0xb9, 0x96, 0x30, 0xb6, 0xb4, 0xb0,
+  0xb9, 0x96, 0xb9, 0xb1, 0x37, 0xb8, 0xb2, 0x16, 0xba, 0x32, 0x3c, 0xba,
+  0x3a, 0xb9, 0xb2, 0xb9, 0x21, 0x06, 0x75, 0x0a, 0x94, 0x28, 0x50, 0xa6,
+  0x40, 0x2c, 0x2c, 0x4d, 0xae, 0x25, 0x8c, 0x2d, 0x2d, 0x6c, 0xae, 0x65,
+  0x6e, 0xec, 0x0d, 0xae, 0xac, 0x65, 0x2e, 0xac, 0x0d, 0x8e, 0xad, 0x4c,
+  0x6e, 0x6e, 0x88, 0x41, 0xa5, 0x02, 0x25, 0x0a, 0x14, 0x2a, 0x0c, 0x21,
+  0xa8, 0x53, 0xa0, 0x52, 0x81, 0xd2, 0x97, 0x16, 0xd5, 0x54, 0x8c, 0xcc,
+  0xd4, 0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0x1b,
+  0x87, 0x34, 0x37, 0xba, 0x21, 0x06, 0xc5, 0x0a, 0xd4, 0x1f, 0x58, 0xce,
+  0x10, 0x83, 0x4a, 0x03, 0xea, 0x0f, 0x2c, 0x67, 0x88, 0x44, 0xad, 0x02,
+  0xf5, 0x07, 0x96, 0x43, 0xfd, 0x81, 0xd5, 0x50, 0xad, 0x60, 0x3d, 0x94,
+  0x2b, 0x58, 0xd0, 0x10, 0x83, 0x7a, 0x05, 0xca, 0x15, 0x2c, 0x68, 0x88,
+  0x41, 0xbd, 0x02, 0xd5, 0x0a, 0xd6, 0x33, 0x22, 0x62, 0x07, 0x76, 0xb0,
+  0x87, 0x76, 0x70, 0x83, 0x76, 0x78, 0x07, 0x72, 0xa8, 0x07, 0x76, 0x28,
+  0x07, 0x37, 0x30, 0x07, 0x76, 0x08, 0x87, 0x73, 0x98, 0x87, 0x29, 0x42,
+  0x30, 0x8c, 0x50, 0xd8, 0x81, 0x1d, 0xec, 0xa1, 0x1d, 0xdc, 0x20, 0x1d,
+  0xc8, 0xa1, 0x1c, 0xdc, 0x81, 0x1e, 0xa6, 0x04, 0xc5, 0x88, 0x25, 0x1c,
+  0xd2, 0x41, 0x1e, 0xdc, 0xc0, 0x1e, 0xca, 0x41, 0x1e, 0xe6, 0x21, 0x1d,
+  0xde, 0xc1, 0x1d, 0xa6, 0x04, 0xc6, 0x08, 0x2a, 0x1c, 0xd2, 0x41, 0x1e,
+  0xdc, 0x80, 0x1d, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1e, 0xc2, 0xe1, 0x1c,
+  0xca, 0xe1, 0x17, 0xec, 0xa1, 0x1c, 0xe4, 0x61, 0x1e, 0xd2, 0xe1, 0x1d,
+  0xdc, 0x61, 0x4a, 0x80, 0x8c, 0x98, 0xc2, 0x21, 0x1d, 0xe4, 0xc1, 0x0d,
+  0xc6, 0xe1, 0x1d, 0xda, 0x01, 0x1e, 0xd2, 0x81, 0x1d, 0xca, 0xe1, 0x17,
+  0xde, 0x01, 0x1e, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0xe6, 0x61, 0xca,
+  0xa0, 0x30, 0xce, 0x08, 0x26, 0x1c, 0xd2, 0x41, 0x1e, 0xdc, 0xc0, 0x1c,
+  0xe4, 0x21, 0x1c, 0xce, 0xa1, 0x1d, 0xca, 0xc1, 0x1d, 0xe8, 0x61, 0x4a,
+  0xb0, 0x07, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33,
+  0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98,
+  0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33,
+  0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05,
+  0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43,
+  0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08,
+  0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78,
+  0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1,
+  0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33,
+  0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e,
+  0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03,
+  0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60,
+  0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80,
+  0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8,
+  0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18,
+  0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee,
+  0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c,
+  0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43,
+  0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3,
+  0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83,
+  0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69,
+  0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60,
+  0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee,
+  0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1,
+  0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e,
+  0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c,
+  0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43,
+  0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4,
+  0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c,
+  0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c,
+  0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3,
+  0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43,
+  0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98,
+  0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98,
+  0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3,
+  0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d,
+  0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83,
+  0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1,
+  0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08,
+  0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb,
+  0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5,
+  0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3,
+  0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4,
+  0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d,
+  0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d,
+  0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43,
+  0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70,
+  0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70,
+  0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec,
+  0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33,
+  0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70,
+  0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90,
+  0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x71,
+  0x20, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x10, 0x06, 0x00, 0x12,
+  0xf9, 0x12, 0xc0, 0x3c, 0x0b, 0xf1, 0x4f, 0xc4, 0x35, 0x51, 0x11, 0xf1,
+  0xdb, 0xc3, 0x0f, 0x44, 0x11, 0x80, 0xf9, 0x15, 0x5e, 0xdc, 0xb6, 0x01,
+  0x3c, 0xdb, 0x82, 0x4c, 0x5f, 0xe4, 0x30, 0x76, 0xa7, 0x45, 0x11, 0x80,
+  0x99, 0xc0, 0x05, 0x20, 0x91, 0x2f, 0x38, 0x4d, 0x45, 0x44, 0x93, 0x5f,
+  0xf8, 0xc5, 0x6d, 0xfb, 0x94, 0x8f, 0xdc, 0xb6, 0x0d, 0x5c, 0x00, 0x12,
+  0xf9, 0x82, 0xd3, 0x54, 0x44, 0x34, 0xf9, 0x94, 0x8f, 0xdc, 0xb6, 0x5f,
+  0xf8, 0xc5, 0x6d, 0x03, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x22,
+  0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0xc4, 0x6a, 0x80, 0xda, 0x08, 0x00, 0x00, 0x00, 0xe3,
+  0x0d, 0xc5, 0x52, 0x51, 0x40, 0xc6, 0x1b, 0x8e, 0xc6, 0xa2, 0x80, 0x58,
+  0xb0, 0xc8, 0xc7, 0x02, 0x02, 0x3e, 0xe3, 0x0d, 0x4b, 0x34, 0x51, 0x30,
+  0x46, 0x0c, 0x08, 0x22, 0xf0, 0x82, 0xf1, 0x06, 0x87, 0xd2, 0x28, 0x20,
+  0x23, 0x06, 0x04, 0x11, 0x88, 0x41, 0x30, 0x62, 0xb0, 0x14, 0x01, 0x19,
+  0x40, 0xcf, 0x41, 0x38, 0x8d, 0x13, 0x64, 0x10, 0x10, 0x03, 0x00, 0x0c,
+  0x00, 0x00, 0x00, 0x5b, 0x8e, 0x20, 0x00, 0x85, 0xa3, 0x14, 0x10, 0x55,
+  0xd8, 0x72, 0x0c, 0x01, 0x28, 0x1c, 0xa5, 0x80, 0xa8, 0xc2, 0x96, 0xe3,
+  0x08, 0x60, 0xe1, 0x28, 0x05, 0x44, 0x15, 0xb6, 0x1c, 0x4a, 0x10, 0x0b,
+  0x47, 0x29, 0x20, 0xaa, 0xb0, 0xa5, 0x60, 0x0e, 0x55, 0x40, 0x4a, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom2DArray_metallib_len = 3747;
+const unsigned char BlitFrom3D_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x6e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0b, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x33, 0x44, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01,
+  0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x78, 0x33, 0x74, 0x8c, 0x91, 0x22,
+  0x5b, 0x37, 0x5a, 0x24, 0x92, 0xcd, 0x37, 0x5c, 0x0c, 0xab, 0x74, 0x33,
+  0x00, 0x59, 0x10, 0x02, 0xb7, 0xbe, 0xb6, 0x2b, 0xd6, 0x76, 0x12, 0xf1,
+  0xe8, 0x4f, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53,
+  0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00,
+  0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x7c, 0x0d, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x5c, 0x03,
+  0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00,
+  0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10,
+  0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04,
+  0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10,
+  0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a,
+  0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07,
+  0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00,
+  0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x1b, 0xc2,
+  0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x60, 0x00, 0x09, 0xa8, 0x88,
+  0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77, 0xc0, 0x87, 0x36, 0x30, 0x87,
+  0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87,
+  0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00,
+  0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0xe1, 0x1c, 0xc2,
+  0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4,
+  0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81, 0x1e, 0xd0, 0x01, 0x88, 0x03,
+  0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77, 0x68, 0x03, 0x71, 0xa8, 0x87,
+  0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77, 0x98, 0x07, 0x80, 0x70, 0x87,
+  0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70, 0x68, 0x87, 0x72, 0x68, 0x03,
+  0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a, 0x28, 0x07, 0x79, 0x68, 0x83,
+  0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c, 0xda,
+  0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e, 0xca,
+  0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0xa1, 0x0d, 0xdc,
+  0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xc2, 0xc1, 0x1c, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83,
+  0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83,
+  0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1d, 0xc2, 0xc1, 0x1d, 0xe6,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77, 0x28, 0x07, 0x72, 0x68, 0x03,
+  0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2,
+  0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1, 0x1c, 0xda, 0xa0, 0x1d, 0xc2,
+  0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x88,
+  0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75, 0x68, 0x03, 0x78, 0x90, 0x87,
+  0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x03,
+  0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72, 0x90, 0x87, 0x36, 0x98, 0x87,
+  0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00, 0x20, 0xea, 0xc1, 0x1d, 0xe6,
+  0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda,
+  0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07,
+  0x60, 0xc3, 0x26, 0x0c, 0xc0, 0x02, 0x54, 0x43, 0x38, 0xa4, 0x83, 0x3c,
+  0xb4, 0x81, 0x38, 0xd4, 0x83, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x1b,
+  0xb8, 0xc3, 0x3b, 0xb4, 0x41, 0x38, 0xb0, 0x43, 0x3a, 0x84, 0xc3, 0x3c,
+  0x00, 0x1b, 0x8c, 0xa1, 0x00, 0x16, 0xa0, 0xda, 0x80, 0x10, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x0c, 0x20, 0x01, 0xd5, 0x06, 0xa3, 0x08, 0x80,
+  0x05, 0xa8, 0x36, 0x18, 0x86, 0x00, 0x2c, 0x40, 0xb5, 0xc1, 0x38, 0xfe,
+  0xff, 0xff, 0xff, 0x7f, 0x00, 0x24, 0x80, 0xda, 0x60, 0x20, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x12, 0x40, 0x6d, 0x40, 0x92, 0xff, 0xff, 0xff,
+  0xff, 0x1f, 0x00, 0x06, 0x90, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x49, 0x18,
+  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18, 0x26, 0x0c,
+  0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48, 0x0a, 0x03,
+  0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x32, 0x22,
+  0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93,
+  0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84,
+  0xa4, 0x4c, 0x10, 0x68, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30, 0x8c, 0x20,
+  0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30, 0xf9, 0xac,
+  0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10, 0x62, 0x80,
+  0x41, 0x04, 0x42, 0x38, 0x4a, 0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x7f, 0x22,
+  0xae, 0x89, 0x8a, 0x88, 0xff, 0x1e, 0xfe, 0x69, 0x8c, 0x00, 0x18, 0x44,
+  0x30, 0x82, 0x8b, 0xa4, 0x29, 0xa2, 0x84, 0xc9, 0xff, 0x25, 0x80, 0x79,
+  0x16, 0x22, 0xfa, 0xa7, 0x31, 0x02, 0x60, 0x10, 0x01, 0x11, 0x8a, 0x11,
+  0x44, 0x28, 0x27, 0x91, 0x1a, 0x46, 0x18, 0x80, 0x39, 0x82, 0x60, 0x18,
+  0x61, 0x18, 0x0a, 0x12, 0x4e, 0x62, 0xcd, 0x35, 0x40, 0xaf, 0x08, 0x60,
+  0x50, 0x1c, 0x08, 0x48, 0x81, 0x31, 0x47, 0x00, 0x0a, 0x83, 0x08, 0x82,
+  0x30, 0x88, 0x00, 0x08, 0x83, 0x08, 0x83, 0x30, 0x02, 0x00, 0x13, 0xa8,
+  0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07,
+  0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8, 0x03,
+  0x37, 0x80, 0x03, 0x37, 0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d, 0x00,
+  0x0f, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80,
+  0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0,
+  0x06, 0xe9, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10,
+  0x07, 0x76, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xf6, 0x40, 0x07, 0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76, 0xa0,
+  0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0,
+  0x06, 0xf6, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80,
+  0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x90,
+  0x07, 0x72, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50,
+  0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20,
+  0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60,
+  0x0f, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xa0,
+  0x07, 0x75, 0x10, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70, 0x20,
+  0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10,
+  0x07, 0x70, 0x20, 0x07, 0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a, 0x10,
+  0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x43, 0x98, 0x05, 0x00, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0x0c, 0x04, 0x04, 0x80, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0x10, 0x46, 0x02, 0x02, 0x60, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x20, 0x0b, 0x04, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e,
+  0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04,
+  0x43, 0x1a, 0x23, 0x00, 0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05, 0x53,
+  0x20, 0x85, 0x52, 0x06, 0x54, 0x0b, 0x62, 0x04, 0xa0, 0x40, 0x0a, 0x85,
+  0xe8, 0x58, 0x42, 0x24, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x44, 0x01,
+  0x00, 0x00, 0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab,
+  0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x70, 0x4c, 0x00, 0x05,
+  0x51, 0xb9, 0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b,
+  0x62, 0x0c, 0xc4, 0x24, 0x0c, 0x06, 0xdf, 0x20, 0x08, 0x0e, 0x8e, 0xad,
+  0x0c, 0xa4, 0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e,
+  0xed, 0xcd, 0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x07,
+  0x04, 0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06,
+  0x46, 0x66, 0xc6, 0x25, 0x07, 0x27, 0x65, 0x88, 0x30, 0x11, 0x43, 0x8c,
+  0x81, 0x18, 0x8a, 0x61, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04,
+  0x99, 0x8e, 0x81, 0x18, 0x88, 0x61, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32,
+  0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26,
+  0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44,
+  0x98, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69,
+  0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68,
+  0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x84, 0x69, 0x21, 0x19,
+  0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9,
+  0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d,
+  0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1, 0x95,
+  0x0d, 0x11, 0xa6, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99, 0x1b,
+  0x59, 0x99, 0xdc, 0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3, 0xb0,
+  0x34, 0x39, 0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0x2f,
+  0xb7, 0xb0, 0xb6, 0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x43,
+  0x90, 0xe9, 0x19, 0x86, 0x09, 0x9a, 0xa2, 0x21, 0xc2, 0x24, 0x51, 0x0a,
+  0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0xfb,
+  0x4a, 0x73, 0x83, 0xab, 0xa3, 0x23, 0x75, 0x56, 0xe6, 0x56, 0x26, 0x17,
+  0x46, 0x57, 0x46, 0x86, 0x32, 0x43, 0x57, 0x86, 0x47, 0x64, 0x27, 0xf3,
+  0x65, 0x96, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d, 0xae,
+  0x4c, 0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c, 0x5c,
+  0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x0d, 0x33, 0xb6, 0xb7, 0x30, 0x3a,
+  0x19, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61,
+  0x6d, 0x65, 0x1c, 0xe8, 0xca, 0xf0, 0x86, 0x48, 0xc3, 0x30, 0x51, 0x53,
+  0x35, 0x59, 0xd3, 0x35, 0x41, 0x13, 0x36, 0x65, 0x93, 0x46, 0x26, 0x2c,
+  0x4d, 0xce, 0x05, 0xee, 0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x8d, 0x52,
+  0x58, 0x9a, 0x9c, 0x8b, 0xdb, 0xdb, 0x17, 0x5c, 0x99, 0xdc, 0x1c, 0x5c,
+  0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x07, 0xb8, 0xb7, 0xb9, 0x21, 0xd0,
+  0x40, 0x4c, 0xdc, 0x64, 0x4d, 0xdd, 0x04, 0x4d, 0xd1, 0x94, 0x4d, 0x1e,
+  0x95, 0xb0, 0x34, 0x39, 0x17, 0xb1, 0x3a, 0x33, 0xb3, 0x32, 0x39, 0x3e,
+  0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73,
+  0x69, 0x7a, 0x65, 0x94, 0xc2, 0xd2, 0xe4, 0x5c, 0xd8, 0xde, 0xc6, 0xc2,
+  0xe8, 0xd2, 0xde, 0xdc, 0xbe, 0xd2, 0xdc, 0xc8, 0xca, 0xf0, 0x88, 0x84,
+  0xa5, 0xc9, 0xb9, 0xc8, 0x95, 0x85, 0x91, 0x91, 0x0a, 0x4b, 0x93, 0x73,
+  0x99, 0xa3, 0x93, 0xab, 0x1b, 0xa3, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb,
+  0x4a, 0x73, 0x33, 0x7b, 0x63, 0x52, 0x65, 0xc5, 0x54, 0x66, 0x46, 0x47,
+  0xf5, 0x06, 0x47, 0xa6, 0xca, 0x8a, 0x28, 0xad, 0xad, 0xcc, 0x6d, 0x2e,
+  0xed, 0xcd, 0x6d, 0x8e, 0x44, 0x5d, 0x9a, 0x1b, 0x1d, 0x91, 0xa6, 0x34,
+  0x38, 0xa6, 0x32, 0xbb, 0x32, 0x36, 0x16, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x64, 0x98, 0xc2, 0xf2, 0xca, 0xe4, 0x9e, 0xe4, 0x88, 0xca, 0xe0, 0xe8,
+  0xd0, 0x86, 0xa0, 0xc1, 0x30, 0x0c, 0xc5, 0x30, 0x4c, 0xd8, 0x54, 0x06,
+  0x43, 0x31, 0x14, 0xc3, 0x30, 0x61, 0x93, 0x19, 0x0c, 0xc9, 0x60, 0x0c,
+  0xc3, 0x74, 0x06, 0x13, 0x1a, 0x0c, 0xca, 0x60, 0x0c, 0xc3, 0x94, 0x06,
+  0x93, 0x1a, 0x30, 0x0a, 0x4b, 0x93, 0x73, 0x09, 0x93, 0x3b, 0xfb, 0xa2,
+  0xcb, 0x83, 0x2b, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0xe3, 0x15, 0x96, 0x26,
+  0xe7, 0x12, 0x26, 0x77, 0xf6, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x15, 0xc6,
+  0x96, 0x76, 0xe6, 0xf6, 0x35, 0x97, 0xa6, 0x57, 0x46, 0x66, 0xea, 0xad,
+  0x4e, 0x6e, 0xac, 0x4c, 0xaa, 0xec, 0x2c, 0xed, 0xcd, 0x8d, 0xcc, 0xdc,
+  0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0xdb, 0x10,
+  0x32, 0x18, 0x8e, 0x09, 0x0c, 0xa6, 0x30, 0x18, 0x90, 0x49, 0x0c, 0x86,
+  0x61, 0x20, 0xa6, 0x31, 0x98, 0xc8, 0x60, 0x5a, 0x83, 0x89, 0x0d, 0x06,
+  0x64, 0x6a, 0x83, 0xa1, 0x98, 0xa0, 0xc9, 0x0d, 0xa6, 0x6c, 0x7a, 0x03,
+  0x2e, 0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65,
+  0x54, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0x88,
+  0xd1, 0x95, 0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0xcd, 0x90, 0xf1, 0x98, 0xb1,
+  0xbd, 0x85, 0xd1, 0xb1, 0x80, 0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xf9,
+  0xb0, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0xa3, 0x2a, 0xc3, 0xa3, 0xab,
+  0x93, 0x2b, 0x1b, 0x42, 0x0d, 0xcb, 0x14, 0x07, 0x93, 0x18, 0x0c, 0xc3,
+  0x40, 0x4c, 0x72, 0x30, 0x41, 0xd3, 0x1c, 0x4c, 0xd9, 0x44, 0x07, 0x5c,
+  0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x78,
+  0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xc9, 0xb1, 0x99, 0x7b, 0xab, 0x93,
+  0x1b, 0x2b, 0x9b, 0x0a, 0x6b, 0x83, 0x63, 0x2b, 0x93, 0x1b, 0x22, 0x0d,
+  0xc6, 0x64, 0x07, 0x93, 0x18, 0x0c, 0xc3, 0x40, 0x4c, 0xd0, 0x74, 0x07,
+  0x53, 0x36, 0xe1, 0xc1, 0x10, 0x65, 0xda, 0xa6, 0x6f, 0x82, 0x83, 0xa9,
+  0x0e, 0xa6, 0x3c, 0x18, 0x62, 0x2c, 0xc0, 0x34, 0x4d, 0x7a, 0xc0, 0xe7,
+  0xad, 0xcd, 0x2d, 0x0d, 0xee, 0x8d, 0xae, 0xcc, 0x8d, 0x0e, 0x64, 0x0c,
+  0x2d, 0x4c, 0x8e, 0xcf, 0x54, 0x5a, 0x1b, 0x1c, 0x5b, 0x19, 0xc8, 0xd0,
+  0xca, 0x0a, 0x08, 0x95, 0x50, 0x50, 0xd0, 0x10, 0x61, 0xea, 0x83, 0x21,
+  0xc6, 0xc4, 0x07, 0x93, 0x1f, 0x54, 0xcd, 0x10, 0x63, 0xfa, 0x83, 0xe9,
+  0x0f, 0xaa, 0x86, 0x5c, 0x58, 0x9a, 0x5c, 0x4b, 0x18, 0x5b, 0x5a, 0xd8,
+  0x5c, 0xcb, 0xdc, 0xd8, 0x1b, 0x5c, 0xd9, 0x1c, 0x8a, 0x10, 0x5b, 0x1a,
+  0x9d, 0x91, 0xdc, 0x5b, 0xdb, 0x0c, 0x51, 0xca, 0x10, 0x62, 0x12, 0x85,
+  0x29, 0x14, 0x68, 0x85, 0xa5, 0xc9, 0xb5, 0x84, 0xb1, 0xa5, 0x85, 0xcd,
+  0xb5, 0xcc, 0x8d, 0xbd, 0xc1, 0x95, 0xb5, 0x84, 0xc9, 0x9d, 0xa1, 0xc8,
+  0xa4, 0x0c, 0x31, 0x26, 0x52, 0x98, 0x44, 0x61, 0x1a, 0x85, 0x21, 0xc2,
+  0x44, 0x0a, 0xc4, 0xc2, 0xd2, 0xe4, 0x5a, 0xc2, 0xd8, 0xd2, 0xc2, 0xe6,
+  0x5a, 0xe6, 0xc6, 0xde, 0xe0, 0xca, 0x5a, 0xe8, 0xca, 0xf0, 0xe8, 0xea,
+  0xe4, 0xca, 0xe6, 0x86, 0x18, 0xd3, 0x29, 0x4c, 0xa2, 0x30, 0x99, 0x02,
+  0xb1, 0xb0, 0x34, 0xb9, 0x96, 0x30, 0xb6, 0xb4, 0xb0, 0xb9, 0x96, 0xb9,
+  0xb1, 0x37, 0xb8, 0xb2, 0x96, 0xb9, 0xb0, 0x36, 0x38, 0xb6, 0x32, 0xb9,
+  0xb9, 0x21, 0xc6, 0x94, 0x0a, 0x93, 0x28, 0x4c, 0xa8, 0x30, 0x84, 0x98,
+  0x4e, 0x61, 0x4a, 0x05, 0x4a, 0x5f, 0x5a, 0x54, 0x53, 0x31, 0x32, 0x53,
+  0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x1c,
+  0xd2, 0xdc, 0xe8, 0x86, 0x18, 0x13, 0x2b, 0x4c, 0x7f, 0x50, 0x35, 0x43,
+  0x8c, 0x29, 0x0d, 0xa6, 0x3f, 0xa8, 0x9a, 0x21, 0xd2, 0xb4, 0x0a, 0xd3,
+  0x1f, 0x54, 0xcd, 0xf4, 0x07, 0x15, 0x33, 0xb5, 0x42, 0xe5, 0x4c, 0xae,
+  0x50, 0x3d, 0x43, 0x8c, 0xe9, 0x15, 0x26, 0x57, 0xa8, 0x9e, 0x21, 0xc6,
+  0xf4, 0x0a, 0x53, 0x2b, 0x54, 0xce, 0x88, 0x88, 0x1d, 0xd8, 0xc1, 0x1e,
+  0xda, 0xc1, 0x0d, 0xda, 0xe1, 0x1d, 0xc8, 0xa1, 0x1e, 0xd8, 0xa1, 0x1c,
+  0xdc, 0xc0, 0x1c, 0xd8, 0x21, 0x1c, 0xce, 0x61, 0x1e, 0xa6, 0x08, 0xc1,
+  0x30, 0x42, 0x61, 0x07, 0x76, 0xb0, 0x87, 0x76, 0x70, 0x83, 0x74, 0x20,
+  0x87, 0x72, 0x70, 0x07, 0x7a, 0x98, 0x12, 0x14, 0x23, 0x96, 0x70, 0x48,
+  0x07, 0x79, 0x70, 0x03, 0x7b, 0x28, 0x07, 0x79, 0x98, 0x87, 0x74, 0x78,
+  0x07, 0x77, 0x98, 0x12, 0x18, 0x23, 0xa8, 0x70, 0x48, 0x07, 0x79, 0x70,
+  0x03, 0x76, 0x08, 0x07, 0x77, 0x38, 0x87, 0x7a, 0x08, 0x87, 0x73, 0x28,
+  0x87, 0x5f, 0xb0, 0x87, 0x72, 0x90, 0x87, 0x79, 0x48, 0x87, 0x77, 0x70,
+  0x87, 0x29, 0x01, 0x32, 0x62, 0x0a, 0x87, 0x74, 0x90, 0x07, 0x37, 0x18,
+  0x87, 0x77, 0x68, 0x07, 0x78, 0x48, 0x07, 0x76, 0x28, 0x87, 0x5f, 0x78,
+  0x07, 0x78, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0x98, 0x87, 0x29, 0x83,
+  0xc2, 0x38, 0x23, 0x98, 0x70, 0x48, 0x07, 0x79, 0x70, 0x03, 0x73, 0x90,
+  0x87, 0x70, 0x38, 0x87, 0x76, 0x28, 0x07, 0x77, 0xa0, 0x87, 0x29, 0xc1,
+  0x1e, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08,
+  0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38,
+  0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71,
+  0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c,
+  0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d,
+  0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d,
+  0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07,
+  0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87,
+  0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30,
+  0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10,
+  0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66,
+  0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c,
+  0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07,
+  0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87,
+  0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05,
+  0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87,
+  0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0,
+  0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca,
+  0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38,
+  0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c,
+  0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87,
+  0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87,
+  0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00,
+  0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20,
+  0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2,
+  0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4,
+  0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a,
+  0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07,
+  0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90,
+  0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8,
+  0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc,
+  0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b,
+  0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b,
+  0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87,
+  0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81,
+  0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30,
+  0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde,
+  0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b,
+  0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39,
+  0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07,
+  0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6,
+  0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30,
+  0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30,
+  0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50,
+  0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8,
+  0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8,
+  0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d,
+  0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07,
+  0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87,
+  0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0,
+  0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28,
+  0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87,
+  0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87,
+  0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20,
+  0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x16, 0xb0, 0x01, 0x48, 0xe4, 0x4b,
+  0x00, 0xf3, 0x2c, 0xc4, 0x3f, 0x11, 0xd7, 0x44, 0x45, 0xc4, 0x7f, 0x0f,
+  0x7e, 0x85, 0x17, 0xb7, 0x6d, 0x00, 0xca, 0xb6, 0x20, 0xd3, 0x17, 0x39,
+  0xcc, 0xdd, 0x99, 0xc0, 0x05, 0x20, 0x91, 0x2f, 0x38, 0x4d, 0x45, 0x44,
+  0x93, 0x5f, 0xf8, 0xc5, 0x6d, 0xfb, 0x94, 0x8f, 0xdc, 0x36, 0x00, 0x00,
+  0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x13, 0x04,
+  0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xe4, 0x46,
+  0x00, 0x68, 0xcc, 0x00, 0x50, 0xab, 0x01, 0x72, 0x73, 0x0c, 0x03, 0x71,
+  0x91, 0x98, 0x01, 0x00, 0x00, 0x00, 0xe3, 0x0d, 0x88, 0x83, 0x51, 0x40,
+  0xc6, 0x1b, 0x14, 0x28, 0xa3, 0x80, 0x58, 0xe0, 0xc8, 0xc7, 0x02, 0x02,
+  0x3e, 0x83, 0x0c, 0xc1, 0x81, 0x8c, 0x37, 0x3c, 0xd5, 0x45, 0xc1, 0x98,
+  0x63, 0x18, 0x82, 0x6e, 0xbc, 0x41, 0xc2, 0x3c, 0x0a, 0xc8, 0x88, 0x01,
+  0x41, 0x04, 0x65, 0x10, 0x8c, 0x18, 0x28, 0x45, 0x70, 0x06, 0xd4, 0x44,
+  0x40, 0x12, 0x14, 0x64, 0x10, 0x10, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00,
+  0x00, 0x00, 0x5b, 0x8e, 0x20, 0x00, 0x85, 0xa3, 0x14, 0x10, 0x55, 0xd8,
+  0x72, 0x0c, 0x01, 0x28, 0x1c, 0xa5, 0x80, 0xa8, 0xc2, 0x96, 0x03, 0x09,
+  0x60, 0xe1, 0x28, 0x05, 0x44, 0x15, 0xb6, 0x1c, 0x4b, 0x10, 0x0b, 0x47,
+  0x29, 0x20, 0xaa, 0xb0, 0xa5, 0x68, 0x0e, 0x55, 0x40, 0x4a, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom3D_metallib_len = 3694;
+const unsigned char BlitFromCube_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x0e, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0d, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x43, 0x75, 0x62, 0x65, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01,
+  0x00, 0x01, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0xd2, 0xe8, 0x3e, 0xc7,
+  0x78, 0x5b, 0xc9, 0x16, 0x13, 0xfb, 0xf4, 0x38, 0xcd, 0x15, 0x4c, 0x67,
+  0x53, 0x5a, 0x33, 0x1a, 0x95, 0x28, 0x3c, 0x95, 0x2f, 0x7b, 0xb6, 0x59,
+  0xef, 0xbd, 0xf1, 0x24, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45,
+  0x52, 0x53, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54,
+  0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b,
+  0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x9c, 0x0e, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00,
+  0xa4, 0x03, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24,
+  0x48, 0x0a, 0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72,
+  0x24, 0x07, 0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0,
+  0x01, 0x00, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00,
+  0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x60, 0x00, 0x09,
+  0xa8, 0x88, 0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77, 0xc0, 0x87, 0x36,
+  0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36,
+  0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1,
+  0x1c, 0x00, 0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0xe1,
+  0x1c, 0xc2, 0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0xe1,
+  0x1d, 0xe4, 0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81, 0x1e, 0xd0, 0x01,
+  0x88, 0x03, 0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77, 0x68, 0x03, 0x71,
+  0xa8, 0x87, 0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77, 0x98, 0x07, 0x80,
+  0x70, 0x87, 0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70, 0x68, 0x87, 0x72,
+  0x68, 0x03, 0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a, 0x28, 0x07, 0x79,
+  0x68, 0x83, 0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80, 0x1e, 0xe4, 0xa1,
+  0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21,
+  0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81,
+  0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0xa1,
+  0x0d, 0xdc, 0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xc2, 0xc1,
+  0x1c, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77,
+  0x68, 0x83, 0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78,
+  0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1,
+  0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1d, 0xc2, 0xc1,
+  0x1d, 0xe6, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81,
+  0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77,
+  0x78, 0x87, 0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77, 0x28, 0x07, 0x72,
+  0x68, 0x03, 0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79, 0x68, 0x03, 0x73,
+  0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41,
+  0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe8, 0x41,
+  0x1e, 0xc2, 0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1, 0x1c, 0xda, 0xa0,
+  0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72,
+  0x00, 0x88, 0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75, 0x68, 0x03, 0x78,
+  0x90, 0x87, 0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79,
+  0x68, 0x03, 0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72, 0x90, 0x87, 0x36,
+  0x98, 0x87, 0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00, 0x20, 0xea, 0xc1,
+  0x1d, 0xe6, 0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1,
+  0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a,
+  0x28, 0x07, 0x60, 0xc3, 0x26, 0x0c, 0xc0, 0x02, 0x54, 0x43, 0x38, 0xa4,
+  0x83, 0x3c, 0xb4, 0x81, 0x38, 0xd4, 0x83, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x1b, 0xb8, 0xc3, 0x3b, 0xb4, 0x41, 0x38, 0xb0, 0x43, 0x3a, 0x84,
+  0xc3, 0x3c, 0x00, 0x1b, 0x8c, 0xa1, 0x00, 0x16, 0xa0, 0xda, 0x80, 0x10,
+  0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x0c, 0x20, 0x01, 0xd5, 0x06, 0xa3,
+  0x08, 0x80, 0x05, 0xa8, 0x36, 0x18, 0x86, 0x00, 0x2c, 0x40, 0xb5, 0xc1,
+  0x38, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x24, 0x80, 0xda, 0x60, 0x20,
+  0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x12, 0x40, 0x6d, 0x40, 0x92, 0xff,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x06, 0x90, 0x80, 0x0a, 0x00, 0x00, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18,
+  0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48,
+  0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x74, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30,
+  0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30,
+  0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10,
+  0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4b, 0x9a, 0x22, 0x4a, 0x98, 0xfc,
+  0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0x5f, 0xa0, 0x02, 0xe2, 0x9f, 0xc6,
+  0x08, 0x80, 0x41, 0x04, 0x23, 0xb8, 0x48, 0x9a, 0x22, 0x4a, 0x98, 0xfc,
+  0x5f, 0x02, 0x98, 0x67, 0x21, 0xa2, 0x7f, 0x1a, 0x23, 0x00, 0x06, 0x11,
+  0x10, 0xa1, 0x18, 0x41, 0x84, 0x72, 0x12, 0xa9, 0x61, 0x84, 0x01, 0x98,
+  0x23, 0x08, 0x8a, 0x11, 0x4e, 0x62, 0x0d, 0x90, 0x2b, 0x02, 0x18, 0x04,
+  0x8b, 0x30, 0x00, 0xc9, 0x81, 0x80, 0x14, 0x18, 0x73, 0x04, 0xa0, 0x30,
+  0x88, 0x20, 0x08, 0x83, 0x08, 0x80, 0x30, 0x05, 0x30, 0x02, 0x30, 0x8c,
+  0x30, 0x0c, 0x83, 0x08, 0x83, 0x00, 0x00, 0x00, 0x13, 0xa8, 0x70, 0x48,
+  0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60,
+  0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8, 0x03, 0x37, 0x80,
+  0x03, 0x37, 0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d, 0x00, 0x0f, 0x7a,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d,
+  0x90, 0x0e, 0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9,
+  0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a,
+  0x10, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6,
+  0x40, 0x07, 0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76, 0xa0, 0x07, 0x71,
+  0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6,
+  0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a,
+  0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x90, 0x07, 0x72,
+  0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76,
+  0xd0, 0x06, 0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75,
+  0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x75,
+  0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75,
+  0x10, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74,
+  0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70,
+  0x20, 0x07, 0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x43, 0x98, 0x05, 0x00, 0x80, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x21, 0xcc, 0x03, 0x04, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x10, 0x26, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x60, 0x08, 0x33, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x90, 0x05, 0x02, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a,
+  0x23, 0x00, 0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05, 0x53, 0x20, 0x85,
+  0x52, 0x06, 0x64, 0x0b, 0x62, 0x04, 0xa0, 0x40, 0x0a, 0x85, 0xea, 0x58,
+  0x42, 0x24, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00,
+  0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9,
+  0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x80, 0x50, 0x40, 0x15, 0x51, 0xb9,
+  0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x0c,
+  0x05, 0x25, 0x0c, 0x07, 0xdf, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4,
+  0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd,
+  0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x07, 0x04, 0xa5,
+  0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46, 0x66,
+  0xc6, 0x25, 0x07, 0x27, 0x65, 0x88, 0x40, 0x11, 0x43, 0x8c, 0xa1, 0x18,
+  0x8c, 0x81, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04, 0xa1, 0x8e,
+  0xa1, 0x18, 0x8a, 0x81, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6,
+  0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36,
+  0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44, 0xa0, 0x12,
+  0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+  0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65,
+  0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x6a, 0x21, 0x19, 0x84, 0xa5,
+  0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9,
+  0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95,
+  0xd1, 0x8d, 0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11,
+  0xa8, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99, 0x1b, 0x59, 0x99,
+  0xdc, 0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3, 0xb0, 0x34, 0x39,
+  0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0x2f, 0xb7, 0xb0,
+  0xb6, 0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x43, 0x10, 0xea,
+  0x19, 0x08, 0x0a, 0xa2, 0xa2, 0x21, 0x02, 0x25, 0x51, 0x0a, 0x4b, 0x93,
+  0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0xfb, 0x4a, 0x73,
+  0x83, 0xab, 0xa3, 0x23, 0x75, 0x56, 0xe6, 0x56, 0x26, 0x17, 0x46, 0x57,
+  0x46, 0x86, 0x32, 0x43, 0x57, 0x86, 0x47, 0x64, 0x27, 0xf3, 0x65, 0x96,
+  0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d, 0xae, 0x4c, 0x8e,
+  0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9, 0x18,
+  0x5d, 0x9a, 0x5d, 0x19, 0x0d, 0x33, 0xb6, 0xb7, 0x30, 0x3a, 0x19, 0x32,
+  0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+  0x1c, 0xe8, 0xca, 0xf0, 0x86, 0x48, 0x03, 0x41, 0x51, 0x54, 0x45, 0x59,
+  0xd4, 0x45, 0x41, 0x14, 0x46, 0x65, 0x94, 0x46, 0x26, 0x2c, 0x4d, 0xce,
+  0x05, 0xee, 0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x8d, 0x52, 0x58, 0x9a,
+  0x9c, 0x8b, 0xdb, 0xdb, 0x17, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9, 0x18,
+  0x5d, 0x9a, 0x5d, 0x19, 0x07, 0xb8, 0xb7, 0xb9, 0x21, 0xd0, 0x50, 0x50,
+  0x1c, 0x65, 0x51, 0x1d, 0x05, 0x51, 0x11, 0x95, 0x51, 0x1e, 0x95, 0xb0,
+  0x34, 0x39, 0x17, 0xb1, 0x3a, 0x33, 0xb3, 0x32, 0x39, 0x3e, 0x61, 0x69,
+  0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a,
+  0x65, 0x94, 0xc2, 0xd2, 0xe4, 0x5c, 0xd8, 0xde, 0xc6, 0xc2, 0xe8, 0xd2,
+  0xde, 0xdc, 0xbe, 0xd2, 0xdc, 0xc8, 0xca, 0xf0, 0x88, 0x84, 0xa5, 0xc9,
+  0xb9, 0xc8, 0x95, 0x85, 0x91, 0x91, 0x0a, 0x4b, 0x93, 0x73, 0x99, 0xa3,
+  0x93, 0xab, 0x1b, 0xa3, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb, 0x4a, 0x73,
+  0x33, 0x7b, 0x63, 0x52, 0x65, 0xc5, 0x54, 0x66, 0x46, 0x47, 0xf5, 0x06,
+  0x47, 0xa6, 0xca, 0x8a, 0x28, 0xad, 0xad, 0xcc, 0x6d, 0x2e, 0xed, 0xcd,
+  0x6d, 0x8e, 0x44, 0x5d, 0x9a, 0x1b, 0x1d, 0x91, 0xa6, 0x34, 0x38, 0xa6,
+  0x32, 0xbb, 0x32, 0x36, 0x16, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x64, 0x98,
+  0xc2, 0xf2, 0xca, 0xe4, 0x9e, 0xe4, 0x88, 0xca, 0xe0, 0xe8, 0xd0, 0x86,
+  0xa0, 0xc1, 0x40, 0x0c, 0xc6, 0x40, 0x50, 0x18, 0x55, 0x06, 0x83, 0x31,
+  0x18, 0x03, 0x41, 0x61, 0x94, 0x19, 0x0c, 0xca, 0x70, 0x0c, 0x04, 0x75,
+  0x06, 0x14, 0x1a, 0x0c, 0xcb, 0x70, 0x0c, 0x04, 0x95, 0x06, 0x94, 0x1a,
+  0x30, 0x0a, 0x4b, 0x93, 0x73, 0x09, 0x93, 0x3b, 0xfb, 0xa2, 0xcb, 0x83,
+  0x2b, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0xe3, 0x15, 0x96, 0x26, 0xe7, 0x12,
+  0x26, 0x77, 0xf6, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x15, 0xc6, 0x96, 0x76,
+  0xe6, 0xf6, 0x35, 0x97, 0xa6, 0x57, 0x46, 0x66, 0xea, 0xad, 0x4e, 0x6e,
+  0xac, 0x4c, 0xaa, 0xec, 0x2c, 0xed, 0xcd, 0x8d, 0xcc, 0xdc, 0x5b, 0x9d,
+  0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0xdb, 0x10, 0x32, 0x18,
+  0x10, 0x0a, 0x0c, 0xa8, 0x30, 0x18, 0x12, 0x4a, 0x0c, 0x06, 0x62, 0x28,
+  0xa8, 0x31, 0xa0, 0xc8, 0x80, 0x5a, 0x03, 0x8a, 0x0d, 0x86, 0x84, 0x6a,
+  0x83, 0xc1, 0xa0, 0x20, 0xca, 0x0d, 0xa8, 0x8c, 0x7a, 0x03, 0x2e, 0x61,
+  0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x54, 0xc2,
+  0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xa8, 0xd1, 0x95,
+  0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0x8d, 0xd5, 0x89, 0x95, 0xf1, 0x98, 0xb1,
+  0xbd, 0x85, 0xd1, 0xb1, 0x80, 0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xf9,
+  0xb0, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0xa3, 0x2a, 0xc3, 0xa3, 0xab,
+  0x93, 0x2b, 0x1b, 0x42, 0x0d, 0x0c, 0x15, 0x07, 0x94, 0x18, 0x0c, 0xc4,
+  0x50, 0x50, 0x72, 0x40, 0x41, 0xd4, 0x1c, 0x50, 0x19, 0x45, 0x07, 0x5c,
+  0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x78,
+  0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xc9, 0xb1, 0x99, 0x7b, 0xab, 0x93,
+  0x1b, 0x2b, 0x9b, 0x0a, 0x6b, 0x83, 0x63, 0x2b, 0x93, 0x1b, 0x22, 0x0d,
+  0x07, 0x65, 0x07, 0x94, 0x18, 0x0c, 0xc4, 0x50, 0x50, 0x10, 0x75, 0x07,
+  0x54, 0x46, 0xe1, 0xc1, 0x10, 0x85, 0xda, 0xa8, 0x8f, 0x82, 0x03, 0xaa,
+  0x0e, 0xa8, 0x3c, 0x18, 0x62, 0x2c, 0x00, 0x35, 0x51, 0x7a, 0xc0, 0xe7,
+  0xad, 0xcd, 0x2d, 0x0d, 0xee, 0x8d, 0xae, 0xcc, 0x8d, 0x0e, 0x64, 0x0c,
+  0x2d, 0x4c, 0x8e, 0xcf, 0x54, 0x5a, 0x1b, 0x1c, 0x5b, 0x19, 0xc8, 0xd0,
+  0xca, 0x0a, 0x08, 0x95, 0x50, 0x50, 0xd0, 0x10, 0x81, 0xea, 0x83, 0x21,
+  0x06, 0xc5, 0x07, 0x94, 0x1f, 0x58, 0xce, 0x10, 0x83, 0xfa, 0x03, 0xea,
+  0x0f, 0x2c, 0x87, 0x5e, 0x58, 0x9a, 0x5c, 0x4b, 0x18, 0x5b, 0x5a, 0xd8,
+  0x5c, 0xcb, 0xdc, 0xd8, 0x1b, 0x5c, 0xd9, 0x1c, 0x8a, 0x10, 0x5b, 0x1a,
+  0x9d, 0x91, 0xdc, 0x5b, 0xdb, 0x50, 0x9d, 0x58, 0x59, 0xca, 0x10, 0x82,
+  0x12, 0x05, 0x2a, 0x14, 0x68, 0x85, 0xa5, 0xc9, 0xb5, 0x84, 0xb1, 0xa5,
+  0x85, 0xcd, 0xb5, 0xcc, 0x8d, 0xbd, 0xc1, 0x95, 0xb5, 0x84, 0xc9, 0x9d,
+  0xa1, 0xc8, 0xa4, 0x0c, 0x31, 0x28, 0x52, 0xa0, 0x44, 0x81, 0x1a, 0x85,
+  0x21, 0x02, 0x45, 0x0a, 0xc4, 0xc2, 0xd2, 0xe4, 0x5a, 0xc2, 0xd8, 0xd2,
+  0xc2, 0xe6, 0x5a, 0xe6, 0xc6, 0xde, 0xe0, 0xca, 0x5a, 0xe8, 0xca, 0xf0,
+  0xe8, 0xea, 0xe4, 0xca, 0xe6, 0x86, 0x18, 0xd4, 0x29, 0x50, 0xa2, 0x40,
+  0x99, 0x02, 0xb1, 0xb0, 0x34, 0xb9, 0x96, 0x30, 0xb6, 0xb4, 0xb0, 0xb9,
+  0x96, 0xb9, 0xb1, 0x37, 0xb8, 0xb2, 0x96, 0xb9, 0xb0, 0x36, 0x38, 0xb6,
+  0x32, 0xb9, 0xb9, 0x21, 0x06, 0x95, 0x0a, 0x94, 0x28, 0x50, 0xa8, 0x30,
+  0x84, 0xa0, 0x4e, 0x81, 0x4a, 0x05, 0x4a, 0x5f, 0x5a, 0x54, 0x53, 0x31,
+  0x32, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f,
+  0x6e, 0x1c, 0xd2, 0xdc, 0xe8, 0x86, 0x18, 0x14, 0x2b, 0x50, 0x7f, 0x60,
+  0x39, 0x43, 0x0c, 0x2a, 0x0d, 0xa8, 0x3f, 0xb0, 0x9c, 0x21, 0x12, 0xb5,
+  0x0a, 0xd4, 0x1f, 0x58, 0x0e, 0xf5, 0x07, 0x56, 0x43, 0xb5, 0x82, 0xf5,
+  0x50, 0xae, 0x60, 0x41, 0x43, 0x0c, 0xea, 0x15, 0x28, 0x57, 0xb0, 0xa0,
+  0x21, 0x06, 0xf5, 0x0a, 0x54, 0x2b, 0x58, 0xcf, 0x88, 0x88, 0x1d, 0xd8,
+  0xc1, 0x1e, 0xda, 0xc1, 0x0d, 0xda, 0xe1, 0x1d, 0xc8, 0xa1, 0x1e, 0xd8,
+  0xa1, 0x1c, 0xdc, 0xc0, 0x1c, 0xd8, 0x21, 0x1c, 0xce, 0x61, 0x1e, 0xa6,
+  0x08, 0xc1, 0x30, 0x42, 0x61, 0x07, 0x76, 0xb0, 0x87, 0x76, 0x70, 0x83,
+  0x74, 0x20, 0x87, 0x72, 0x70, 0x07, 0x7a, 0x98, 0x12, 0x14, 0x23, 0x96,
+  0x70, 0x48, 0x07, 0x79, 0x70, 0x03, 0x7b, 0x28, 0x07, 0x79, 0x98, 0x87,
+  0x74, 0x78, 0x07, 0x77, 0x98, 0x12, 0x18, 0x23, 0xa8, 0x70, 0x48, 0x07,
+  0x79, 0x70, 0x03, 0x76, 0x08, 0x07, 0x77, 0x38, 0x87, 0x7a, 0x08, 0x87,
+  0x73, 0x28, 0x87, 0x5f, 0xb0, 0x87, 0x72, 0x90, 0x87, 0x79, 0x48, 0x87,
+  0x77, 0x70, 0x87, 0x29, 0x01, 0x32, 0x62, 0x0a, 0x87, 0x74, 0x90, 0x07,
+  0x37, 0x18, 0x87, 0x77, 0x68, 0x07, 0x78, 0x48, 0x07, 0x76, 0x28, 0x87,
+  0x5f, 0x78, 0x07, 0x78, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0x98, 0x87,
+  0x29, 0x83, 0xc2, 0x38, 0x23, 0x98, 0x70, 0x48, 0x07, 0x79, 0x70, 0x03,
+  0x73, 0x90, 0x87, 0x70, 0x38, 0x87, 0x76, 0x28, 0x07, 0x77, 0xa0, 0x87,
+  0x29, 0xc1, 0x1e, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
+  0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88,
+  0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73,
+  0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e,
+  0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30,
+  0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8,
+  0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b,
+  0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76,
+  0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e,
+  0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e,
+  0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61,
+  0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4,
+  0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37,
+  0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76,
+  0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71,
+  0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e,
+  0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61,
+  0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8,
+  0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc,
+  0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7,
+  0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78,
+  0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f,
+  0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f,
+  0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1,
+  0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0,
+  0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0,
+  0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b,
+  0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c,
+  0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61,
+  0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1,
+  0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc,
+  0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4,
+  0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79,
+  0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72,
+  0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e,
+  0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1,
+  0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4,
+  0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8,
+  0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71,
+  0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19,
+  0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f,
+  0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e,
+  0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e,
+  0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81,
+  0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21,
+  0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc,
+  0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70,
+  0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77,
+  0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e,
+  0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e,
+  0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a,
+  0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73,
+  0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x20, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x26, 0x70, 0x01, 0x48,
+  0xe4, 0x0b, 0x4e, 0x53, 0x11, 0xd1, 0xe4, 0x17, 0x7e, 0x71, 0xdb, 0x3e,
+  0xe5, 0x23, 0xb7, 0x6d, 0x03, 0x17, 0x80, 0x44, 0xbe, 0xe0, 0x34, 0x15,
+  0x11, 0x4d, 0x3e, 0xe5, 0x23, 0xb7, 0xed, 0x17, 0x7e, 0x71, 0xdb, 0x16,
+  0xd0, 0x01, 0x48, 0xe4, 0x4b, 0x00, 0xf3, 0x2c, 0xc4, 0x3f, 0x11, 0xd7,
+  0x44, 0x45, 0xc4, 0x2f, 0x50, 0x01, 0xe1, 0x57, 0x78, 0x71, 0xdb, 0x06,
+  0xc0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0x70, 0x54, 0x40, 0x00, 0x00,
+  0x61, 0x20, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x13, 0x04, 0x48, 0x2c,
+  0x10, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0xb4, 0xc7, 0x1a, 0x80,
+  0x40, 0xa0, 0x56, 0x03, 0x34, 0x4a, 0x81, 0xc0, 0x18, 0x01, 0x08, 0x82,
+  0x20, 0xfe, 0x0b, 0x63, 0x04, 0x20, 0x08, 0x82, 0xf8, 0x37, 0x02, 0x30,
+  0x46, 0x00, 0x82, 0x20, 0x08, 0x82, 0x01, 0x85, 0x39, 0x88, 0x0d, 0x0d,
+  0xd0, 0xc0, 0x0c, 0xe6, 0x20, 0x34, 0x34, 0x40, 0x03, 0x33, 0x98, 0x83,
+  0x40, 0x03, 0x0d, 0x0d, 0xcc, 0x60, 0x0e, 0x02, 0x0d, 0x36, 0x34, 0x30,
+  0x83, 0x39, 0x08, 0x34, 0x40, 0x83, 0xcd, 0x0c, 0xe6, 0x20, 0xd0, 0x00,
+  0x0d, 0x34, 0x33, 0x98, 0x83, 0xe0, 0x38, 0xce, 0x0c, 0x66, 0x00, 0x08,
+  0xcc, 0x00, 0x8c, 0x11, 0x80, 0x20, 0x08, 0x82, 0xa0, 0x30, 0x03, 0x00,
+  0xe3, 0x0d, 0xd5, 0x56, 0x06, 0x14, 0x90, 0xf1, 0x86, 0xab, 0x33, 0x03,
+  0x0a, 0x88, 0x05, 0x9b, 0x7c, 0x2c, 0x20, 0xe0, 0x33, 0x86, 0x10, 0xac,
+  0x81, 0x05, 0x93, 0x7c, 0x2c, 0xb8, 0xe0, 0x33, 0x86, 0x40, 0xb4, 0x81,
+  0x05, 0x96, 0x7c, 0x2c, 0xd0, 0xe0, 0x33, 0xde, 0x10, 0x06, 0x67, 0x90,
+  0x06, 0x14, 0x8c, 0x11, 0x03, 0x82, 0x08, 0xe8, 0x20, 0x18, 0xe6, 0x19,
+  0x82, 0x83, 0x08, 0x0a, 0x01, 0x19, 0x18, 0xe2, 0x28, 0x32, 0xc3, 0x22,
+  0x22, 0x3e, 0x73, 0x0c, 0x5b, 0x40, 0x07, 0x36, 0x25, 0xf1, 0x99, 0x63,
+  0x10, 0x82, 0x39, 0x98, 0x25, 0x38, 0xac, 0x42, 0xe2, 0x33, 0xc7, 0xe0,
+  0x05, 0x78, 0x30, 0xc7, 0x10, 0x34, 0x76, 0x30, 0x4b, 0x70, 0xcc, 0x31,
+  0x7c, 0xce, 0x1e, 0x58, 0xc6, 0xc4, 0x67, 0x8e, 0x41, 0x08, 0xf2, 0x60,
+  0x96, 0xe0, 0x98, 0x63, 0x08, 0x83, 0xc8, 0x0f, 0xe6, 0x18, 0x82, 0x67,
+  0x0f, 0x66, 0x09, 0x0e, 0xeb, 0xa0, 0xf8, 0xcc, 0x31, 0x8c, 0x01, 0x15,
+  0x0a, 0x73, 0x0c, 0x81, 0x10, 0x0a, 0xb3, 0x04, 0x87, 0x81, 0x81, 0x15,
+  0x1f, 0x0b, 0x03, 0x2a, 0x3e, 0x73, 0x0c, 0x66, 0x20, 0x94, 0xc2, 0x1c,
+  0x43, 0x20, 0x94, 0xc2, 0x2c, 0xc1, 0x31, 0xd0, 0x13, 0x08, 0x86, 0x52,
+  0x40, 0x04, 0x35, 0x68, 0x02, 0x18, 0x04, 0xae, 0x00, 0x0c, 0x32, 0x04,
+  0x67, 0x50, 0x07, 0xe3, 0x0d, 0x79, 0xf0, 0x07, 0xa5, 0x40, 0x01, 0x19,
+  0x31, 0x20, 0x88, 0xa0, 0x15, 0x82, 0x11, 0x03, 0xa4, 0x08, 0x5e, 0x61,
+  0x0f, 0xf4, 0x80, 0xc0, 0x83, 0x20, 0x83, 0x80, 0x18, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x5b, 0x8e, 0x20, 0x00, 0x85, 0xa3, 0x14, 0x10,
+  0x55, 0xd8, 0x72, 0x0c, 0x01, 0x28, 0x1c, 0xa5, 0x80, 0xa8, 0xc2, 0x96,
+  0xa3, 0x09, 0x60, 0xe1, 0x28, 0x05, 0x44, 0x15, 0xb6, 0x1c, 0x6c, 0x10,
+  0xc4, 0xc2, 0x51, 0x0a, 0x88, 0x2a, 0x6c, 0x29, 0xdc, 0xe0, 0x50, 0x05,
+  0xa4, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFromCube_metallib_len = 3984;
+#endif
+#elif defined(SDL_PLATFORM_TVOS)
+#if TARGET_OS_SIMULATOR
+const unsigned char FullscreenVert_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x84, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0f, 0x00, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63,
+  0x72, 0x65, 0x65, 0x6e, 0x56, 0x65, 0x72, 0x74, 0x00, 0x54, 0x59, 0x50,
+  0x45, 0x01, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x2e, 0x1e,
+  0xd4, 0x6a, 0x55, 0x70, 0x5f, 0xf4, 0x2e, 0xba, 0x3b, 0x28, 0xfb, 0x35,
+  0xba, 0x0f, 0x45, 0x11, 0x9d, 0x35, 0x85, 0x00, 0x13, 0x2a, 0xcb, 0x9c,
+  0x01, 0xe8, 0x6d, 0xf0, 0xbf, 0x13, 0x4d, 0x44, 0x53, 0x5a, 0x08, 0x00,
+  0x90, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x46, 0x46, 0x54,
+  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x02, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x45, 0x4e, 0x44, 0x54,
+  0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x7c, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x42, 0x43, 0xc0, 0xde, 0x35, 0x14, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x62, 0x0c, 0x30, 0x24, 0x80, 0x10, 0x05, 0xc8, 0x14, 0x00, 0x00, 0x00,
+  0x21, 0x0c, 0x00, 0x00, 0x97, 0x02, 0x00, 0x00, 0x0b, 0x02, 0x21, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91,
+  0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c,
+  0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02,
+  0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b,
+  0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5,
+  0x00, 0x19, 0x32, 0x42, 0x04, 0x49, 0x0e, 0x90, 0x11, 0x22, 0xc4, 0x50,
+  0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, 0x06,
+  0x51, 0x18, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x1b, 0x7a, 0x24, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0x01, 0x90, 0x00, 0x8a, 0x08, 0x07, 0x78, 0x80,
+  0x07, 0x79, 0x78, 0x07, 0x7c, 0x68, 0x03, 0x73, 0xa8, 0x07, 0x77, 0x18,
+  0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40,
+  0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xda, 0x21, 0x1d,
+  0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d,
+  0xec, 0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e,
+  0xd2, 0x81, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x38, 0x00, 0x06, 0x77, 0x78,
+  0x87, 0x36, 0x10, 0x87, 0x7a, 0x48, 0x07, 0x76, 0xa0, 0x87, 0x74, 0x70,
+  0x87, 0x79, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30, 0x07, 0x79, 0x08,
+  0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48, 0x07, 0x77, 0xa0,
+  0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48, 0x87, 0x76, 0x00,
+  0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d,
+  0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d, 0xca, 0xa1, 0x0d, 0xe0, 0xe1, 0x1d,
+  0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xca, 0x81, 0x1d,
+  0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d, 0xde, 0xc1, 0x1d, 0xda, 0x80, 0x1d,
+  0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00,
+  0x08, 0x77, 0x78, 0x87, 0x36, 0x48, 0x07, 0x77, 0x30, 0x87, 0x79, 0x68,
+  0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00,
+  0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d,
+  0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d,
+  0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28,
+  0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83, 0x79, 0x48, 0x87, 0x73, 0x70,
+  0x87, 0x72, 0x20, 0x87, 0x36, 0xd0, 0x87, 0x72, 0x90, 0x87, 0x77, 0x98,
+  0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40,
+  0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d,
+  0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c, 0xe0, 0x01, 0x1e, 0xd2, 0xc1, 0x1d,
+  0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90,
+  0x87, 0x7a, 0x28, 0x07, 0x80, 0x98, 0x07, 0x7a, 0x08, 0x87, 0x71, 0x58,
+  0x87, 0x36, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7a, 0x28, 0x87, 0x71, 0xa0,
+  0x87, 0x77, 0x90, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x30, 0x07, 0x73, 0x28,
+  0x07, 0x79, 0x68, 0x83, 0x79, 0x48, 0x07, 0x7d, 0x28, 0x07, 0x00, 0x0f,
+  0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e, 0xc2, 0xc1, 0x1c, 0xca, 0xa1, 0x0d,
+  0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0,
+  0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x36, 0x18, 0xc2, 0xff, 0xff, 0xff,
+  0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b, 0x8c, 0xe1, 0xff, 0xff, 0xff, 0xff,
+  0x07, 0x40, 0x02, 0x28, 0x00, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06,
+  0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84,
+  0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c,
+  0x0b, 0x84, 0x84, 0x4c, 0x10, 0x38, 0x33, 0x00, 0xc3, 0x08, 0x02, 0x30,
+  0x8c, 0x40, 0x00, 0x56, 0x08, 0x99, 0x23, 0x00, 0x83, 0x22, 0x0c, 0x51,
+  0x15, 0x01, 0x88, 0x6e, 0x20, 0x20, 0x05, 0x68, 0x8e, 0x00, 0x14, 0x86,
+  0x11, 0x08, 0x62, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0xc0, 0x20, 0x1c,
+  0xd2, 0x41, 0x1e, 0xec, 0x80, 0x0e, 0xda, 0x20, 0x1c, 0xe0, 0x01, 0x1e,
+  0xd8, 0xa1, 0x1c, 0xda, 0x80, 0x1e, 0xec, 0xe1, 0x1d, 0xe6, 0x21, 0x0e,
+  0xe6, 0xc0, 0x0d, 0xe0, 0xc0, 0x0d, 0xe0, 0xa0, 0x0d, 0xe6, 0x21, 0x1d,
+  0xda, 0xa1, 0x1e, 0xd8, 0x21, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4, 0x61, 0xc3,
+  0x6d, 0x94, 0x43, 0x1b, 0xc0, 0x83, 0x1e, 0xd8, 0x01, 0x1d, 0xe8, 0x81,
+  0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x41, 0x3a, 0xc4, 0x81,
+  0x1e, 0xe0, 0x81, 0x1e, 0xe0, 0x41, 0x1b, 0xa4, 0x03, 0x1e, 0xe8, 0x01,
+  0x1e, 0xe8, 0x01, 0x1e, 0xb4, 0x41, 0x3a, 0xc4, 0x81, 0x1d, 0xe8, 0x41,
+  0x1c, 0xd8, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xb4, 0x41, 0x3a, 0xcc, 0x81,
+  0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x41,
+  0x3a, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01,
+  0x1d, 0xb4, 0x81, 0x39, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81,
+  0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81, 0x39, 0xd8, 0x01, 0x1d, 0xe8, 0x81,
+  0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xc4, 0x81,
+  0x1d, 0xe8, 0x41, 0x1c, 0xd8, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xb4, 0x81,
+  0x3d, 0xc8, 0x01, 0x1d, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81,
+  0x1c, 0xb4, 0x81, 0x3d, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81,
+  0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xd0, 0x01, 0x1e, 0xe8, 0x81,
+  0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xd8, 0x01,
+  0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81,
+  0x3d, 0xe4, 0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xc8, 0x01, 0x1e, 0xe8, 0x41,
+  0x1c, 0xc8, 0x01, 0x1e, 0xb4, 0x81, 0x3d, 0xc4, 0x81, 0x1c, 0xe0, 0x81,
+  0x1e, 0xc4, 0x81, 0x1c, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1c, 0xe0, 0x41,
+  0x1b, 0xd8, 0x43, 0x1c, 0xe4, 0x81, 0x1c, 0xe8, 0x81, 0x1c, 0xd4, 0x81,
+  0x1d, 0xe8, 0x81, 0x1c, 0xd4, 0x81, 0x1d, 0xb4, 0x81, 0x3d, 0xc8, 0x41,
+  0x1d, 0xd8, 0x81, 0x1e, 0xc8, 0x41, 0x1d, 0xd8, 0x81, 0x1e, 0xc8, 0x41,
+  0x1d, 0xd8, 0x41, 0x1b, 0xd8, 0x43, 0x1d, 0xc4, 0x81, 0x1c, 0xe8, 0x41,
+  0x1d, 0xc4, 0x81, 0x1c, 0xe8, 0x41, 0x1d, 0xc4, 0x81, 0x1c, 0xb4, 0x81,
+  0x3d, 0xc4, 0x01, 0x1c, 0xc8, 0x01, 0x1d, 0xe8, 0x41, 0x1c, 0xc0, 0x81,
+  0x1c, 0xd0, 0x81, 0x1e, 0xc4, 0x01, 0x1c, 0xc8, 0x01, 0x1d, 0xb4, 0x81,
+  0x3b, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xe8, 0xc1, 0x1c, 0xc8, 0x81,
+  0x46, 0x08, 0x43, 0x3a, 0x1f, 0xb5, 0x2c, 0x92, 0x10, 0x11, 0x44, 0xf3,
+  0x12, 0xd1, 0x34, 0x24, 0x02, 0x9c, 0x02, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x00, 0x86, 0x44, 0xce, 0x75, 0x00, 0x01, 0x20,
+  0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0xc4, 0x06, 0x81, 0xa2,
+  0x99, 0x02, 0x00, 0x00, 0x59, 0x20, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x32, 0x1e, 0x98, 0x0c, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47,
+  0xc6, 0x04, 0x43, 0xa2, 0x22, 0x28, 0x81, 0x42, 0x18, 0x01, 0x20, 0x1d,
+  0x4b, 0x88, 0x04, 0x00, 0xb1, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
+  0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88,
+  0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73,
+  0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e,
+  0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30,
+  0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8,
+  0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b,
+  0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76,
+  0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e,
+  0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e,
+  0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61,
+  0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4,
+  0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37,
+  0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76,
+  0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71,
+  0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e,
+  0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61,
+  0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8,
+  0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc,
+  0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7,
+  0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78,
+  0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f,
+  0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f,
+  0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1,
+  0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0,
+  0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0,
+  0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b,
+  0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c,
+  0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61,
+  0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1,
+  0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc,
+  0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4,
+  0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79,
+  0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72,
+  0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e,
+  0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1,
+  0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4,
+  0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8,
+  0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71,
+  0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19,
+  0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f,
+  0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e,
+  0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e,
+  0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81,
+  0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21,
+  0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc,
+  0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70,
+  0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77,
+  0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e,
+  0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e,
+  0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a,
+  0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73,
+  0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x79, 0x20, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x32, 0x9a, 0x08, 0x14,
+  0x02, 0x85, 0x8c, 0x27, 0x46, 0x46, 0xc8, 0x11, 0x32, 0x64, 0xd4, 0x26,
+  0xe8, 0x4c, 0x00, 0x00, 0x8b, 0xf2, 0x06, 0xc5, 0xc6, 0x91, 0x41, 0x44,
+  0x45, 0x06, 0x33, 0x30, 0xc6, 0xd0, 0x10, 0x02, 0x53, 0x44, 0x4b, 0x20,
+  0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x77, 0x63, 0x68, 0x61, 0x72,
+  0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x6d,
+  0x65, 0x74, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+  0x20, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x20, 0x28, 0x6d,
+  0x65, 0x74, 0x61, 0x6c, 0x66, 0x65, 0x2d, 0x33, 0x32, 0x30, 0x32, 0x33,
+  0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65, 0x74, 0x61, 0x6c, 0x61, 0x69, 0x72,
+  0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x64, 0x65, 0x6e,
+  0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e,
+  0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e,
+  0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70,
+  0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x62, 0x75, 0x66,
+  0x66, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x65, 0x6e,
+  0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x65, 0x72, 0x74,
+  0x65, 0x78, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x67, 0x65, 0x6e,
+  0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x28, 0x33, 0x74, 0x65, 0x78, 0x44,
+  0x76, 0x32, 0x5f, 0x66, 0x29, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67,
+  0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x66, 0x6c,
+  0x6f, 0x61, 0x74, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f,
+  0x6e, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x78, 0x61, 0x69, 0x72, 0x2e, 0x70,
+  0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x34, 0x70, 0x6f, 0x73, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x65, 0x72, 0x74,
+  0x65, 0x78, 0x5f, 0x69, 0x64, 0x75, 0x69, 0x6e, 0x74, 0x76, 0x49, 0x00,
+  0x23, 0x08, 0x84, 0x30, 0x82, 0xa0, 0x18, 0x23, 0x08, 0xc4, 0x30, 0x82,
+  0x40, 0x10, 0x23, 0x08, 0x44, 0x31, 0x82, 0x60, 0x00, 0x33, 0x0c, 0x54,
+  0x50, 0xcd, 0x30, 0x58, 0xc2, 0x35, 0x43, 0x30, 0xcc, 0x30, 0x50, 0x14,
+  0x36, 0x03, 0x41, 0x58, 0x16, 0x36, 0x43, 0x50, 0xcc, 0x10, 0x18, 0x33,
+  0x04, 0xc7, 0x0c, 0x06, 0x92, 0x28, 0x0b, 0xd3, 0xcc, 0x50, 0x38, 0xca,
+  0xc3, 0x40, 0x33, 0x08, 0x62, 0x30, 0x06, 0x33, 0x18, 0x58, 0xa4, 0x48,
+  0xcc, 0x34, 0x43, 0x50, 0x06, 0x33, 0x0c, 0x19, 0x19, 0x98, 0x81, 0x8c,
+  0x04, 0x26, 0xe8, 0x22, 0x36, 0x36, 0xbb, 0x36, 0x97, 0xb6, 0x37, 0xb2,
+  0x3a, 0xb6, 0x32, 0x17, 0x33, 0xb6, 0xb0, 0xb3, 0xb9, 0x51, 0x84, 0x4c,
+  0x3b, 0x85, 0x8d, 0xcd, 0xae, 0xcd, 0x25, 0x8d, 0xac, 0xcc, 0x8d, 0x6e,
+  0x94, 0x60, 0xbb, 0x25, 0x2c, 0x4d, 0xce, 0xc5, 0xae, 0x4c, 0x6e, 0x2e,
+  0xed, 0xcd, 0x6d, 0x94, 0x80, 0x3b, 0x2a, 0x2c, 0x4d, 0xce, 0x85, 0x2d,
+  0xcc, 0xed, 0xac, 0x2e, 0xec, 0xac, 0xec, 0xcb, 0xae, 0x4c, 0x6e, 0x2e,
+  0xed, 0xcd, 0x6d, 0x94, 0xa0, 0xbb, 0x29, 0x2c, 0x4d, 0xce, 0x65, 0xec,
+  0xad, 0x0d, 0x2e, 0x8d, 0xad, 0xec, 0xeb, 0x0d, 0x8e, 0x2e, 0xed, 0xcd,
+  0x6d, 0x6e, 0x94, 0xc1, 0xfb, 0xc0, 0xe0, 0x94, 0xb0, 0x34, 0x39, 0x17,
+  0xbb, 0x32, 0x39, 0xba, 0x32, 0xbc, 0x51, 0x02, 0x33, 0x00, 0x00, 0x00,
+  0xa9, 0x18, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x72, 0x28,
+  0x87, 0x77, 0x80, 0x07, 0x7a, 0x58, 0x70, 0x98, 0x43, 0x3d, 0xb8, 0xc3,
+  0x38, 0xb0, 0x43, 0x39, 0xd0, 0xc3, 0x82, 0xe6, 0x1c, 0xc6, 0xa1, 0x0d,
+  0xe8, 0x41, 0x1e, 0xc2, 0xc1, 0x1d, 0xe6, 0x21, 0x1d, 0xe8, 0x21, 0x1d,
+  0xde, 0xc1, 0x1d, 0x16, 0x34, 0xe3, 0x60, 0x0e, 0xe7, 0x50, 0x0f, 0xe1,
+  0x20, 0x0f, 0xe4, 0x40, 0x0f, 0xe1, 0x20, 0x0f, 0xe7, 0x50, 0x0e, 0xf4,
+  0xb0, 0x80, 0x81, 0x07, 0x79, 0x28, 0x87, 0x70, 0x60, 0x07, 0x76, 0x78,
+  0x87, 0x71, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x58, 0x70, 0x9c, 0xc3,
+  0x38, 0xb4, 0x01, 0x3b, 0xa4, 0x83, 0x3d, 0x94, 0xc3, 0x02, 0x6b, 0x1c,
+  0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c, 0xdc, 0x20, 0x1c, 0xe4, 0x61, 0x1c,
+  0xdc, 0x20, 0x1c, 0xe8, 0x81, 0x1e, 0xc2, 0x61, 0x1c, 0xd0, 0xa1, 0x1c,
+  0xc8, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0x61, 0xc1, 0x01, 0x0f, 0xf4,
+  0x20, 0x0f, 0xe1, 0x50, 0x0f, 0xf4, 0x80, 0x0e, 0x00, 0x00, 0x00, 0x00,
+  0xd1, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0xcc, 0x3c, 0xa4,
+  0x83, 0x3b, 0x9c, 0x03, 0x3b, 0x94, 0x03, 0x3d, 0xa0, 0x83, 0x3c, 0x94,
+  0x43, 0x38, 0x90, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x44, 0x33, 0x00, 0xb4, 0x23, 0x00, 0x25, 0x40,
+  0x3c, 0x07, 0x51, 0x0c, 0x08, 0x32, 0x16, 0x01, 0x04, 0xc6, 0x41, 0x30,
+  0x03, 0x30, 0x02, 0x30, 0x46, 0x00, 0x82, 0x20, 0x88, 0x7f, 0x14, 0x33,
+  0x00, 0x63, 0x09, 0x20, 0x08, 0x82, 0x20, 0x18, 0x80, 0x20, 0x08, 0x82,
+  0xe0, 0x30, 0x96, 0x00, 0x82, 0x20, 0x88, 0xff, 0x02, 0x08, 0x82, 0x20,
+  0xfe, 0xcd, 0x00, 0x90, 0xcc, 0x41, 0x34, 0x8d, 0xf3, 0xd0, 0xcc, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf5, 0x4c, 0x57, 0x41, 0xa5, 0x23, 0x06, 0xc6,
+  0x10, 0x82, 0x60, 0xe1, 0x1f, 0xc7, 0x15, 0xcc, 0x31, 0x24, 0x01, 0x54,
+  0x13, 0xa6, 0x23, 0x06, 0xc6, 0x10, 0x82, 0x60, 0xe1, 0x1f, 0x87, 0x16,
+  0xcc, 0x31, 0x0c, 0x81, 0x64, 0x01, 0x23, 0xfe, 0x16, 0x30, 0xe0, 0x3f,
+  0xc8, 0x10, 0x30, 0xd4, 0x20, 0x43, 0xc0, 0x50, 0xb3, 0x0d, 0x4c, 0x01,
+  0xcc, 0x36, 0x04, 0x42, 0x90, 0x01, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x32, 0x0e, 0x10, 0x22, 0x84, 0x00, 0xf2, 0x04,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x0c, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0x28, 0x01, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x00, 0x24, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x08, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x0c, 0x00, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0xad, 0x00, 0x00, 0x00, 0x00,
+  0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x56, 0x65,
+  0x72, 0x74, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72,
+  0x74, 0x2e, 0x66, 0x2e, 0x66, 0x33, 0x32, 0x2e, 0x75, 0x2e, 0x69, 0x33,
+  0x32, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x61, 0x69, 0x72,
+  0x36, 0x34, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2d, 0x74, 0x76, 0x6f,
+  0x73, 0x31, 0x33, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x73, 0x69, 0x6d, 0x75,
+  0x6c, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int FullscreenVert_metallib_len = 3204;
+const unsigned char BlitFrom2D_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0b, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x32, 0x44, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01,
+  0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x43, 0x70, 0xfa, 0xc8, 0xf6, 0x38,
+  0xe9, 0xd2, 0xab, 0xa0, 0x58, 0xac, 0xf6, 0x22, 0xbd, 0xaa, 0x22, 0xd5,
+  0x67, 0x05, 0x3b, 0x97, 0x5c, 0x75, 0x25, 0xa4, 0x41, 0xf0, 0x2e, 0x32,
+  0x93, 0x64, 0x4d, 0x44, 0x53, 0x5a, 0x08, 0x00, 0x90, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45,
+  0x52, 0x53, 0x08, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54,
+  0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x74, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde,
+  0x35, 0x14, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x0c, 0x30, 0x24,
+  0x80, 0x10, 0x05, 0xc8, 0x14, 0x00, 0x00, 0x00, 0x21, 0x0c, 0x00, 0x00,
+  0x8a, 0x03, 0x00, 0x00, 0x0b, 0x02, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88,
+  0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42,
+  0x04, 0x49, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c,
+  0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00,
+  0x83, 0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff,
+  0x01, 0x58, 0x03, 0x40, 0x02, 0x2a, 0x22, 0x1c, 0xe0, 0x01, 0x1e, 0xe4,
+  0xe1, 0x1d, 0xf0, 0xa1, 0x0d, 0xcc, 0xa1, 0x1e, 0xdc, 0x61, 0x1c, 0xda,
+  0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x68, 0x87, 0x74, 0x70, 0x87,
+  0x36, 0x60, 0x87, 0x72, 0x38, 0x87, 0x70, 0x60, 0x87, 0x36, 0xb0, 0x87,
+  0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x83, 0x7b, 0x48, 0x07,
+  0x72, 0xa0, 0x07, 0x74, 0x00, 0xe2, 0x40, 0x0e, 0xf0, 0x00, 0x18, 0xdc,
+  0xe1, 0x1d, 0xda, 0x40, 0x1c, 0xea, 0x21, 0x1d, 0xd8, 0x81, 0x1e, 0xd2,
+  0xc1, 0x1d, 0xe6, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4,
+  0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc,
+  0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87,
+  0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07,
+  0x76, 0x48, 0x87, 0x76, 0x68, 0x03, 0x77, 0x78, 0x07, 0x77, 0x68, 0x03,
+  0x76, 0x28, 0x87, 0x70, 0x30, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x20, 0x1d, 0xdc, 0xc1, 0x1c, 0xe6,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x70, 0x87, 0x70, 0x70, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xce,
+  0xc1, 0x1d, 0xca, 0x81, 0x1c, 0xda, 0x40, 0x1f, 0xca, 0x41, 0x1e, 0xde,
+  0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8,
+  0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87,
+  0x77, 0x68, 0x03, 0x7a, 0x90, 0x87, 0x70, 0x80, 0x07, 0x78, 0x48, 0x07,
+  0x77, 0x38, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8,
+  0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0x62, 0x1e, 0xe8, 0x21, 0x1c, 0xc6,
+  0x61, 0x1d, 0xda, 0x00, 0x1e, 0xe4, 0xe1, 0x1d, 0xe8, 0xa1, 0x1c, 0xc6,
+  0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0x40, 0x1c, 0xea, 0xc1, 0x1c, 0xcc,
+  0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xf4, 0xa1, 0x1c, 0x00,
+  0x3c, 0x00, 0x88, 0x7a, 0x70, 0x87, 0x79, 0x08, 0x07, 0x73, 0x28, 0x87,
+  0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07,
+  0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0xd8, 0xe0, 0x09, 0x03, 0xb0,
+  0x00, 0x55, 0x90, 0x06, 0xd8, 0x10, 0x0e, 0xe9, 0x20, 0x0f, 0x6d, 0x20,
+  0x0e, 0xf5, 0x60, 0x0e, 0xe6, 0x50, 0x0e, 0xf2, 0xd0, 0x06, 0xee, 0xf0,
+  0x0e, 0x6d, 0x10, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0xc0, 0x06,
+  0x63, 0x28, 0x80, 0x05, 0xa8, 0x36, 0x28, 0xc4, 0xff, 0xff, 0xff, 0xff,
+  0x0f, 0x40, 0x1b, 0x00, 0x6b, 0x00, 0x48, 0x40, 0xb5, 0xc1, 0x28, 0x02,
+  0x60, 0x01, 0xaa, 0x0d, 0x86, 0x21, 0x00, 0x0b, 0x50, 0x6d, 0x30, 0x8e,
+  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa0, 0x36, 0x18, 0xc8, 0xff,
+  0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b, 0x94, 0xe4, 0xff, 0xff,
+  0xff, 0xff, 0x07, 0xa0, 0x0d, 0x80, 0x35, 0x00, 0x24, 0xa0, 0x02, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18,
+  0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48,
+  0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x68, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30,
+  0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30,
+  0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10,
+  0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4a, 0x9a, 0x22, 0x4a, 0x98, 0xfc,
+  0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0xdf, 0x1e, 0xfe, 0x69, 0x8c, 0x00,
+  0x18, 0x44, 0x30, 0x82, 0x8b, 0xa4, 0x29, 0xa2, 0x84, 0xc9, 0xff, 0x25,
+  0x80, 0x79, 0x16, 0x22, 0xfa, 0xa7, 0x31, 0x02, 0x60, 0x10, 0x01, 0x11,
+  0x8a, 0x11, 0x44, 0x28, 0x27, 0x91, 0x9a, 0x23, 0x40, 0x8c, 0x10, 0xd8,
+  0x1c, 0x41, 0x30, 0x8c, 0x20, 0x0c, 0x45, 0x69, 0x27, 0x09, 0xf7, 0x1c,
+  0x00, 0x83, 0x60, 0x11, 0xc0, 0x20, 0x39, 0x10, 0x90, 0x02, 0x63, 0x8e,
+  0x00, 0x14, 0x06, 0x11, 0x04, 0x61, 0x10, 0x61, 0x10, 0x46, 0x00, 0x00,
+  0x13, 0xc0, 0x20, 0x1c, 0xd2, 0x41, 0x1e, 0xec, 0x80, 0x0e, 0xda, 0x20,
+  0x1c, 0xe0, 0x01, 0x1e, 0xd8, 0xa1, 0x1c, 0xda, 0x80, 0x1e, 0xec, 0xe1,
+  0x1d, 0xe6, 0x21, 0x0e, 0xe6, 0xc0, 0x0d, 0xe0, 0xc0, 0x0d, 0xe0, 0xa0,
+  0x0d, 0xe6, 0x21, 0x1d, 0xda, 0xa1, 0x1e, 0xd8, 0x21, 0x1c, 0xe8, 0xe1,
+  0x1d, 0xe4, 0x61, 0xc3, 0x6d, 0x94, 0x43, 0x1b, 0xc0, 0x83, 0x1e, 0xd8,
+  0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4,
+  0x41, 0x3a, 0xc4, 0x81, 0x1e, 0xe0, 0x81, 0x1e, 0xe0, 0x41, 0x1b, 0xa4,
+  0x03, 0x1e, 0xe8, 0x01, 0x1e, 0xe8, 0x01, 0x1e, 0xb4, 0x41, 0x3a, 0xc4,
+  0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xd8, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xb4,
+  0x41, 0x3a, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc,
+  0x81, 0x1c, 0xb4, 0x41, 0x3a, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0,
+  0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x39, 0xcc, 0x81, 0x1c, 0xe8,
+  0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81, 0x39, 0xd8,
+  0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4,
+  0x81, 0x3d, 0xc4, 0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xd8, 0x81, 0x1e, 0xc4,
+  0x81, 0x1d, 0xb4, 0x81, 0x3d, 0xc8, 0x01, 0x1d, 0xe8, 0xc1, 0x1c, 0xc8,
+  0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xcc, 0x81, 0x1c, 0xe8,
+  0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xd0,
+  0x01, 0x1e, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4,
+  0x81, 0x3d, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8,
+  0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xe4, 0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xc8,
+  0x01, 0x1e, 0xe8, 0x41, 0x1c, 0xc8, 0x01, 0x1e, 0xb4, 0x81, 0x3d, 0xc4,
+  0x81, 0x1c, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1c, 0xe0, 0x81, 0x1e, 0xc4,
+  0x81, 0x1c, 0xe0, 0x41, 0x1b, 0xd8, 0x43, 0x1c, 0xe4, 0x81, 0x1c, 0xe8,
+  0x81, 0x1c, 0xd4, 0x81, 0x1d, 0xe8, 0x81, 0x1c, 0xd4, 0x81, 0x1d, 0xb4,
+  0x81, 0x3d, 0xc8, 0x41, 0x1d, 0xd8, 0x81, 0x1e, 0xc8, 0x41, 0x1d, 0xd8,
+  0x81, 0x1e, 0xc8, 0x41, 0x1d, 0xd8, 0x41, 0x1b, 0xd8, 0x43, 0x1d, 0xc4,
+  0x81, 0x1c, 0xe8, 0x41, 0x1d, 0xc4, 0x81, 0x1c, 0xe8, 0x41, 0x1d, 0xc4,
+  0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xc4, 0x01, 0x1c, 0xc8, 0x01, 0x1d, 0xe8,
+  0x41, 0x1c, 0xc0, 0x81, 0x1c, 0xd0, 0x81, 0x1e, 0xc4, 0x01, 0x1c, 0xc8,
+  0x01, 0x1d, 0xb4, 0x81, 0x3b, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xe8,
+  0xc1, 0x1c, 0xc8, 0x81, 0x46, 0x08, 0x43, 0x2a, 0xdb, 0x82, 0x4c, 0x5f,
+  0xe4, 0x30, 0x76, 0x37, 0x24, 0x02, 0x14, 0x05, 0x00, 0x80, 0x00, 0x00,
+  0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x86, 0x44, 0xca, 0x06, 0x01, 0x01,
+  0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc0, 0x90, 0xa8, 0x0c,
+  0x2e, 0x09, 0x08, 0x80, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x24, 0x36, 0x08, 0x14, 0x65, 0x1c, 0x00, 0x00, 0xc8, 0x02, 0x01, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90,
+  0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a, 0x45, 0x50, 0x02, 0x85,
+  0x30, 0x02, 0x50, 0x30, 0x05, 0x51, 0x20, 0x85, 0x52, 0x06, 0x64, 0x47,
+  0x00, 0x0a, 0xa2, 0x40, 0x0a, 0x85, 0xea, 0x58, 0x42, 0x24, 0x00, 0x00,
+  0xb1, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c,
+  0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3,
+  0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6,
+  0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03,
+  0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48,
+  0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20,
+  0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e,
+  0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d,
+  0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89,
+  0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83,
+  0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78,
+  0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98,
+  0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5,
+  0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c,
+  0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43,
+  0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82,
+  0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58,
+  0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18,
+  0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2,
+  0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec,
+  0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e,
+  0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d,
+  0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83,
+  0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60,
+  0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0,
+  0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d,
+  0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d,
+  0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43,
+  0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3,
+  0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18,
+  0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3,
+  0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1,
+  0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e,
+  0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3,
+  0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3,
+  0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60,
+  0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec,
+  0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5,
+  0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5,
+  0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8,
+  0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17,
+  0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d,
+  0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03,
+  0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78,
+  0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce,
+  0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef,
+  0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08,
+  0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0,
+  0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8,
+  0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00, 0x00,
+  0xff, 0x00, 0x00, 0x00, 0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c, 0x27,
+  0x46, 0x46, 0xc8, 0x11, 0x32, 0x64, 0xd4, 0xd4, 0x80, 0x0c, 0xee, 0x09,
+  0x8b, 0xf2, 0x06, 0xc5, 0xc6, 0x91, 0x41, 0x14, 0x19, 0x12, 0xa5, 0x3c,
+  0x06, 0x33, 0x30, 0xd2, 0xa0, 0x3c, 0x12, 0x42, 0x25, 0x0c, 0x81, 0x14,
+  0x4c, 0x74, 0x31, 0xcc, 0xa2, 0x60, 0xcd, 0x72, 0x34, 0x00, 0x00, 0x00,
+  0x53, 0x44, 0x4b, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x77,
+  0x63, 0x68, 0x61, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41, 0x70, 0x70,
+  0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72,
+  0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39,
+  0x38, 0x20, 0x28, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x66, 0x65, 0x2d, 0x33,
+  0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65, 0x74, 0x61,
+  0x6c, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+  0x2e, 0x64, 0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64, 0x69, 0x73,
+  0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70,
+  0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74,
+  0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e,
+  0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72, 0x61, 0x6d,
+  0x65, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x74, 0x63,
+  0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e,
+  0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65,
+  0x74, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70,
+  0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
+  0x61, 0x69, 0x72, 0x2e, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74,
+  0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61,
+  0x74, 0x65, 0x64, 0x28, 0x33, 0x74, 0x65, 0x78, 0x44, 0x76, 0x32, 0x5f,
+  0x66, 0x29, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72,
+  0x61, 0x69, 0x72, 0x2e, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74,
+  0x69, 0x76, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x61, 0x69, 0x72,
+  0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x78,
+  0x61, 0x69, 0x72, 0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+  0x61, 0x69, 0x72, 0x2e, 0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x70,
+  0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x70, 0x6f, 0x73, 0x61, 0x69, 0x72,
+  0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x62,
+  0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61, 0x69,
+  0x72, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69,
+  0x6e, 0x64, 0x65, 0x78, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x61, 0x64,
+  0x61, 0x69, 0x72, 0x2e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74,
+  0x79, 0x70, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x55, 0x56, 0x4c, 0x65,
+  0x66, 0x74, 0x54, 0x6f, 0x70, 0x55, 0x56, 0x44, 0x69, 0x6d, 0x65, 0x6e,
+  0x73, 0x69, 0x6f, 0x6e, 0x73, 0x75, 0x69, 0x6e, 0x74, 0x4d, 0x69, 0x70,
+  0x4c, 0x65, 0x76, 0x65, 0x6c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x4c, 0x61,
+  0x79, 0x65, 0x72, 0x4f, 0x72, 0x44, 0x65, 0x70, 0x74, 0x68, 0x61, 0x69,
+  0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73,
+  0x69, 0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74,
+  0x79, 0x70, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x5f, 0x73, 0x69,
+  0x7a, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69,
+  0x6f, 0x6e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69,
+  0x6f, 0x6e, 0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
+  0x65, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x74,
+  0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x64, 0x3c, 0x66, 0x6c, 0x6f,
+  0x61, 0x74, 0x2c, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3e, 0x73,
+  0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73,
+  0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+  0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x00, 0xc4, 0x62, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x30, 0x82, 0x30, 0x0c, 0x23, 0x08, 0x15, 0x34,
+  0x82, 0x30, 0x10, 0x23, 0x08, 0x43, 0x31, 0x82, 0x30, 0x18, 0x23, 0x08,
+  0x0b, 0x30, 0x82, 0x30, 0x1c, 0x23, 0x08, 0x03, 0x32, 0x82, 0x30, 0x24,
+  0x23, 0x08, 0x83, 0x32, 0x82, 0x30, 0x2c, 0x33, 0x0c, 0x6b, 0x10, 0xb0,
+  0xc1, 0x0c, 0x43, 0x1b, 0x08, 0x6e, 0x30, 0x43, 0x30, 0xcc, 0x30, 0xac,
+  0xc1, 0x1a, 0xbc, 0xc1, 0x0c, 0x04, 0xd1, 0x06, 0x6d, 0xf0, 0x06, 0x33,
+  0x04, 0xc5, 0x0c, 0x81, 0x31, 0x43, 0x70, 0xcc, 0x50, 0x20, 0x6f, 0xf0,
+  0x06, 0x89, 0x32, 0x43, 0xe0, 0x07, 0x33, 0x24, 0x6f, 0xb0, 0x30, 0x8d,
+  0x93, 0x3c, 0x50, 0x34, 0x03, 0xd2, 0x06, 0x52, 0x33, 0x25, 0x0a, 0x44,
+  0xcd, 0x40, 0xbd, 0x81, 0x1c, 0xbc, 0xc1, 0xa3, 0xc9, 0x81, 0x1c, 0xbc,
+  0xc1, 0xb3, 0xcd, 0x81, 0x1b, 0xbc, 0x01, 0xd7, 0xd1, 0x81, 0x1b, 0xbc,
+  0x81, 0xf7, 0xcd, 0x20, 0xad, 0x41, 0x65, 0xc5, 0xc1, 0xf5, 0x06, 0x6d,
+  0x80, 0x65, 0xa2, 0x00, 0x06, 0x71, 0x10, 0x06, 0x72, 0x90, 0x88, 0x01,
+  0x34, 0x06, 0x33, 0x28, 0x75, 0x40, 0x06, 0xd7, 0x1b, 0xb4, 0x41, 0x19,
+  0x24, 0x66, 0x00, 0x9d, 0xc1, 0x0c, 0x89, 0x1b, 0xa0, 0xc1, 0xf5, 0x06,
+  0x6d, 0x90, 0xa4, 0x01, 0xa4, 0x06, 0x33, 0x14, 0xa0, 0x10, 0x0a, 0xa3,
+  0x40, 0x0a, 0xa5, 0x30, 0xc3, 0x00, 0x07, 0x7f, 0x60, 0x0a, 0xd5, 0x01,
+  0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0xb9, 0x81, 0x1b, 0x58,
+  0x74, 0xa0, 0x07, 0x96, 0x65, 0xe9, 0x01, 0xc7, 0x0a, 0xa6, 0x00, 0x1b,
+  0x7e, 0x61, 0x0f, 0xea, 0xc0, 0x0a, 0x32, 0x12, 0x98, 0xa0, 0x8b, 0xd8,
+  0xd8, 0xec, 0xda, 0x5c, 0xda, 0xde, 0xc8, 0xea, 0xd8, 0xca, 0x5c, 0xcc,
+  0xd8, 0xc2, 0xce, 0xe6, 0x46, 0x11, 0xea, 0xc0, 0x0e, 0x4e, 0x61, 0x63,
+  0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3, 0x1b, 0x25, 0xb8, 0x83,
+  0x5b, 0xc2, 0xd2, 0xe4, 0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2, 0xde, 0xdc,
+  0x46, 0x09, 0xf0, 0xe0, 0xa8, 0xb0, 0x34, 0x39, 0x17, 0xb6, 0x30, 0xb7,
+  0xb3, 0xba, 0xb0, 0xb3, 0xb2, 0x2f, 0xbb, 0x32, 0xb9, 0xb9, 0xb4, 0x37,
+  0xb7, 0x51, 0x82, 0x3c, 0xb8, 0x29, 0x2c, 0x4d, 0xce, 0x65, 0xec, 0xad,
+  0x0d, 0x2e, 0x8d, 0xad, 0xec, 0xeb, 0x0d, 0x8e, 0x2e, 0xed, 0xcd, 0x6d,
+  0x6e, 0x94, 0x41, 0x0f, 0xf6, 0x80, 0x0f, 0x8e, 0x09, 0x4b, 0x93, 0x73,
+  0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0x1b, 0x25, 0x30, 0x05,
+  0x00, 0x00, 0x00, 0x00, 0xa9, 0x18, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x0b, 0x0a, 0x72, 0x28, 0x87, 0x77, 0x80, 0x07, 0x7a, 0x58, 0x70, 0x98,
+  0x43, 0x3d, 0xb8, 0xc3, 0x38, 0xb0, 0x43, 0x39, 0xd0, 0xc3, 0x82, 0xe6,
+  0x1c, 0xc6, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2, 0xc1, 0x1d, 0xe6, 0x21,
+  0x1d, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x16, 0x34, 0xe3, 0x60, 0x0e,
+  0xe7, 0x50, 0x0f, 0xe1, 0x20, 0x0f, 0xe4, 0x40, 0x0f, 0xe1, 0x20, 0x0f,
+  0xe7, 0x50, 0x0e, 0xf4, 0xb0, 0x80, 0x81, 0x07, 0x79, 0x28, 0x87, 0x70,
+  0x60, 0x07, 0x76, 0x78, 0x87, 0x71, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72,
+  0x58, 0x70, 0x9c, 0xc3, 0x38, 0xb4, 0x01, 0x3b, 0xa4, 0x83, 0x3d, 0x94,
+  0xc3, 0x02, 0x6b, 0x1c, 0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c, 0xdc, 0x20,
+  0x1c, 0xe4, 0x61, 0x1c, 0xdc, 0x20, 0x1c, 0xe8, 0x81, 0x1e, 0xc2, 0x61,
+  0x1c, 0xd0, 0xa1, 0x1c, 0xc8, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0x61,
+  0xc1, 0x01, 0x0f, 0xf4, 0x20, 0x0f, 0xe1, 0x50, 0x0f, 0xf4, 0x80, 0x0e,
+  0x00, 0x00, 0x00, 0x00, 0xd1, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x07, 0xcc, 0x3c, 0xa4, 0x83, 0x3b, 0x9c, 0x03, 0x3b, 0x94, 0x03, 0x3d,
+  0xa0, 0x83, 0x3c, 0x94, 0x43, 0x38, 0x90, 0xc3, 0x01, 0x00, 0x00, 0x00,
+  0x61, 0x20, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c,
+  0x10, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xe4, 0x6a, 0x80, 0xde,
+  0x08, 0x00, 0x81, 0x11, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x30, 0x00, 0x00,
+  0x43, 0x00, 0x00, 0x00, 0x22, 0x47, 0xc8, 0x90, 0x51, 0x22, 0x48, 0x4f,
+  0x00, 0x00, 0x00, 0x00, 0xcf, 0xc3, 0x59, 0x18, 0x26, 0x0d, 0x00, 0x00,
+  0x6f, 0x6d, 0x6e, 0x69, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x63,
+  0x68, 0x61, 0x72, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x2b,
+  0x2b, 0x20, 0x54, 0x42, 0x41, 0x41, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c,
+  0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x28, 0x42,
+  0x6c, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x32, 0x44, 0x29, 0x61, 0x69,
+  0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70,
+  0x65, 0x2d, 0x61, 0x72, 0x67, 0x28, 0x32, 0x29, 0x61, 0x69, 0x72, 0x2d,
+  0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d,
+  0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x61, 0x69, 0x72, 0x2d,
+  0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d,
+  0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5f, 0x5a, 0x54, 0x53,
+  0x31, 0x32, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69,
+  0x6f, 0x6e, 0x69, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x13, 0x04, 0x8b, 0x99,
+  0x20, 0x58, 0xcd, 0x04, 0xc1, 0x72, 0x26, 0x08, 0xd6, 0xb3, 0x42, 0xa0,
+  0x05, 0x55, 0x58, 0x31, 0xd4, 0x02, 0x2d, 0xac, 0xc2, 0x8a, 0xc1, 0x16,
+  0x68, 0x81, 0x15, 0x56, 0x0c, 0xb7, 0x40, 0x0b, 0xad, 0xb0, 0x21, 0x48,
+  0x85, 0x0d, 0x03, 0x2a, 0xe0, 0x02, 0x2c, 0x6c, 0x18, 0x72, 0x21, 0x17,
+  0x60, 0x61, 0x43, 0x50, 0x0b, 0x1b, 0x84, 0x5b, 0xb0, 0x85, 0x0d, 0xc3,
+  0x2b, 0xe4, 0x02, 0x2c, 0x6c, 0x18, 0xbc, 0x5c, 0x80, 0x85, 0x0d, 0x89,
+  0x2b, 0xe4, 0x02, 0x2c, 0xe4, 0x42, 0x2c, 0xf4, 0x82, 0x2c, 0xf8, 0xc2,
+  0x2c, 0x6c, 0x18, 0x7e, 0xa1, 0x17, 0x64, 0x01, 0x9b, 0x0c, 0x46, 0x33,
+  0x51, 0x20, 0xc8, 0x26, 0x03, 0xf2, 0x5c, 0x14, 0x08, 0x62, 0x01, 0x23,
+  0xfe, 0x16, 0x10, 0xe0, 0xbf, 0xc9, 0xc0, 0x4c, 0x1c, 0x05, 0x83, 0x8c,
+  0x18, 0x18, 0x44, 0x08, 0x82, 0x85, 0x7f, 0x48, 0x5f, 0x30, 0x62, 0xd0,
+  0x14, 0x21, 0x08, 0x06, 0x50, 0x18, 0x38, 0x0d, 0xc1, 0x2c, 0x4c, 0xa0,
+  0x70, 0xa3, 0x09, 0x01, 0x90, 0x41, 0x40, 0x0c, 0x09, 0x00, 0x00, 0x00,
+  0x5b, 0x8e, 0x20, 0xc8, 0x85, 0x43, 0x17, 0x90, 0x5d, 0xd8, 0x72, 0x0c,
+  0x41, 0x2e, 0x1c, 0xba, 0x80, 0xec, 0xc2, 0x96, 0xe3, 0x08, 0x7e, 0xe1,
+  0xd0, 0x05, 0x64, 0x17, 0xb6, 0x14, 0xc9, 0xb1, 0x0b, 0x88, 0x2e, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x32, 0x0e, 0x10, 0x22, 0x84, 0x00, 0xa5, 0x06, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x65, 0x0c, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
+  0x12, 0x03, 0x94, 0x60, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x24, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x1b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x5d, 0x0c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x12, 0x03, 0x94, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x42, 0x6c, 0x69, 0x74,
+  0x46, 0x72, 0x6f, 0x6d, 0x32, 0x44, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61,
+  0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65,
+  0x5f, 0x32, 0x64, 0x2e, 0x76, 0x34, 0x66, 0x33, 0x32, 0x61, 0x69, 0x72,
+  0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2e, 0x66, 0x2e, 0x66,
+  0x33, 0x32, 0x2e, 0x75, 0x2e, 0x69, 0x33, 0x32, 0x33, 0x32, 0x30, 0x32,
+  0x33, 0x2e, 0x39, 0x38, 0x61, 0x69, 0x72, 0x36, 0x34, 0x2d, 0x61, 0x70,
+  0x70, 0x6c, 0x65, 0x2d, 0x74, 0x76, 0x6f, 0x73, 0x31, 0x33, 0x2e, 0x30,
+  0x2e, 0x30, 0x2d, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 0x72,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom2D_metallib_len = 4224;
+const unsigned char BlitFrom2DArray_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x15, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x10, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x32, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79, 0x00, 0x54, 0x59,
+  0x50, 0x45, 0x01, 0x00, 0x01, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x67,
+  0xae, 0x9f, 0x65, 0xad, 0x3d, 0x8e, 0xb2, 0x66, 0x17, 0x36, 0x24, 0x03,
+  0xbc, 0x48, 0xb4, 0x85, 0x92, 0x11, 0xdf, 0xa6, 0x52, 0xe2, 0x2c, 0x7c,
+  0x99, 0x6b, 0x22, 0xa0, 0x20, 0x75, 0x31, 0x4d, 0x44, 0x53, 0x5a, 0x08,
+  0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x46, 0x46,
+  0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x02, 0x00, 0x02,
+  0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x45, 0x4e, 0x44,
+  0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00,
+  0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00,
+  0x00, 0x14, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0x42, 0x43, 0xc0, 0xde, 0x35, 0x14, 0x00, 0x00, 0x03, 0x00, 0x00,
+  0x00, 0x62, 0x0c, 0x30, 0x24, 0x80, 0x10, 0x05, 0xc8, 0x14, 0x00, 0x00,
+  0x00, 0x21, 0x0c, 0x00, 0x00, 0x9f, 0x03, 0x00, 0x00, 0x0b, 0x02, 0x21,
+  0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23,
+  0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84,
+  0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45,
+  0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18,
+  0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88,
+  0xa5, 0x00, 0x19, 0x32, 0x42, 0x04, 0x49, 0x0e, 0x90, 0x91, 0x22, 0xc4,
+  0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46,
+  0x06, 0x51, 0x18, 0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24,
+  0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x58, 0x03, 0x40, 0x02, 0x2a, 0x22,
+  0x1c, 0xe0, 0x01, 0x1e, 0xe4, 0xe1, 0x1d, 0xf0, 0xa1, 0x0d, 0xcc, 0xa1,
+  0x1e, 0xdc, 0x61, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21,
+  0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80,
+  0x68, 0x87, 0x74, 0x70, 0x87, 0x36, 0x60, 0x87, 0x72, 0x38, 0x87, 0x70,
+  0x60, 0x87, 0x36, 0xb0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79,
+  0x68, 0x83, 0x7b, 0x48, 0x07, 0x72, 0xa0, 0x07, 0x74, 0x00, 0xe2, 0x40,
+  0x0e, 0xf0, 0x00, 0x18, 0xdc, 0xe1, 0x1d, 0xda, 0x40, 0x1c, 0xea, 0x21,
+  0x1d, 0xd8, 0x81, 0x1e, 0xd2, 0xc1, 0x1d, 0xe6, 0x01, 0x20, 0xdc, 0xe1,
+  0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00,
+  0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0,
+  0x1c, 0xd8, 0x21, 0x1d, 0xda, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72,
+  0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76,
+  0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72,
+  0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48, 0x87, 0x76, 0x68, 0x03, 0x77,
+  0x78, 0x07, 0x77, 0x68, 0x03, 0x76, 0x28, 0x87, 0x70, 0x30, 0x07, 0x80,
+  0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x20,
+  0x1d, 0xdc, 0xc1, 0x1c, 0xe6, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0,
+  0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72,
+  0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x70, 0x87, 0x70, 0x70, 0x87, 0x79,
+  0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74,
+  0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1,
+  0x0d, 0xe6, 0x21, 0x1d, 0xce, 0xc1, 0x1d, 0xca, 0x81, 0x1c, 0xda, 0x40,
+  0x1f, 0xca, 0x41, 0x1e, 0xde, 0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0, 0xa1,
+  0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a,
+  0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x03, 0x7a, 0x90, 0x87, 0x70,
+  0x80, 0x07, 0x78, 0x48, 0x07, 0x77, 0x38, 0x87, 0x36, 0x68, 0x87, 0x70,
+  0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0x62,
+  0x1e, 0xe8, 0x21, 0x1c, 0xc6, 0x61, 0x1d, 0xda, 0x00, 0x1e, 0xe4, 0xe1,
+  0x1d, 0xe8, 0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0x40,
+  0x1c, 0xea, 0xc1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xe6, 0x21,
+  0x1d, 0xf4, 0xa1, 0x1c, 0x00, 0x3c, 0x00, 0x88, 0x7a, 0x70, 0x87, 0x79,
+  0x08, 0x07, 0x73, 0x28, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76,
+  0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01,
+  0xd8, 0xe0, 0x09, 0x03, 0xb0, 0x00, 0x55, 0x90, 0x06, 0xd8, 0x10, 0x0e,
+  0xe9, 0x20, 0x0f, 0x6d, 0x20, 0x0e, 0xf5, 0x60, 0x0e, 0xe6, 0x50, 0x0e,
+  0xf2, 0xd0, 0x06, 0xee, 0xf0, 0x0e, 0x6d, 0x10, 0x0e, 0xec, 0x90, 0x0e,
+  0xe1, 0x30, 0x0f, 0xc0, 0x06, 0x63, 0x28, 0x80, 0x05, 0xa8, 0x36, 0x28,
+  0xc4, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x40, 0x1b, 0x00, 0x6b, 0x00, 0x48,
+  0x40, 0xb5, 0xc1, 0x28, 0x02, 0x60, 0x01, 0xaa, 0x0d, 0x86, 0x21, 0x00,
+  0x0b, 0x50, 0x6d, 0x30, 0x8e, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09,
+  0xa0, 0x36, 0x18, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50,
+  0x1b, 0x94, 0xe4, 0xff, 0xff, 0xff, 0xff, 0x07, 0xa0, 0x0d, 0x80, 0x35,
+  0x00, 0x24, 0xa0, 0x02, 0x00, 0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00,
+  0x00, 0x13, 0x86, 0x40, 0x18, 0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e,
+  0x09, 0x01, 0x32, 0x61, 0x48, 0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00,
+  0x00, 0x2a, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85,
+  0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90,
+  0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x74, 0x33,
+  0x00, 0xc3, 0x08, 0x04, 0x30, 0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70,
+  0x93, 0x34, 0x45, 0x94, 0x30, 0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12,
+  0x06, 0xe2, 0x34, 0x88, 0x10, 0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4d,
+  0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0xdf,
+  0x1e, 0x7e, 0x20, 0x8a, 0x00, 0xec, 0x9f, 0xc6, 0x08, 0x80, 0x41, 0x04,
+  0x23, 0xb8, 0x48, 0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x5f, 0x02, 0x98, 0x67,
+  0x21, 0xa2, 0x7f, 0x1a, 0x23, 0x00, 0x06, 0x11, 0x10, 0xa1, 0x18, 0x41,
+  0x84, 0x72, 0x12, 0xa9, 0x39, 0x02, 0xc4, 0x08, 0x81, 0xcd, 0x11, 0x04,
+  0xc3, 0x08, 0xc2, 0x50, 0x96, 0x76, 0x92, 0x18, 0xee, 0x39, 0x00, 0x06,
+  0xc1, 0x22, 0x80, 0x41, 0xb2, 0x08, 0x03, 0x10, 0x1d, 0x08, 0x48, 0x81,
+  0x31, 0x47, 0x00, 0x0a, 0x83, 0x08, 0x82, 0x30, 0x88, 0x00, 0x08, 0x83,
+  0x08, 0x83, 0x30, 0x02, 0x00, 0x13, 0xc0, 0x20, 0x1c, 0xd2, 0x41, 0x1e,
+  0xec, 0x80, 0x0e, 0xda, 0x20, 0x1c, 0xe0, 0x01, 0x1e, 0xd8, 0xa1, 0x1c,
+  0xda, 0x80, 0x1e, 0xec, 0xe1, 0x1d, 0xe6, 0x21, 0x0e, 0xe6, 0xc0, 0x0d,
+  0xe0, 0xc0, 0x0d, 0xe0, 0xa0, 0x0d, 0xe6, 0x21, 0x1d, 0xda, 0xa1, 0x1e,
+  0xd8, 0x21, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4, 0x61, 0xc3, 0x6d, 0x94, 0x43,
+  0x1b, 0xc0, 0x83, 0x1e, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81,
+  0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x41, 0x3a, 0xc4, 0x81, 0x1e, 0xe0, 0x81,
+  0x1e, 0xe0, 0x41, 0x1b, 0xa4, 0x03, 0x1e, 0xe8, 0x01, 0x1e, 0xe8, 0x01,
+  0x1e, 0xb4, 0x41, 0x3a, 0xc4, 0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xd8, 0x81,
+  0x1e, 0xc4, 0x81, 0x1d, 0xb4, 0x41, 0x3a, 0xcc, 0x81, 0x1c, 0xe8, 0xc1,
+  0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x41, 0x3a, 0xd8, 0x01,
+  0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81,
+  0x39, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81,
+  0x1c, 0xb4, 0x81, 0x39, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81,
+  0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xc4, 0x81, 0x1d, 0xe8, 0x41,
+  0x1c, 0xd8, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xb4, 0x81, 0x3d, 0xc8, 0x01,
+  0x1d, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81,
+  0x3d, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81,
+  0x1c, 0xb4, 0x81, 0x3d, 0xd0, 0x01, 0x1e, 0xe8, 0x81, 0x1d, 0xd0, 0x81,
+  0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xd8, 0x01, 0x1d, 0xe8, 0x81,
+  0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xe4, 0x81,
+  0x1d, 0xe8, 0x41, 0x1c, 0xc8, 0x01, 0x1e, 0xe8, 0x41, 0x1c, 0xc8, 0x01,
+  0x1e, 0xb4, 0x81, 0x3d, 0xc4, 0x81, 0x1c, 0xe0, 0x81, 0x1e, 0xc4, 0x81,
+  0x1c, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1c, 0xe0, 0x41, 0x1b, 0xd8, 0x43,
+  0x1c, 0xe4, 0x81, 0x1c, 0xe8, 0x81, 0x1c, 0xd4, 0x81, 0x1d, 0xe8, 0x81,
+  0x1c, 0xd4, 0x81, 0x1d, 0xb4, 0x81, 0x3d, 0xc8, 0x41, 0x1d, 0xd8, 0x81,
+  0x1e, 0xc8, 0x41, 0x1d, 0xd8, 0x81, 0x1e, 0xc8, 0x41, 0x1d, 0xd8, 0x41,
+  0x1b, 0xd8, 0x43, 0x1d, 0xc4, 0x81, 0x1c, 0xe8, 0x41, 0x1d, 0xc4, 0x81,
+  0x1c, 0xe8, 0x41, 0x1d, 0xc4, 0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xc4, 0x01,
+  0x1c, 0xc8, 0x01, 0x1d, 0xe8, 0x41, 0x1c, 0xc0, 0x81, 0x1c, 0xd0, 0x81,
+  0x1e, 0xc4, 0x01, 0x1c, 0xc8, 0x01, 0x1d, 0xb4, 0x81, 0x3b, 0xe0, 0x81,
+  0x1e, 0xc4, 0x81, 0x1d, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x46, 0x08, 0x43,
+  0x3e, 0xdb, 0x82, 0x4c, 0x5f, 0xe4, 0x30, 0x76, 0xa7, 0x45, 0x11, 0x80,
+  0x0d, 0x89, 0x80, 0x47, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00,
+  0x00, 0x00, 0x80, 0x21, 0xd1, 0x13, 0x06, 0x10, 0x10, 0x00, 0x02, 0x00,
+  0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x89, 0xe0, 0xe0, 0x92, 0x80,
+  0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x60, 0x48, 0x74,
+  0x0a, 0x17, 0x05, 0x04, 0xc0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x12, 0x1b, 0x04, 0x8a, 0x86, 0x0e, 0x00, 0x00, 0x64, 0x81, 0x00,
+  0x00, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c,
+  0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a, 0x45, 0x50, 0x02,
+  0x85, 0x30, 0x02, 0x50, 0x30, 0x05, 0x51, 0x20, 0x85, 0x52, 0x06, 0x84,
+  0x47, 0x00, 0x0a, 0xa2, 0x40, 0x0a, 0x85, 0xee, 0x58, 0x42, 0x24, 0x00,
+  0x00, 0xb1, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80,
+  0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84,
+  0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c,
+  0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42,
+  0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88,
+  0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c,
+  0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79,
+  0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70,
+  0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f,
+  0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4,
+  0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30,
+  0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc,
+  0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b,
+  0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70,
+  0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76,
+  0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72,
+  0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e,
+  0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21,
+  0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94,
+  0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc,
+  0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70,
+  0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74,
+  0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f,
+  0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e,
+  0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41,
+  0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1,
+  0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c,
+  0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37,
+  0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f,
+  0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21,
+  0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21,
+  0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0,
+  0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88,
+  0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77,
+  0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c,
+  0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23,
+  0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01,
+  0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84,
+  0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8,
+  0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76,
+  0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e,
+  0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f,
+  0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e,
+  0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e,
+  0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1,
+  0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21,
+  0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8,
+  0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77,
+  0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19,
+  0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e,
+  0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30,
+  0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71,
+  0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77,
+  0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00,
+  0x00, 0x01, 0x01, 0x00, 0x00, 0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c,
+  0x27, 0x46, 0x46, 0xc8, 0x11, 0x32, 0x64, 0xd4, 0xd4, 0x80, 0x0c, 0xfa,
+  0x09, 0x8b, 0xf2, 0x06, 0xc5, 0xc6, 0x91, 0x41, 0x14, 0x19, 0x12, 0xa5,
+  0x3c, 0x06, 0x33, 0x30, 0xd2, 0xa0, 0x3c, 0x12, 0x42, 0x25, 0x0c, 0x81,
+  0x14, 0x4c, 0x74, 0x31, 0xcc, 0xa2, 0x78, 0xcd, 0x72, 0x34, 0x00, 0x00,
+  0x00, 0x53, 0x44, 0x4b, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+  0x77, 0x63, 0x68, 0x61, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41, 0x70,
+  0x70, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x20, 0x76, 0x65,
+  0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e,
+  0x39, 0x38, 0x20, 0x28, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x66, 0x65, 0x2d,
+  0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65, 0x74,
+  0x61, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c,
+  0x65, 0x2e, 0x64, 0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64, 0x69,
+  0x73, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
+  0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61,
+  0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72,
+  0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72, 0x61,
+  0x6d, 0x65, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x74,
+  0x63, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72,
+  0x2e, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x72, 0x67,
+  0x65, 0x74, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79,
+  0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x34, 0x61, 0x69, 0x72, 0x2e, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e,
+  0x74, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x67, 0x65, 0x6e, 0x65, 0x72,
+  0x61, 0x74, 0x65, 0x64, 0x28, 0x33, 0x74, 0x65, 0x78, 0x44, 0x76, 0x32,
+  0x5f, 0x66, 0x29, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65,
+  0x72, 0x61, 0x69, 0x72, 0x2e, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63,
+  0x74, 0x69, 0x76, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x61, 0x69,
+  0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x74, 0x65,
+  0x78, 0x61, 0x69, 0x72, 0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
+  0x6e, 0x61, 0x69, 0x72, 0x2e, 0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x73,
+  0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x70, 0x6f, 0x73, 0x61, 0x69,
+  0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e,
+  0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61,
+  0x69, 0x72, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
+  0x69, 0x6e, 0x64, 0x65, 0x78, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x61,
+  0x64, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f,
+  0x74, 0x79, 0x70, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x55, 0x56, 0x4c,
+  0x65, 0x66, 0x74, 0x54, 0x6f, 0x70, 0x55, 0x56, 0x44, 0x69, 0x6d, 0x65,
+  0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x75, 0x69, 0x6e, 0x74, 0x4d, 0x69,
+  0x70, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x4c,
+  0x61, 0x79, 0x65, 0x72, 0x4f, 0x72, 0x44, 0x65, 0x70, 0x74, 0x68, 0x61,
+  0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f,
+  0x73, 0x69, 0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f,
+  0x74, 0x79, 0x70, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x5f, 0x73,
+  0x69, 0x7a, 0x65, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67,
+  0x69, 0x6f, 0x6e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67,
+  0x69, 0x6f, 0x6e, 0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75,
+  0x72, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+  0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x64, 0x5f, 0x61, 0x72,
+  0x72, 0x61, 0x79, 0x3c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x2c, 0x20, 0x73,
+  0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+  0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x73,
+  0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+  0x72, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70, 0x6c,
+  0x65, 0x72, 0x00, 0x00, 0x00, 0xc4, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x30, 0x82, 0x30, 0x10, 0x23, 0x08, 0x57, 0x34, 0x82, 0x30, 0x14,
+  0x23, 0x08, 0x83, 0x31, 0x82, 0x30, 0x1c, 0x23, 0x08, 0x0b, 0x30, 0x82,
+  0x30, 0x20, 0x23, 0x08, 0x43, 0x32, 0x82, 0x30, 0x28, 0x23, 0x08, 0xc3,
+  0x32, 0x82, 0x30, 0x30, 0x33, 0x0c, 0x6b, 0x10, 0xb0, 0xc1, 0x0c, 0x43,
+  0x1b, 0x08, 0x6e, 0x30, 0x43, 0x30, 0xcc, 0x30, 0xac, 0xc1, 0x1a, 0xbc,
+  0xc1, 0x0c, 0x04, 0xd1, 0x06, 0x6d, 0xf0, 0x06, 0x33, 0x04, 0xc5, 0x0c,
+  0x81, 0x31, 0x43, 0x70, 0xcc, 0x50, 0x20, 0x6f, 0xf0, 0x06, 0x89, 0x32,
+  0x43, 0xe0, 0x07, 0x33, 0x24, 0x6f, 0xb0, 0x30, 0x8d, 0x93, 0x3c, 0x50,
+  0x34, 0x03, 0xd2, 0x06, 0x52, 0x33, 0x25, 0x0a, 0x44, 0xcd, 0x40, 0xbd,
+  0x81, 0x1c, 0xbc, 0xc1, 0xa3, 0xc9, 0x81, 0x1c, 0xbc, 0xc1, 0xb3, 0xcd,
+  0x81, 0x1b, 0xbc, 0x01, 0xd7, 0xd1, 0x81, 0x1b, 0xbc, 0x81, 0xf7, 0xcd,
+  0x20, 0xad, 0x41, 0x65, 0xc5, 0xc1, 0xf5, 0x06, 0x6d, 0x80, 0x65, 0xa2,
+  0x00, 0x06, 0x71, 0x10, 0x06, 0x72, 0x90, 0x88, 0x01, 0x34, 0x06, 0x33,
+  0x28, 0x75, 0x40, 0x06, 0xd7, 0x1b, 0xb4, 0x41, 0x19, 0x24, 0x66, 0x00,
+  0x9d, 0xc1, 0x0c, 0x89, 0x1b, 0xa0, 0xc1, 0xf5, 0x06, 0x6d, 0x90, 0xa4,
+  0x01, 0xa4, 0x06, 0x33, 0x14, 0xa0, 0x10, 0x0a, 0xa3, 0x40, 0x0a, 0xa5,
+  0x30, 0xc3, 0x00, 0x07, 0x7f, 0x60, 0x0a, 0xd5, 0x01, 0x1c, 0xc7, 0x71,
+  0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0xb9, 0x81, 0x1b, 0x58, 0x74, 0xa0, 0x07,
+  0x96, 0x65, 0xe9, 0x01, 0xc7, 0x0a, 0xa6, 0x00, 0x1b, 0x7e, 0x61, 0x0f,
+  0xea, 0xc0, 0x0a, 0x32, 0x12, 0x98, 0xa0, 0x8b, 0xd8, 0xd8, 0xec, 0xda,
+  0x5c, 0xda, 0xde, 0xc8, 0xea, 0xd8, 0xca, 0x5c, 0xcc, 0xd8, 0xc2, 0xce,
+  0xe6, 0x46, 0x11, 0xea, 0xc0, 0x0e, 0x4e, 0x61, 0x63, 0xb3, 0x6b, 0x73,
+  0x49, 0x23, 0x2b, 0x73, 0xa3, 0x1b, 0x25, 0xb8, 0x83, 0x5b, 0xc2, 0xd2,
+  0xe4, 0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2, 0xde, 0xdc, 0x46, 0x09, 0xf0,
+  0xe0, 0xa8, 0xb0, 0x34, 0x39, 0x17, 0xb6, 0x30, 0xb7, 0xb3, 0xba, 0xb0,
+  0xb3, 0xb2, 0x2f, 0xbb, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x51, 0x82,
+  0x3c, 0xb8, 0x29, 0x2c, 0x4d, 0xce, 0x65, 0xec, 0xad, 0x0d, 0x2e, 0x8d,
+  0xad, 0xec, 0xeb, 0x0d, 0x8e, 0x2e, 0xed, 0xcd, 0x6d, 0x6e, 0x94, 0x41,
+  0x0f, 0xf6, 0x80, 0x0f, 0x8e, 0x09, 0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b,
+  0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0x1b, 0x25, 0x30, 0x05, 0x00, 0x00, 0x00,
+  0x00, 0xa9, 0x18, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x72,
+  0x28, 0x87, 0x77, 0x80, 0x07, 0x7a, 0x58, 0x70, 0x98, 0x43, 0x3d, 0xb8,
+  0xc3, 0x38, 0xb0, 0x43, 0x39, 0xd0, 0xc3, 0x82, 0xe6, 0x1c, 0xc6, 0xa1,
+  0x0d, 0xe8, 0x41, 0x1e, 0xc2, 0xc1, 0x1d, 0xe6, 0x21, 0x1d, 0xe8, 0x21,
+  0x1d, 0xde, 0xc1, 0x1d, 0x16, 0x34, 0xe3, 0x60, 0x0e, 0xe7, 0x50, 0x0f,
+  0xe1, 0x20, 0x0f, 0xe4, 0x40, 0x0f, 0xe1, 0x20, 0x0f, 0xe7, 0x50, 0x0e,
+  0xf4, 0xb0, 0x80, 0x81, 0x07, 0x79, 0x28, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x78, 0x87, 0x71, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x58, 0x70, 0x9c,
+  0xc3, 0x38, 0xb4, 0x01, 0x3b, 0xa4, 0x83, 0x3d, 0x94, 0xc3, 0x02, 0x6b,
+  0x1c, 0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c, 0xdc, 0x20, 0x1c, 0xe4, 0x61,
+  0x1c, 0xdc, 0x20, 0x1c, 0xe8, 0x81, 0x1e, 0xc2, 0x61, 0x1c, 0xd0, 0xa1,
+  0x1c, 0xc8, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0x61, 0xc1, 0x01, 0x0f,
+  0xf4, 0x20, 0x0f, 0xe1, 0x50, 0x0f, 0xf4, 0x80, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0xd1, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0xcc, 0x3c,
+  0xa4, 0x83, 0x3b, 0x9c, 0x03, 0x3b, 0x94, 0x03, 0x3d, 0xa0, 0x83, 0x3c,
+  0x94, 0x43, 0x38, 0x90, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00,
+  0x00, 0x70, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00,
+  0x00, 0x03, 0x00, 0x00, 0x00, 0xe4, 0x6a, 0x80, 0xde, 0x08, 0x00, 0x81,
+  0x11, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x30, 0x00, 0x00, 0x46, 0x00, 0x00,
+  0x00, 0x22, 0x47, 0xc8, 0x90, 0x51, 0x22, 0x88, 0x58, 0x00, 0x00, 0x00,
+  0x00, 0xcf, 0x13, 0x06, 0x16, 0x86, 0x49, 0x03, 0x00, 0x6f, 0x6d, 0x6e,
+  0x69, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72,
+  0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x54,
+  0x42, 0x41, 0x41, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73,
+  0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x28, 0x42, 0x6c, 0x69, 0x74,
+  0x46, 0x72, 0x6f, 0x6d, 0x32, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79, 0x29,
+  0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63,
+  0x6f, 0x70, 0x65, 0x2d, 0x61, 0x72, 0x67, 0x28, 0x32, 0x29, 0x61, 0x69,
+  0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70,
+  0x65, 0x2d, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x61, 0x69,
+  0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70,
+  0x65, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73, 0x5f, 0x5a,
+  0x54, 0x53, 0x31, 0x32, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65,
+  0x67, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x74, 0x00, 0x00, 0x13, 0x04, 0xac,
+  0x99, 0x20, 0x60, 0xce, 0x04, 0x01, 0x7b, 0x26, 0x08, 0x18, 0xb4, 0x42,
+  0xa0, 0x05, 0x55, 0x58, 0x31, 0xd4, 0x02, 0x2d, 0xac, 0xc2, 0x8a, 0xc1,
+  0x16, 0x68, 0x81, 0x15, 0x56, 0x0c, 0xb7, 0x40, 0x0b, 0xad, 0xb0, 0x21,
+  0x48, 0x85, 0x0d, 0x03, 0x2a, 0xe0, 0x02, 0x2c, 0x6c, 0x18, 0x72, 0x21,
+  0x17, 0x60, 0x61, 0x43, 0x50, 0x0b, 0x1b, 0x84, 0x5b, 0xb0, 0x85, 0x0d,
+  0xc3, 0x2b, 0xe4, 0x02, 0x2c, 0x6c, 0x18, 0xbc, 0x5c, 0x80, 0x85, 0x0d,
+  0x89, 0x2b, 0xe4, 0x02, 0x2c, 0xe4, 0x42, 0x2c, 0xf4, 0x82, 0x2c, 0xf8,
+  0xc2, 0x2c, 0x6c, 0x18, 0x7e, 0xc1, 0x17, 0x66, 0x61, 0xc3, 0xf0, 0x0b,
+  0xbd, 0x20, 0x0b, 0x00, 0x00, 0x9b, 0x0c, 0x46, 0x33, 0x51, 0x20, 0xc8,
+  0x26, 0x03, 0xf2, 0x5c, 0x14, 0x08, 0x62, 0x01, 0x23, 0xfe, 0x16, 0x10,
+  0xe0, 0xbf, 0xc9, 0xc0, 0x4c, 0x14, 0x05, 0x60, 0x8c, 0x18, 0x14, 0x44,
+  0x08, 0x82, 0x01, 0xf5, 0x05, 0x9b, 0x0c, 0x8f, 0xf5, 0x51, 0x30, 0xc8,
+  0x88, 0x81, 0x41, 0x84, 0x20, 0x58, 0xf8, 0x87, 0x34, 0x06, 0xc1, 0x88,
+  0x81, 0x53, 0x84, 0x20, 0x18, 0x40, 0x65, 0x10, 0x41, 0x07, 0xf1, 0x38,
+  0x4f, 0xd0, 0x7c, 0xa3, 0x09, 0x01, 0x90, 0x41, 0x40, 0x0c, 0x00, 0x00,
+  0x00, 0x0c, 0x00, 0x00, 0x00, 0x5b, 0x8e, 0x20, 0xc8, 0x85, 0x43, 0x17,
+  0x90, 0x5d, 0xd8, 0x72, 0x0c, 0x41, 0x2e, 0x1c, 0xba, 0x80, 0xec, 0xc2,
+  0x96, 0xe3, 0x08, 0x7e, 0xe1, 0xd0, 0x05, 0x64, 0x17, 0xb6, 0x1c, 0x4a,
+  0x00, 0x0e, 0x87, 0x2e, 0x20, 0xbb, 0xb0, 0xa5, 0x60, 0x8e, 0x5d, 0x40,
+  0x74, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00,
+  0x00, 0x03, 0x00, 0x00, 0x00, 0x32, 0x0e, 0x10, 0x22, 0x84, 0x00, 0xaf,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x0c, 0x00,
+  0x00, 0x31, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0x78, 0x01, 0x00, 0x00,
+  0x00, 0x03, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+  0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00,
+  0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
+  0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0x00, 0x24, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00,
+  0x00, 0x0f, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0x08, 0x24, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00,
+  0x00, 0x30, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0x08, 0x24, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00,
+  0x00, 0x47, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0x08, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x0c, 0x00,
+  0x00, 0x25, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0x26, 0x01, 0x00, 0x00,
+  0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x32, 0x44, 0x41,
+  0x72, 0x72, 0x61, 0x79, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70,
+  0x6c, 0x65, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x32,
+  0x64, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x2e, 0x76, 0x34, 0x66, 0x33,
+  0x32, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74,
+  0x2e, 0x66, 0x2e, 0x66, 0x33, 0x32, 0x2e, 0x75, 0x2e, 0x69, 0x33, 0x32,
+  0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2e,
+  0x75, 0x2e, 0x69, 0x33, 0x32, 0x2e, 0x66, 0x2e, 0x66, 0x33, 0x32, 0x33,
+  0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x61, 0x69, 0x72, 0x36, 0x34,
+  0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2d, 0x74, 0x76, 0x6f, 0x73, 0x31,
+  0x33, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61,
+  0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom2DArray_metallib_len = 4373;
+const unsigned char BlitFrom3D_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0b, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x33, 0x44, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01,
+  0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x2a, 0x93, 0x21, 0xcc, 0x4b, 0xdf,
+  0xd3, 0x40, 0x7c, 0xb1, 0x05, 0x9a, 0x19, 0xbd, 0x80, 0x3d, 0x5f, 0xfa,
+  0xf7, 0xe2, 0x92, 0x0a, 0x4e, 0xdd, 0x5d, 0xa9, 0xc0, 0xf2, 0xe0, 0x67,
+  0xd4, 0x3a, 0x4d, 0x44, 0x53, 0x5a, 0x08, 0x00, 0xd0, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45,
+  0x52, 0x53, 0x08, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54,
+  0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0xb0, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde,
+  0x35, 0x14, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x0c, 0x30, 0x24,
+  0x80, 0x10, 0x05, 0xc8, 0x14, 0x00, 0x00, 0x00, 0x21, 0x0c, 0x00, 0x00,
+  0x99, 0x03, 0x00, 0x00, 0x0b, 0x02, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88,
+  0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42,
+  0x04, 0x49, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c,
+  0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00,
+  0x83, 0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff,
+  0x01, 0x58, 0x03, 0x40, 0x02, 0x2a, 0x22, 0x1c, 0xe0, 0x01, 0x1e, 0xe4,
+  0xe1, 0x1d, 0xf0, 0xa1, 0x0d, 0xcc, 0xa1, 0x1e, 0xdc, 0x61, 0x1c, 0xda,
+  0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x68, 0x87, 0x74, 0x70, 0x87,
+  0x36, 0x60, 0x87, 0x72, 0x38, 0x87, 0x70, 0x60, 0x87, 0x36, 0xb0, 0x87,
+  0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x83, 0x7b, 0x48, 0x07,
+  0x72, 0xa0, 0x07, 0x74, 0x00, 0xe2, 0x40, 0x0e, 0xf0, 0x00, 0x18, 0xdc,
+  0xe1, 0x1d, 0xda, 0x40, 0x1c, 0xea, 0x21, 0x1d, 0xd8, 0x81, 0x1e, 0xd2,
+  0xc1, 0x1d, 0xe6, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4,
+  0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc,
+  0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87,
+  0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07,
+  0x76, 0x48, 0x87, 0x76, 0x68, 0x03, 0x77, 0x78, 0x07, 0x77, 0x68, 0x03,
+  0x76, 0x28, 0x87, 0x70, 0x30, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x20, 0x1d, 0xdc, 0xc1, 0x1c, 0xe6,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x70, 0x87, 0x70, 0x70, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xce,
+  0xc1, 0x1d, 0xca, 0x81, 0x1c, 0xda, 0x40, 0x1f, 0xca, 0x41, 0x1e, 0xde,
+  0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8,
+  0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87,
+  0x77, 0x68, 0x03, 0x7a, 0x90, 0x87, 0x70, 0x80, 0x07, 0x78, 0x48, 0x07,
+  0x77, 0x38, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8,
+  0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0x62, 0x1e, 0xe8, 0x21, 0x1c, 0xc6,
+  0x61, 0x1d, 0xda, 0x00, 0x1e, 0xe4, 0xe1, 0x1d, 0xe8, 0xa1, 0x1c, 0xc6,
+  0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0x40, 0x1c, 0xea, 0xc1, 0x1c, 0xcc,
+  0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xf4, 0xa1, 0x1c, 0x00,
+  0x3c, 0x00, 0x88, 0x7a, 0x70, 0x87, 0x79, 0x08, 0x07, 0x73, 0x28, 0x87,
+  0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07,
+  0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0xd8, 0xe0, 0x09, 0x03, 0xb0,
+  0x00, 0x55, 0x90, 0x06, 0xd8, 0x10, 0x0e, 0xe9, 0x20, 0x0f, 0x6d, 0x20,
+  0x0e, 0xf5, 0x60, 0x0e, 0xe6, 0x50, 0x0e, 0xf2, 0xd0, 0x06, 0xee, 0xf0,
+  0x0e, 0x6d, 0x10, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0xc0, 0x06,
+  0x63, 0x28, 0x80, 0x05, 0xa8, 0x36, 0x28, 0xc4, 0xff, 0xff, 0xff, 0xff,
+  0x0f, 0x40, 0x1b, 0x00, 0x6b, 0x00, 0x48, 0x40, 0xb5, 0xc1, 0x28, 0x02,
+  0x60, 0x01, 0xaa, 0x0d, 0x86, 0x21, 0x00, 0x0b, 0x50, 0x6d, 0x30, 0x8e,
+  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa0, 0x36, 0x18, 0xc8, 0xff,
+  0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b, 0x94, 0xe4, 0xff, 0xff,
+  0xff, 0xff, 0x07, 0xa0, 0x0d, 0x80, 0x35, 0x00, 0x24, 0xa0, 0x02, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18,
+  0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48,
+  0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x70, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30,
+  0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30,
+  0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10,
+  0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4a, 0x9a, 0x22, 0x4a, 0x98, 0xfc,
+  0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0xff, 0x1e, 0xfe, 0x69, 0x8c, 0x00,
+  0x18, 0x44, 0x30, 0x82, 0x8b, 0xa4, 0x29, 0xa2, 0x84, 0xc9, 0xff, 0x25,
+  0x80, 0x79, 0x16, 0x22, 0xfa, 0xa7, 0x31, 0x02, 0x60, 0x10, 0x01, 0x11,
+  0x8a, 0x11, 0x44, 0x28, 0x27, 0x91, 0x9a, 0x23, 0x40, 0x8c, 0x10, 0xd8,
+  0x30, 0xc2, 0x00, 0xcc, 0x11, 0x04, 0xc3, 0x08, 0xc3, 0x50, 0x94, 0x76,
+  0x92, 0x7b, 0xf0, 0x01, 0x30, 0x28, 0x16, 0x01, 0x0c, 0x9a, 0x03, 0x01,
+  0x29, 0x30, 0xe6, 0x08, 0x40, 0x61, 0x10, 0x41, 0x10, 0x06, 0x11, 0x00,
+  0x61, 0x10, 0x61, 0x10, 0x46, 0x00, 0x00, 0x00, 0x13, 0xc0, 0x20, 0x1c,
+  0xd2, 0x41, 0x1e, 0xec, 0x80, 0x0e, 0xda, 0x20, 0x1c, 0xe0, 0x01, 0x1e,
+  0xd8, 0xa1, 0x1c, 0xda, 0x80, 0x1e, 0xec, 0xe1, 0x1d, 0xe6, 0x21, 0x0e,
+  0xe6, 0xc0, 0x0d, 0xe0, 0xc0, 0x0d, 0xe0, 0xa0, 0x0d, 0xe6, 0x21, 0x1d,
+  0xda, 0xa1, 0x1e, 0xd8, 0x21, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4, 0x61, 0xc3,
+  0x6d, 0x94, 0x43, 0x1b, 0xc0, 0x83, 0x1e, 0xd8, 0x01, 0x1d, 0xe8, 0x81,
+  0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x41, 0x3a, 0xc4, 0x81,
+  0x1e, 0xe0, 0x81, 0x1e, 0xe0, 0x41, 0x1b, 0xa4, 0x03, 0x1e, 0xe8, 0x01,
+  0x1e, 0xe8, 0x01, 0x1e, 0xb4, 0x41, 0x3a, 0xc4, 0x81, 0x1d, 0xe8, 0x41,
+  0x1c, 0xd8, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xb4, 0x41, 0x3a, 0xcc, 0x81,
+  0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x41,
+  0x3a, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01,
+  0x1d, 0xb4, 0x81, 0x39, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81,
+  0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81, 0x39, 0xd8, 0x01, 0x1d, 0xe8, 0x81,
+  0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xc4, 0x81,
+  0x1d, 0xe8, 0x41, 0x1c, 0xd8, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xb4, 0x81,
+  0x3d, 0xc8, 0x01, 0x1d, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81,
+  0x1c, 0xb4, 0x81, 0x3d, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81,
+  0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xd0, 0x01, 0x1e, 0xe8, 0x81,
+  0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xd8, 0x01,
+  0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81,
+  0x3d, 0xe4, 0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xc8, 0x01, 0x1e, 0xe8, 0x41,
+  0x1c, 0xc8, 0x01, 0x1e, 0xb4, 0x81, 0x3d, 0xc4, 0x81, 0x1c, 0xe0, 0x81,
+  0x1e, 0xc4, 0x81, 0x1c, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1c, 0xe0, 0x41,
+  0x1b, 0xd8, 0x43, 0x1c, 0xe4, 0x81, 0x1c, 0xe8, 0x81, 0x1c, 0xd4, 0x81,
+  0x1d, 0xe8, 0x81, 0x1c, 0xd4, 0x81, 0x1d, 0xb4, 0x81, 0x3d, 0xc8, 0x41,
+  0x1d, 0xd8, 0x81, 0x1e, 0xc8, 0x41, 0x1d, 0xd8, 0x81, 0x1e, 0xc8, 0x41,
+  0x1d, 0xd8, 0x41, 0x1b, 0xd8, 0x43, 0x1d, 0xc4, 0x81, 0x1c, 0xe8, 0x41,
+  0x1d, 0xc4, 0x81, 0x1c, 0xe8, 0x41, 0x1d, 0xc4, 0x81, 0x1c, 0xb4, 0x81,
+  0x3d, 0xc4, 0x01, 0x1c, 0xc8, 0x01, 0x1d, 0xe8, 0x41, 0x1c, 0xc0, 0x81,
+  0x1c, 0xd0, 0x81, 0x1e, 0xc4, 0x01, 0x1c, 0xc8, 0x01, 0x1d, 0xb4, 0x81,
+  0x3b, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xe8, 0xc1, 0x1c, 0xc8, 0x81,
+  0x46, 0x08, 0x43, 0x2a, 0xdb, 0x82, 0x4c, 0x5f, 0xe4, 0x30, 0x77, 0x37,
+  0x24, 0x02, 0x14, 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+  0x00, 0x00, 0x86, 0x44, 0xca, 0x16, 0x01, 0x01, 0x20, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0xc0, 0x90, 0xa8, 0x0c, 0xae, 0x09, 0x08, 0x80,
+  0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x24, 0x36, 0x08, 0x14,
+  0xdd, 0x1c, 0x00, 0x00, 0xc8, 0x02, 0x01, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47,
+  0xc6, 0x04, 0x43, 0x1a, 0x45, 0x50, 0x02, 0x85, 0x30, 0x02, 0x50, 0x30,
+  0x05, 0x51, 0x20, 0x85, 0x52, 0x06, 0x74, 0x47, 0x00, 0x0a, 0xa2, 0x40,
+  0x0a, 0x85, 0xec, 0x58, 0x42, 0x24, 0x00, 0x00, 0xb1, 0x18, 0x00, 0x00,
+  0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66,
+  0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10,
+  0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce,
+  0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b,
+  0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c,
+  0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07,
+  0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11,
+  0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0,
+  0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8,
+  0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b,
+  0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b,
+  0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87,
+  0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07,
+  0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87,
+  0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81,
+  0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30,
+  0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca,
+  0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b,
+  0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b,
+  0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83,
+  0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87,
+  0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90,
+  0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20,
+  0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc,
+  0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66,
+  0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24,
+  0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07,
+  0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e,
+  0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e,
+  0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54,
+  0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39,
+  0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c,
+  0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07,
+  0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0,
+  0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4,
+  0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b,
+  0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39,
+  0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c,
+  0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87,
+  0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0,
+  0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50,
+  0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0,
+  0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec,
+  0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6,
+  0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66,
+  0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39,
+  0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07,
+  0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10,
+  0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90,
+  0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07,
+  0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07,
+  0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+  0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c, 0x27, 0x46, 0x46, 0xc8, 0x11,
+  0x32, 0x64, 0xd4, 0xd4, 0x80, 0x0c, 0xee, 0x09, 0x8b, 0xf2, 0x06, 0xc5,
+  0xc6, 0x91, 0x41, 0x14, 0x19, 0x12, 0xa5, 0x3c, 0x06, 0x33, 0x30, 0xd2,
+  0xa0, 0x3c, 0x12, 0x42, 0x25, 0x0c, 0x81, 0x14, 0x4c, 0x74, 0x31, 0xcc,
+  0xa2, 0x60, 0xcd, 0x72, 0x34, 0x00, 0x00, 0x00, 0x53, 0x44, 0x4b, 0x20,
+  0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x77, 0x63, 0x68, 0x61, 0x72,
+  0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x6d,
+  0x65, 0x74, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+  0x20, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x20, 0x28, 0x6d,
+  0x65, 0x74, 0x61, 0x6c, 0x66, 0x65, 0x2d, 0x33, 0x32, 0x30, 0x32, 0x33,
+  0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65, 0x74, 0x61, 0x6c, 0x61, 0x69, 0x72,
+  0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x64, 0x65, 0x6e,
+  0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e,
+  0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e,
+  0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70,
+  0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x62, 0x75, 0x66,
+  0x66, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x65, 0x6e,
+  0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x6e, 0x64,
+  0x65, 0x72, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x61, 0x69, 0x72,
+  0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61,
+  0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x61, 0x69, 0x72, 0x2e,
+  0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x70,
+  0x75, 0x74, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x28,
+  0x33, 0x74, 0x65, 0x78, 0x44, 0x76, 0x32, 0x5f, 0x66, 0x29, 0x61, 0x69,
+  0x72, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e,
+  0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67,
+  0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x78, 0x61, 0x69, 0x72, 0x2e,
+  0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x69, 0x72, 0x2e,
+  0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69,
+  0x76, 0x65, 0x70, 0x6f, 0x73, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66,
+  0x66, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65,
+  0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x6c, 0x6f,
+  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78,
+  0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x61, 0x64, 0x61, 0x69, 0x72, 0x2e,
+  0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f,
+  0x69, 0x6e, 0x66, 0x6f, 0x55, 0x56, 0x4c, 0x65, 0x66, 0x74, 0x54, 0x6f,
+  0x70, 0x55, 0x56, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+  0x73, 0x75, 0x69, 0x6e, 0x74, 0x4d, 0x69, 0x70, 0x4c, 0x65, 0x76, 0x65,
+  0x6c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x4f,
+  0x72, 0x44, 0x65, 0x70, 0x74, 0x68, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72,
+  0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61,
+  0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f,
+  0x61, 0x6c, 0x69, 0x67, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x53, 0x6f,
+  0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x73, 0x6f,
+  0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x61, 0x69,
+  0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x61, 0x69, 0x72,
+  0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x78, 0x74, 0x75,
+  0x72, 0x65, 0x33, 0x64, 0x3c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x2c, 0x20,
+  0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3e, 0x73, 0x6f, 0x75, 0x72, 0x63,
+  0x65, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x61, 0x69, 0x72, 0x2e,
+  0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x61, 0x6d, 0x70, 0x6c,
+  0x65, 0x72, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x61, 0x6d, 0x70,
+  0x6c, 0x65, 0x72, 0x00, 0xc4, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x30, 0x82, 0x30, 0x0c, 0x23, 0x08, 0x16, 0x34, 0x82, 0x30, 0x10, 0x23,
+  0x08, 0x43, 0x31, 0x82, 0x30, 0x18, 0x23, 0x08, 0x0b, 0x30, 0x82, 0x30,
+  0x1c, 0x23, 0x08, 0x03, 0x32, 0x82, 0x30, 0x24, 0x23, 0x08, 0x83, 0x32,
+  0x82, 0x30, 0x2c, 0x33, 0x0c, 0x6b, 0x10, 0xb0, 0xc1, 0x0c, 0x43, 0x1b,
+  0x08, 0x6e, 0x30, 0x43, 0x30, 0xcc, 0x30, 0xac, 0xc1, 0x1a, 0xbc, 0xc1,
+  0x0c, 0x04, 0xd1, 0x06, 0x6d, 0xf0, 0x06, 0x33, 0x04, 0xc5, 0x0c, 0x81,
+  0x31, 0x43, 0x70, 0xcc, 0x50, 0x20, 0x6f, 0xf0, 0x06, 0x89, 0x32, 0x43,
+  0xe0, 0x07, 0x33, 0x24, 0x6f, 0xb0, 0x30, 0x8d, 0x93, 0x3c, 0x50, 0x34,
+  0x03, 0xd2, 0x06, 0x52, 0x33, 0x25, 0x0a, 0x44, 0xcd, 0x40, 0xbd, 0x81,
+  0x1c, 0xbc, 0xc1, 0xa3, 0xc9, 0x81, 0x1c, 0xbc, 0xc1, 0xb3, 0xcd, 0x81,
+  0x1b, 0xbc, 0x01, 0xd7, 0xd1, 0x81, 0x1b, 0xbc, 0x81, 0xf7, 0xcd, 0x20,
+  0xad, 0x41, 0x65, 0xc5, 0xc1, 0xf5, 0x06, 0x6d, 0x80, 0x65, 0xa2, 0x00,
+  0x06, 0x71, 0x10, 0x06, 0x72, 0x90, 0x88, 0x01, 0x34, 0x06, 0x33, 0x28,
+  0x75, 0x40, 0x06, 0xd7, 0x1b, 0xb4, 0x41, 0x19, 0x24, 0x66, 0x00, 0x9d,
+  0xc1, 0x0c, 0x89, 0x1b, 0xa0, 0xc1, 0xf5, 0x06, 0x6d, 0x90, 0xa4, 0x01,
+  0xa4, 0x06, 0x33, 0x14, 0xa0, 0x10, 0x0a, 0xa3, 0x40, 0x0a, 0xa5, 0x30,
+  0xc3, 0x00, 0x07, 0x7f, 0x60, 0x0a, 0xd5, 0x01, 0x1c, 0xc7, 0x71, 0x1c,
+  0xc7, 0x71, 0x1c, 0xc7, 0xb9, 0x81, 0x1b, 0x58, 0x74, 0xa0, 0x07, 0x96,
+  0x65, 0xe9, 0x01, 0xc7, 0x0a, 0xa6, 0x00, 0x1b, 0x7e, 0x61, 0x0f, 0xea,
+  0xc0, 0x0a, 0x32, 0x12, 0x98, 0xa0, 0x8b, 0xd8, 0xd8, 0xec, 0xda, 0x5c,
+  0xda, 0xde, 0xc8, 0xea, 0xd8, 0xca, 0x5c, 0xcc, 0xd8, 0xc2, 0xce, 0xe6,
+  0x46, 0x11, 0xea, 0xc0, 0x0e, 0x4e, 0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49,
+  0x23, 0x2b, 0x73, 0xa3, 0x1b, 0x25, 0xb8, 0x83, 0x5b, 0xc2, 0xd2, 0xe4,
+  0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2, 0xde, 0xdc, 0x46, 0x09, 0xf0, 0xe0,
+  0xa8, 0xb0, 0x34, 0x39, 0x17, 0xb6, 0x30, 0xb7, 0xb3, 0xba, 0xb0, 0xb3,
+  0xb2, 0x2f, 0xbb, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x51, 0x82, 0x3c,
+  0xb8, 0x29, 0x2c, 0x4d, 0xce, 0x65, 0xec, 0xad, 0x0d, 0x2e, 0x8d, 0xad,
+  0xec, 0xeb, 0x0d, 0x8e, 0x2e, 0xed, 0xcd, 0x6d, 0x6e, 0x94, 0x41, 0x0f,
+  0xf6, 0x80, 0x0f, 0x8e, 0x09, 0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b,
+  0x6b, 0x2b, 0x73, 0xa3, 0x1b, 0x25, 0x30, 0x05, 0x00, 0x00, 0x00, 0x00,
+  0xa9, 0x18, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x72, 0x28,
+  0x87, 0x77, 0x80, 0x07, 0x7a, 0x58, 0x70, 0x98, 0x43, 0x3d, 0xb8, 0xc3,
+  0x38, 0xb0, 0x43, 0x39, 0xd0, 0xc3, 0x82, 0xe6, 0x1c, 0xc6, 0xa1, 0x0d,
+  0xe8, 0x41, 0x1e, 0xc2, 0xc1, 0x1d, 0xe6, 0x21, 0x1d, 0xe8, 0x21, 0x1d,
+  0xde, 0xc1, 0x1d, 0x16, 0x34, 0xe3, 0x60, 0x0e, 0xe7, 0x50, 0x0f, 0xe1,
+  0x20, 0x0f, 0xe4, 0x40, 0x0f, 0xe1, 0x20, 0x0f, 0xe7, 0x50, 0x0e, 0xf4,
+  0xb0, 0x80, 0x81, 0x07, 0x79, 0x28, 0x87, 0x70, 0x60, 0x07, 0x76, 0x78,
+  0x87, 0x71, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x58, 0x70, 0x9c, 0xc3,
+  0x38, 0xb4, 0x01, 0x3b, 0xa4, 0x83, 0x3d, 0x94, 0xc3, 0x02, 0x6b, 0x1c,
+  0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c, 0xdc, 0x20, 0x1c, 0xe4, 0x61, 0x1c,
+  0xdc, 0x20, 0x1c, 0xe8, 0x81, 0x1e, 0xc2, 0x61, 0x1c, 0xd0, 0xa1, 0x1c,
+  0xc8, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0x61, 0xc1, 0x01, 0x0f, 0xf4,
+  0x20, 0x0f, 0xe1, 0x50, 0x0f, 0xf4, 0x80, 0x0e, 0x00, 0x00, 0x00, 0x00,
+  0xd1, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0xcc, 0x3c, 0xa4,
+  0x83, 0x3b, 0x9c, 0x03, 0x3b, 0x94, 0x03, 0x3d, 0xa0, 0x83, 0x3c, 0x94,
+  0x43, 0x38, 0x90, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00,
+  0x72, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x34, 0x66, 0x00, 0xe8, 0xd5, 0x00, 0xc1, 0x39,
+  0x06, 0x83, 0xb0, 0x46, 0x00, 0xe8, 0x16, 0x01, 0x81, 0x11, 0x00, 0x12,
+  0x33, 0x00, 0x00, 0x00, 0xf1, 0x30, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00,
+  0x22, 0x47, 0xc8, 0x90, 0x51, 0x22, 0x48, 0x4f, 0x00, 0x00, 0x00, 0x00,
+  0xcf, 0xc3, 0x59, 0x18, 0x26, 0x0d, 0x00, 0x00, 0x6f, 0x6d, 0x6e, 0x69,
+  0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x53,
+  0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x54, 0x42,
+  0x41, 0x41, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d,
+  0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x28, 0x42, 0x6c, 0x69, 0x74, 0x46,
+  0x72, 0x6f, 0x6d, 0x33, 0x44, 0x29, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c,
+  0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x61, 0x72,
+  0x67, 0x28, 0x32, 0x29, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61,
+  0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x73, 0x61, 0x6d, 0x70,
+  0x6c, 0x65, 0x72, 0x73, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61,
+  0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x74, 0x65, 0x78, 0x74,
+  0x75, 0x72, 0x65, 0x73, 0x5f, 0x5a, 0x54, 0x53, 0x31, 0x32, 0x53, 0x6f,
+  0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x69, 0x6e,
+  0x74, 0x00, 0x00, 0x00, 0x13, 0x84, 0x8b, 0x99, 0x20, 0x5c, 0xcd, 0x04,
+  0xe1, 0x72, 0x26, 0x08, 0xd7, 0xb3, 0x42, 0xa0, 0x05, 0x55, 0x58, 0x31,
+  0xd4, 0x02, 0x2d, 0xac, 0xc2, 0x8a, 0xc1, 0x16, 0x68, 0x81, 0x15, 0x56,
+  0x0c, 0xb7, 0x40, 0x0b, 0xad, 0xb0, 0x21, 0x48, 0x85, 0x0d, 0x03, 0x2a,
+  0xe0, 0x02, 0x2c, 0x6c, 0x18, 0x72, 0x21, 0x17, 0x60, 0x61, 0x43, 0x50,
+  0x0b, 0x1b, 0x84, 0x5b, 0xb0, 0x85, 0x0d, 0xc3, 0x2b, 0xe4, 0x02, 0x2c,
+  0x6c, 0x18, 0xbc, 0x5c, 0x80, 0x85, 0x0d, 0x89, 0x2b, 0xe4, 0x02, 0x2c,
+  0xe4, 0x42, 0x2c, 0xf4, 0x82, 0x2c, 0xf8, 0xc2, 0x2c, 0x6c, 0x18, 0x7e,
+  0xc1, 0x17, 0x66, 0x61, 0xc3, 0xf0, 0x0b, 0xbd, 0x20, 0x0b, 0x00, 0x00,
+  0x9b, 0x0c, 0x4a, 0x74, 0x51, 0x20, 0xc8, 0x26, 0x03, 0x33, 0x6d, 0x14,
+  0x08, 0x62, 0x01, 0x24, 0xfe, 0x16, 0x10, 0xe0, 0x3f, 0xc8, 0x10, 0x1c,
+  0xcb, 0x26, 0x43, 0x84, 0x65, 0x14, 0x80, 0x31, 0xc7, 0x30, 0x04, 0xcc,
+  0x26, 0x03, 0xb5, 0x91, 0x01, 0x05, 0x83, 0x8c, 0x18, 0x18, 0x44, 0x08,
+  0x82, 0x85, 0x7f, 0x4c, 0x67, 0x10, 0x8c, 0x18, 0x34, 0x45, 0x08, 0x82,
+  0x41, 0x94, 0x06, 0x56, 0x45, 0x4c, 0xd1, 0x14, 0x3c, 0x64, 0x30, 0x9a,
+  0x10, 0x00, 0x19, 0x04, 0xc4, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x5b, 0x8e, 0x20, 0xc8, 0x85, 0x43, 0x17, 0x90, 0x5d, 0xd8, 0x72, 0x0c,
+  0x41, 0x2e, 0x1c, 0xba, 0x80, 0xec, 0xc2, 0x96, 0x03, 0x09, 0x7e, 0xe1,
+  0xd0, 0x05, 0x64, 0x17, 0xb6, 0x1c, 0x4b, 0x00, 0x0e, 0x87, 0x2e, 0x20,
+  0xbb, 0xb0, 0xa5, 0x68, 0x8e, 0x5d, 0x40, 0x74, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x32, 0x0e, 0x10, 0x22, 0x84, 0x00, 0xa7, 0x06, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x65, 0x0c, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
+  0x12, 0x03, 0x94, 0x60, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x3c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x24, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x1b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x24, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x5d, 0x0c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x12, 0x03, 0x94, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x42, 0x6c, 0x69, 0x74,
+  0x46, 0x72, 0x6f, 0x6d, 0x33, 0x44, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61,
+  0x6d, 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65,
+  0x5f, 0x33, 0x64, 0x2e, 0x76, 0x34, 0x66, 0x33, 0x32, 0x61, 0x69, 0x72,
+  0x2e, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2e, 0x66, 0x2e, 0x66,
+  0x33, 0x32, 0x2e, 0x75, 0x2e, 0x69, 0x33, 0x32, 0x33, 0x32, 0x30, 0x32,
+  0x33, 0x2e, 0x39, 0x38, 0x61, 0x69, 0x72, 0x36, 0x34, 0x2d, 0x61, 0x70,
+  0x70, 0x6c, 0x65, 0x2d, 0x74, 0x76, 0x6f, 0x73, 0x31, 0x33, 0x2e, 0x30,
+  0x2e, 0x30, 0x2d, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 0x72,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom3D_metallib_len = 4288;
+const unsigned char BlitFromCube_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0d, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x43, 0x75, 0x62, 0x65, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01,
+  0x00, 0x01, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0xca, 0xa4, 0x82, 0x29,
+  0xfd, 0x2f, 0x92, 0xc9, 0x54, 0xbb, 0xb8, 0x5c, 0x1e, 0x76, 0xae, 0xb2,
+  0x24, 0x20, 0x56, 0x85, 0x4d, 0x58, 0x65, 0xc0, 0xc4, 0xe0, 0x85, 0x3b,
+  0x84, 0xe9, 0x07, 0x9f, 0x4d, 0x44, 0x53, 0x5a, 0x08, 0x00, 0x10, 0x11,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00,
+  0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00,
+  0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00,
+  0x00, 0x00, 0xf0, 0x10, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43,
+  0xc0, 0xde, 0x35, 0x14, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x0c,
+  0x30, 0x24, 0x80, 0x10, 0x05, 0xc8, 0x14, 0x00, 0x00, 0x00, 0x21, 0x0c,
+  0x00, 0x00, 0xdc, 0x03, 0x00, 0x00, 0x0b, 0x02, 0x21, 0x00, 0x02, 0x00,
+  0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8,
+  0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05,
+  0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92,
+  0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32,
+  0x52, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19,
+  0x32, 0x42, 0x04, 0x49, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51,
+  0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18,
+  0x00, 0x00, 0x83, 0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff,
+  0xff, 0xff, 0x01, 0x58, 0x03, 0x40, 0x02, 0x2a, 0x22, 0x1c, 0xe0, 0x01,
+  0x1e, 0xe4, 0xe1, 0x1d, 0xf0, 0xa1, 0x0d, 0xcc, 0xa1, 0x1e, 0xdc, 0x61,
+  0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01,
+  0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x68, 0x87, 0x74,
+  0x70, 0x87, 0x36, 0x60, 0x87, 0x72, 0x38, 0x87, 0x70, 0x60, 0x87, 0x36,
+  0xb0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x83, 0x7b,
+  0x48, 0x07, 0x72, 0xa0, 0x07, 0x74, 0x00, 0xe2, 0x40, 0x0e, 0xf0, 0x00,
+  0x18, 0xdc, 0xe1, 0x1d, 0xda, 0x40, 0x1c, 0xea, 0x21, 0x1d, 0xd8, 0x81,
+  0x1e, 0xd2, 0xc1, 0x1d, 0xe6, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0,
+  0x1c, 0xe4, 0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21,
+  0x1d, 0xdc, 0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21,
+  0x1d, 0xda, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77,
+  0x78, 0x87, 0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36,
+  0x80, 0x87, 0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36,
+  0x28, 0x07, 0x76, 0x48, 0x87, 0x76, 0x68, 0x03, 0x77, 0x78, 0x07, 0x77,
+  0x68, 0x03, 0x76, 0x28, 0x87, 0x70, 0x30, 0x07, 0x80, 0x1e, 0xe4, 0xa1,
+  0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x20, 0x1d, 0xdc, 0xc1,
+  0x1c, 0xe6, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81,
+  0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77,
+  0x78, 0x87, 0x36, 0x70, 0x87, 0x70, 0x70, 0x87, 0x79, 0x68, 0x03, 0x73,
+  0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41,
+  0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe6, 0x21,
+  0x1d, 0xce, 0xc1, 0x1d, 0xca, 0x81, 0x1c, 0xda, 0x40, 0x1f, 0xca, 0x41,
+  0x1e, 0xde, 0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21,
+  0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80,
+  0x70, 0x87, 0x77, 0x68, 0x03, 0x7a, 0x90, 0x87, 0x70, 0x80, 0x07, 0x78,
+  0x48, 0x07, 0x77, 0x38, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74,
+  0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0x62, 0x1e, 0xe8, 0x21,
+  0x1c, 0xc6, 0x61, 0x1d, 0xda, 0x00, 0x1e, 0xe4, 0xe1, 0x1d, 0xe8, 0xa1,
+  0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0x40, 0x1c, 0xea, 0xc1,
+  0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xf4, 0xa1,
+  0x1c, 0x00, 0x3c, 0x00, 0x88, 0x7a, 0x70, 0x87, 0x79, 0x08, 0x07, 0x73,
+  0x28, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a,
+  0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0xd8, 0xe0, 0x09,
+  0x03, 0xb0, 0x00, 0x55, 0x90, 0x06, 0xd8, 0x10, 0x0e, 0xe9, 0x20, 0x0f,
+  0x6d, 0x20, 0x0e, 0xf5, 0x60, 0x0e, 0xe6, 0x50, 0x0e, 0xf2, 0xd0, 0x06,
+  0xee, 0xf0, 0x0e, 0x6d, 0x10, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f,
+  0xc0, 0x06, 0x63, 0x28, 0x80, 0x05, 0xa8, 0x36, 0x28, 0xc4, 0xff, 0xff,
+  0xff, 0xff, 0x0f, 0x40, 0x1b, 0x00, 0x6b, 0x00, 0x48, 0x40, 0xb5, 0xc1,
+  0x28, 0x02, 0x60, 0x01, 0xaa, 0x0d, 0x86, 0x21, 0x00, 0x0b, 0x50, 0x6d,
+  0x30, 0x8e, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa0, 0x36, 0x18,
+  0xc8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b, 0x94, 0xe4,
+  0xff, 0xff, 0xff, 0xff, 0x07, 0xa0, 0x0d, 0x80, 0x35, 0x00, 0x24, 0xa0,
+  0x02, 0x00, 0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86,
+  0x40, 0x18, 0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32,
+  0x61, 0x48, 0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x2b, 0x00,
+  0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22,
+  0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c,
+  0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x7c, 0x33, 0x00, 0xc3, 0x08,
+  0x04, 0x30, 0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45,
+  0x94, 0x30, 0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34,
+  0x88, 0x10, 0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4b, 0x9a, 0x22, 0x4a,
+  0x98, 0xfc, 0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0x5f, 0xa0, 0x02, 0xe2,
+  0x9f, 0xc6, 0x08, 0x80, 0x41, 0x04, 0x23, 0xb8, 0x48, 0x9a, 0x22, 0x4a,
+  0x98, 0xfc, 0x5f, 0x02, 0x98, 0x67, 0x21, 0xa2, 0x7f, 0x1a, 0x23, 0x00,
+  0x06, 0x11, 0x10, 0xa1, 0x18, 0x41, 0x84, 0x72, 0x12, 0xa9, 0x39, 0x02,
+  0xc4, 0x08, 0x81, 0x0d, 0x23, 0x0c, 0xc0, 0x1c, 0x41, 0x50, 0x90, 0x76,
+  0x92, 0x7b, 0x00, 0x0c, 0x82, 0x45, 0x00, 0x83, 0x64, 0x11, 0x06, 0x20,
+  0x3a, 0x10, 0x90, 0x02, 0x63, 0x8e, 0x00, 0x14, 0x06, 0x11, 0x04, 0x61,
+  0x10, 0x01, 0x10, 0xa6, 0x00, 0x46, 0x00, 0x86, 0x11, 0x86, 0x61, 0x10,
+  0x61, 0x10, 0x00, 0x00, 0x00, 0x00, 0x13, 0xc0, 0x20, 0x1c, 0xd2, 0x41,
+  0x1e, 0xec, 0x80, 0x0e, 0xda, 0x20, 0x1c, 0xe0, 0x01, 0x1e, 0xd8, 0xa1,
+  0x1c, 0xda, 0x80, 0x1e, 0xec, 0xe1, 0x1d, 0xe6, 0x21, 0x0e, 0xe6, 0xc0,
+  0x0d, 0xe0, 0xc0, 0x0d, 0xe0, 0xa0, 0x0d, 0xe6, 0x21, 0x1d, 0xda, 0xa1,
+  0x1e, 0xd8, 0x21, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4, 0x61, 0xc3, 0x6d, 0x94,
+  0x43, 0x1b, 0xc0, 0x83, 0x1e, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0,
+  0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x41, 0x3a, 0xc4, 0x81, 0x1e, 0xe0,
+  0x81, 0x1e, 0xe0, 0x41, 0x1b, 0xa4, 0x03, 0x1e, 0xe8, 0x01, 0x1e, 0xe8,
+  0x01, 0x1e, 0xb4, 0x41, 0x3a, 0xc4, 0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xd8,
+  0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xb4, 0x41, 0x3a, 0xcc, 0x81, 0x1c, 0xe8,
+  0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x41, 0x3a, 0xd8,
+  0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4,
+  0x81, 0x39, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc,
+  0x81, 0x1c, 0xb4, 0x81, 0x39, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0,
+  0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xc4, 0x81, 0x1d, 0xe8,
+  0x41, 0x1c, 0xd8, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xb4, 0x81, 0x3d, 0xc8,
+  0x01, 0x1d, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4,
+  0x81, 0x3d, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc,
+  0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xd0, 0x01, 0x1e, 0xe8, 0x81, 0x1d, 0xd0,
+  0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xd8, 0x01, 0x1d, 0xe8,
+  0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xe4,
+  0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xc8, 0x01, 0x1e, 0xe8, 0x41, 0x1c, 0xc8,
+  0x01, 0x1e, 0xb4, 0x81, 0x3d, 0xc4, 0x81, 0x1c, 0xe0, 0x81, 0x1e, 0xc4,
+  0x81, 0x1c, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1c, 0xe0, 0x41, 0x1b, 0xd8,
+  0x43, 0x1c, 0xe4, 0x81, 0x1c, 0xe8, 0x81, 0x1c, 0xd4, 0x81, 0x1d, 0xe8,
+  0x81, 0x1c, 0xd4, 0x81, 0x1d, 0xb4, 0x81, 0x3d, 0xc8, 0x41, 0x1d, 0xd8,
+  0x81, 0x1e, 0xc8, 0x41, 0x1d, 0xd8, 0x81, 0x1e, 0xc8, 0x41, 0x1d, 0xd8,
+  0x41, 0x1b, 0xd8, 0x43, 0x1d, 0xc4, 0x81, 0x1c, 0xe8, 0x41, 0x1d, 0xc4,
+  0x81, 0x1c, 0xe8, 0x41, 0x1d, 0xc4, 0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xc4,
+  0x01, 0x1c, 0xc8, 0x01, 0x1d, 0xe8, 0x41, 0x1c, 0xc0, 0x81, 0x1c, 0xd0,
+  0x81, 0x1e, 0xc4, 0x01, 0x1c, 0xc8, 0x01, 0x1d, 0xb4, 0x81, 0x3b, 0xe0,
+  0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x46, 0x08,
+  0x43, 0x32, 0xdb, 0x82, 0x4c, 0x5f, 0xe4, 0x30, 0x1c, 0x15, 0x10, 0x43,
+  0x22, 0x80, 0x51, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+  0x00, 0x60, 0x48, 0xc4, 0x74, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x0c, 0x89, 0xd2, 0xe0, 0x92, 0x80, 0x00, 0x18,
+  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x60, 0x48, 0x04, 0x0a, 0x17,
+  0x05, 0x04, 0xc0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x12,
+  0x1b, 0x04, 0x8a, 0x7a, 0x0f, 0x00, 0x00, 0x64, 0x81, 0x00, 0x0b, 0x00,
+  0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09,
+  0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a, 0x45, 0x50, 0x02, 0x85, 0x30, 0x02,
+  0x50, 0x30, 0x05, 0x51, 0x20, 0x85, 0x52, 0x06, 0x84, 0x47, 0x00, 0x0a,
+  0xa2, 0x40, 0x0a, 0x85, 0xee, 0x58, 0x42, 0x24, 0x00, 0x00, 0xb1, 0x18,
+  0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1,
+  0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42,
+  0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f,
+  0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1,
+  0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84,
+  0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc,
+  0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70,
+  0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19,
+  0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f,
+  0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21,
+  0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc,
+  0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84,
+  0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37,
+  0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70,
+  0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77,
+  0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79,
+  0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e,
+  0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81,
+  0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88,
+  0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4,
+  0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72,
+  0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74,
+  0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e,
+  0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e,
+  0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21,
+  0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01,
+  0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc,
+  0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77,
+  0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e,
+  0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1,
+  0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61,
+  0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0,
+  0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0,
+  0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74,
+  0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e,
+  0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41,
+  0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48,
+  0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c,
+  0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4,
+  0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71,
+  0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f,
+  0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f,
+  0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f,
+  0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23,
+  0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21,
+  0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21,
+  0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94,
+  0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a,
+  0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e,
+  0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e,
+  0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74,
+  0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74,
+  0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78,
+  0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c, 0x27, 0x46, 0x46,
+  0xc8, 0x11, 0x32, 0x64, 0xd4, 0xd4, 0x80, 0x0c, 0xf2, 0x09, 0x8b, 0xf2,
+  0x06, 0xc5, 0xc6, 0x91, 0x41, 0x14, 0x19, 0x12, 0xa5, 0x3c, 0x06, 0x33,
+  0x30, 0xd2, 0xa0, 0x3c, 0x12, 0x42, 0x25, 0x0c, 0x81, 0x14, 0x4c, 0x74,
+  0x31, 0xcc, 0xa2, 0x68, 0xcd, 0x72, 0x34, 0x00, 0x00, 0x00, 0x53, 0x44,
+  0x4b, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x77, 0x63, 0x68,
+  0x61, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65,
+  0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
+  0x6f, 0x6e, 0x20, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x20,
+  0x28, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x66, 0x65, 0x2d, 0x33, 0x32, 0x30,
+  0x32, 0x33, 0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65, 0x74, 0x61, 0x6c, 0x61,
+  0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x64,
+  0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62,
+  0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c,
+  0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f,
+  0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f,
+  0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x62,
+  0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f,
+  0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65,
+  0x6e, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x61,
+  0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f,
+  0x6e, 0x61, 0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x61, 0x69,
+  0x72, 0x2e, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69,
+  0x6e, 0x70, 0x75, 0x74, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
+  0x64, 0x28, 0x33, 0x74, 0x65, 0x78, 0x44, 0x76, 0x32, 0x5f, 0x66, 0x29,
+  0x61, 0x69, 0x72, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x69,
+  0x72, 0x2e, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76,
+  0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61,
+  0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x78, 0x61, 0x69,
+  0x72, 0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x69,
+  0x72, 0x2e, 0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63,
+  0x74, 0x69, 0x76, 0x65, 0x70, 0x6f, 0x73, 0x61, 0x69, 0x72, 0x2e, 0x62,
+  0x75, 0x66, 0x66, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66,
+  0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e,
+  0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64,
+  0x65, 0x78, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x61, 0x64, 0x61, 0x69,
+  0x72, 0x2e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70,
+  0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x55, 0x56, 0x4c, 0x65, 0x66, 0x74,
+  0x54, 0x6f, 0x70, 0x55, 0x56, 0x44, 0x69, 0x6d, 0x65, 0x6e, 0x73, 0x69,
+  0x6f, 0x6e, 0x73, 0x75, 0x69, 0x6e, 0x74, 0x4d, 0x69, 0x70, 0x4c, 0x65,
+  0x76, 0x65, 0x6c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x4c, 0x61, 0x79, 0x65,
+  0x72, 0x4f, 0x72, 0x44, 0x65, 0x70, 0x74, 0x68, 0x61, 0x69, 0x72, 0x2e,
+  0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73, 0x69, 0x7a,
+  0x65, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70,
+  0x65, 0x5f, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65,
+  0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e,
+  0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e,
+  0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x61,
+  0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x78,
+  0x74, 0x75, 0x72, 0x65, 0x63, 0x75, 0x62, 0x65, 0x3c, 0x66, 0x6c, 0x6f,
+  0x61, 0x74, 0x2c, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3e, 0x73,
+  0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65,
+  0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73,
+  0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
+  0x53, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x00, 0x00, 0x00, 0xc4, 0x62,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x82, 0x30, 0x10, 0x23, 0x08,
+  0x57, 0x34, 0x82, 0x30, 0x14, 0x23, 0x08, 0x83, 0x31, 0x82, 0x30, 0x1c,
+  0x23, 0x08, 0x0b, 0x30, 0x82, 0x30, 0x20, 0x23, 0x08, 0x43, 0x32, 0x82,
+  0x30, 0x28, 0x23, 0x08, 0xc3, 0x32, 0x82, 0x30, 0x30, 0x33, 0x0c, 0x6b,
+  0x10, 0xb0, 0xc1, 0x0c, 0x43, 0x1b, 0x08, 0x6e, 0x30, 0x43, 0x30, 0xcc,
+  0x30, 0xac, 0xc1, 0x1a, 0xbc, 0xc1, 0x0c, 0x04, 0xd1, 0x06, 0x6d, 0xf0,
+  0x06, 0x33, 0x04, 0xc5, 0x0c, 0x81, 0x31, 0x43, 0x70, 0xcc, 0x50, 0x20,
+  0x6f, 0xf0, 0x06, 0x89, 0x32, 0x43, 0xe0, 0x07, 0x33, 0x24, 0x6f, 0xb0,
+  0x30, 0x8d, 0x93, 0x3c, 0x50, 0x34, 0x03, 0xd2, 0x06, 0x52, 0x33, 0x25,
+  0x0a, 0x44, 0xcd, 0x40, 0xbd, 0x81, 0x1c, 0xbc, 0xc1, 0xa3, 0xc9, 0x81,
+  0x1c, 0xbc, 0xc1, 0xb3, 0xcd, 0x81, 0x1b, 0xbc, 0x01, 0xd7, 0xd1, 0x81,
+  0x1b, 0xbc, 0x81, 0xf7, 0xcd, 0x20, 0xad, 0x41, 0x65, 0xc5, 0xc1, 0xf5,
+  0x06, 0x6d, 0x80, 0x65, 0xa2, 0x00, 0x06, 0x71, 0x10, 0x06, 0x72, 0x90,
+  0x88, 0x01, 0x34, 0x06, 0x33, 0x28, 0x75, 0x40, 0x06, 0xd7, 0x1b, 0xb4,
+  0x41, 0x19, 0x24, 0x66, 0x00, 0x9d, 0xc1, 0x0c, 0x89, 0x1b, 0xa0, 0xc1,
+  0xf5, 0x06, 0x6d, 0x90, 0xa4, 0x01, 0xa4, 0x06, 0x33, 0x14, 0xa0, 0x10,
+  0x0a, 0xa3, 0x40, 0x0a, 0xa5, 0x30, 0xc3, 0x00, 0x07, 0x7f, 0x60, 0x0a,
+  0xd5, 0x01, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0xb9, 0x81,
+  0x1b, 0x58, 0x74, 0xa0, 0x07, 0x96, 0x65, 0xe9, 0x01, 0xc7, 0x0a, 0xa6,
+  0x00, 0x1b, 0x7e, 0x61, 0x0f, 0xea, 0xc0, 0x0a, 0x32, 0x12, 0x98, 0xa0,
+  0x8b, 0xd8, 0xd8, 0xec, 0xda, 0x5c, 0xda, 0xde, 0xc8, 0xea, 0xd8, 0xca,
+  0x5c, 0xcc, 0xd8, 0xc2, 0xce, 0xe6, 0x46, 0x11, 0xea, 0xc0, 0x0e, 0x4e,
+  0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3, 0x1b, 0x25,
+  0xb8, 0x83, 0x5b, 0xc2, 0xd2, 0xe4, 0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2,
+  0xde, 0xdc, 0x46, 0x09, 0xf0, 0xe0, 0xa8, 0xb0, 0x34, 0x39, 0x17, 0xb6,
+  0x30, 0xb7, 0xb3, 0xba, 0xb0, 0xb3, 0xb2, 0x2f, 0xbb, 0x32, 0xb9, 0xb9,
+  0xb4, 0x37, 0xb7, 0x51, 0x82, 0x3c, 0xb8, 0x29, 0x2c, 0x4d, 0xce, 0x65,
+  0xec, 0xad, 0x0d, 0x2e, 0x8d, 0xad, 0xec, 0xeb, 0x0d, 0x8e, 0x2e, 0xed,
+  0xcd, 0x6d, 0x6e, 0x94, 0x41, 0x0f, 0xf6, 0x80, 0x0f, 0x8e, 0x09, 0x4b,
+  0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0x1b, 0x25,
+  0x30, 0x05, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x18, 0x00, 0x00, 0x25, 0x00,
+  0x00, 0x00, 0x0b, 0x0a, 0x72, 0x28, 0x87, 0x77, 0x80, 0x07, 0x7a, 0x58,
+  0x70, 0x98, 0x43, 0x3d, 0xb8, 0xc3, 0x38, 0xb0, 0x43, 0x39, 0xd0, 0xc3,
+  0x82, 0xe6, 0x1c, 0xc6, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2, 0xc1, 0x1d,
+  0xe6, 0x21, 0x1d, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x16, 0x34, 0xe3,
+  0x60, 0x0e, 0xe7, 0x50, 0x0f, 0xe1, 0x20, 0x0f, 0xe4, 0x40, 0x0f, 0xe1,
+  0x20, 0x0f, 0xe7, 0x50, 0x0e, 0xf4, 0xb0, 0x80, 0x81, 0x07, 0x79, 0x28,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x78, 0x87, 0x71, 0x08, 0x07, 0x7a, 0x28,
+  0x07, 0x72, 0x58, 0x70, 0x9c, 0xc3, 0x38, 0xb4, 0x01, 0x3b, 0xa4, 0x83,
+  0x3d, 0x94, 0xc3, 0x02, 0x6b, 0x1c, 0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c,
+  0xdc, 0x20, 0x1c, 0xe4, 0x61, 0x1c, 0xdc, 0x20, 0x1c, 0xe8, 0x81, 0x1e,
+  0xc2, 0x61, 0x1c, 0xd0, 0xa1, 0x1c, 0xc8, 0x61, 0x1c, 0xc2, 0x81, 0x1d,
+  0xd8, 0x61, 0xc1, 0x01, 0x0f, 0xf4, 0x20, 0x0f, 0xe1, 0x50, 0x0f, 0xf4,
+  0x80, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x10, 0x00, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0x07, 0xcc, 0x3c, 0xa4, 0x83, 0x3b, 0x9c, 0x03, 0x3b, 0x94,
+  0x03, 0x3d, 0xa0, 0x83, 0x3c, 0x94, 0x43, 0x38, 0x90, 0xc3, 0x01, 0x00,
+  0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x13, 0x04,
+  0x48, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x34, 0x4a,
+  0x81, 0x5e, 0x0d, 0x10, 0x2e, 0x81, 0x22, 0xa0, 0x3e, 0xd6, 0x00, 0x04,
+  0x02, 0x81, 0x19, 0x80, 0x31, 0x02, 0x10, 0x04, 0x41, 0x10, 0x14, 0x66,
+  0x00, 0xc6, 0x08, 0x40, 0x10, 0x04, 0xf1, 0x5f, 0x18, 0x01, 0x18, 0x23,
+  0x00, 0x41, 0x10, 0xc4, 0xbf, 0x31, 0x02, 0x10, 0x04, 0x41, 0x10, 0x0c,
+  0x28, 0xcc, 0x41, 0x84, 0x01, 0xc7, 0x79, 0x73, 0x10, 0x1f, 0xc7, 0x79,
+  0x73, 0x10, 0xdc, 0xc7, 0x79, 0x73, 0x10, 0x5c, 0x18, 0x70, 0xde, 0x1c,
+  0x04, 0xc7, 0x85, 0x81, 0x37, 0x07, 0xc1, 0x71, 0x9f, 0x37, 0x07, 0x01,
+  0x06, 0x60, 0x00, 0x06, 0xde, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x30,
+  0x00, 0x00, 0x45, 0x00, 0x00, 0x00, 0x22, 0x47, 0xc8, 0x90, 0x51, 0x22,
+  0xc8, 0x4f, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xe3, 0x59, 0x18, 0x26, 0x0d,
+  0x00, 0x00, 0x6f, 0x6d, 0x6e, 0x69, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74,
+  0x20, 0x63, 0x68, 0x61, 0x72, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20,
+  0x43, 0x2b, 0x2b, 0x20, 0x54, 0x42, 0x41, 0x41, 0x61, 0x69, 0x72, 0x2d,
+  0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73,
+  0x28, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x75, 0x62,
+  0x65, 0x29, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d,
+  0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x61, 0x72, 0x67, 0x28, 0x32, 0x29,
+  0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63,
+  0x6f, 0x70, 0x65, 0x2d, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73,
+  0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63,
+  0x6f, 0x70, 0x65, 0x2d, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x73,
+  0x5f, 0x5a, 0x54, 0x53, 0x31, 0x32, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
+  0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x74, 0x00, 0x13, 0x04,
+  0xac, 0x99, 0x20, 0x60, 0xce, 0x04, 0x01, 0x7b, 0x26, 0x08, 0x18, 0xb4,
+  0x42, 0xa0, 0x05, 0x55, 0x58, 0x31, 0xd4, 0x02, 0x2d, 0xac, 0xc2, 0x8a,
+  0xc1, 0x16, 0x68, 0x81, 0x15, 0x56, 0x0c, 0xb7, 0x40, 0x0b, 0xad, 0xb0,
+  0x21, 0x48, 0x85, 0x0d, 0x03, 0x2a, 0xe0, 0x02, 0x2c, 0x6c, 0x18, 0x72,
+  0x21, 0x17, 0x60, 0x61, 0x43, 0x50, 0x0b, 0x1b, 0x84, 0x5b, 0xb0, 0x85,
+  0x0d, 0xc3, 0x2b, 0xe4, 0x02, 0x2c, 0x6c, 0x18, 0xbc, 0x5c, 0x80, 0x85,
+  0x0d, 0x89, 0x2b, 0xe4, 0x02, 0x2c, 0xe4, 0x42, 0x2c, 0xf4, 0x82, 0x2c,
+  0xf8, 0xc2, 0x2c, 0x6c, 0x18, 0x7e, 0xc1, 0x17, 0x66, 0x61, 0xc3, 0xf0,
+  0x0b, 0xbd, 0x20, 0x0b, 0x00, 0x00, 0x9b, 0x0c, 0x97, 0x47, 0x06, 0x14,
+  0x08, 0xb2, 0xc9, 0x90, 0x81, 0x01, 0x1a, 0x50, 0x20, 0x88, 0x05, 0x9d,
+  0xf8, 0x5b, 0x40, 0x80, 0xff, 0x18, 0x42, 0x40, 0x06, 0x16, 0x40, 0xe2,
+  0x6f, 0x01, 0x05, 0xfe, 0x63, 0x08, 0xc4, 0x66, 0xc1, 0x24, 0xfe, 0x16,
+  0x5c, 0xe0, 0xbf, 0xc9, 0x30, 0x06, 0x6a, 0xb0, 0x06, 0x14, 0x80, 0x31,
+  0x62, 0x50, 0x10, 0x21, 0x08, 0x06, 0x94, 0x1d, 0x04, 0xc3, 0x3c, 0x43,
+  0x70, 0x1c, 0x41, 0x21, 0x10, 0x03, 0x43, 0x18, 0xc5, 0x65, 0x58, 0x47,
+  0x84, 0xff, 0x1c, 0x03, 0x16, 0x88, 0x81, 0x7d, 0x49, 0xf8, 0xcf, 0x31,
+  0x08, 0xc1, 0x18, 0xcc, 0x12, 0x1c, 0x16, 0x06, 0x48, 0xf8, 0xcf, 0x31,
+  0x6c, 0x81, 0x19, 0xcc, 0x31, 0x04, 0x8d, 0x19, 0xcc, 0x12, 0x1c, 0x73,
+  0x0c, 0x9c, 0x43, 0x07, 0x56, 0x06, 0x4c, 0xf8, 0xcf, 0x31, 0x08, 0x41,
+  0x1a, 0xcc, 0x12, 0x1c, 0x73, 0x0c, 0x5e, 0x74, 0x07, 0x73, 0x0c, 0xc1,
+  0xb3, 0x06, 0xb3, 0x04, 0x87, 0xa5, 0x01, 0x14, 0xfe, 0x73, 0x0c, 0x60,
+  0x40, 0xe9, 0xc1, 0x1c, 0x43, 0x20, 0xbc, 0xc1, 0x2c, 0xc1, 0x61, 0x6c,
+  0x60, 0x85, 0xbf, 0xb5, 0x01, 0x15, 0xfe, 0x73, 0x0c, 0x63, 0x20, 0xf8,
+  0xc1, 0x1c, 0x43, 0x20, 0xcc, 0xc1, 0x2c, 0xc1, 0x31, 0xd0, 0x13, 0x08,
+  0x86, 0x52, 0x40, 0x04, 0x35, 0x68, 0x02, 0x18, 0x04, 0xa8, 0x00, 0x0c,
+  0x32, 0x04, 0x64, 0x30, 0x07, 0x9b, 0x0c, 0x7b, 0x20, 0x0a, 0xab, 0x40,
+  0xc1, 0x20, 0x23, 0x06, 0x06, 0x11, 0x82, 0x60, 0xe1, 0x1f, 0xd2, 0x2b,
+  0x04, 0x23, 0x06, 0x4b, 0x11, 0x82, 0x60, 0x00, 0xc5, 0x42, 0x1f, 0xf0,
+  0x01, 0xa1, 0x07, 0x81, 0x1c, 0xac, 0xc2, 0x68, 0x42, 0x00, 0x64, 0x10,
+  0x10, 0x03, 0x0c, 0x00, 0x00, 0x00, 0x5b, 0x8e, 0x20, 0xc8, 0x85, 0x43,
+  0x17, 0x90, 0x5d, 0xd8, 0x72, 0x0c, 0x41, 0x2e, 0x1c, 0xba, 0x80, 0xec,
+  0xc2, 0x96, 0xa3, 0x09, 0x7e, 0xe1, 0xd0, 0x05, 0x64, 0x17, 0xb6, 0x1c,
+  0x6c, 0x10, 0x80, 0xc3, 0xa1, 0x0b, 0xc8, 0x2e, 0x6c, 0x29, 0xdc, 0xe0,
+  0xd8, 0x05, 0x44, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x32, 0x0e, 0x10, 0x22, 0x84, 0x00,
+  0xae, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x0c,
+  0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0x78, 0x01, 0x00,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00,
+  0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+  0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x00, 0x24, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1d, 0x00,
+  0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x17, 0x00,
+  0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x17, 0x00,
+  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x08, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x0c,
+  0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x75,
+  0x62, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65,
+  0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x63, 0x75, 0x62,
+  0x65, 0x2e, 0x76, 0x34, 0x66, 0x33, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x63,
+  0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2e, 0x66, 0x2e, 0x66, 0x33, 0x32,
+  0x2e, 0x75, 0x2e, 0x69, 0x33, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f,
+  0x6e, 0x76, 0x65, 0x72, 0x74, 0x2e, 0x75, 0x2e, 0x69, 0x33, 0x32, 0x2e,
+  0x66, 0x2e, 0x66, 0x33, 0x32, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39,
+  0x38, 0x61, 0x69, 0x72, 0x36, 0x34, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65,
+  0x2d, 0x74, 0x76, 0x6f, 0x73, 0x31, 0x33, 0x2e, 0x30, 0x2e, 0x30, 0x2d,
+  0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00
+};
+const unsigned int BlitFromCube_metallib_len = 4610;
+#else
+const unsigned char FullscreenVert_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa2, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0f, 0x00, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63,
+  0x72, 0x65, 0x65, 0x6e, 0x56, 0x65, 0x72, 0x74, 0x00, 0x54, 0x59, 0x50,
+  0x45, 0x01, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x09, 0x3f,
+  0x09, 0xcf, 0x14, 0xb2, 0xfb, 0xb5, 0xe2, 0x14, 0x3b, 0xbe, 0x99, 0x33,
+  0x7a, 0x9f, 0x6b, 0x94, 0xd6, 0x41, 0x46, 0xd3, 0xa9, 0x59, 0xe0, 0x34,
+  0xbf, 0xca, 0x49, 0x0d, 0xfb, 0x05, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
+  0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0,
+  0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa8, 0x09,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c,
+  0x00, 0x00, 0x67, 0x02, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00,
+  0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8,
+  0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05,
+  0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92,
+  0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32,
+  0x44, 0x24, 0x48, 0x0a, 0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19,
+  0x21, 0x72, 0x24, 0x07, 0xc8, 0x08, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40,
+  0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x6c, 0x00,
+  0x00, 0x00, 0x1b, 0x7a, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x90,
+  0x00, 0x8a, 0x08, 0x07, 0x78, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7c, 0x68,
+  0x03, 0x73, 0xa8, 0x07, 0x77, 0x18, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68,
+  0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e,
+  0xca, 0x01, 0x20, 0xda, 0x21, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c,
+  0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d, 0xec, 0xa1, 0x1c, 0xc6, 0x81, 0x1e,
+  0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e, 0xd2, 0x81, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x38, 0x00, 0x06, 0x77, 0x78, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x48,
+  0x07, 0x76, 0xa0, 0x87, 0x74, 0x70, 0x87, 0x79, 0x00, 0x08, 0x77, 0x78,
+  0x87, 0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80,
+  0x87, 0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28,
+  0x07, 0x76, 0x48, 0x87, 0x76, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c,
+  0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d,
+  0xca, 0xa1, 0x0d, 0xe0, 0xe1, 0x1d, 0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x0d, 0xca, 0x81, 0x1d, 0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d,
+  0xde, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0,
+  0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x48,
+  0x07, 0x77, 0x30, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68,
+  0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c,
+  0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e,
+  0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68,
+  0x83, 0x79, 0x48, 0x87, 0x73, 0x70, 0x87, 0x72, 0x20, 0x87, 0x36, 0xd0,
+  0x87, 0x72, 0x90, 0x87, 0x77, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68,
+  0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e,
+  0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c,
+  0xe0, 0x01, 0x1e, 0xd2, 0xc1, 0x1d, 0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c,
+  0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x98,
+  0x07, 0x7a, 0x08, 0x87, 0x71, 0x58, 0x87, 0x36, 0x80, 0x07, 0x79, 0x78,
+  0x07, 0x7a, 0x28, 0x87, 0x71, 0xa0, 0x87, 0x77, 0x90, 0x87, 0x36, 0x10,
+  0x87, 0x7a, 0x30, 0x07, 0x73, 0x28, 0x07, 0x79, 0x68, 0x83, 0x79, 0x48,
+  0x07, 0x7d, 0x28, 0x07, 0x00, 0x0f, 0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e,
+  0xc2, 0xc1, 0x1c, 0xca, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d,
+  0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00,
+  0x36, 0x18, 0xc2, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b,
+  0x8c, 0xe1, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0x28, 0x00, 0x00,
+  0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82,
+  0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20,
+  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, 0x20, 0x64,
+  0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1,
+  0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x34,
+  0x33, 0x00, 0xc3, 0x08, 0x02, 0x30, 0x8c, 0x40, 0x00, 0x56, 0x08, 0x99,
+  0x23, 0x00, 0x83, 0x22, 0x0c, 0x51, 0x15, 0x01, 0x88, 0x6e, 0x20, 0x20,
+  0x05, 0x68, 0x18, 0x81, 0x20, 0x46, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa8,
+  0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07,
+  0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8, 0x03,
+  0x37, 0x80, 0x03, 0x37, 0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d, 0x00,
+  0x0f, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80,
+  0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0,
+  0x06, 0xe9, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10,
+  0x07, 0x76, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xf6, 0x40, 0x07, 0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76, 0xa0,
+  0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0,
+  0x06, 0xf6, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80,
+  0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x90,
+  0x07, 0x72, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50,
+  0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20,
+  0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60,
+  0x0f, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xa0,
+  0x07, 0x75, 0x10, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70, 0x20,
+  0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10,
+  0x07, 0x70, 0x20, 0x07, 0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a, 0x10,
+  0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x43, 0x18, 0x03, 0x00, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0x0c, 0x02, 0x04, 0x80, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x40, 0x16, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x32, 0x1e, 0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09,
+  0x26, 0x47, 0xc6, 0x04, 0x43, 0xa2, 0x12, 0x18, 0x01, 0x28, 0x82, 0x42,
+  0x28, 0x08, 0xd2, 0xb1, 0x84, 0x48, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18,
+  0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29,
+  0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x21, 0x06,
+  0x41, 0x24, 0x80, 0x72, 0x50, 0xb9, 0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a,
+  0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x10, 0x42, 0x22, 0x10, 0x05, 0xdf, 0x20,
+  0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4, 0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4,
+  0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x0d, 0x64, 0x46, 0x06, 0x46, 0x66,
+  0xc6, 0x25, 0x07, 0x07, 0x04, 0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac,
+  0xac, 0x65, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x27, 0x65, 0x88,
+  0x90, 0x10, 0x43, 0x0c, 0x42, 0x20, 0x0c, 0x62, 0x60, 0xd1, 0x54, 0x46,
+  0x17, 0xc6, 0x36, 0x04, 0x49, 0x0e, 0x42, 0x20, 0x04, 0x62, 0xe0, 0x16,
+  0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42,
+  0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26,
+  0xc6, 0x56, 0x36, 0x44, 0x48, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63,
+  0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f,
+  0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43,
+  0x84, 0x64, 0x21, 0x19, 0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1,
+  0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99,
+  0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x95, 0xb9,
+  0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11, 0x92, 0x86, 0x51, 0x58, 0x9a, 0x9c,
+  0x8b, 0x5d, 0x99, 0x1c, 0x5d, 0x19, 0xde, 0xd7, 0x5b, 0x1d, 0x1d, 0x5c,
+  0x1d, 0x1d, 0xa9, 0xb3, 0x32, 0xb7, 0x32, 0xb9, 0x30, 0xba, 0x32, 0x32,
+  0x94, 0x19, 0xba, 0x32, 0x3c, 0x22, 0x3b, 0x99, 0x2f, 0xb3, 0x14, 0x46,
+  0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65,
+  0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x34, 0xcc, 0xd8, 0xde, 0xc2, 0xe8, 0x64,
+  0xc8, 0x84, 0xa5, 0xc9, 0xb9, 0x84, 0xc9, 0x9d, 0x7d, 0xb9, 0x85, 0xb5,
+  0x95, 0x71, 0xa0, 0x2b, 0xc3, 0x1b, 0xc2, 0x24, 0x4f, 0x02, 0x25, 0x51,
+  0x22, 0x25, 0x53, 0x42, 0x91, 0x09, 0x4b, 0x93, 0x73, 0x81, 0x7b, 0x9b,
+  0x4b, 0xa3, 0x4b, 0x7b, 0x73, 0xa3, 0x61, 0xc6, 0xf6, 0x16, 0x46, 0x47,
+  0xc3, 0x01, 0xee, 0x6d, 0x6e, 0x88, 0x92, 0x58, 0x49, 0x94, 0x5c, 0xc9,
+  0x94, 0x60, 0x43, 0x88, 0xa4, 0x4a, 0x32, 0x36, 0x61, 0x69, 0x72, 0x2e,
+  0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x64, 0x24, 0xea, 0xd2,
+  0xdc, 0xe8, 0x28, 0xd8, 0x25, 0x0d, 0x61, 0x88, 0x21, 0xd9, 0x92, 0x28,
+  0xe1, 0x92, 0x29, 0xe9, 0x86, 0x08, 0x89, 0x37, 0xc4, 0x30, 0x80, 0x44,
+  0x4b, 0xbe, 0x11, 0x11, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0xb4,
+  0xc3, 0x3b, 0x90, 0x43, 0x3d, 0xb0, 0x43, 0x39, 0xb8, 0x81, 0x39, 0xb0,
+  0x43, 0x38, 0x9c, 0xc3, 0x3c, 0x4c, 0x11, 0x82, 0x61, 0x84, 0xc2, 0x0e,
+  0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xe9, 0x40, 0x0e, 0xe5, 0xe0, 0x0e,
+  0xf4, 0x30, 0x25, 0x28, 0x46, 0x2c, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06,
+  0xf6, 0x50, 0x0e, 0xf2, 0x30, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x25,
+  0x30, 0x46, 0x50, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xec, 0x10, 0x0e,
+  0xee, 0x70, 0x0e, 0xf5, 0x10, 0x0e, 0xe7, 0x50, 0x0e, 0xbf, 0x60, 0x0f,
+  0xe5, 0x20, 0x0f, 0xf3, 0x90, 0x0e, 0xef, 0xe0, 0x0e, 0x53, 0x02, 0x64,
+  0xc4, 0x14, 0x0e, 0xe9, 0x20, 0x0f, 0x6e, 0x30, 0x0e, 0xef, 0xd0, 0x0e,
+  0xf0, 0x90, 0x0e, 0xec, 0x50, 0x0e, 0xbf, 0xf0, 0x0e, 0xf0, 0x40, 0x0f,
+  0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x0f, 0x53, 0x06, 0x85, 0x71, 0x46, 0x28,
+  0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e, 0xf2, 0x40, 0x0f,
+  0xe5, 0x80, 0x0f, 0x53, 0x02, 0x30, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18,
+  0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1,
+  0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42,
+  0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f,
+  0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1,
+  0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84,
+  0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc,
+  0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70,
+  0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19,
+  0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f,
+  0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21,
+  0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc,
+  0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84,
+  0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37,
+  0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70,
+  0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77,
+  0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79,
+  0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e,
+  0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81,
+  0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88,
+  0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4,
+  0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72,
+  0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74,
+  0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e,
+  0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e,
+  0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21,
+  0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01,
+  0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc,
+  0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77,
+  0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e,
+  0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1,
+  0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61,
+  0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0,
+  0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0,
+  0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74,
+  0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e,
+  0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41,
+  0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48,
+  0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c,
+  0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4,
+  0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71,
+  0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f,
+  0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f,
+  0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f,
+  0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23,
+  0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21,
+  0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21,
+  0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94,
+  0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a,
+  0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e,
+  0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e,
+  0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74,
+  0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74,
+  0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78,
+  0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x09, 0x00,
+  0x00, 0x00, 0x06, 0xe0, 0x7c, 0xd4, 0xb2, 0x48, 0x42, 0x44, 0x10, 0xcd,
+  0x4b, 0x44, 0x93, 0x05, 0x5c, 0x00, 0x12, 0xf9, 0x82, 0xd3, 0x54, 0x44,
+  0x34, 0xf9, 0x85, 0x5f, 0xdc, 0xb6, 0x4f, 0xf9, 0xc8, 0x6d, 0x03, 0x00,
+  0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x13, 0x04,
+  0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xb4, 0x63,
+  0x11, 0x40, 0x60, 0x1c, 0x73, 0x10, 0x83, 0xb0, 0x2c, 0x44, 0x33, 0x00,
+  0x14, 0x33, 0x00, 0x63, 0x09, 0x20, 0x08, 0x82, 0x20, 0x18, 0x80, 0x20,
+  0x08, 0x82, 0xe0, 0x30, 0x96, 0x00, 0x82, 0x20, 0x88, 0xff, 0x02, 0x08,
+  0x82, 0x20, 0xfe, 0xcd, 0x00, 0x90, 0xcc, 0x41, 0x50, 0xd4, 0x24, 0xd1,
+  0xcc, 0x00, 0x10, 0x8c, 0x11, 0x80, 0x20, 0x08, 0xe2, 0xdf, 0x08, 0xc0,
+  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x4c, 0x57, 0x81, 0xa4, 0x23,
+  0x06, 0xc4, 0x10, 0x58, 0xc1, 0x1c, 0x03, 0x13, 0x54, 0x15, 0x55, 0x3a,
+  0x62, 0x40, 0x0c, 0x41, 0x16, 0xcc, 0x31, 0x0c, 0x41, 0x66, 0xc1, 0x23,
+  0x1f, 0x0b, 0x1e, 0xf8, 0x0c, 0x32, 0x04, 0x0f, 0x35, 0xc8, 0x10, 0x3c,
+  0xd6, 0x6c, 0xc3, 0x53, 0x00, 0xb3, 0x0d, 0x81, 0x10, 0x64, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int FullscreenVert_metallib_len = 2722;
+const unsigned char BlitFrom2D_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x3e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0b, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x32, 0x44, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01,
+  0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x8e, 0xc1, 0x03, 0x5e, 0x12, 0x72,
+  0x1f, 0x9e, 0x32, 0x93, 0x48, 0x9e, 0xbb, 0x7b, 0xe5, 0xaf, 0x2a, 0x2b,
+  0x49, 0x9f, 0x09, 0x1b, 0x0e, 0x1e, 0xec, 0x02, 0xbd, 0x97, 0xa6, 0x39,
+  0xcf, 0xb8, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53,
+  0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00,
+  0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x48, 0x0d, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x4f, 0x03,
+  0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00,
+  0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10,
+  0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04,
+  0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10,
+  0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a,
+  0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07,
+  0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00,
+  0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x1b, 0xc2,
+  0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x60, 0x00, 0x09, 0xa8, 0x88,
+  0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77, 0xc0, 0x87, 0x36, 0x30, 0x87,
+  0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87,
+  0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00,
+  0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0xe1, 0x1c, 0xc2,
+  0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4,
+  0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81, 0x1e, 0xd0, 0x01, 0x88, 0x03,
+  0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77, 0x68, 0x03, 0x71, 0xa8, 0x87,
+  0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77, 0x98, 0x07, 0x80, 0x70, 0x87,
+  0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70, 0x68, 0x87, 0x72, 0x68, 0x03,
+  0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a, 0x28, 0x07, 0x79, 0x68, 0x83,
+  0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c, 0xda,
+  0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e, 0xca,
+  0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0xa1, 0x0d, 0xdc,
+  0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xc2, 0xc1, 0x1c, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83,
+  0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83,
+  0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1d, 0xc2, 0xc1, 0x1d, 0xe6,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77, 0x28, 0x07, 0x72, 0x68, 0x03,
+  0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2,
+  0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1, 0x1c, 0xda, 0xa0, 0x1d, 0xc2,
+  0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x88,
+  0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75, 0x68, 0x03, 0x78, 0x90, 0x87,
+  0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x03,
+  0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72, 0x90, 0x87, 0x36, 0x98, 0x87,
+  0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00, 0x20, 0xea, 0xc1, 0x1d, 0xe6,
+  0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda,
+  0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07,
+  0x60, 0xc3, 0x26, 0x0c, 0xc0, 0x02, 0x54, 0x43, 0x38, 0xa4, 0x83, 0x3c,
+  0xb4, 0x81, 0x38, 0xd4, 0x83, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x1b,
+  0xb8, 0xc3, 0x3b, 0xb4, 0x41, 0x38, 0xb0, 0x43, 0x3a, 0x84, 0xc3, 0x3c,
+  0x00, 0x1b, 0x8c, 0xa1, 0x00, 0x16, 0xa0, 0xda, 0x80, 0x10, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x0c, 0x20, 0x01, 0xd5, 0x06, 0xa3, 0x08, 0x80,
+  0x05, 0xa8, 0x36, 0x18, 0x86, 0x00, 0x2c, 0x40, 0xb5, 0xc1, 0x38, 0xfe,
+  0xff, 0xff, 0xff, 0x7f, 0x00, 0x24, 0x80, 0xda, 0x60, 0x20, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x12, 0x40, 0x6d, 0x40, 0x92, 0xff, 0xff, 0xff,
+  0xff, 0x1f, 0x00, 0x06, 0x90, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x49, 0x18,
+  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18, 0x26, 0x0c,
+  0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48, 0x0a, 0x03,
+  0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x32, 0x22,
+  0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93,
+  0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84,
+  0xa4, 0x4c, 0x10, 0x60, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30, 0x8c, 0x20,
+  0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30, 0xf9, 0xac,
+  0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10, 0x62, 0x80,
+  0x41, 0x04, 0x42, 0x38, 0x4a, 0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x7f, 0x22,
+  0xae, 0x89, 0x8a, 0x88, 0xdf, 0x1e, 0xfe, 0x69, 0x8c, 0x00, 0x18, 0x44,
+  0x30, 0x82, 0x8b, 0xa4, 0x29, 0xa2, 0x84, 0xc9, 0xff, 0x25, 0x80, 0x79,
+  0x16, 0x22, 0xfa, 0xa7, 0x31, 0x02, 0x60, 0x10, 0x01, 0x11, 0x8a, 0x11,
+  0x44, 0x28, 0x27, 0x91, 0x9a, 0x23, 0x08, 0x86, 0x11, 0x84, 0xa1, 0x20,
+  0xe1, 0x24, 0xc1, 0x1a, 0x03, 0xe4, 0x8a, 0x00, 0x06, 0xc1, 0x81, 0x80,
+  0x14, 0x18, 0x73, 0x04, 0xa0, 0x30, 0x88, 0x20, 0x08, 0x83, 0x08, 0x83,
+  0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa8, 0x70, 0x48, 0x07, 0x79,
+  0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72,
+  0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8, 0x03, 0x37, 0x80, 0x03, 0x37,
+  0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06,
+  0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d, 0x90, 0x0e,
+  0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06,
+  0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06,
+  0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07,
+  0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x40, 0x07,
+  0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06,
+  0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07,
+  0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x20, 0x07,
+  0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07,
+  0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07,
+  0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x90, 0x07, 0x72, 0xa0, 0x07,
+  0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06,
+  0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07,
+  0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x75, 0x10, 0x07,
+  0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07,
+  0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07,
+  0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07,
+  0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x43, 0x98, 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0x21, 0xcc, 0x03, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc0, 0x10, 0x26, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+  0x0b, 0x04, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11,
+  0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a, 0x23, 0x00,
+  0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05, 0x53, 0x20, 0x85, 0x52, 0x06,
+  0x44, 0x0b, 0x65, 0x04, 0xa0, 0x40, 0x0a, 0x82, 0xe6, 0x58, 0x42, 0x24,
+  0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x42, 0x01, 0x00, 0x00, 0x1a, 0x03,
+  0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9, 0xb9, 0xb4,
+  0x37, 0xb7, 0x21, 0xc6, 0x70, 0x48, 0xc0, 0x04, 0x51, 0xb9, 0x1b, 0x43,
+  0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x0c, 0x84, 0x24,
+  0x0c, 0x06, 0xdf, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4, 0xad, 0x8c,
+  0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x0d, 0x64,
+  0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x07, 0x04, 0xa5, 0xad, 0x8c,
+  0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25,
+  0x07, 0x27, 0x65, 0x88, 0x20, 0x11, 0x43, 0x8c, 0x81, 0x18, 0x8a, 0x61,
+  0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04, 0x91, 0x8e, 0x81, 0x18,
+  0x88, 0x61, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6, 0x06, 0x97,
+  0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36, 0xf7, 0x45,
+  0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44, 0x90, 0x12, 0x72, 0x61,
+  0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66,
+  0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61,
+  0x62, 0x6c, 0x65, 0x43, 0x04, 0x69, 0x21, 0x19, 0x84, 0xa5, 0xc9, 0xb9,
+  0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9, 0x85, 0xb5,
+  0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95, 0xd1, 0x8d,
+  0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11, 0xa4, 0x86,
+  0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99, 0x1b, 0x59, 0x99, 0xdc, 0x17,
+  0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3, 0xb0, 0x34, 0x39, 0x97, 0x30,
+  0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0x2f, 0xb7, 0xb0, 0xb6, 0x32,
+  0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x43, 0x10, 0xe9, 0x19, 0x06,
+  0x09, 0x92, 0xa2, 0x21, 0x82, 0x24, 0x51, 0x0a, 0x4b, 0x93, 0x73, 0x31,
+  0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0xfb, 0x4a, 0x73, 0x83, 0xab,
+  0xa3, 0x23, 0x75, 0x56, 0xe6, 0x56, 0x26, 0x17, 0x46, 0x57, 0x46, 0x86,
+  0x32, 0x43, 0x57, 0x86, 0x47, 0x64, 0x27, 0xf3, 0x65, 0x96, 0x42, 0x25,
+  0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d, 0xae, 0x4c, 0x8e, 0x4f, 0x58,
+  0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9, 0x18, 0x5d, 0x9a,
+  0x5d, 0x19, 0x0d, 0x33, 0xb6, 0xb7, 0x30, 0x3a, 0x19, 0x32, 0x61, 0x69,
+  0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x1c, 0xe8,
+  0xca, 0xf0, 0x86, 0x48, 0xc3, 0x20, 0x51, 0x52, 0x25, 0x59, 0xd2, 0x25,
+  0x41, 0x12, 0x26, 0x65, 0x92, 0x46, 0x26, 0x2c, 0x4d, 0xce, 0x05, 0xee,
+  0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x8d, 0x52, 0x58, 0x9a, 0x9c, 0x8b,
+  0xdb, 0xdb, 0x17, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9, 0x18, 0x5d, 0x9a,
+  0x5d, 0x19, 0x07, 0xb8, 0xb7, 0xb9, 0x21, 0xd0, 0x40, 0x48, 0x9c, 0x64,
+  0x49, 0x9d, 0x04, 0x49, 0x91, 0x94, 0x49, 0x1e, 0x95, 0xb0, 0x34, 0x39,
+  0x17, 0xb1, 0x3a, 0x33, 0xb3, 0x32, 0x39, 0x3e, 0x61, 0x69, 0x72, 0x2e,
+  0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x94,
+  0xc2, 0xd2, 0xe4, 0x5c, 0xd8, 0xde, 0xc6, 0xc2, 0xe8, 0xd2, 0xde, 0xdc,
+  0xbe, 0xd2, 0xdc, 0xc8, 0xca, 0xf0, 0x88, 0x84, 0xa5, 0xc9, 0xb9, 0xc8,
+  0x95, 0x85, 0x91, 0x91, 0x0a, 0x4b, 0x93, 0x73, 0x99, 0xa3, 0x93, 0xab,
+  0x1b, 0xa3, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb, 0x4a, 0x73, 0x33, 0x7b,
+  0x63, 0x52, 0x65, 0xc5, 0x54, 0x66, 0x46, 0x47, 0xf5, 0x06, 0x47, 0xa6,
+  0xca, 0x8a, 0x28, 0xad, 0xad, 0xcc, 0x6d, 0x2e, 0xed, 0xcd, 0x6d, 0x8e,
+  0x44, 0x5d, 0x9a, 0x1b, 0x1d, 0x91, 0xa6, 0x34, 0x38, 0xa6, 0x32, 0xbb,
+  0x32, 0x36, 0x16, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x64, 0x98, 0xc2, 0xf2,
+  0xca, 0xe4, 0x9e, 0xe4, 0x88, 0xca, 0xe0, 0xe8, 0xd0, 0x86, 0xa0, 0xc1,
+  0x30, 0x0c, 0xc5, 0x30, 0x48, 0x98, 0x54, 0x06, 0x43, 0x31, 0x14, 0xc3,
+  0x20, 0x61, 0x92, 0x19, 0x0c, 0xc9, 0x60, 0x0c, 0x83, 0x74, 0x06, 0x12,
+  0x1a, 0x0c, 0xca, 0x60, 0x0c, 0x83, 0x94, 0x06, 0x92, 0x1a, 0x30, 0x0a,
+  0x4b, 0x93, 0x73, 0x09, 0x93, 0x3b, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb,
+  0x9a, 0x4b, 0xd3, 0x2b, 0xe3, 0x15, 0x96, 0x26, 0xe7, 0x12, 0x26, 0x77,
+  0xf6, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x15, 0xc6, 0x96, 0x76, 0xe6, 0xf6,
+  0x35, 0x97, 0xa6, 0x57, 0x46, 0x66, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x4c,
+  0xaa, 0xec, 0x2c, 0xed, 0xcd, 0x8d, 0xcc, 0xdc, 0x5b, 0x9d, 0xdc, 0x58,
+  0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0xdb, 0x10, 0x32, 0x18, 0x0e, 0x09,
+  0x0c, 0xa4, 0x30, 0x18, 0x10, 0x49, 0x0c, 0x86, 0x61, 0x20, 0xa4, 0x31,
+  0x90, 0xc8, 0x40, 0x5a, 0x03, 0x89, 0x0d, 0x06, 0x44, 0x6a, 0x83, 0xa1,
+  0x90, 0x20, 0xc9, 0x0d, 0xa4, 0x4c, 0x7a, 0x03, 0x2e, 0x61, 0x69, 0x72,
+  0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x54, 0xc2, 0xd2, 0xe4,
+  0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0x88, 0xd1, 0x95, 0xe1, 0xd1,
+  0xd5, 0xc9, 0x95, 0xc9, 0x90, 0xf1, 0x98, 0xb1, 0xbd, 0x85, 0xd1, 0xb1,
+  0x80, 0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xf9, 0xb0, 0x99, 0x7b, 0xab,
+  0x93, 0x1b, 0x2b, 0xa3, 0x2a, 0xc3, 0xa3, 0xab, 0x93, 0x2b, 0x1b, 0x42,
+  0x0d, 0x8b, 0x14, 0x07, 0x92, 0x18, 0x0c, 0xc3, 0x40, 0x48, 0x72, 0x20,
+  0x41, 0xd2, 0x1c, 0x48, 0x99, 0x44, 0x07, 0x5c, 0xc2, 0xd2, 0xe4, 0x5c,
+  0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x78, 0xcc, 0x85, 0xb5, 0xc1,
+  0xb1, 0x95, 0xc9, 0xb1, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0x9b, 0x0a,
+  0x6b, 0x83, 0x63, 0x2b, 0x93, 0x1b, 0x22, 0x0d, 0x86, 0x64, 0x07, 0x92,
+  0x18, 0x0c, 0xc3, 0x40, 0x48, 0x90, 0x74, 0x07, 0x52, 0x26, 0xe1, 0xc1,
+  0x10, 0x45, 0xda, 0xa4, 0x4f, 0x82, 0x03, 0xa9, 0x0e, 0xa4, 0x3c, 0x18,
+  0x62, 0x2c, 0x80, 0x34, 0x49, 0x7a, 0xc0, 0xe7, 0xad, 0xcd, 0x2d, 0x0d,
+  0xee, 0x8d, 0xae, 0xcc, 0x8d, 0x0e, 0x64, 0x0c, 0x2d, 0x4c, 0x8e, 0xcf,
+  0x54, 0x5a, 0x1b, 0x1c, 0x5b, 0x19, 0xc8, 0xd0, 0xca, 0x0a, 0x08, 0x95,
+  0x50, 0x50, 0xd0, 0x10, 0x41, 0xea, 0x83, 0x21, 0x86, 0xc4, 0x07, 0x92,
+  0x1f, 0x50, 0xcd, 0x10, 0x43, 0xfa, 0x03, 0xe9, 0x0f, 0xa8, 0x86, 0x5c,
+  0x58, 0x9a, 0x5c, 0x4b, 0x18, 0x5b, 0x5a, 0xd8, 0x5c, 0xcb, 0xdc, 0xd8,
+  0x1b, 0x5c, 0xd9, 0x1c, 0x8a, 0x10, 0x5b, 0x1a, 0x9d, 0x91, 0xdc, 0x5b,
+  0x9b, 0x0c, 0x51, 0xca, 0x10, 0x42, 0x12, 0x05, 0x29, 0x14, 0x68, 0x85,
+  0xa5, 0xc9, 0xb5, 0x84, 0xb1, 0xa5, 0x85, 0xcd, 0xb5, 0xcc, 0x8d, 0xbd,
+  0xc1, 0x95, 0xb5, 0x84, 0xc9, 0x9d, 0xa1, 0xc8, 0xa4, 0x0c, 0x31, 0x24,
+  0x52, 0x90, 0x44, 0x41, 0x1a, 0x85, 0x21, 0x82, 0x44, 0x0a, 0xc4, 0xc2,
+  0xd2, 0xe4, 0x5a, 0xc2, 0xd8, 0xd2, 0xc2, 0xe6, 0x5a, 0xe6, 0xc6, 0xde,
+  0xe0, 0xca, 0x5a, 0xe8, 0xca, 0xf0, 0xe8, 0xea, 0xe4, 0xca, 0xe6, 0x86,
+  0x18, 0xd2, 0x29, 0x48, 0xa2, 0x20, 0x99, 0x02, 0xb1, 0xb0, 0x34, 0xb9,
+  0x96, 0x30, 0xb6, 0xb4, 0xb0, 0xb9, 0x96, 0xb9, 0xb1, 0x37, 0xb8, 0xb2,
+  0x96, 0xb9, 0xb0, 0x36, 0x38, 0xb6, 0x32, 0xb9, 0xb9, 0x21, 0x86, 0x94,
+  0x0a, 0x92, 0x28, 0x48, 0xa8, 0x30, 0x84, 0x90, 0x4e, 0x41, 0x4a, 0x05,
+  0x4a, 0x5f, 0x5a, 0x54, 0x53, 0x31, 0x32, 0x53, 0x6f, 0x75, 0x72, 0x63,
+  0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x1c, 0xd2, 0xdc, 0xe8, 0x86,
+  0x18, 0x12, 0x2b, 0x48, 0x7f, 0x40, 0x35, 0x43, 0x0c, 0x29, 0x0d, 0xa4,
+  0x3f, 0xa0, 0x9a, 0x21, 0x92, 0xb4, 0x0a, 0xd2, 0x1f, 0x50, 0x8d, 0xf4,
+  0x07, 0xd4, 0x23, 0xb5, 0x02, 0xe5, 0x48, 0xae, 0x40, 0x31, 0x43, 0x0c,
+  0xe9, 0x15, 0xa4, 0x56, 0xa0, 0x9c, 0x11, 0x11, 0x3b, 0xb0, 0x83, 0x3d,
+  0xb4, 0x83, 0x1b, 0xb4, 0xc3, 0x3b, 0x90, 0x43, 0x3d, 0xb0, 0x43, 0x39,
+  0xb8, 0x81, 0x39, 0xb0, 0x43, 0x38, 0x9c, 0xc3, 0x3c, 0x4c, 0x11, 0x82,
+  0x61, 0x84, 0xc2, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xe9, 0x40,
+  0x0e, 0xe5, 0xe0, 0x0e, 0xf4, 0x30, 0x25, 0x28, 0x46, 0x2c, 0xe1, 0x90,
+  0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e, 0xf2, 0x30, 0x0f, 0xe9, 0xf0,
+  0x0e, 0xee, 0x30, 0x25, 0x30, 0x46, 0x50, 0xe1, 0x90, 0x0e, 0xf2, 0xe0,
+  0x06, 0xec, 0x10, 0x0e, 0xee, 0x70, 0x0e, 0xf5, 0x10, 0x0e, 0xe7, 0x50,
+  0x0e, 0xbf, 0x60, 0x0f, 0xe5, 0x20, 0x0f, 0xf3, 0x90, 0x0e, 0xef, 0xe0,
+  0x0e, 0x53, 0x02, 0x64, 0xc4, 0x14, 0x0e, 0xe9, 0x20, 0x0f, 0x6e, 0x30,
+  0x0e, 0xef, 0xd0, 0x0e, 0xf0, 0x90, 0x0e, 0xec, 0x50, 0x0e, 0xbf, 0xf0,
+  0x0e, 0xf0, 0x40, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x0f, 0x53, 0x06,
+  0x85, 0x71, 0x46, 0x30, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xe6, 0x20,
+  0x0f, 0xe1, 0x70, 0x0e, 0xed, 0x50, 0x0e, 0xee, 0x40, 0x0f, 0x53, 0x82,
+  0x3d, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08,
+  0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38,
+  0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71,
+  0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c,
+  0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d,
+  0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d,
+  0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07,
+  0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87,
+  0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30,
+  0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10,
+  0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66,
+  0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c,
+  0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07,
+  0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87,
+  0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05,
+  0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87,
+  0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0,
+  0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca,
+  0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38,
+  0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c,
+  0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87,
+  0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87,
+  0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00,
+  0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20,
+  0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2,
+  0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4,
+  0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a,
+  0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07,
+  0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90,
+  0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8,
+  0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc,
+  0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b,
+  0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b,
+  0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87,
+  0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81,
+  0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30,
+  0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde,
+  0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b,
+  0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39,
+  0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07,
+  0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6,
+  0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30,
+  0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30,
+  0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50,
+  0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8,
+  0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8,
+  0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d,
+  0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07,
+  0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87,
+  0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0,
+  0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28,
+  0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87,
+  0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87,
+  0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20,
+  0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x16, 0xb0, 0x01, 0x48, 0xe4, 0x4b,
+  0x00, 0xf3, 0x2c, 0xc4, 0x3f, 0x11, 0xd7, 0x44, 0x45, 0xc4, 0x6f, 0x0f,
+  0x7e, 0x85, 0x17, 0xb7, 0x6d, 0x00, 0xca, 0xb6, 0x20, 0xd3, 0x17, 0x39,
+  0x8c, 0xdd, 0x99, 0xc0, 0x05, 0x20, 0x91, 0x2f, 0x38, 0x4d, 0x45, 0x44,
+  0x93, 0x5f, 0xf8, 0xc5, 0x6d, 0xfb, 0x94, 0x8f, 0xdc, 0x36, 0x00, 0x00,
+  0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x13, 0x04,
+  0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc4, 0x6a,
+  0x80, 0xda, 0x08, 0x00, 0x00, 0x00, 0xe3, 0x0d, 0xc5, 0x52, 0x51, 0x40,
+  0xc6, 0x1b, 0x8e, 0xc6, 0xa2, 0x80, 0x58, 0xb0, 0xc8, 0xc7, 0x02, 0x02,
+  0x3e, 0xe3, 0x0d, 0x4b, 0x74, 0x51, 0x40, 0x46, 0x0c, 0x08, 0x22, 0xf0,
+  0x82, 0x11, 0x03, 0xa5, 0x08, 0xc0, 0xa0, 0x61, 0x88, 0x45, 0x59, 0x82,
+  0x0c, 0x02, 0x62, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5b, 0x8e,
+  0x20, 0x00, 0x85, 0xa3, 0x14, 0x10, 0x55, 0xd8, 0x72, 0x0c, 0x01, 0x28,
+  0x1c, 0xa5, 0x80, 0xa8, 0xc2, 0x96, 0xe3, 0x08, 0x60, 0xe1, 0x28, 0x05,
+  0x44, 0x15, 0xb6, 0x14, 0xc9, 0xa1, 0x0a, 0x48, 0x29, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom2D_metallib_len = 3646;
+const unsigned char BlitFrom2DArray_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xa3, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x10, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x32, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79, 0x00, 0x54, 0x59,
+  0x50, 0x45, 0x01, 0x00, 0x01, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x55,
+  0x4c, 0xff, 0xde, 0xd2, 0x71, 0x33, 0x89, 0x2c, 0xf4, 0xc8, 0xd4, 0x34,
+  0x23, 0x27, 0x12, 0x5f, 0x96, 0x0f, 0xc8, 0x4c, 0x26, 0xda, 0x7d, 0x82,
+  0xf5, 0xbd, 0x20, 0x44, 0x17, 0x29, 0x47, 0x4f, 0x46, 0x46, 0x54, 0x18,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01,
+  0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45,
+  0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde,
+  0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa8,
+  0x0d, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21,
+  0x0c, 0x00, 0x00, 0x67, 0x03, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41,
+  0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25,
+  0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42,
+  0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a,
+  0x32, 0x44, 0x24, 0x48, 0x0a, 0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c,
+  0x19, 0x21, 0x72, 0x24, 0x07, 0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8,
+  0x40, 0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x81,
+  0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x60, 0x00, 0x09, 0xa8, 0x88, 0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77,
+  0xc0, 0x87, 0x36, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73,
+  0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41,
+  0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80,
+  0x1d, 0xca, 0xe1, 0x1c, 0xc2, 0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61,
+  0x1c, 0xe8, 0xe1, 0x1d, 0xe4, 0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81,
+  0x1e, 0xd0, 0x01, 0x88, 0x03, 0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77,
+  0x68, 0x03, 0x71, 0xa8, 0x87, 0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77,
+  0x98, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70,
+  0x68, 0x87, 0x72, 0x68, 0x03, 0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a,
+  0x28, 0x07, 0x79, 0x68, 0x83, 0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80,
+  0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0,
+  0x1c, 0xe4, 0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21,
+  0x1d, 0xdc, 0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21,
+  0x1d, 0xda, 0xa1, 0x0d, 0xdc, 0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1,
+  0x1c, 0xc2, 0xc1, 0x1c, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80,
+  0x70, 0x87, 0x77, 0x68, 0x83, 0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36,
+  0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80,
+  0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0,
+  0x1d, 0xc2, 0xc1, 0x1d, 0xe6, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0,
+  0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72,
+  0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77,
+  0x28, 0x07, 0x72, 0x68, 0x03, 0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79,
+  0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74,
+  0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1,
+  0x0d, 0xe8, 0x41, 0x1e, 0xc2, 0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1,
+  0x1c, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79,
+  0xa8, 0x87, 0x72, 0x00, 0x88, 0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75,
+  0x68, 0x03, 0x78, 0x90, 0x87, 0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a,
+  0x78, 0x07, 0x79, 0x68, 0x03, 0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72,
+  0x90, 0x87, 0x36, 0x98, 0x87, 0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00,
+  0x20, 0xea, 0xc1, 0x1d, 0xe6, 0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0,
+  0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a,
+  0x90, 0x87, 0x7a, 0x28, 0x07, 0x60, 0xc3, 0x26, 0x0c, 0xc0, 0x02, 0x54,
+  0x43, 0x38, 0xa4, 0x83, 0x3c, 0xb4, 0x81, 0x38, 0xd4, 0x83, 0x39, 0x98,
+  0x43, 0x39, 0xc8, 0x43, 0x1b, 0xb8, 0xc3, 0x3b, 0xb4, 0x41, 0x38, 0xb0,
+  0x43, 0x3a, 0x84, 0xc3, 0x3c, 0x00, 0x1b, 0x8c, 0xa1, 0x00, 0x16, 0xa0,
+  0xda, 0x80, 0x10, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x0c, 0x20, 0x01,
+  0xd5, 0x06, 0xa3, 0x08, 0x80, 0x05, 0xa8, 0x36, 0x18, 0x86, 0x00, 0x2c,
+  0x40, 0xb5, 0xc1, 0x38, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x24, 0x80,
+  0xda, 0x60, 0x20, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x12, 0x40, 0x6d,
+  0x40, 0x92, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x06, 0x90, 0x80, 0x0a,
+  0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13,
+  0x86, 0x40, 0x18, 0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01,
+  0x32, 0x61, 0x48, 0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x29,
+  0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93,
+  0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12,
+  0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x6c, 0x33, 0x00, 0xc3,
+  0x08, 0x04, 0x30, 0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34,
+  0x45, 0x94, 0x30, 0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2,
+  0x34, 0x88, 0x10, 0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4d, 0x9a, 0x22,
+  0x4a, 0x98, 0xfc, 0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0xdf, 0x1e, 0x7e,
+  0x20, 0x8a, 0x00, 0xec, 0x9f, 0xc6, 0x08, 0x80, 0x41, 0x04, 0x23, 0xb8,
+  0x48, 0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x5f, 0x02, 0x98, 0x67, 0x21, 0xa2,
+  0x7f, 0x1a, 0x23, 0x00, 0x06, 0x11, 0x10, 0xa1, 0x18, 0x41, 0x84, 0x72,
+  0x12, 0xa9, 0x39, 0x82, 0x60, 0x18, 0x41, 0x18, 0x4a, 0x12, 0x4e, 0x12,
+  0x83, 0x35, 0x06, 0xc8, 0x15, 0x01, 0x0c, 0x82, 0x45, 0x18, 0x80, 0xe4,
+  0x40, 0x40, 0x0a, 0x8c, 0x39, 0x02, 0x50, 0x18, 0x44, 0x10, 0x84, 0x41,
+  0x04, 0x40, 0x18, 0x44, 0x18, 0x84, 0x11, 0x00, 0x00, 0x00, 0x00, 0x13,
+  0xa8, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80,
+  0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8,
+  0x03, 0x37, 0x80, 0x03, 0x37, 0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d,
+  0x00, 0x0f, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a,
+  0x80, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78,
+  0xd0, 0x06, 0xe9, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a,
+  0x10, 0x07, 0x76, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6,
+  0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71,
+  0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6,
+  0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xd0, 0x06, 0xf6, 0x40, 0x07, 0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76,
+  0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78,
+  0xd0, 0x06, 0xf6, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72,
+  0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71,
+  0x90, 0x07, 0x72, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72,
+  0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a,
+  0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d,
+  0x60, 0x0f, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72,
+  0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70,
+  0x20, 0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a,
+  0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a,
+  0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x43, 0x98, 0x05, 0x00,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0xcc, 0x03, 0x04, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x10, 0x26, 0x02, 0x02, 0x60, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x33, 0x01, 0x01, 0x30, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x90, 0x05, 0x02, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x32,
+  0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6,
+  0x04, 0x43, 0x1a, 0x23, 0x00, 0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05,
+  0x53, 0x20, 0x85, 0x52, 0x06, 0x64, 0x0b, 0x62, 0x04, 0xa0, 0x40, 0x0a,
+  0x85, 0xea, 0x58, 0x42, 0x24, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x47,
+  0x01, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10,
+  0xab, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x80, 0x50, 0x40,
+  0x15, 0x51, 0xb9, 0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b,
+  0x1b, 0x62, 0x0c, 0x05, 0x25, 0x0c, 0x07, 0xdf, 0x20, 0x08, 0x0e, 0x8e,
+  0xad, 0x0c, 0xa4, 0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e,
+  0x2e, 0xed, 0xcd, 0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07,
+  0x07, 0x04, 0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46,
+  0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x27, 0x65, 0x88, 0x40, 0x11, 0x43,
+  0x8c, 0xa1, 0x18, 0x8c, 0x81, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36,
+  0x04, 0xa1, 0x8e, 0xa1, 0x18, 0x8a, 0x81, 0xe0, 0x16, 0x96, 0x26, 0xe7,
+  0x32, 0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6,
+  0x26, 0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36,
+  0x44, 0xa0, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70,
+  0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74,
+  0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x6a, 0x21,
+  0x19, 0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95,
+  0xb9, 0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9,
+  0x7d, 0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1,
+  0x95, 0x0d, 0x11, 0xa8, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99,
+  0x1b, 0x59, 0x99, 0xdc, 0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3,
+  0xb0, 0x34, 0x39, 0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2,
+  0x2f, 0xb7, 0xb0, 0xb6, 0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
+  0x43, 0x10, 0xea, 0x19, 0x08, 0x0a, 0xa2, 0xa2, 0x21, 0x02, 0x25, 0x51,
+  0x0a, 0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3,
+  0xfb, 0x4a, 0x73, 0x83, 0xab, 0xa3, 0x23, 0x75, 0x56, 0xe6, 0x56, 0x26,
+  0x17, 0x46, 0x57, 0x46, 0x86, 0x32, 0x43, 0x57, 0x86, 0x47, 0x64, 0x27,
+  0xf3, 0x65, 0x96, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d,
+  0xae, 0x4c, 0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c,
+  0x5c, 0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x0d, 0x33, 0xb6, 0xb7, 0x30,
+  0x3a, 0x19, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e,
+  0x61, 0x6d, 0x65, 0x1c, 0xe8, 0xca, 0xf0, 0x86, 0x48, 0x03, 0x41, 0x51,
+  0x54, 0x45, 0x59, 0xd4, 0x45, 0x41, 0x14, 0x46, 0x65, 0x94, 0x46, 0x26,
+  0x2c, 0x4d, 0xce, 0x05, 0xee, 0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x8d,
+  0x52, 0x58, 0x9a, 0x9c, 0x8b, 0xdb, 0xdb, 0x17, 0x5c, 0x99, 0xdc, 0x1c,
+  0x5c, 0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x07, 0xb8, 0xb7, 0xb9, 0x21,
+  0xd0, 0x50, 0x50, 0x1c, 0x65, 0x51, 0x1d, 0x05, 0x51, 0x11, 0x95, 0x51,
+  0x1e, 0x95, 0xb0, 0x34, 0x39, 0x17, 0xb1, 0x3a, 0x33, 0xb3, 0x32, 0x39,
+  0x3e, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f,
+  0x73, 0x69, 0x7a, 0x65, 0x94, 0xc2, 0xd2, 0xe4, 0x5c, 0xd8, 0xde, 0xc6,
+  0xc2, 0xe8, 0xd2, 0xde, 0xdc, 0xbe, 0xd2, 0xdc, 0xc8, 0xca, 0xf0, 0x88,
+  0x84, 0xa5, 0xc9, 0xb9, 0xc8, 0x95, 0x85, 0x91, 0x91, 0x0a, 0x4b, 0x93,
+  0x73, 0x99, 0xa3, 0x93, 0xab, 0x1b, 0xa3, 0xfb, 0xa2, 0xcb, 0x83, 0x2b,
+  0xfb, 0x4a, 0x73, 0x33, 0x7b, 0x63, 0x52, 0x65, 0xc5, 0x54, 0x66, 0x46,
+  0x47, 0xf5, 0x06, 0x47, 0xa6, 0xca, 0x8a, 0x28, 0xad, 0xad, 0xcc, 0x6d,
+  0x2e, 0xed, 0xcd, 0x6d, 0x8e, 0x44, 0x5d, 0x9a, 0x1b, 0x1d, 0x91, 0xa6,
+  0x34, 0x38, 0xa6, 0x32, 0xbb, 0x32, 0x36, 0x16, 0x66, 0x6c, 0x6f, 0x61,
+  0x74, 0x64, 0x98, 0xc2, 0xf2, 0xca, 0xe4, 0x9e, 0xe4, 0x88, 0xca, 0xe0,
+  0xe8, 0xd0, 0x86, 0xa0, 0xc1, 0x40, 0x0c, 0xc6, 0x40, 0x50, 0x18, 0x55,
+  0x06, 0x83, 0x31, 0x18, 0x03, 0x41, 0x61, 0x94, 0x19, 0x0c, 0xca, 0x70,
+  0x0c, 0x04, 0x75, 0x06, 0x14, 0x1a, 0x0c, 0xcb, 0x70, 0x0c, 0x04, 0x95,
+  0x06, 0x94, 0x1a, 0x30, 0x0a, 0x4b, 0x93, 0x73, 0x09, 0x93, 0x3b, 0xfb,
+  0xa2, 0xcb, 0x83, 0x2b, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0xe3, 0x15, 0x96,
+  0x26, 0xe7, 0x12, 0x26, 0x77, 0xf6, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x15,
+  0xc6, 0x96, 0x76, 0xe6, 0xf6, 0x35, 0x97, 0xa6, 0x57, 0x46, 0x66, 0xea,
+  0xad, 0x4e, 0x6e, 0xac, 0x4c, 0xaa, 0xec, 0x2c, 0xed, 0xcd, 0x8d, 0xcc,
+  0xdc, 0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0xdb,
+  0x10, 0x32, 0x18, 0x10, 0x0a, 0x0c, 0xa8, 0x30, 0x18, 0x12, 0x4a, 0x0c,
+  0x06, 0x62, 0x28, 0xa8, 0x31, 0xa0, 0xc8, 0x80, 0x5a, 0x03, 0x8a, 0x0d,
+  0x86, 0x84, 0x6a, 0x83, 0xc1, 0xa0, 0x20, 0xca, 0x0d, 0xa8, 0x8c, 0x7a,
+  0x03, 0x2e, 0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
+  0x65, 0x54, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca,
+  0xe8, 0xd1, 0x95, 0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0xc9, 0x90, 0x7d, 0x85,
+  0xc9, 0xc9, 0x85, 0xe5, 0xf1, 0x98, 0xb1, 0xbd, 0x85, 0xd1, 0xb1, 0x80,
+  0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xf9, 0xb0, 0x99, 0x7b, 0xab, 0x93,
+  0x1b, 0x2b, 0xa3, 0x2a, 0xc3, 0xa3, 0xab, 0x93, 0x2b, 0x1b, 0x42, 0x0d,
+  0x0c, 0x15, 0x07, 0x94, 0x18, 0x0c, 0xc4, 0x50, 0x50, 0x72, 0x40, 0x41,
+  0xd4, 0x1c, 0x50, 0x19, 0x45, 0x07, 0x5c, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6,
+  0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x78, 0xcc, 0x85, 0xb5, 0xc1, 0xb1,
+  0x95, 0xc9, 0xb1, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0x9b, 0x0a, 0x6b,
+  0x83, 0x63, 0x2b, 0x93, 0x1b, 0x22, 0x0d, 0x07, 0x65, 0x07, 0x94, 0x18,
+  0x0c, 0xc4, 0x50, 0x50, 0x10, 0x75, 0x07, 0x54, 0x46, 0xe1, 0xc1, 0x10,
+  0x85, 0xda, 0xa8, 0x8f, 0x82, 0x03, 0xaa, 0x0e, 0xa8, 0x3c, 0x18, 0x62,
+  0x2c, 0x00, 0x35, 0x51, 0x7a, 0xc0, 0xe7, 0xad, 0xcd, 0x2d, 0x0d, 0xee,
+  0x8d, 0xae, 0xcc, 0x8d, 0x0e, 0x64, 0x0c, 0x2d, 0x4c, 0x8e, 0xcf, 0x54,
+  0x5a, 0x1b, 0x1c, 0x5b, 0x19, 0xc8, 0xd0, 0xca, 0x0a, 0x08, 0x95, 0x50,
+  0x50, 0xd0, 0x10, 0x81, 0xea, 0x83, 0x21, 0x06, 0xc5, 0x07, 0x94, 0x1f,
+  0x58, 0xce, 0x10, 0x83, 0xfa, 0x03, 0xea, 0x0f, 0x2c, 0x87, 0x61, 0x10,
+  0x96, 0x26, 0xd7, 0x12, 0xc6, 0x96, 0x16, 0x36, 0xd7, 0x32, 0x37, 0xf6,
+  0x06, 0x57, 0x36, 0x87, 0x22, 0xc4, 0x96, 0x46, 0x67, 0x24, 0xf7, 0xd6,
+  0x26, 0x43, 0x14, 0x24, 0x27, 0x17, 0x96, 0x97, 0x32, 0x84, 0xa0, 0x44,
+  0x81, 0x0a, 0x05, 0x5a, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61,
+  0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x61, 0x72, 0x67, 0x28,
+  0x32, 0x29, 0x43, 0x0c, 0x8a, 0x14, 0x28, 0x51, 0xa0, 0x46, 0x61, 0x88,
+  0x40, 0x91, 0x02, 0xb1, 0xb0, 0x34, 0xb9, 0x96, 0x30, 0xb6, 0xb4, 0xb0,
+  0xb9, 0x96, 0xb9, 0xb1, 0x37, 0xb8, 0xb2, 0x16, 0xba, 0x32, 0x3c, 0xba,
+  0x3a, 0xb9, 0xb2, 0xb9, 0x21, 0x06, 0x75, 0x0a, 0x94, 0x28, 0x50, 0xa6,
+  0x40, 0x2c, 0x2c, 0x4d, 0xae, 0x25, 0x8c, 0x2d, 0x2d, 0x6c, 0xae, 0x65,
+  0x6e, 0xec, 0x0d, 0xae, 0xac, 0x65, 0x2e, 0xac, 0x0d, 0x8e, 0xad, 0x4c,
+  0x6e, 0x6e, 0x88, 0x41, 0xa5, 0x02, 0x25, 0x0a, 0x14, 0x2a, 0x0c, 0x21,
+  0xa8, 0x53, 0xa0, 0x52, 0x81, 0xd2, 0x97, 0x16, 0xd5, 0x54, 0x8c, 0xcc,
+  0xd4, 0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0x1b,
+  0x87, 0x34, 0x37, 0xba, 0x21, 0x06, 0xc5, 0x0a, 0xd4, 0x1f, 0x58, 0xce,
+  0x10, 0x83, 0x4a, 0x03, 0xea, 0x0f, 0x2c, 0x67, 0x88, 0x44, 0xad, 0x02,
+  0xf5, 0x07, 0x96, 0x43, 0xfd, 0x81, 0xd5, 0x50, 0xad, 0x60, 0x3d, 0x94,
+  0x2b, 0x58, 0xd0, 0x10, 0x83, 0x7a, 0x05, 0xca, 0x15, 0x2c, 0x68, 0x88,
+  0x41, 0xbd, 0x02, 0xd5, 0x0a, 0xd6, 0x33, 0x22, 0x62, 0x07, 0x76, 0xb0,
+  0x87, 0x76, 0x70, 0x83, 0x76, 0x78, 0x07, 0x72, 0xa8, 0x07, 0x76, 0x28,
+  0x07, 0x37, 0x30, 0x07, 0x76, 0x08, 0x87, 0x73, 0x98, 0x87, 0x29, 0x42,
+  0x30, 0x8c, 0x50, 0xd8, 0x81, 0x1d, 0xec, 0xa1, 0x1d, 0xdc, 0x20, 0x1d,
+  0xc8, 0xa1, 0x1c, 0xdc, 0x81, 0x1e, 0xa6, 0x04, 0xc5, 0x88, 0x25, 0x1c,
+  0xd2, 0x41, 0x1e, 0xdc, 0xc0, 0x1e, 0xca, 0x41, 0x1e, 0xe6, 0x21, 0x1d,
+  0xde, 0xc1, 0x1d, 0xa6, 0x04, 0xc6, 0x08, 0x2a, 0x1c, 0xd2, 0x41, 0x1e,
+  0xdc, 0x80, 0x1d, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1e, 0xc2, 0xe1, 0x1c,
+  0xca, 0xe1, 0x17, 0xec, 0xa1, 0x1c, 0xe4, 0x61, 0x1e, 0xd2, 0xe1, 0x1d,
+  0xdc, 0x61, 0x4a, 0x80, 0x8c, 0x98, 0xc2, 0x21, 0x1d, 0xe4, 0xc1, 0x0d,
+  0xc6, 0xe1, 0x1d, 0xda, 0x01, 0x1e, 0xd2, 0x81, 0x1d, 0xca, 0xe1, 0x17,
+  0xde, 0x01, 0x1e, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0xe6, 0x61, 0xca,
+  0xa0, 0x30, 0xce, 0x08, 0x26, 0x1c, 0xd2, 0x41, 0x1e, 0xdc, 0xc0, 0x1c,
+  0xe4, 0x21, 0x1c, 0xce, 0xa1, 0x1d, 0xca, 0xc1, 0x1d, 0xe8, 0x61, 0x4a,
+  0xb0, 0x07, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33,
+  0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98,
+  0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33,
+  0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05,
+  0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43,
+  0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08,
+  0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78,
+  0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1,
+  0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33,
+  0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e,
+  0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03,
+  0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60,
+  0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80,
+  0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8,
+  0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18,
+  0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee,
+  0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c,
+  0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43,
+  0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3,
+  0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83,
+  0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69,
+  0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60,
+  0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee,
+  0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1,
+  0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e,
+  0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c,
+  0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43,
+  0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4,
+  0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c,
+  0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c,
+  0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3,
+  0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43,
+  0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98,
+  0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98,
+  0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3,
+  0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d,
+  0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83,
+  0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1,
+  0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08,
+  0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb,
+  0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5,
+  0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3,
+  0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4,
+  0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d,
+  0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d,
+  0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43,
+  0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70,
+  0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70,
+  0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec,
+  0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33,
+  0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70,
+  0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90,
+  0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x71,
+  0x20, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x10, 0x06, 0x00, 0x12,
+  0xf9, 0x12, 0xc0, 0x3c, 0x0b, 0xf1, 0x4f, 0xc4, 0x35, 0x51, 0x11, 0xf1,
+  0xdb, 0xc3, 0x0f, 0x44, 0x11, 0x80, 0xf9, 0x15, 0x5e, 0xdc, 0xb6, 0x01,
+  0x3c, 0xdb, 0x82, 0x4c, 0x5f, 0xe4, 0x30, 0x76, 0xa7, 0x45, 0x11, 0x80,
+  0x99, 0xc0, 0x05, 0x20, 0x91, 0x2f, 0x38, 0x4d, 0x45, 0x44, 0x93, 0x5f,
+  0xf8, 0xc5, 0x6d, 0xfb, 0x94, 0x8f, 0xdc, 0xb6, 0x0d, 0x5c, 0x00, 0x12,
+  0xf9, 0x82, 0xd3, 0x54, 0x44, 0x34, 0xf9, 0x94, 0x8f, 0xdc, 0xb6, 0x5f,
+  0xf8, 0xc5, 0x6d, 0x03, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x22,
+  0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0xc4, 0x6a, 0x80, 0xda, 0x08, 0x00, 0x00, 0x00, 0xe3,
+  0x0d, 0xc5, 0x52, 0x51, 0x40, 0xc6, 0x1b, 0x8e, 0xc6, 0xa2, 0x80, 0x58,
+  0xb0, 0xc8, 0xc7, 0x02, 0x02, 0x3e, 0xe3, 0x0d, 0x4b, 0x34, 0x51, 0x30,
+  0x46, 0x0c, 0x08, 0x22, 0xf0, 0x82, 0xf1, 0x06, 0x87, 0xd2, 0x28, 0x20,
+  0x23, 0x06, 0x04, 0x11, 0x88, 0x41, 0x30, 0x62, 0xb0, 0x14, 0x01, 0x19,
+  0x40, 0xcf, 0x41, 0x38, 0x8d, 0x13, 0x64, 0x10, 0x10, 0x03, 0x00, 0x0c,
+  0x00, 0x00, 0x00, 0x5b, 0x8e, 0x20, 0x00, 0x85, 0xa3, 0x14, 0x10, 0x55,
+  0xd8, 0x72, 0x0c, 0x01, 0x28, 0x1c, 0xa5, 0x80, 0xa8, 0xc2, 0x96, 0xe3,
+  0x08, 0x60, 0xe1, 0x28, 0x05, 0x44, 0x15, 0xb6, 0x1c, 0x4a, 0x10, 0x0b,
+  0x47, 0x29, 0x20, 0xaa, 0xb0, 0xa5, 0x60, 0x0e, 0x55, 0x40, 0x4a, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom2DArray_metallib_len = 3747;
+const unsigned char BlitFrom3D_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x6e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0b, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x33, 0x44, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01,
+  0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x78, 0x33, 0x74, 0x8c, 0x91, 0x22,
+  0x5b, 0x37, 0x5a, 0x24, 0x92, 0xcd, 0x37, 0x5c, 0x0c, 0xab, 0x74, 0x33,
+  0x00, 0x59, 0x10, 0x02, 0xb7, 0xbe, 0xb6, 0x2b, 0xd6, 0x76, 0x12, 0xf1,
+  0xe8, 0x4f, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53,
+  0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00,
+  0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x7c, 0x0d, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x5c, 0x03,
+  0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00,
+  0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10,
+  0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04,
+  0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10,
+  0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a,
+  0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07,
+  0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00,
+  0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x1b, 0xc2,
+  0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x60, 0x00, 0x09, 0xa8, 0x88,
+  0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77, 0xc0, 0x87, 0x36, 0x30, 0x87,
+  0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87,
+  0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00,
+  0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0xe1, 0x1c, 0xc2,
+  0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4,
+  0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81, 0x1e, 0xd0, 0x01, 0x88, 0x03,
+  0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77, 0x68, 0x03, 0x71, 0xa8, 0x87,
+  0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77, 0x98, 0x07, 0x80, 0x70, 0x87,
+  0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70, 0x68, 0x87, 0x72, 0x68, 0x03,
+  0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a, 0x28, 0x07, 0x79, 0x68, 0x83,
+  0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c, 0xda,
+  0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e, 0xca,
+  0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0xa1, 0x0d, 0xdc,
+  0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xc2, 0xc1, 0x1c, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83,
+  0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83,
+  0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1d, 0xc2, 0xc1, 0x1d, 0xe6,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77, 0x28, 0x07, 0x72, 0x68, 0x03,
+  0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2,
+  0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1, 0x1c, 0xda, 0xa0, 0x1d, 0xc2,
+  0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x88,
+  0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75, 0x68, 0x03, 0x78, 0x90, 0x87,
+  0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x03,
+  0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72, 0x90, 0x87, 0x36, 0x98, 0x87,
+  0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00, 0x20, 0xea, 0xc1, 0x1d, 0xe6,
+  0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda,
+  0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07,
+  0x60, 0xc3, 0x26, 0x0c, 0xc0, 0x02, 0x54, 0x43, 0x38, 0xa4, 0x83, 0x3c,
+  0xb4, 0x81, 0x38, 0xd4, 0x83, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x1b,
+  0xb8, 0xc3, 0x3b, 0xb4, 0x41, 0x38, 0xb0, 0x43, 0x3a, 0x84, 0xc3, 0x3c,
+  0x00, 0x1b, 0x8c, 0xa1, 0x00, 0x16, 0xa0, 0xda, 0x80, 0x10, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x0c, 0x20, 0x01, 0xd5, 0x06, 0xa3, 0x08, 0x80,
+  0x05, 0xa8, 0x36, 0x18, 0x86, 0x00, 0x2c, 0x40, 0xb5, 0xc1, 0x38, 0xfe,
+  0xff, 0xff, 0xff, 0x7f, 0x00, 0x24, 0x80, 0xda, 0x60, 0x20, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x12, 0x40, 0x6d, 0x40, 0x92, 0xff, 0xff, 0xff,
+  0xff, 0x1f, 0x00, 0x06, 0x90, 0x80, 0x0a, 0x00, 0x00, 0x00, 0x49, 0x18,
+  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18, 0x26, 0x0c,
+  0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48, 0x0a, 0x03,
+  0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x32, 0x22,
+  0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93,
+  0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84,
+  0xa4, 0x4c, 0x10, 0x68, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30, 0x8c, 0x20,
+  0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30, 0xf9, 0xac,
+  0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10, 0x62, 0x80,
+  0x41, 0x04, 0x42, 0x38, 0x4a, 0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x7f, 0x22,
+  0xae, 0x89, 0x8a, 0x88, 0xff, 0x1e, 0xfe, 0x69, 0x8c, 0x00, 0x18, 0x44,
+  0x30, 0x82, 0x8b, 0xa4, 0x29, 0xa2, 0x84, 0xc9, 0xff, 0x25, 0x80, 0x79,
+  0x16, 0x22, 0xfa, 0xa7, 0x31, 0x02, 0x60, 0x10, 0x01, 0x11, 0x8a, 0x11,
+  0x44, 0x28, 0x27, 0x91, 0x1a, 0x46, 0x18, 0x80, 0x39, 0x82, 0x60, 0x18,
+  0x61, 0x18, 0x0a, 0x12, 0x4e, 0x62, 0xcd, 0x35, 0x40, 0xaf, 0x08, 0x60,
+  0x50, 0x1c, 0x08, 0x48, 0x81, 0x31, 0x47, 0x00, 0x0a, 0x83, 0x08, 0x82,
+  0x30, 0x88, 0x00, 0x08, 0x83, 0x08, 0x83, 0x30, 0x02, 0x00, 0x13, 0xa8,
+  0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07,
+  0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8, 0x03,
+  0x37, 0x80, 0x03, 0x37, 0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d, 0x00,
+  0x0f, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80,
+  0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0,
+  0x06, 0xe9, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10,
+  0x07, 0x76, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xf6, 0x40, 0x07, 0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60,
+  0x07, 0x74, 0xd0, 0x06, 0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76, 0xa0,
+  0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0,
+  0x06, 0xf6, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80,
+  0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x90,
+  0x07, 0x72, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50,
+  0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20,
+  0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60,
+  0x0f, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xa0,
+  0x07, 0x75, 0x10, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70, 0x20,
+  0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10,
+  0x07, 0x70, 0x20, 0x07, 0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a, 0x10,
+  0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x43, 0x98, 0x05, 0x00, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0x0c, 0x04, 0x04, 0x80, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0x10, 0x46, 0x02, 0x02, 0x60, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x20, 0x0b, 0x04, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e,
+  0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04,
+  0x43, 0x1a, 0x23, 0x00, 0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05, 0x53,
+  0x20, 0x85, 0x52, 0x06, 0x54, 0x0b, 0x62, 0x04, 0xa0, 0x40, 0x0a, 0x85,
+  0xe8, 0x58, 0x42, 0x24, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x44, 0x01,
+  0x00, 0x00, 0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab,
+  0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x70, 0x4c, 0x00, 0x05,
+  0x51, 0xb9, 0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b,
+  0x62, 0x0c, 0xc4, 0x24, 0x0c, 0x06, 0xdf, 0x20, 0x08, 0x0e, 0x8e, 0xad,
+  0x0c, 0xa4, 0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e,
+  0xed, 0xcd, 0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x07,
+  0x04, 0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06,
+  0x46, 0x66, 0xc6, 0x25, 0x07, 0x27, 0x65, 0x88, 0x30, 0x11, 0x43, 0x8c,
+  0x81, 0x18, 0x8a, 0x61, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04,
+  0x99, 0x8e, 0x81, 0x18, 0x88, 0x61, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32,
+  0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26,
+  0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44,
+  0x98, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69,
+  0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68,
+  0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x84, 0x69, 0x21, 0x19,
+  0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9,
+  0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d,
+  0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1, 0x95,
+  0x0d, 0x11, 0xa6, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99, 0x1b,
+  0x59, 0x99, 0xdc, 0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3, 0xb0,
+  0x34, 0x39, 0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0x2f,
+  0xb7, 0xb0, 0xb6, 0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x43,
+  0x90, 0xe9, 0x19, 0x86, 0x09, 0x9a, 0xa2, 0x21, 0xc2, 0x24, 0x51, 0x0a,
+  0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0xfb,
+  0x4a, 0x73, 0x83, 0xab, 0xa3, 0x23, 0x75, 0x56, 0xe6, 0x56, 0x26, 0x17,
+  0x46, 0x57, 0x46, 0x86, 0x32, 0x43, 0x57, 0x86, 0x47, 0x64, 0x27, 0xf3,
+  0x65, 0x96, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d, 0xae,
+  0x4c, 0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c, 0x5c,
+  0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x0d, 0x33, 0xb6, 0xb7, 0x30, 0x3a,
+  0x19, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61,
+  0x6d, 0x65, 0x1c, 0xe8, 0xca, 0xf0, 0x86, 0x48, 0xc3, 0x30, 0x51, 0x53,
+  0x35, 0x59, 0xd3, 0x35, 0x41, 0x13, 0x36, 0x65, 0x93, 0x46, 0x26, 0x2c,
+  0x4d, 0xce, 0x05, 0xee, 0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x8d, 0x52,
+  0x58, 0x9a, 0x9c, 0x8b, 0xdb, 0xdb, 0x17, 0x5c, 0x99, 0xdc, 0x1c, 0x5c,
+  0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x07, 0xb8, 0xb7, 0xb9, 0x21, 0xd0,
+  0x40, 0x4c, 0xdc, 0x64, 0x4d, 0xdd, 0x04, 0x4d, 0xd1, 0x94, 0x4d, 0x1e,
+  0x95, 0xb0, 0x34, 0x39, 0x17, 0xb1, 0x3a, 0x33, 0xb3, 0x32, 0x39, 0x3e,
+  0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73,
+  0x69, 0x7a, 0x65, 0x94, 0xc2, 0xd2, 0xe4, 0x5c, 0xd8, 0xde, 0xc6, 0xc2,
+  0xe8, 0xd2, 0xde, 0xdc, 0xbe, 0xd2, 0xdc, 0xc8, 0xca, 0xf0, 0x88, 0x84,
+  0xa5, 0xc9, 0xb9, 0xc8, 0x95, 0x85, 0x91, 0x91, 0x0a, 0x4b, 0x93, 0x73,
+  0x99, 0xa3, 0x93, 0xab, 0x1b, 0xa3, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb,
+  0x4a, 0x73, 0x33, 0x7b, 0x63, 0x52, 0x65, 0xc5, 0x54, 0x66, 0x46, 0x47,
+  0xf5, 0x06, 0x47, 0xa6, 0xca, 0x8a, 0x28, 0xad, 0xad, 0xcc, 0x6d, 0x2e,
+  0xed, 0xcd, 0x6d, 0x8e, 0x44, 0x5d, 0x9a, 0x1b, 0x1d, 0x91, 0xa6, 0x34,
+  0x38, 0xa6, 0x32, 0xbb, 0x32, 0x36, 0x16, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x64, 0x98, 0xc2, 0xf2, 0xca, 0xe4, 0x9e, 0xe4, 0x88, 0xca, 0xe0, 0xe8,
+  0xd0, 0x86, 0xa0, 0xc1, 0x30, 0x0c, 0xc5, 0x30, 0x4c, 0xd8, 0x54, 0x06,
+  0x43, 0x31, 0x14, 0xc3, 0x30, 0x61, 0x93, 0x19, 0x0c, 0xc9, 0x60, 0x0c,
+  0xc3, 0x74, 0x06, 0x13, 0x1a, 0x0c, 0xca, 0x60, 0x0c, 0xc3, 0x94, 0x06,
+  0x93, 0x1a, 0x30, 0x0a, 0x4b, 0x93, 0x73, 0x09, 0x93, 0x3b, 0xfb, 0xa2,
+  0xcb, 0x83, 0x2b, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0xe3, 0x15, 0x96, 0x26,
+  0xe7, 0x12, 0x26, 0x77, 0xf6, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x15, 0xc6,
+  0x96, 0x76, 0xe6, 0xf6, 0x35, 0x97, 0xa6, 0x57, 0x46, 0x66, 0xea, 0xad,
+  0x4e, 0x6e, 0xac, 0x4c, 0xaa, 0xec, 0x2c, 0xed, 0xcd, 0x8d, 0xcc, 0xdc,
+  0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0xdb, 0x10,
+  0x32, 0x18, 0x8e, 0x09, 0x0c, 0xa6, 0x30, 0x18, 0x90, 0x49, 0x0c, 0x86,
+  0x61, 0x20, 0xa6, 0x31, 0x98, 0xc8, 0x60, 0x5a, 0x83, 0x89, 0x0d, 0x06,
+  0x64, 0x6a, 0x83, 0xa1, 0x98, 0xa0, 0xc9, 0x0d, 0xa6, 0x6c, 0x7a, 0x03,
+  0x2e, 0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65,
+  0x54, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0x88,
+  0xd1, 0x95, 0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0xcd, 0x90, 0xf1, 0x98, 0xb1,
+  0xbd, 0x85, 0xd1, 0xb1, 0x80, 0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xf9,
+  0xb0, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0xa3, 0x2a, 0xc3, 0xa3, 0xab,
+  0x93, 0x2b, 0x1b, 0x42, 0x0d, 0xcb, 0x14, 0x07, 0x93, 0x18, 0x0c, 0xc3,
+  0x40, 0x4c, 0x72, 0x30, 0x41, 0xd3, 0x1c, 0x4c, 0xd9, 0x44, 0x07, 0x5c,
+  0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x78,
+  0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xc9, 0xb1, 0x99, 0x7b, 0xab, 0x93,
+  0x1b, 0x2b, 0x9b, 0x0a, 0x6b, 0x83, 0x63, 0x2b, 0x93, 0x1b, 0x22, 0x0d,
+  0xc6, 0x64, 0x07, 0x93, 0x18, 0x0c, 0xc3, 0x40, 0x4c, 0xd0, 0x74, 0x07,
+  0x53, 0x36, 0xe1, 0xc1, 0x10, 0x65, 0xda, 0xa6, 0x6f, 0x82, 0x83, 0xa9,
+  0x0e, 0xa6, 0x3c, 0x18, 0x62, 0x2c, 0xc0, 0x34, 0x4d, 0x7a, 0xc0, 0xe7,
+  0xad, 0xcd, 0x2d, 0x0d, 0xee, 0x8d, 0xae, 0xcc, 0x8d, 0x0e, 0x64, 0x0c,
+  0x2d, 0x4c, 0x8e, 0xcf, 0x54, 0x5a, 0x1b, 0x1c, 0x5b, 0x19, 0xc8, 0xd0,
+  0xca, 0x0a, 0x08, 0x95, 0x50, 0x50, 0xd0, 0x10, 0x61, 0xea, 0x83, 0x21,
+  0xc6, 0xc4, 0x07, 0x93, 0x1f, 0x54, 0xcd, 0x10, 0x63, 0xfa, 0x83, 0xe9,
+  0x0f, 0xaa, 0x86, 0x5c, 0x58, 0x9a, 0x5c, 0x4b, 0x18, 0x5b, 0x5a, 0xd8,
+  0x5c, 0xcb, 0xdc, 0xd8, 0x1b, 0x5c, 0xd9, 0x1c, 0x8a, 0x10, 0x5b, 0x1a,
+  0x9d, 0x91, 0xdc, 0x5b, 0xdb, 0x0c, 0x51, 0xca, 0x10, 0x62, 0x12, 0x85,
+  0x29, 0x14, 0x68, 0x85, 0xa5, 0xc9, 0xb5, 0x84, 0xb1, 0xa5, 0x85, 0xcd,
+  0xb5, 0xcc, 0x8d, 0xbd, 0xc1, 0x95, 0xb5, 0x84, 0xc9, 0x9d, 0xa1, 0xc8,
+  0xa4, 0x0c, 0x31, 0x26, 0x52, 0x98, 0x44, 0x61, 0x1a, 0x85, 0x21, 0xc2,
+  0x44, 0x0a, 0xc4, 0xc2, 0xd2, 0xe4, 0x5a, 0xc2, 0xd8, 0xd2, 0xc2, 0xe6,
+  0x5a, 0xe6, 0xc6, 0xde, 0xe0, 0xca, 0x5a, 0xe8, 0xca, 0xf0, 0xe8, 0xea,
+  0xe4, 0xca, 0xe6, 0x86, 0x18, 0xd3, 0x29, 0x4c, 0xa2, 0x30, 0x99, 0x02,
+  0xb1, 0xb0, 0x34, 0xb9, 0x96, 0x30, 0xb6, 0xb4, 0xb0, 0xb9, 0x96, 0xb9,
+  0xb1, 0x37, 0xb8, 0xb2, 0x96, 0xb9, 0xb0, 0x36, 0x38, 0xb6, 0x32, 0xb9,
+  0xb9, 0x21, 0xc6, 0x94, 0x0a, 0x93, 0x28, 0x4c, 0xa8, 0x30, 0x84, 0x98,
+  0x4e, 0x61, 0x4a, 0x05, 0x4a, 0x5f, 0x5a, 0x54, 0x53, 0x31, 0x32, 0x53,
+  0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x1c,
+  0xd2, 0xdc, 0xe8, 0x86, 0x18, 0x13, 0x2b, 0x4c, 0x7f, 0x50, 0x35, 0x43,
+  0x8c, 0x29, 0x0d, 0xa6, 0x3f, 0xa8, 0x9a, 0x21, 0xd2, 0xb4, 0x0a, 0xd3,
+  0x1f, 0x54, 0xcd, 0xf4, 0x07, 0x15, 0x33, 0xb5, 0x42, 0xe5, 0x4c, 0xae,
+  0x50, 0x3d, 0x43, 0x8c, 0xe9, 0x15, 0x26, 0x57, 0xa8, 0x9e, 0x21, 0xc6,
+  0xf4, 0x0a, 0x53, 0x2b, 0x54, 0xce, 0x88, 0x88, 0x1d, 0xd8, 0xc1, 0x1e,
+  0xda, 0xc1, 0x0d, 0xda, 0xe1, 0x1d, 0xc8, 0xa1, 0x1e, 0xd8, 0xa1, 0x1c,
+  0xdc, 0xc0, 0x1c, 0xd8, 0x21, 0x1c, 0xce, 0x61, 0x1e, 0xa6, 0x08, 0xc1,
+  0x30, 0x42, 0x61, 0x07, 0x76, 0xb0, 0x87, 0x76, 0x70, 0x83, 0x74, 0x20,
+  0x87, 0x72, 0x70, 0x07, 0x7a, 0x98, 0x12, 0x14, 0x23, 0x96, 0x70, 0x48,
+  0x07, 0x79, 0x70, 0x03, 0x7b, 0x28, 0x07, 0x79, 0x98, 0x87, 0x74, 0x78,
+  0x07, 0x77, 0x98, 0x12, 0x18, 0x23, 0xa8, 0x70, 0x48, 0x07, 0x79, 0x70,
+  0x03, 0x76, 0x08, 0x07, 0x77, 0x38, 0x87, 0x7a, 0x08, 0x87, 0x73, 0x28,
+  0x87, 0x5f, 0xb0, 0x87, 0x72, 0x90, 0x87, 0x79, 0x48, 0x87, 0x77, 0x70,
+  0x87, 0x29, 0x01, 0x32, 0x62, 0x0a, 0x87, 0x74, 0x90, 0x07, 0x37, 0x18,
+  0x87, 0x77, 0x68, 0x07, 0x78, 0x48, 0x07, 0x76, 0x28, 0x87, 0x5f, 0x78,
+  0x07, 0x78, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0x98, 0x87, 0x29, 0x83,
+  0xc2, 0x38, 0x23, 0x98, 0x70, 0x48, 0x07, 0x79, 0x70, 0x03, 0x73, 0x90,
+  0x87, 0x70, 0x38, 0x87, 0x76, 0x28, 0x07, 0x77, 0xa0, 0x87, 0x29, 0xc1,
+  0x1e, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08,
+  0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38,
+  0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71,
+  0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c,
+  0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d,
+  0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d,
+  0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07,
+  0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87,
+  0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30,
+  0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10,
+  0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66,
+  0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c,
+  0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07,
+  0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87,
+  0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05,
+  0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87,
+  0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0,
+  0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca,
+  0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38,
+  0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c,
+  0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87,
+  0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87,
+  0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00,
+  0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20,
+  0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2,
+  0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4,
+  0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a,
+  0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07,
+  0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90,
+  0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8,
+  0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc,
+  0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b,
+  0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b,
+  0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87,
+  0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81,
+  0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30,
+  0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde,
+  0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b,
+  0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39,
+  0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07,
+  0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6,
+  0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30,
+  0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30,
+  0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50,
+  0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8,
+  0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8,
+  0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d,
+  0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07,
+  0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87,
+  0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0,
+  0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28,
+  0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87,
+  0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87,
+  0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20,
+  0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x16, 0xb0, 0x01, 0x48, 0xe4, 0x4b,
+  0x00, 0xf3, 0x2c, 0xc4, 0x3f, 0x11, 0xd7, 0x44, 0x45, 0xc4, 0x7f, 0x0f,
+  0x7e, 0x85, 0x17, 0xb7, 0x6d, 0x00, 0xca, 0xb6, 0x20, 0xd3, 0x17, 0x39,
+  0xcc, 0xdd, 0x99, 0xc0, 0x05, 0x20, 0x91, 0x2f, 0x38, 0x4d, 0x45, 0x44,
+  0x93, 0x5f, 0xf8, 0xc5, 0x6d, 0xfb, 0x94, 0x8f, 0xdc, 0x36, 0x00, 0x00,
+  0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x13, 0x04,
+  0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xe4, 0x46,
+  0x00, 0x68, 0xcc, 0x00, 0x50, 0xab, 0x01, 0x72, 0x73, 0x0c, 0x03, 0x71,
+  0x91, 0x98, 0x01, 0x00, 0x00, 0x00, 0xe3, 0x0d, 0x88, 0x83, 0x51, 0x40,
+  0xc6, 0x1b, 0x14, 0x28, 0xa3, 0x80, 0x58, 0xe0, 0xc8, 0xc7, 0x02, 0x02,
+  0x3e, 0x83, 0x0c, 0xc1, 0x81, 0x8c, 0x37, 0x3c, 0xd5, 0x45, 0xc1, 0x98,
+  0x63, 0x18, 0x82, 0x6e, 0xbc, 0x41, 0xc2, 0x3c, 0x0a, 0xc8, 0x88, 0x01,
+  0x41, 0x04, 0x65, 0x10, 0x8c, 0x18, 0x28, 0x45, 0x70, 0x06, 0xd4, 0x44,
+  0x40, 0x12, 0x14, 0x64, 0x10, 0x10, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00,
+  0x00, 0x00, 0x5b, 0x8e, 0x20, 0x00, 0x85, 0xa3, 0x14, 0x10, 0x55, 0xd8,
+  0x72, 0x0c, 0x01, 0x28, 0x1c, 0xa5, 0x80, 0xa8, 0xc2, 0x96, 0x03, 0x09,
+  0x60, 0xe1, 0x28, 0x05, 0x44, 0x15, 0xb6, 0x1c, 0x4b, 0x10, 0x0b, 0x47,
+  0x29, 0x20, 0xaa, 0xb0, 0xa5, 0x68, 0x0e, 0x55, 0x40, 0x4a, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom3D_metallib_len = 3694;
+const unsigned char BlitFromCube_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x0e, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0d, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x43, 0x75, 0x62, 0x65, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01,
+  0x00, 0x01, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0xd2, 0xe8, 0x3e, 0xc7,
+  0x78, 0x5b, 0xc9, 0x16, 0x13, 0xfb, 0xf4, 0x38, 0xcd, 0x15, 0x4c, 0x67,
+  0x53, 0x5a, 0x33, 0x1a, 0x95, 0x28, 0x3c, 0x95, 0x2f, 0x7b, 0xb6, 0x59,
+  0xef, 0xbd, 0xf1, 0x24, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45,
+  0x52, 0x53, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54,
+  0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b,
+  0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x9c, 0x0e, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00,
+  0xa4, 0x03, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24,
+  0x48, 0x0a, 0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72,
+  0x24, 0x07, 0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0,
+  0x01, 0x00, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00,
+  0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x60, 0x00, 0x09,
+  0xa8, 0x88, 0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77, 0xc0, 0x87, 0x36,
+  0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36,
+  0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1,
+  0x1c, 0x00, 0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0xe1,
+  0x1c, 0xc2, 0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0xe1,
+  0x1d, 0xe4, 0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81, 0x1e, 0xd0, 0x01,
+  0x88, 0x03, 0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77, 0x68, 0x03, 0x71,
+  0xa8, 0x87, 0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77, 0x98, 0x07, 0x80,
+  0x70, 0x87, 0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70, 0x68, 0x87, 0x72,
+  0x68, 0x03, 0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a, 0x28, 0x07, 0x79,
+  0x68, 0x83, 0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80, 0x1e, 0xe4, 0xa1,
+  0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21,
+  0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81,
+  0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0xa1,
+  0x0d, 0xdc, 0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xc2, 0xc1,
+  0x1c, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77,
+  0x68, 0x83, 0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78,
+  0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1,
+  0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1d, 0xc2, 0xc1,
+  0x1d, 0xe6, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81,
+  0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77,
+  0x78, 0x87, 0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77, 0x28, 0x07, 0x72,
+  0x68, 0x03, 0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79, 0x68, 0x03, 0x73,
+  0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41,
+  0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe8, 0x41,
+  0x1e, 0xc2, 0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1, 0x1c, 0xda, 0xa0,
+  0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72,
+  0x00, 0x88, 0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75, 0x68, 0x03, 0x78,
+  0x90, 0x87, 0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79,
+  0x68, 0x03, 0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72, 0x90, 0x87, 0x36,
+  0x98, 0x87, 0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00, 0x20, 0xea, 0xc1,
+  0x1d, 0xe6, 0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1,
+  0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a,
+  0x28, 0x07, 0x60, 0xc3, 0x26, 0x0c, 0xc0, 0x02, 0x54, 0x43, 0x38, 0xa4,
+  0x83, 0x3c, 0xb4, 0x81, 0x38, 0xd4, 0x83, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x1b, 0xb8, 0xc3, 0x3b, 0xb4, 0x41, 0x38, 0xb0, 0x43, 0x3a, 0x84,
+  0xc3, 0x3c, 0x00, 0x1b, 0x8c, 0xa1, 0x00, 0x16, 0xa0, 0xda, 0x80, 0x10,
+  0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x0c, 0x20, 0x01, 0xd5, 0x06, 0xa3,
+  0x08, 0x80, 0x05, 0xa8, 0x36, 0x18, 0x86, 0x00, 0x2c, 0x40, 0xb5, 0xc1,
+  0x38, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x24, 0x80, 0xda, 0x60, 0x20,
+  0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x12, 0x40, 0x6d, 0x40, 0x92, 0xff,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x06, 0x90, 0x80, 0x0a, 0x00, 0x00, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18,
+  0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48,
+  0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x74, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30,
+  0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30,
+  0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10,
+  0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4b, 0x9a, 0x22, 0x4a, 0x98, 0xfc,
+  0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0x5f, 0xa0, 0x02, 0xe2, 0x9f, 0xc6,
+  0x08, 0x80, 0x41, 0x04, 0x23, 0xb8, 0x48, 0x9a, 0x22, 0x4a, 0x98, 0xfc,
+  0x5f, 0x02, 0x98, 0x67, 0x21, 0xa2, 0x7f, 0x1a, 0x23, 0x00, 0x06, 0x11,
+  0x10, 0xa1, 0x18, 0x41, 0x84, 0x72, 0x12, 0xa9, 0x61, 0x84, 0x01, 0x98,
+  0x23, 0x08, 0x8a, 0x11, 0x4e, 0x62, 0x0d, 0x90, 0x2b, 0x02, 0x18, 0x04,
+  0x8b, 0x30, 0x00, 0xc9, 0x81, 0x80, 0x14, 0x18, 0x73, 0x04, 0xa0, 0x30,
+  0x88, 0x20, 0x08, 0x83, 0x08, 0x80, 0x30, 0x05, 0x30, 0x02, 0x30, 0x8c,
+  0x30, 0x0c, 0x83, 0x08, 0x83, 0x00, 0x00, 0x00, 0x13, 0xa8, 0x70, 0x48,
+  0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60,
+  0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8, 0x03, 0x37, 0x80,
+  0x03, 0x37, 0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d, 0x00, 0x0f, 0x7a,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d,
+  0x90, 0x0e, 0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9,
+  0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a,
+  0x10, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6,
+  0x40, 0x07, 0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76, 0xa0, 0x07, 0x71,
+  0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6,
+  0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a,
+  0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x90, 0x07, 0x72,
+  0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76,
+  0xd0, 0x06, 0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75,
+  0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x75,
+  0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75,
+  0x10, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74,
+  0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70,
+  0x20, 0x07, 0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x43, 0x98, 0x05, 0x00, 0x80, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x21, 0xcc, 0x03, 0x04, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x10, 0x26, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x60, 0x08, 0x33, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x90, 0x05, 0x02, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a,
+  0x23, 0x00, 0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05, 0x53, 0x20, 0x85,
+  0x52, 0x06, 0x64, 0x0b, 0x62, 0x04, 0xa0, 0x40, 0x0a, 0x85, 0xea, 0x58,
+  0x42, 0x24, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x45, 0x01, 0x00, 0x00,
+  0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9,
+  0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x80, 0x50, 0x40, 0x15, 0x51, 0xb9,
+  0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x0c,
+  0x05, 0x25, 0x0c, 0x07, 0xdf, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4,
+  0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd,
+  0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x07, 0x04, 0xa5,
+  0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46, 0x66,
+  0xc6, 0x25, 0x07, 0x27, 0x65, 0x88, 0x40, 0x11, 0x43, 0x8c, 0xa1, 0x18,
+  0x8c, 0x81, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04, 0xa1, 0x8e,
+  0xa1, 0x18, 0x8a, 0x81, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6,
+  0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36,
+  0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44, 0xa0, 0x12,
+  0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+  0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65,
+  0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x6a, 0x21, 0x19, 0x84, 0xa5,
+  0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9,
+  0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95,
+  0xd1, 0x8d, 0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11,
+  0xa8, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99, 0x1b, 0x59, 0x99,
+  0xdc, 0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3, 0xb0, 0x34, 0x39,
+  0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0x2f, 0xb7, 0xb0,
+  0xb6, 0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x43, 0x10, 0xea,
+  0x19, 0x08, 0x0a, 0xa2, 0xa2, 0x21, 0x02, 0x25, 0x51, 0x0a, 0x4b, 0x93,
+  0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0xfb, 0x4a, 0x73,
+  0x83, 0xab, 0xa3, 0x23, 0x75, 0x56, 0xe6, 0x56, 0x26, 0x17, 0x46, 0x57,
+  0x46, 0x86, 0x32, 0x43, 0x57, 0x86, 0x47, 0x64, 0x27, 0xf3, 0x65, 0x96,
+  0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d, 0xae, 0x4c, 0x8e,
+  0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9, 0x18,
+  0x5d, 0x9a, 0x5d, 0x19, 0x0d, 0x33, 0xb6, 0xb7, 0x30, 0x3a, 0x19, 0x32,
+  0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+  0x1c, 0xe8, 0xca, 0xf0, 0x86, 0x48, 0x03, 0x41, 0x51, 0x54, 0x45, 0x59,
+  0xd4, 0x45, 0x41, 0x14, 0x46, 0x65, 0x94, 0x46, 0x26, 0x2c, 0x4d, 0xce,
+  0x05, 0xee, 0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x8d, 0x52, 0x58, 0x9a,
+  0x9c, 0x8b, 0xdb, 0xdb, 0x17, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9, 0x18,
+  0x5d, 0x9a, 0x5d, 0x19, 0x07, 0xb8, 0xb7, 0xb9, 0x21, 0xd0, 0x50, 0x50,
+  0x1c, 0x65, 0x51, 0x1d, 0x05, 0x51, 0x11, 0x95, 0x51, 0x1e, 0x95, 0xb0,
+  0x34, 0x39, 0x17, 0xb1, 0x3a, 0x33, 0xb3, 0x32, 0x39, 0x3e, 0x61, 0x69,
+  0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a,
+  0x65, 0x94, 0xc2, 0xd2, 0xe4, 0x5c, 0xd8, 0xde, 0xc6, 0xc2, 0xe8, 0xd2,
+  0xde, 0xdc, 0xbe, 0xd2, 0xdc, 0xc8, 0xca, 0xf0, 0x88, 0x84, 0xa5, 0xc9,
+  0xb9, 0xc8, 0x95, 0x85, 0x91, 0x91, 0x0a, 0x4b, 0x93, 0x73, 0x99, 0xa3,
+  0x93, 0xab, 0x1b, 0xa3, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb, 0x4a, 0x73,
+  0x33, 0x7b, 0x63, 0x52, 0x65, 0xc5, 0x54, 0x66, 0x46, 0x47, 0xf5, 0x06,
+  0x47, 0xa6, 0xca, 0x8a, 0x28, 0xad, 0xad, 0xcc, 0x6d, 0x2e, 0xed, 0xcd,
+  0x6d, 0x8e, 0x44, 0x5d, 0x9a, 0x1b, 0x1d, 0x91, 0xa6, 0x34, 0x38, 0xa6,
+  0x32, 0xbb, 0x32, 0x36, 0x16, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x64, 0x98,
+  0xc2, 0xf2, 0xca, 0xe4, 0x9e, 0xe4, 0x88, 0xca, 0xe0, 0xe8, 0xd0, 0x86,
+  0xa0, 0xc1, 0x40, 0x0c, 0xc6, 0x40, 0x50, 0x18, 0x55, 0x06, 0x83, 0x31,
+  0x18, 0x03, 0x41, 0x61, 0x94, 0x19, 0x0c, 0xca, 0x70, 0x0c, 0x04, 0x75,
+  0x06, 0x14, 0x1a, 0x0c, 0xcb, 0x70, 0x0c, 0x04, 0x95, 0x06, 0x94, 0x1a,
+  0x30, 0x0a, 0x4b, 0x93, 0x73, 0x09, 0x93, 0x3b, 0xfb, 0xa2, 0xcb, 0x83,
+  0x2b, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0xe3, 0x15, 0x96, 0x26, 0xe7, 0x12,
+  0x26, 0x77, 0xf6, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x15, 0xc6, 0x96, 0x76,
+  0xe6, 0xf6, 0x35, 0x97, 0xa6, 0x57, 0x46, 0x66, 0xea, 0xad, 0x4e, 0x6e,
+  0xac, 0x4c, 0xaa, 0xec, 0x2c, 0xed, 0xcd, 0x8d, 0xcc, 0xdc, 0x5b, 0x9d,
+  0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0xdb, 0x10, 0x32, 0x18,
+  0x10, 0x0a, 0x0c, 0xa8, 0x30, 0x18, 0x12, 0x4a, 0x0c, 0x06, 0x62, 0x28,
+  0xa8, 0x31, 0xa0, 0xc8, 0x80, 0x5a, 0x03, 0x8a, 0x0d, 0x86, 0x84, 0x6a,
+  0x83, 0xc1, 0xa0, 0x20, 0xca, 0x0d, 0xa8, 0x8c, 0x7a, 0x03, 0x2e, 0x61,
+  0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x54, 0xc2,
+  0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xa8, 0xd1, 0x95,
+  0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0x8d, 0xd5, 0x89, 0x95, 0xf1, 0x98, 0xb1,
+  0xbd, 0x85, 0xd1, 0xb1, 0x80, 0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xf9,
+  0xb0, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0xa3, 0x2a, 0xc3, 0xa3, 0xab,
+  0x93, 0x2b, 0x1b, 0x42, 0x0d, 0x0c, 0x15, 0x07, 0x94, 0x18, 0x0c, 0xc4,
+  0x50, 0x50, 0x72, 0x40, 0x41, 0xd4, 0x1c, 0x50, 0x19, 0x45, 0x07, 0x5c,
+  0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x78,
+  0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xc9, 0xb1, 0x99, 0x7b, 0xab, 0x93,
+  0x1b, 0x2b, 0x9b, 0x0a, 0x6b, 0x83, 0x63, 0x2b, 0x93, 0x1b, 0x22, 0x0d,
+  0x07, 0x65, 0x07, 0x94, 0x18, 0x0c, 0xc4, 0x50, 0x50, 0x10, 0x75, 0x07,
+  0x54, 0x46, 0xe1, 0xc1, 0x10, 0x85, 0xda, 0xa8, 0x8f, 0x82, 0x03, 0xaa,
+  0x0e, 0xa8, 0x3c, 0x18, 0x62, 0x2c, 0x00, 0x35, 0x51, 0x7a, 0xc0, 0xe7,
+  0xad, 0xcd, 0x2d, 0x0d, 0xee, 0x8d, 0xae, 0xcc, 0x8d, 0x0e, 0x64, 0x0c,
+  0x2d, 0x4c, 0x8e, 0xcf, 0x54, 0x5a, 0x1b, 0x1c, 0x5b, 0x19, 0xc8, 0xd0,
+  0xca, 0x0a, 0x08, 0x95, 0x50, 0x50, 0xd0, 0x10, 0x81, 0xea, 0x83, 0x21,
+  0x06, 0xc5, 0x07, 0x94, 0x1f, 0x58, 0xce, 0x10, 0x83, 0xfa, 0x03, 0xea,
+  0x0f, 0x2c, 0x87, 0x5e, 0x58, 0x9a, 0x5c, 0x4b, 0x18, 0x5b, 0x5a, 0xd8,
+  0x5c, 0xcb, 0xdc, 0xd8, 0x1b, 0x5c, 0xd9, 0x1c, 0x8a, 0x10, 0x5b, 0x1a,
+  0x9d, 0x91, 0xdc, 0x5b, 0xdb, 0x50, 0x9d, 0x58, 0x59, 0xca, 0x10, 0x82,
+  0x12, 0x05, 0x2a, 0x14, 0x68, 0x85, 0xa5, 0xc9, 0xb5, 0x84, 0xb1, 0xa5,
+  0x85, 0xcd, 0xb5, 0xcc, 0x8d, 0xbd, 0xc1, 0x95, 0xb5, 0x84, 0xc9, 0x9d,
+  0xa1, 0xc8, 0xa4, 0x0c, 0x31, 0x28, 0x52, 0xa0, 0x44, 0x81, 0x1a, 0x85,
+  0x21, 0x02, 0x45, 0x0a, 0xc4, 0xc2, 0xd2, 0xe4, 0x5a, 0xc2, 0xd8, 0xd2,
+  0xc2, 0xe6, 0x5a, 0xe6, 0xc6, 0xde, 0xe0, 0xca, 0x5a, 0xe8, 0xca, 0xf0,
+  0xe8, 0xea, 0xe4, 0xca, 0xe6, 0x86, 0x18, 0xd4, 0x29, 0x50, 0xa2, 0x40,
+  0x99, 0x02, 0xb1, 0xb0, 0x34, 0xb9, 0x96, 0x30, 0xb6, 0xb4, 0xb0, 0xb9,
+  0x96, 0xb9, 0xb1, 0x37, 0xb8, 0xb2, 0x96, 0xb9, 0xb0, 0x36, 0x38, 0xb6,
+  0x32, 0xb9, 0xb9, 0x21, 0x06, 0x95, 0x0a, 0x94, 0x28, 0x50, 0xa8, 0x30,
+  0x84, 0xa0, 0x4e, 0x81, 0x4a, 0x05, 0x4a, 0x5f, 0x5a, 0x54, 0x53, 0x31,
+  0x32, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x6f,
+  0x6e, 0x1c, 0xd2, 0xdc, 0xe8, 0x86, 0x18, 0x14, 0x2b, 0x50, 0x7f, 0x60,
+  0x39, 0x43, 0x0c, 0x2a, 0x0d, 0xa8, 0x3f, 0xb0, 0x9c, 0x21, 0x12, 0xb5,
+  0x0a, 0xd4, 0x1f, 0x58, 0x0e, 0xf5, 0x07, 0x56, 0x43, 0xb5, 0x82, 0xf5,
+  0x50, 0xae, 0x60, 0x41, 0x43, 0x0c, 0xea, 0x15, 0x28, 0x57, 0xb0, 0xa0,
+  0x21, 0x06, 0xf5, 0x0a, 0x54, 0x2b, 0x58, 0xcf, 0x88, 0x88, 0x1d, 0xd8,
+  0xc1, 0x1e, 0xda, 0xc1, 0x0d, 0xda, 0xe1, 0x1d, 0xc8, 0xa1, 0x1e, 0xd8,
+  0xa1, 0x1c, 0xdc, 0xc0, 0x1c, 0xd8, 0x21, 0x1c, 0xce, 0x61, 0x1e, 0xa6,
+  0x08, 0xc1, 0x30, 0x42, 0x61, 0x07, 0x76, 0xb0, 0x87, 0x76, 0x70, 0x83,
+  0x74, 0x20, 0x87, 0x72, 0x70, 0x07, 0x7a, 0x98, 0x12, 0x14, 0x23, 0x96,
+  0x70, 0x48, 0x07, 0x79, 0x70, 0x03, 0x7b, 0x28, 0x07, 0x79, 0x98, 0x87,
+  0x74, 0x78, 0x07, 0x77, 0x98, 0x12, 0x18, 0x23, 0xa8, 0x70, 0x48, 0x07,
+  0x79, 0x70, 0x03, 0x76, 0x08, 0x07, 0x77, 0x38, 0x87, 0x7a, 0x08, 0x87,
+  0x73, 0x28, 0x87, 0x5f, 0xb0, 0x87, 0x72, 0x90, 0x87, 0x79, 0x48, 0x87,
+  0x77, 0x70, 0x87, 0x29, 0x01, 0x32, 0x62, 0x0a, 0x87, 0x74, 0x90, 0x07,
+  0x37, 0x18, 0x87, 0x77, 0x68, 0x07, 0x78, 0x48, 0x07, 0x76, 0x28, 0x87,
+  0x5f, 0x78, 0x07, 0x78, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0x98, 0x87,
+  0x29, 0x83, 0xc2, 0x38, 0x23, 0x98, 0x70, 0x48, 0x07, 0x79, 0x70, 0x03,
+  0x73, 0x90, 0x87, 0x70, 0x38, 0x87, 0x76, 0x28, 0x07, 0x77, 0xa0, 0x87,
+  0x29, 0xc1, 0x1e, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00,
+  0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88,
+  0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73,
+  0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e,
+  0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30,
+  0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8,
+  0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b,
+  0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76,
+  0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e,
+  0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e,
+  0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61,
+  0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4,
+  0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37,
+  0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76,
+  0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71,
+  0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e,
+  0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61,
+  0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8,
+  0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc,
+  0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7,
+  0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78,
+  0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f,
+  0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f,
+  0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1,
+  0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0,
+  0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0,
+  0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b,
+  0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c,
+  0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61,
+  0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1,
+  0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc,
+  0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4,
+  0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79,
+  0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72,
+  0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e,
+  0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1,
+  0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4,
+  0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8,
+  0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71,
+  0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19,
+  0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f,
+  0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e,
+  0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e,
+  0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81,
+  0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21,
+  0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc,
+  0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70,
+  0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77,
+  0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e,
+  0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e,
+  0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a,
+  0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73,
+  0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x71, 0x20, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x26, 0x70, 0x01, 0x48,
+  0xe4, 0x0b, 0x4e, 0x53, 0x11, 0xd1, 0xe4, 0x17, 0x7e, 0x71, 0xdb, 0x3e,
+  0xe5, 0x23, 0xb7, 0x6d, 0x03, 0x17, 0x80, 0x44, 0xbe, 0xe0, 0x34, 0x15,
+  0x11, 0x4d, 0x3e, 0xe5, 0x23, 0xb7, 0xed, 0x17, 0x7e, 0x71, 0xdb, 0x16,
+  0xd0, 0x01, 0x48, 0xe4, 0x4b, 0x00, 0xf3, 0x2c, 0xc4, 0x3f, 0x11, 0xd7,
+  0x44, 0x45, 0xc4, 0x2f, 0x50, 0x01, 0xe1, 0x57, 0x78, 0x71, 0xdb, 0x06,
+  0xc0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0x70, 0x54, 0x40, 0x00, 0x00,
+  0x61, 0x20, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x13, 0x04, 0x48, 0x2c,
+  0x10, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0xb4, 0xc7, 0x1a, 0x80,
+  0x40, 0xa0, 0x56, 0x03, 0x34, 0x4a, 0x81, 0xc0, 0x18, 0x01, 0x08, 0x82,
+  0x20, 0xfe, 0x0b, 0x63, 0x04, 0x20, 0x08, 0x82, 0xf8, 0x37, 0x02, 0x30,
+  0x46, 0x00, 0x82, 0x20, 0x08, 0x82, 0x01, 0x85, 0x39, 0x88, 0x0d, 0x0d,
+  0xd0, 0xc0, 0x0c, 0xe6, 0x20, 0x34, 0x34, 0x40, 0x03, 0x33, 0x98, 0x83,
+  0x40, 0x03, 0x0d, 0x0d, 0xcc, 0x60, 0x0e, 0x02, 0x0d, 0x36, 0x34, 0x30,
+  0x83, 0x39, 0x08, 0x34, 0x40, 0x83, 0xcd, 0x0c, 0xe6, 0x20, 0xd0, 0x00,
+  0x0d, 0x34, 0x33, 0x98, 0x83, 0xe0, 0x38, 0xce, 0x0c, 0x66, 0x00, 0x08,
+  0xcc, 0x00, 0x8c, 0x11, 0x80, 0x20, 0x08, 0x82, 0xa0, 0x30, 0x03, 0x00,
+  0xe3, 0x0d, 0xd5, 0x56, 0x06, 0x14, 0x90, 0xf1, 0x86, 0xab, 0x33, 0x03,
+  0x0a, 0x88, 0x05, 0x9b, 0x7c, 0x2c, 0x20, 0xe0, 0x33, 0x86, 0x10, 0xac,
+  0x81, 0x05, 0x93, 0x7c, 0x2c, 0xb8, 0xe0, 0x33, 0x86, 0x40, 0xb4, 0x81,
+  0x05, 0x96, 0x7c, 0x2c, 0xd0, 0xe0, 0x33, 0xde, 0x10, 0x06, 0x67, 0x90,
+  0x06, 0x14, 0x8c, 0x11, 0x03, 0x82, 0x08, 0xe8, 0x20, 0x18, 0xe6, 0x19,
+  0x82, 0x83, 0x08, 0x0a, 0x01, 0x19, 0x18, 0xe2, 0x28, 0x32, 0xc3, 0x22,
+  0x22, 0x3e, 0x73, 0x0c, 0x5b, 0x40, 0x07, 0x36, 0x25, 0xf1, 0x99, 0x63,
+  0x10, 0x82, 0x39, 0x98, 0x25, 0x38, 0xac, 0x42, 0xe2, 0x33, 0xc7, 0xe0,
+  0x05, 0x78, 0x30, 0xc7, 0x10, 0x34, 0x76, 0x30, 0x4b, 0x70, 0xcc, 0x31,
+  0x7c, 0xce, 0x1e, 0x58, 0xc6, 0xc4, 0x67, 0x8e, 0x41, 0x08, 0xf2, 0x60,
+  0x96, 0xe0, 0x98, 0x63, 0x08, 0x83, 0xc8, 0x0f, 0xe6, 0x18, 0x82, 0x67,
+  0x0f, 0x66, 0x09, 0x0e, 0xeb, 0xa0, 0xf8, 0xcc, 0x31, 0x8c, 0x01, 0x15,
+  0x0a, 0x73, 0x0c, 0x81, 0x10, 0x0a, 0xb3, 0x04, 0x87, 0x81, 0x81, 0x15,
+  0x1f, 0x0b, 0x03, 0x2a, 0x3e, 0x73, 0x0c, 0x66, 0x20, 0x94, 0xc2, 0x1c,
+  0x43, 0x20, 0x94, 0xc2, 0x2c, 0xc1, 0x31, 0xd0, 0x13, 0x08, 0x86, 0x52,
+  0x40, 0x04, 0x35, 0x68, 0x02, 0x18, 0x04, 0xae, 0x00, 0x0c, 0x32, 0x04,
+  0x67, 0x50, 0x07, 0xe3, 0x0d, 0x79, 0xf0, 0x07, 0xa5, 0x40, 0x01, 0x19,
+  0x31, 0x20, 0x88, 0xa0, 0x15, 0x82, 0x11, 0x03, 0xa4, 0x08, 0x5e, 0x61,
+  0x0f, 0xf4, 0x80, 0xc0, 0x83, 0x20, 0x83, 0x80, 0x18, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x5b, 0x8e, 0x20, 0x00, 0x85, 0xa3, 0x14, 0x10,
+  0x55, 0xd8, 0x72, 0x0c, 0x01, 0x28, 0x1c, 0xa5, 0x80, 0xa8, 0xc2, 0x96,
+  0xa3, 0x09, 0x60, 0xe1, 0x28, 0x05, 0x44, 0x15, 0xb6, 0x1c, 0x6c, 0x10,
+  0xc4, 0xc2, 0x51, 0x0a, 0x88, 0x2a, 0x6c, 0x29, 0xdc, 0xe0, 0x50, 0x05,
+  0xa4, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFromCube_metallib_len = 3984;
+#endif
+#else
+const unsigned char FullscreenVert_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xb2, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x09, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0f, 0x00, 0x46, 0x75, 0x6c, 0x6c, 0x73, 0x63,
+  0x72, 0x65, 0x65, 0x6e, 0x56, 0x65, 0x72, 0x74, 0x00, 0x54, 0x59, 0x50,
+  0x45, 0x01, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x46, 0x2e,
+  0xbf, 0xd5, 0xcc, 0x19, 0x56, 0x6b, 0xf4, 0xa0, 0x62, 0x71, 0x32, 0x51,
+  0x90, 0xa1, 0x27, 0xe8, 0x24, 0x33, 0x78, 0x63, 0x0b, 0x92, 0x28, 0xc3,
+  0xe9, 0xbf, 0x5e, 0x6e, 0xd8, 0x9a, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00,
+  0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0,
+  0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xb0, 0x09,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c,
+  0x00, 0x00, 0x69, 0x02, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00,
+  0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8,
+  0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05,
+  0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92,
+  0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32,
+  0x44, 0x24, 0x48, 0x0a, 0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19,
+  0x21, 0x72, 0x24, 0x07, 0xc8, 0x08, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40,
+  0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x6c, 0x00,
+  0x00, 0x00, 0x1b, 0x7a, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x90,
+  0x00, 0x8a, 0x08, 0x07, 0x78, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7c, 0x68,
+  0x03, 0x73, 0xa8, 0x07, 0x77, 0x18, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68,
+  0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e,
+  0xca, 0x01, 0x20, 0xda, 0x21, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c,
+  0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d, 0xec, 0xa1, 0x1c, 0xc6, 0x81, 0x1e,
+  0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e, 0xd2, 0x81, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x38, 0x00, 0x06, 0x77, 0x78, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x48,
+  0x07, 0x76, 0xa0, 0x87, 0x74, 0x70, 0x87, 0x79, 0x00, 0x08, 0x77, 0x78,
+  0x87, 0x36, 0x30, 0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80,
+  0x87, 0x77, 0x48, 0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28,
+  0x07, 0x76, 0x48, 0x87, 0x76, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c,
+  0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d,
+  0xca, 0xa1, 0x0d, 0xe0, 0xe1, 0x1d, 0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x0d, 0xca, 0x81, 0x1d, 0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d,
+  0xde, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0,
+  0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x48,
+  0x07, 0x77, 0x30, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68,
+  0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c,
+  0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e,
+  0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68,
+  0x83, 0x79, 0x48, 0x87, 0x73, 0x70, 0x87, 0x72, 0x20, 0x87, 0x36, 0xd0,
+  0x87, 0x72, 0x90, 0x87, 0x77, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68,
+  0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e,
+  0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c,
+  0xe0, 0x01, 0x1e, 0xd2, 0xc1, 0x1d, 0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c,
+  0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x98,
+  0x07, 0x7a, 0x08, 0x87, 0x71, 0x58, 0x87, 0x36, 0x80, 0x07, 0x79, 0x78,
+  0x07, 0x7a, 0x28, 0x87, 0x71, 0xa0, 0x87, 0x77, 0x90, 0x87, 0x36, 0x10,
+  0x87, 0x7a, 0x30, 0x07, 0x73, 0x28, 0x07, 0x79, 0x68, 0x83, 0x79, 0x48,
+  0x07, 0x7d, 0x28, 0x07, 0x00, 0x0f, 0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e,
+  0xc2, 0xc1, 0x1c, 0xca, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d,
+  0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00,
+  0x36, 0x18, 0xc2, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0x04, 0x50, 0x1b,
+  0x8c, 0xe1, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0x28, 0x00, 0x00,
+  0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82,
+  0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20,
+  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, 0x20, 0x64,
+  0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1,
+  0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x34,
+  0x33, 0x00, 0xc3, 0x08, 0x02, 0x30, 0x8c, 0x40, 0x00, 0x56, 0x08, 0x99,
+  0x23, 0x00, 0x83, 0x22, 0x0c, 0x51, 0x15, 0x01, 0x88, 0x6e, 0x20, 0x20,
+  0x05, 0x68, 0x18, 0x81, 0x20, 0x46, 0x00, 0x00, 0x00, 0x00, 0x13, 0xb2,
+  0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07,
+  0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x76, 0x08, 0x87, 0x71, 0x78, 0x87,
+  0x79, 0xc0, 0x87, 0x38, 0x80, 0x03, 0x37, 0x88, 0x83, 0x38, 0x70, 0x03,
+  0x38, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06, 0xf0, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x90,
+  0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9, 0x80,
+  0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60,
+  0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x90,
+  0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60,
+  0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x73, 0x20, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x74, 0x80,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60,
+  0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80,
+  0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x20,
+  0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20,
+  0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x79, 0x20, 0x07, 0x7a, 0x20,
+  0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60,
+  0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0,
+  0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x50, 0x07, 0x71, 0x20,
+  0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20,
+  0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10,
+  0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40,
+  0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0x30, 0x84, 0x31, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x18, 0xc2, 0x20, 0x40, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x64, 0x81, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x32, 0x1e,
+  0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04,
+  0x43, 0xa2, 0x12, 0x18, 0x01, 0x28, 0x82, 0x42, 0x28, 0x08, 0xd2, 0xb1,
+  0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x8b, 0x00,
+  0x00, 0x00, 0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab,
+  0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x21, 0x06, 0x41, 0x24, 0x80, 0x72,
+  0x50, 0xb9, 0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b,
+  0x62, 0x10, 0x42, 0x22, 0x10, 0x05, 0xe3, 0x20, 0x08, 0x0e, 0x8e, 0xad,
+  0x0c, 0xa4, 0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e,
+  0xed, 0xcd, 0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x06, 0x26,
+  0x06, 0x04, 0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46,
+  0x06, 0x46, 0x66, 0xc6, 0x25, 0x06, 0x26, 0x26, 0x65, 0x88, 0x90, 0x10,
+  0x43, 0x0c, 0x42, 0x20, 0x0c, 0x62, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6,
+  0x36, 0x04, 0x49, 0x0e, 0x42, 0x20, 0x04, 0x62, 0xe0, 0x16, 0x96, 0x26,
+  0xe7, 0x32, 0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6,
+  0xf6, 0x26, 0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56,
+  0x36, 0x44, 0x48, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
+  0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61,
+  0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x84, 0x64,
+  0x61, 0x19, 0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1,
+  0x95, 0xb9, 0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95,
+  0xc9, 0x7d, 0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x91, 0xa5, 0xcd, 0x85,
+  0x89, 0xb1, 0x95, 0x0d, 0x11, 0x92, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b,
+  0x5d, 0x99, 0x1c, 0x5d, 0x19, 0xde, 0xd7, 0x5b, 0x1d, 0x1d, 0x5c, 0x1d,
+  0x1d, 0xa9, 0xb3, 0x32, 0xb7, 0x32, 0xb9, 0x30, 0xba, 0x32, 0x32, 0x94,
+  0x19, 0xba, 0x32, 0x3c, 0x22, 0x3b, 0x99, 0x2f, 0xb3, 0x14, 0x46, 0x61,
+  0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f,
+  0x6e, 0x61, 0x6d, 0x65, 0x34, 0xcc, 0xd8, 0xde, 0xc2, 0xe8, 0x64, 0xc8,
+  0x84, 0xa5, 0xc9, 0xb9, 0x84, 0xc9, 0x9d, 0x7d, 0xb9, 0x85, 0xb5, 0x95,
+  0x71, 0xa0, 0x2b, 0xc3, 0x1b, 0xc2, 0x24, 0x4f, 0x02, 0x25, 0x51, 0x22,
+  0x25, 0x53, 0x42, 0x91, 0x09, 0x4b, 0x93, 0x73, 0x81, 0x7b, 0x9b, 0x4b,
+  0xa3, 0x4b, 0x7b, 0x73, 0xa3, 0x61, 0xc6, 0xf6, 0x16, 0x46, 0x47, 0xc3,
+  0x01, 0xee, 0x6d, 0x6e, 0x88, 0x92, 0x58, 0x49, 0x94, 0x5c, 0xc9, 0x94,
+  0x60, 0x43, 0x88, 0xa4, 0x4a, 0x32, 0x36, 0x61, 0x69, 0x72, 0x2e, 0x76,
+  0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x64, 0x24, 0xea, 0xd2, 0xdc,
+  0xe8, 0x28, 0xd8, 0x25, 0x0d, 0x61, 0x88, 0x21, 0xd9, 0x92, 0x28, 0xe1,
+  0x92, 0x29, 0xe9, 0x86, 0x08, 0x89, 0x37, 0xc4, 0x30, 0x80, 0x44, 0x4b,
+  0xbe, 0x11, 0x11, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0xb4, 0xc3,
+  0x3b, 0x90, 0x43, 0x3d, 0xb0, 0x43, 0x39, 0xb8, 0x81, 0x39, 0xb0, 0x43,
+  0x38, 0x9c, 0xc3, 0x3c, 0x4c, 0x11, 0x82, 0x61, 0x84, 0xc2, 0x0e, 0xec,
+  0x60, 0x0f, 0xed, 0xe0, 0x06, 0xe9, 0x40, 0x0e, 0xe5, 0xe0, 0x0e, 0xf4,
+  0x30, 0x25, 0x28, 0x46, 0x2c, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xf6,
+  0x50, 0x0e, 0xf2, 0x30, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x25, 0x30,
+  0x46, 0x50, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xec, 0x10, 0x0e, 0xee,
+  0x70, 0x0e, 0xf5, 0x10, 0x0e, 0xe7, 0x50, 0x0e, 0xbf, 0x60, 0x0f, 0xe5,
+  0x20, 0x0f, 0xf3, 0x90, 0x0e, 0xef, 0xe0, 0x0e, 0x53, 0x02, 0x64, 0xc4,
+  0x14, 0x0e, 0xe9, 0x20, 0x0f, 0x6e, 0x30, 0x0e, 0xef, 0xd0, 0x0e, 0xf0,
+  0x90, 0x0e, 0xec, 0x50, 0x0e, 0xbf, 0xf0, 0x0e, 0xf0, 0x40, 0x0f, 0xe9,
+  0xf0, 0x0e, 0xee, 0x30, 0x0f, 0x53, 0x06, 0x85, 0x71, 0x46, 0x28, 0xe1,
+  0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e, 0xf2, 0x40, 0x0f, 0xe5,
+  0x80, 0x0f, 0x53, 0x02, 0x30, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00,
+  0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01,
+  0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78,
+  0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4,
+  0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c,
+  0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03,
+  0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70,
+  0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70,
+  0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec,
+  0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0,
+  0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d,
+  0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43,
+  0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0,
+  0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68,
+  0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28,
+  0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08,
+  0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee,
+  0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62,
+  0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06,
+  0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3,
+  0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3,
+  0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68,
+  0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce,
+  0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3,
+  0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d,
+  0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e,
+  0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51,
+  0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60,
+  0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98,
+  0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e,
+  0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e,
+  0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83,
+  0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2,
+  0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a,
+  0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28,
+  0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5,
+  0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17,
+  0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83,
+  0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3,
+  0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48,
+  0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58,
+  0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0,
+  0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e,
+  0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9,
+  0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c,
+  0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d,
+  0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d,
+  0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58,
+  0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48,
+  0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0,
+  0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4,
+  0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30,
+  0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8,
+  0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x06, 0xe0,
+  0x7c, 0xd4, 0xb2, 0x48, 0x42, 0x44, 0x10, 0xcd, 0x4b, 0x44, 0x93, 0x05,
+  0x5c, 0x00, 0x12, 0xf9, 0x82, 0xd3, 0x54, 0x44, 0x34, 0xf9, 0x85, 0x5f,
+  0xdc, 0xb6, 0x4f, 0xf9, 0xc8, 0x6d, 0x03, 0x00, 0x00, 0x00, 0x61, 0x20,
+  0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00,
+  0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xb4, 0x63, 0x11, 0x40, 0x60, 0x1c,
+  0x73, 0x10, 0x83, 0xb0, 0x2c, 0x44, 0x33, 0x00, 0x14, 0x33, 0x00, 0x63,
+  0x09, 0x20, 0x08, 0x82, 0x20, 0x18, 0x80, 0x20, 0x08, 0x82, 0xe0, 0x30,
+  0x96, 0x00, 0x82, 0x20, 0x88, 0xff, 0x02, 0x08, 0x82, 0x20, 0xfe, 0xcd,
+  0x00, 0x90, 0xcc, 0x41, 0x50, 0xd4, 0x24, 0xd1, 0xcc, 0x00, 0x10, 0x8c,
+  0x11, 0x80, 0x20, 0x08, 0xe2, 0xdf, 0x08, 0xc0, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xd5, 0x4c, 0x57, 0x81, 0xa4, 0x23, 0x06, 0xc4, 0x10, 0x58,
+  0xc1, 0x1c, 0x03, 0x13, 0x54, 0x15, 0x55, 0x3a, 0x62, 0x40, 0x0c, 0x41,
+  0x16, 0xcc, 0x31, 0x0c, 0x41, 0x66, 0xc1, 0x23, 0x1f, 0x0b, 0x1e, 0xf8,
+  0x0c, 0x32, 0x04, 0x0f, 0x35, 0xc8, 0x10, 0x3c, 0xd6, 0x6c, 0xc3, 0x53,
+  0x00, 0xb3, 0x0d, 0x81, 0x10, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00
+};
+const unsigned int FullscreenVert_metallib_len = 2738;
+const unsigned char BlitFrom2D_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0b, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x32, 0x44, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01,
+  0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x38, 0x54, 0x59, 0x43, 0x0e, 0x70,
+  0x93, 0x80, 0x40, 0x9a, 0xd3, 0xbc, 0xb0, 0x0d, 0x08, 0x04, 0x18, 0xb6,
+  0x26, 0x57, 0x8b, 0x4c, 0x00, 0x83, 0xc4, 0x77, 0x0b, 0x6a, 0xf0, 0x3d,
+  0x39, 0xa4, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53,
+  0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00,
+  0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x3d, 0x03,
+  0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00,
+  0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10,
+  0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04,
+  0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10,
+  0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a,
+  0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07,
+  0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00,
+  0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x1b, 0xc2,
+  0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x60, 0x00, 0x09, 0xa8, 0x88,
+  0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77, 0xc0, 0x87, 0x36, 0x30, 0x87,
+  0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87,
+  0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00,
+  0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0xe1, 0x1c, 0xc2,
+  0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4,
+  0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81, 0x1e, 0xd0, 0x01, 0x88, 0x03,
+  0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77, 0x68, 0x03, 0x71, 0xa8, 0x87,
+  0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77, 0x98, 0x07, 0x80, 0x70, 0x87,
+  0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70, 0x68, 0x87, 0x72, 0x68, 0x03,
+  0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a, 0x28, 0x07, 0x79, 0x68, 0x83,
+  0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c, 0xda,
+  0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e, 0xca,
+  0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0xa1, 0x0d, 0xdc,
+  0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xc2, 0xc1, 0x1c, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83,
+  0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83,
+  0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1d, 0xc2, 0xc1, 0x1d, 0xe6,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77, 0x28, 0x07, 0x72, 0x68, 0x03,
+  0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2,
+  0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1, 0x1c, 0xda, 0xa0, 0x1d, 0xc2,
+  0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x88,
+  0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75, 0x68, 0x03, 0x78, 0x90, 0x87,
+  0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x03,
+  0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72, 0x90, 0x87, 0x36, 0x98, 0x87,
+  0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00, 0x20, 0xea, 0xc1, 0x1d, 0xe6,
+  0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda,
+  0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07,
+  0x60, 0x83, 0x21, 0x0c, 0xc0, 0x02, 0x54, 0x1b, 0x8c, 0xa1, 0x00, 0x16,
+  0xa0, 0xda, 0x80, 0x10, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x0c, 0x20,
+  0x01, 0xd5, 0x06, 0xa3, 0x08, 0x80, 0x05, 0xa8, 0x36, 0x18, 0x86, 0x00,
+  0x2c, 0x40, 0xb5, 0xc1, 0x38, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x24,
+  0x80, 0xda, 0x60, 0x20, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x12, 0x40,
+  0x6d, 0x40, 0x92, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x06, 0x90, 0x80,
+  0x0a, 0x00, 0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86,
+  0x40, 0x18, 0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32,
+  0x61, 0x48, 0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x26, 0x00,
+  0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22,
+  0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c,
+  0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x60, 0x33, 0x00, 0xc3, 0x08,
+  0x04, 0x30, 0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45,
+  0x94, 0x30, 0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34,
+  0x88, 0x10, 0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4a, 0x9a, 0x22, 0x4a,
+  0x98, 0xfc, 0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0xdf, 0x1e, 0xfe, 0x69,
+  0x8c, 0x00, 0x18, 0x44, 0x30, 0x82, 0x8b, 0xa4, 0x29, 0xa2, 0x84, 0xc9,
+  0xff, 0x25, 0x80, 0x79, 0x16, 0x22, 0xfa, 0xa7, 0x31, 0x02, 0x60, 0x10,
+  0x01, 0x11, 0x8a, 0x11, 0x44, 0x28, 0x27, 0x91, 0x9a, 0x23, 0x08, 0x86,
+  0x11, 0x84, 0xa1, 0x20, 0xe1, 0x24, 0xc1, 0x1a, 0x03, 0xe4, 0x8a, 0x00,
+  0x06, 0xc1, 0x81, 0x80, 0x14, 0x18, 0x73, 0x04, 0xa0, 0x30, 0x88, 0x20,
+  0x08, 0x83, 0x08, 0x83, 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x13, 0xb2,
+  0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07,
+  0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x76, 0x08, 0x87, 0x71, 0x78, 0x87,
+  0x79, 0xc0, 0x87, 0x38, 0x80, 0x03, 0x37, 0x88, 0x83, 0x38, 0x70, 0x03,
+  0x38, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06, 0xf0, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x90,
+  0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9, 0x80,
+  0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60,
+  0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x90,
+  0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60,
+  0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x73, 0x20, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x74, 0x80,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60,
+  0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80,
+  0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x20,
+  0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20,
+  0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x79, 0x20, 0x07, 0x7a, 0x20,
+  0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60,
+  0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0,
+  0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x50, 0x07, 0x71, 0x20,
+  0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20,
+  0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10,
+  0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40,
+  0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0x30, 0x84, 0x59, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x18, 0xc2, 0x3c, 0x40, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x61, 0x22, 0x20, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2,
+  0x40, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11,
+  0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a, 0x23, 0x00,
+  0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05, 0x53, 0x20, 0x85, 0x52, 0x06,
+  0x44, 0x0b, 0x65, 0x04, 0xa0, 0x40, 0x0a, 0x82, 0xe6, 0x58, 0x82, 0x23,
+  0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x3a, 0x01, 0x00, 0x00, 0x1a, 0x03,
+  0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9, 0xb9, 0xb4,
+  0x37, 0xb7, 0x21, 0xc6, 0x70, 0x48, 0xc0, 0x04, 0x51, 0xb9, 0x1b, 0x43,
+  0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x0c, 0x84, 0x24,
+  0x0c, 0x06, 0xe3, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4, 0xad, 0x8c,
+  0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x0d, 0x64,
+  0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x06, 0x26, 0x06, 0x04, 0xa5, 0xad,
+  0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46, 0x66, 0xc6,
+  0x25, 0x06, 0x26, 0x26, 0x65, 0x88, 0x20, 0x11, 0x43, 0x8c, 0x81, 0x18,
+  0x8a, 0x61, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04, 0x91, 0x8e,
+  0x81, 0x18, 0x88, 0x61, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6,
+  0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36,
+  0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44, 0x90, 0x12,
+  0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+  0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65,
+  0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x69, 0x61, 0x19, 0x84, 0xa5,
+  0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9,
+  0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95,
+  0xd1, 0x8d, 0xa1, 0x7d, 0x91, 0xa5, 0xcd, 0x85, 0x89, 0xb1, 0x95, 0x0d,
+  0x11, 0xa4, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99, 0x1b, 0x59,
+  0x99, 0xdc, 0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3, 0xb0, 0x34,
+  0x39, 0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0x2f, 0xb7,
+  0xb0, 0xb6, 0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x43, 0x10,
+  0xe9, 0x19, 0x06, 0x09, 0x92, 0xa2, 0x21, 0x82, 0x24, 0x51, 0x0a, 0x4b,
+  0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0xfb, 0x4a,
+  0x73, 0x83, 0xab, 0xa3, 0x23, 0x75, 0x56, 0xe6, 0x56, 0x26, 0x17, 0x46,
+  0x57, 0x46, 0x86, 0x32, 0x43, 0x57, 0x86, 0x47, 0x64, 0x27, 0xf3, 0x65,
+  0x96, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d, 0xae, 0x4c,
+  0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9,
+  0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x0d, 0x33, 0xb6, 0xb7, 0x30, 0x3a, 0x19,
+  0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d,
+  0x65, 0x1c, 0xe8, 0xca, 0xf0, 0x86, 0x48, 0xc3, 0x20, 0x51, 0x52, 0x25,
+  0x59, 0xd2, 0x25, 0x41, 0x12, 0x26, 0x65, 0x92, 0x46, 0x26, 0x2c, 0x4d,
+  0xce, 0x05, 0xee, 0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x8d, 0x52, 0x58,
+  0x9a, 0x9c, 0x8b, 0xdb, 0xdb, 0x17, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9,
+  0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x07, 0xb8, 0xb7, 0xb9, 0x21, 0xd0, 0x40,
+  0x48, 0x9c, 0x64, 0x49, 0x9d, 0x04, 0x49, 0x91, 0x94, 0x49, 0x1e, 0x95,
+  0xb0, 0x34, 0x39, 0x17, 0xb1, 0x3a, 0x33, 0xb3, 0x32, 0x39, 0x3e, 0x61,
+  0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69,
+  0x7a, 0x65, 0x94, 0xc2, 0xd2, 0xe4, 0x5c, 0xd8, 0xde, 0xc6, 0xc2, 0xe8,
+  0xd2, 0xde, 0xdc, 0xbe, 0xd2, 0xdc, 0xc8, 0xca, 0xf0, 0x88, 0x84, 0xa5,
+  0xc9, 0xb9, 0xc8, 0x95, 0x85, 0x91, 0x91, 0x0a, 0x4b, 0x93, 0x73, 0x99,
+  0xa3, 0x93, 0xab, 0x1b, 0xa3, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb, 0x4a,
+  0x73, 0x33, 0x7b, 0x63, 0x52, 0x65, 0xc5, 0x54, 0x66, 0x46, 0x47, 0xf5,
+  0x06, 0x47, 0xa6, 0xca, 0x8a, 0x28, 0xad, 0xad, 0xcc, 0x6d, 0x2e, 0xed,
+  0xcd, 0x6d, 0x8e, 0x44, 0x5d, 0x9a, 0x1b, 0x1d, 0x91, 0xa6, 0x34, 0x38,
+  0xa6, 0x32, 0xbb, 0x32, 0x36, 0x16, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x64,
+  0x98, 0xc2, 0xf2, 0xca, 0xe4, 0x9e, 0xe4, 0x88, 0xca, 0xe0, 0xe8, 0xd0,
+  0x86, 0xa0, 0xc1, 0x30, 0x0c, 0xc5, 0x30, 0x48, 0x98, 0x54, 0x06, 0x43,
+  0x31, 0x14, 0xc3, 0x20, 0x61, 0x92, 0x19, 0x0c, 0xc9, 0x60, 0x0c, 0x83,
+  0x74, 0x06, 0x12, 0x1a, 0x0c, 0xca, 0x60, 0x0c, 0x83, 0x94, 0x06, 0x92,
+  0x1a, 0x30, 0x0a, 0x4b, 0x93, 0x73, 0x09, 0x93, 0x3b, 0xfb, 0xa2, 0xcb,
+  0x83, 0x2b, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0xe3, 0x15, 0x96, 0x26, 0xe7,
+  0x12, 0x26, 0x77, 0xf6, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x15, 0xc6, 0x96,
+  0x76, 0xe6, 0xf6, 0x35, 0x97, 0xa6, 0x57, 0x46, 0x66, 0xea, 0xad, 0x4e,
+  0x6e, 0xac, 0x4c, 0xaa, 0xec, 0x2c, 0xed, 0xcd, 0x8d, 0xcc, 0xdc, 0x5b,
+  0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0xdb, 0x10, 0x32,
+  0x18, 0x0e, 0x09, 0x0c, 0xa4, 0x30, 0x18, 0x10, 0x49, 0x0c, 0x86, 0x61,
+  0x20, 0xa4, 0x31, 0x90, 0xc8, 0x40, 0x5a, 0x03, 0x89, 0x0d, 0x06, 0x44,
+  0x6a, 0x83, 0xa1, 0x90, 0x20, 0xc9, 0x0d, 0xa4, 0x4c, 0x7a, 0x03, 0x2e,
+  0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x54,
+  0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0x88, 0xd1,
+  0x95, 0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0xc9, 0x90, 0xf1, 0x98, 0xb1, 0xbd,
+  0x85, 0xd1, 0xb1, 0x80, 0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xf9, 0xb0,
+  0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0xa3, 0x2a, 0xc3, 0xa3, 0xab, 0x93,
+  0x2b, 0x1b, 0x42, 0x0d, 0x8b, 0x14, 0x07, 0x92, 0x18, 0x0c, 0xc3, 0x40,
+  0x48, 0x72, 0x20, 0x41, 0xd2, 0x1c, 0x48, 0x99, 0x44, 0x07, 0x5c, 0xc2,
+  0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x78, 0xcc,
+  0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xc9, 0xb1, 0x99, 0x7b, 0xab, 0x93, 0x1b,
+  0x2b, 0x9b, 0x0a, 0x6b, 0x83, 0x63, 0x2b, 0x93, 0x1b, 0x22, 0x0d, 0x86,
+  0x64, 0x07, 0x92, 0x18, 0x0c, 0xc3, 0x40, 0x48, 0x90, 0x74, 0x07, 0x52,
+  0x26, 0xe1, 0xc1, 0x10, 0x45, 0xda, 0xa4, 0x4f, 0x82, 0x03, 0xa9, 0x0e,
+  0xa4, 0x3c, 0x18, 0x62, 0x2c, 0x80, 0x34, 0x49, 0x7a, 0xc0, 0xe7, 0xad,
+  0xcd, 0x2d, 0x0d, 0xee, 0x8d, 0xae, 0xcc, 0x8d, 0x0e, 0x64, 0x0c, 0x2d,
+  0x4c, 0x8e, 0xcf, 0x54, 0x5a, 0x1b, 0x1c, 0x5b, 0x19, 0xc8, 0xd0, 0xca,
+  0x0a, 0x08, 0x95, 0x50, 0x50, 0xd0, 0x10, 0x41, 0xea, 0x83, 0x21, 0x86,
+  0xc4, 0x07, 0x92, 0x1f, 0x50, 0xcd, 0x10, 0x43, 0xfa, 0x03, 0xe9, 0x0f,
+  0xa8, 0x86, 0xd2, 0x97, 0x16, 0xd5, 0x54, 0x8c, 0xcc, 0xd4, 0x5b, 0x9d,
+  0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0x1b, 0x87, 0x34, 0x37,
+  0xba, 0x21, 0x86, 0x24, 0x0a, 0xd2, 0x1f, 0x50, 0xcd, 0x10, 0x43, 0x4a,
+  0x03, 0xe9, 0x0f, 0xa8, 0x66, 0x88, 0x24, 0x85, 0x82, 0xf4, 0x07, 0x54,
+  0x23, 0xfd, 0x01, 0xf5, 0x48, 0xa3, 0x40, 0x39, 0x12, 0x29, 0x50, 0xcc,
+  0x10, 0x43, 0x2a, 0x05, 0x69, 0x14, 0x28, 0x87, 0x5c, 0x58, 0x9a, 0x5c,
+  0x4b, 0x18, 0x5b, 0x5a, 0xd8, 0x5c, 0xcb, 0xdc, 0xd8, 0x1b, 0x5c, 0xd9,
+  0x1c, 0x8a, 0x10, 0x5b, 0x1a, 0x9d, 0x91, 0xdc, 0x5b, 0x9b, 0x0c, 0x51,
+  0xca, 0x10, 0x42, 0x42, 0x05, 0xe9, 0x14, 0x88, 0x85, 0xa5, 0xc9, 0xb5,
+  0x84, 0xb1, 0xa5, 0x85, 0xcd, 0xb5, 0xcc, 0x8d, 0xbd, 0xc1, 0x95, 0xb5,
+  0xd0, 0x95, 0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0xcd, 0x0d, 0x31, 0x24, 0x55,
+  0x90, 0x50, 0x41, 0x4a, 0x05, 0x62, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c,
+  0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2d, 0x73, 0x61,
+  0x6d, 0x70, 0x6c, 0x65, 0x72, 0x73, 0x43, 0x0c, 0x89, 0x15, 0x24, 0x54,
+  0x90, 0x56, 0x61, 0x08, 0x21, 0xa9, 0x82, 0xc4, 0x0a, 0x23, 0x22, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x77, 0x20, 0x87, 0x7a,
+  0x60, 0x87, 0x72, 0x70, 0x03, 0x73, 0x60, 0x87, 0x70, 0x38, 0x87, 0x79,
+  0x98, 0x22, 0x04, 0xc3, 0x08, 0x85, 0x1d, 0xd8, 0xc1, 0x1e, 0xda, 0xc1,
+  0x0d, 0xd2, 0x81, 0x1c, 0xca, 0xc1, 0x1d, 0xe8, 0x61, 0x4a, 0x50, 0x8c,
+  0x58, 0xc2, 0x21, 0x1d, 0xe4, 0xc1, 0x0d, 0xec, 0xa1, 0x1c, 0xe4, 0x61,
+  0x1e, 0xd2, 0xe1, 0x1d, 0xdc, 0x61, 0x4a, 0x60, 0x8c, 0xa0, 0xc2, 0x21,
+  0x1d, 0xe4, 0xc1, 0x0d, 0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c, 0xea, 0x21,
+  0x1c, 0xce, 0xa1, 0x1c, 0x7e, 0xc1, 0x1e, 0xca, 0x41, 0x1e, 0xe6, 0x21,
+  0x1d, 0xde, 0xc1, 0x1d, 0xa6, 0x04, 0xc8, 0x88, 0x29, 0x1c, 0xd2, 0x41,
+  0x1e, 0xdc, 0x60, 0x1c, 0xde, 0xa1, 0x1d, 0xe0, 0x21, 0x1d, 0xd8, 0xa1,
+  0x1c, 0x7e, 0xe1, 0x1d, 0xe0, 0x81, 0x1e, 0xd2, 0xe1, 0x1d, 0xdc, 0x61,
+  0x1e, 0xa6, 0x0c, 0x0a, 0xe3, 0x8c, 0x60, 0xc2, 0x21, 0x1d, 0xe4, 0xc1,
+  0x0d, 0xcc, 0x41, 0x1e, 0xc2, 0xe1, 0x1c, 0xda, 0xa1, 0x1c, 0xdc, 0x81,
+  0x1e, 0xa6, 0x04, 0x7b, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00,
+  0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01,
+  0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78,
+  0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4,
+  0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c,
+  0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03,
+  0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70,
+  0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70,
+  0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec,
+  0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0,
+  0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d,
+  0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43,
+  0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0,
+  0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68,
+  0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28,
+  0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08,
+  0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee,
+  0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62,
+  0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06,
+  0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3,
+  0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3,
+  0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68,
+  0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce,
+  0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3,
+  0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d,
+  0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e,
+  0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51,
+  0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60,
+  0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98,
+  0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e,
+  0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e,
+  0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83,
+  0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2,
+  0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a,
+  0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28,
+  0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5,
+  0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17,
+  0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83,
+  0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3,
+  0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48,
+  0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58,
+  0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0,
+  0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e,
+  0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9,
+  0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c,
+  0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d,
+  0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d,
+  0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58,
+  0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48,
+  0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0,
+  0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4,
+  0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30,
+  0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8,
+  0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x16, 0xb0,
+  0x01, 0x48, 0xe4, 0x4b, 0x00, 0xf3, 0x2c, 0xc4, 0x3f, 0x11, 0xd7, 0x44,
+  0x45, 0xc4, 0x6f, 0x0f, 0x7e, 0x85, 0x17, 0xb7, 0x6d, 0x00, 0xca, 0xb6,
+  0x20, 0xd3, 0x17, 0x39, 0x8c, 0xdd, 0x99, 0xc0, 0x05, 0x20, 0x91, 0x2f,
+  0x38, 0x4d, 0x45, 0x44, 0x93, 0x5f, 0xf8, 0xc5, 0x6d, 0xfb, 0x94, 0x8f,
+  0xdc, 0x36, 0x00, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x18, 0x00,
+  0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00,
+  0x00, 0x00, 0xc4, 0x6a, 0x80, 0xda, 0x08, 0x00, 0x00, 0x00, 0xe3, 0x0d,
+  0xc5, 0x52, 0x51, 0x40, 0xc6, 0x1b, 0x8e, 0xc6, 0xa2, 0x80, 0x58, 0xb0,
+  0xc8, 0xc7, 0x02, 0x02, 0x3e, 0xe3, 0x0d, 0x4b, 0x74, 0x51, 0x40, 0x46,
+  0x0c, 0x08, 0x22, 0xf0, 0x82, 0x11, 0x03, 0xa5, 0x08, 0xc0, 0xa0, 0x61,
+  0x88, 0x45, 0x59, 0x82, 0x0c, 0x02, 0x62, 0x00, 0x00, 0x00, 0x05, 0x00,
+  0x00, 0x00, 0x5b, 0x86, 0x20, 0x00, 0x85, 0x2d, 0xc3, 0x10, 0x80, 0xc2,
+  0x96, 0xe1, 0x08, 0x4c, 0x61, 0xcb, 0x90, 0x1c, 0xad, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom2D_metallib_len = 3582;
+const unsigned char BlitFrom2DArray_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x53, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x10, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x32, 0x44, 0x41, 0x72, 0x72, 0x61, 0x79, 0x00, 0x54, 0x59,
+  0x50, 0x45, 0x01, 0x00, 0x01, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0xb1,
+  0x0c, 0xe0, 0xbe, 0x6d, 0x0a, 0x5e, 0xb6, 0xf9, 0x62, 0x0a, 0x25, 0x81,
+  0x8c, 0x07, 0x8b, 0x66, 0x48, 0xa9, 0xf7, 0xb1, 0x6f, 0xa7, 0xfd, 0x47,
+  0x3f, 0x88, 0x53, 0x23, 0x50, 0x2c, 0xfb, 0x4f, 0x46, 0x46, 0x54, 0x18,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01,
+  0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45,
+  0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde,
+  0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x5c,
+  0x0d, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21,
+  0x0c, 0x00, 0x00, 0x54, 0x03, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41,
+  0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25,
+  0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42,
+  0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a,
+  0x32, 0x44, 0x24, 0x48, 0x0a, 0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c,
+  0x19, 0x21, 0x72, 0x24, 0x07, 0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8,
+  0x40, 0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x79,
+  0x00, 0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x60, 0x00, 0x09, 0xa8, 0x88, 0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77,
+  0xc0, 0x87, 0x36, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73,
+  0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41,
+  0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80,
+  0x1d, 0xca, 0xe1, 0x1c, 0xc2, 0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61,
+  0x1c, 0xe8, 0xe1, 0x1d, 0xe4, 0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81,
+  0x1e, 0xd0, 0x01, 0x88, 0x03, 0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77,
+  0x68, 0x03, 0x71, 0xa8, 0x87, 0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77,
+  0x98, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70,
+  0x68, 0x87, 0x72, 0x68, 0x03, 0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a,
+  0x28, 0x07, 0x79, 0x68, 0x83, 0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80,
+  0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0,
+  0x1c, 0xe4, 0x21, 0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21,
+  0x1d, 0xdc, 0x81, 0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21,
+  0x1d, 0xda, 0xa1, 0x0d, 0xdc, 0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1,
+  0x1c, 0xc2, 0xc1, 0x1c, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80,
+  0x70, 0x87, 0x77, 0x68, 0x83, 0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36,
+  0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80,
+  0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0,
+  0x1d, 0xc2, 0xc1, 0x1d, 0xe6, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0,
+  0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72,
+  0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77,
+  0x28, 0x07, 0x72, 0x68, 0x03, 0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79,
+  0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74,
+  0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1,
+  0x0d, 0xe8, 0x41, 0x1e, 0xc2, 0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1,
+  0x1c, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79,
+  0xa8, 0x87, 0x72, 0x00, 0x88, 0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75,
+  0x68, 0x03, 0x78, 0x90, 0x87, 0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a,
+  0x78, 0x07, 0x79, 0x68, 0x03, 0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72,
+  0x90, 0x87, 0x36, 0x98, 0x87, 0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00,
+  0x20, 0xea, 0xc1, 0x1d, 0xe6, 0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0,
+  0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a,
+  0x90, 0x87, 0x7a, 0x28, 0x07, 0x60, 0x83, 0x21, 0x0c, 0xc0, 0x02, 0x54,
+  0x1b, 0x8c, 0xa1, 0x00, 0x16, 0xa0, 0xda, 0x80, 0x10, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x0c, 0x20, 0x01, 0xd5, 0x06, 0xa3, 0x08, 0x80, 0x05,
+  0xa8, 0x36, 0x18, 0x86, 0x00, 0x2c, 0x40, 0xb5, 0xc1, 0x38, 0xfe, 0xff,
+  0xff, 0xff, 0x7f, 0x00, 0x24, 0x80, 0xda, 0x60, 0x20, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x12, 0x40, 0x6d, 0x40, 0x92, 0xff, 0xff, 0xff, 0xff,
+  0x1f, 0x00, 0x06, 0x90, 0x80, 0x0a, 0x00, 0x49, 0x18, 0x00, 0x00, 0x05,
+  0x00, 0x00, 0x00, 0x13, 0x86, 0x40, 0x18, 0x26, 0x0c, 0x44, 0x61, 0x4c,
+  0x08, 0x8e, 0x09, 0x01, 0x32, 0x61, 0x48, 0x0a, 0x03, 0x00, 0x00, 0x89,
+  0x20, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20,
+  0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84,
+  0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10,
+  0x6c, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x30, 0x8c, 0x20, 0x00, 0x73, 0x04,
+  0x60, 0x70, 0x93, 0x34, 0x45, 0x94, 0x30, 0xf9, 0xac, 0x43, 0x45, 0x02,
+  0xb1, 0x12, 0x06, 0xe2, 0x34, 0x88, 0x10, 0x62, 0x80, 0x41, 0x04, 0x42,
+  0x38, 0x4d, 0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x7f, 0x22, 0xae, 0x89, 0x8a,
+  0x88, 0xdf, 0x1e, 0x7e, 0x20, 0x8a, 0x00, 0xec, 0x9f, 0xc6, 0x08, 0x80,
+  0x41, 0x04, 0x23, 0xb8, 0x48, 0x9a, 0x22, 0x4a, 0x98, 0xfc, 0x5f, 0x02,
+  0x98, 0x67, 0x21, 0xa2, 0x7f, 0x1a, 0x23, 0x00, 0x06, 0x11, 0x10, 0xa1,
+  0x18, 0x41, 0x84, 0x72, 0x12, 0xa9, 0x39, 0x82, 0x60, 0x18, 0x41, 0x18,
+  0x4a, 0x12, 0x4e, 0x12, 0x83, 0x35, 0x06, 0xc8, 0x15, 0x01, 0x0c, 0x82,
+  0x45, 0x18, 0x80, 0xe4, 0x40, 0x40, 0x0a, 0x8c, 0x39, 0x02, 0x50, 0x18,
+  0x44, 0x10, 0x84, 0x41, 0x04, 0x40, 0x18, 0x44, 0x18, 0x84, 0x11, 0x00,
+  0x00, 0x00, 0x00, 0x13, 0xb2, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a,
+  0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x76,
+  0x08, 0x87, 0x71, 0x78, 0x87, 0x79, 0xc0, 0x87, 0x38, 0x80, 0x03, 0x37,
+  0x88, 0x83, 0x38, 0x70, 0x03, 0x38, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06,
+  0xf0, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07,
+  0x78, 0xd0, 0x06, 0xe9, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07,
+  0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x6d, 0x90, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x60, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x60, 0x0f, 0x74, 0x80, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07,
+  0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07,
+  0x6d, 0x60, 0x0f, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07,
+  0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07,
+  0x79, 0x20, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07,
+  0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07,
+  0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06,
+  0xf6, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07,
+  0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07,
+  0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07,
+  0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0x30, 0x84, 0x59, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc2, 0x3c, 0x40, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x61, 0x22, 0x20, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x86, 0x30, 0x13, 0x10, 0x00, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x59, 0x20, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x32,
+  0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6,
+  0x04, 0x43, 0x1a, 0x23, 0x00, 0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05,
+  0x53, 0x20, 0x85, 0x52, 0x06, 0x64, 0x0b, 0x62, 0x04, 0xa0, 0x40, 0x0a,
+  0x85, 0xea, 0x58, 0x82, 0x23, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x3f,
+  0x01, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10,
+  0xab, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x80, 0x50, 0x40,
+  0x15, 0x51, 0xb9, 0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b,
+  0x1b, 0x62, 0x0c, 0x05, 0x25, 0x0c, 0x07, 0xe3, 0x20, 0x08, 0x0e, 0x8e,
+  0xad, 0x0c, 0xa4, 0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e,
+  0x2e, 0xed, 0xcd, 0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x06,
+  0x26, 0x06, 0x04, 0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65,
+  0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x06, 0x26, 0x26, 0x65, 0x88, 0x40,
+  0x11, 0x43, 0x8c, 0xa1, 0x18, 0x8c, 0x81, 0x60, 0xd1, 0x54, 0x46, 0x17,
+  0xc6, 0x36, 0x04, 0xa1, 0x8e, 0xa1, 0x18, 0x8a, 0x81, 0xe0, 0x16, 0x96,
+  0x26, 0xe7, 0x32, 0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56,
+  0xe6, 0xf6, 0x26, 0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6,
+  0x56, 0x36, 0x44, 0xa0, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f,
+  0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d,
+  0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x04,
+  0x6a, 0x61, 0x19, 0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5,
+  0xb1, 0x95, 0xb9, 0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99,
+  0x95, 0xc9, 0x7d, 0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x91, 0xa5, 0xcd,
+  0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11, 0xa8, 0x86, 0x51, 0x58, 0x9a, 0x9c,
+  0x8b, 0x5c, 0x99, 0x1b, 0x59, 0x99, 0xdc, 0x17, 0x5d, 0x98, 0xdc, 0x59,
+  0x19, 0x1d, 0xa3, 0xb0, 0x34, 0x39, 0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba,
+  0x3c, 0xb8, 0xb2, 0x2f, 0xb7, 0xb0, 0xb6, 0x32, 0x1a, 0x66, 0x6c, 0x6f,
+  0x61, 0x74, 0x34, 0x43, 0x10, 0xea, 0x19, 0x08, 0x0a, 0xa2, 0xa2, 0x21,
+  0x02, 0x25, 0x51, 0x0a, 0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b,
+  0x2b, 0x73, 0xa3, 0xfb, 0x4a, 0x73, 0x83, 0xab, 0xa3, 0x23, 0x75, 0x56,
+  0xe6, 0x56, 0x26, 0x17, 0x46, 0x57, 0x46, 0x86, 0x32, 0x43, 0x57, 0x86,
+  0x47, 0x64, 0x27, 0xf3, 0x65, 0x96, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65,
+  0xac, 0xcc, 0x8d, 0xae, 0x4c, 0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c,
+  0x99, 0xdc, 0x1c, 0x5c, 0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x0d, 0x33,
+  0xb6, 0xb7, 0x30, 0x3a, 0x19, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72,
+  0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x1c, 0xe8, 0xca, 0xf0, 0x86, 0x48,
+  0x03, 0x41, 0x51, 0x54, 0x45, 0x59, 0xd4, 0x45, 0x41, 0x14, 0x46, 0x65,
+  0x94, 0x46, 0x26, 0x2c, 0x4d, 0xce, 0x05, 0xee, 0x6d, 0x2e, 0x8d, 0x2e,
+  0xed, 0xcd, 0x8d, 0x52, 0x58, 0x9a, 0x9c, 0x8b, 0xdb, 0xdb, 0x17, 0x5c,
+  0x99, 0xdc, 0x1c, 0x5c, 0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x07, 0xb8,
+  0xb7, 0xb9, 0x21, 0xd0, 0x50, 0x50, 0x1c, 0x65, 0x51, 0x1d, 0x05, 0x51,
+  0x11, 0x95, 0x51, 0x1e, 0x95, 0xb0, 0x34, 0x39, 0x17, 0xb1, 0x3a, 0x33,
+  0xb3, 0x32, 0x39, 0x3e, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66,
+  0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x94, 0xc2, 0xd2, 0xe4, 0x5c,
+  0xd8, 0xde, 0xc6, 0xc2, 0xe8, 0xd2, 0xde, 0xdc, 0xbe, 0xd2, 0xdc, 0xc8,
+  0xca, 0xf0, 0x88, 0x84, 0xa5, 0xc9, 0xb9, 0xc8, 0x95, 0x85, 0x91, 0x91,
+  0x0a, 0x4b, 0x93, 0x73, 0x99, 0xa3, 0x93, 0xab, 0x1b, 0xa3, 0xfb, 0xa2,
+  0xcb, 0x83, 0x2b, 0xfb, 0x4a, 0x73, 0x33, 0x7b, 0x63, 0x52, 0x65, 0xc5,
+  0x54, 0x66, 0x46, 0x47, 0xf5, 0x06, 0x47, 0xa6, 0xca, 0x8a, 0x28, 0xad,
+  0xad, 0xcc, 0x6d, 0x2e, 0xed, 0xcd, 0x6d, 0x8e, 0x44, 0x5d, 0x9a, 0x1b,
+  0x1d, 0x91, 0xa6, 0x34, 0x38, 0xa6, 0x32, 0xbb, 0x32, 0x36, 0x16, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x64, 0x98, 0xc2, 0xf2, 0xca, 0xe4, 0x9e, 0xe4,
+  0x88, 0xca, 0xe0, 0xe8, 0xd0, 0x86, 0xa0, 0xc1, 0x40, 0x0c, 0xc6, 0x40,
+  0x50, 0x18, 0x55, 0x06, 0x83, 0x31, 0x18, 0x03, 0x41, 0x61, 0x94, 0x19,
+  0x0c, 0xca, 0x70, 0x0c, 0x04, 0x75, 0x06, 0x14, 0x1a, 0x0c, 0xcb, 0x70,
+  0x0c, 0x04, 0x95, 0x06, 0x94, 0x1a, 0x30, 0x0a, 0x4b, 0x93, 0x73, 0x09,
+  0x93, 0x3b, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b,
+  0xe3, 0x15, 0x96, 0x26, 0xe7, 0x12, 0x26, 0x77, 0xf6, 0x45, 0x97, 0x07,
+  0x57, 0xf6, 0x15, 0xc6, 0x96, 0x76, 0xe6, 0xf6, 0x35, 0x97, 0xa6, 0x57,
+  0x46, 0x66, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x4c, 0xaa, 0xec, 0x2c, 0xed,
+  0xcd, 0x8d, 0xcc, 0xdc, 0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59,
+  0xda, 0x9b, 0xdb, 0x10, 0x32, 0x18, 0x10, 0x0a, 0x0c, 0xa8, 0x30, 0x18,
+  0x12, 0x4a, 0x0c, 0x06, 0x62, 0x28, 0xa8, 0x31, 0xa0, 0xc8, 0x80, 0x5a,
+  0x03, 0x8a, 0x0d, 0x86, 0x84, 0x6a, 0x83, 0xc1, 0xa0, 0x20, 0xca, 0x0d,
+  0xa8, 0x8c, 0x7a, 0x03, 0x2e, 0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78,
+  0x74, 0x75, 0x72, 0x65, 0x54, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda,
+  0xe0, 0xd8, 0xca, 0xe8, 0xd1, 0x95, 0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0xc9,
+  0x90, 0x7d, 0x85, 0xc9, 0xc9, 0x85, 0xe5, 0xf1, 0x98, 0xb1, 0xbd, 0x85,
+  0xd1, 0xb1, 0x80, 0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xf9, 0xb0, 0x99,
+  0x7b, 0xab, 0x93, 0x1b, 0x2b, 0xa3, 0x2a, 0xc3, 0xa3, 0xab, 0x93, 0x2b,
+  0x1b, 0x42, 0x0d, 0x0c, 0x15, 0x07, 0x94, 0x18, 0x0c, 0xc4, 0x50, 0x50,
+  0x72, 0x40, 0x41, 0xd4, 0x1c, 0x50, 0x19, 0x45, 0x07, 0x5c, 0xc2, 0xd2,
+  0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x78, 0xcc, 0x85,
+  0xb5, 0xc1, 0xb1, 0x95, 0xc9, 0xb1, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b,
+  0x9b, 0x0a, 0x6b, 0x83, 0x63, 0x2b, 0x93, 0x1b, 0x22, 0x0d, 0x07, 0x65,
+  0x07, 0x94, 0x18, 0x0c, 0xc4, 0x50, 0x50, 0x10, 0x75, 0x07, 0x54, 0x46,
+  0xe1, 0xc1, 0x10, 0x85, 0xda, 0xa8, 0x8f, 0x82, 0x03, 0xaa, 0x0e, 0xa8,
+  0x3c, 0x18, 0x62, 0x2c, 0x00, 0x35, 0x51, 0x7a, 0xc0, 0xe7, 0xad, 0xcd,
+  0x2d, 0x0d, 0xee, 0x8d, 0xae, 0xcc, 0x8d, 0x0e, 0x64, 0x0c, 0x2d, 0x4c,
+  0x8e, 0xcf, 0x54, 0x5a, 0x1b, 0x1c, 0x5b, 0x19, 0xc8, 0xd0, 0xca, 0x0a,
+  0x08, 0x95, 0x50, 0x50, 0xd0, 0x10, 0x81, 0xea, 0x83, 0x21, 0x06, 0xc5,
+  0x07, 0x94, 0x1f, 0x58, 0xce, 0x10, 0x83, 0xfa, 0x03, 0xea, 0x0f, 0x2c,
+  0x87, 0xd2, 0x97, 0x16, 0xd5, 0x54, 0x8c, 0xcc, 0xd4, 0x5b, 0x9d, 0xdc,
+  0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0x1b, 0x87, 0x34, 0x37, 0xba,
+  0x21, 0x06, 0x25, 0x0a, 0xd4, 0x1f, 0x58, 0xce, 0x10, 0x83, 0x4a, 0x03,
+  0xea, 0x0f, 0x2c, 0x67, 0x88, 0x44, 0x85, 0x02, 0xf5, 0x07, 0x96, 0x43,
+  0xfd, 0x81, 0xd5, 0x50, 0xa3, 0x60, 0x3d, 0x14, 0x29, 0x58, 0xd0, 0x10,
+  0x83, 0x2a, 0x05, 0x8a, 0x14, 0x2c, 0x68, 0x88, 0x41, 0x95, 0x02, 0x35,
+  0x0a, 0xd6, 0xc3, 0x30, 0x08, 0x4b, 0x93, 0x6b, 0x09, 0x63, 0x4b, 0x0b,
+  0x9b, 0x6b, 0x99, 0x1b, 0x7b, 0x83, 0x2b, 0x9b, 0x43, 0x11, 0x62, 0x4b,
+  0xa3, 0x33, 0x92, 0x7b, 0x6b, 0x93, 0x21, 0x0a, 0x92, 0x93, 0x0b, 0xcb,
+  0x4b, 0x19, 0x42, 0x50, 0xa9, 0x40, 0xa1, 0x02, 0xb1, 0xb0, 0x34, 0xb9,
+  0x96, 0x30, 0xb6, 0xb4, 0xb0, 0xb9, 0x96, 0xb9, 0xb1, 0x37, 0xb8, 0xb2,
+  0x16, 0xba, 0x32, 0x3c, 0xba, 0x3a, 0xb9, 0xb2, 0xb9, 0x21, 0x06, 0xb5,
+  0x0a, 0x54, 0x2a, 0x50, 0xaa, 0x40, 0x2c, 0x2c, 0x4d, 0xae, 0x25, 0x8c,
+  0x2d, 0x2d, 0x6c, 0xae, 0x65, 0x6e, 0xec, 0x0d, 0xae, 0xac, 0x65, 0x2e,
+  0xac, 0x0d, 0x8e, 0xad, 0x4c, 0x6e, 0x6e, 0x88, 0x41, 0xb5, 0x02, 0x95,
+  0x0a, 0x14, 0x2b, 0x0c, 0x21, 0xa8, 0x55, 0xa0, 0x5a, 0x61, 0x44, 0xc4,
+  0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xed, 0xf0, 0x0e, 0xe4, 0x50,
+  0x0f, 0xec, 0x50, 0x0e, 0x6e, 0x60, 0x0e, 0xec, 0x10, 0x0e, 0xe7, 0x30,
+  0x0f, 0x53, 0x84, 0x60, 0x18, 0xa1, 0xb0, 0x03, 0x3b, 0xd8, 0x43, 0x3b,
+  0xb8, 0x41, 0x3a, 0x90, 0x43, 0x39, 0xb8, 0x03, 0x3d, 0x4c, 0x09, 0x8a,
+  0x11, 0x4b, 0x38, 0xa4, 0x83, 0x3c, 0xb8, 0x81, 0x3d, 0x94, 0x83, 0x3c,
+  0xcc, 0x43, 0x3a, 0xbc, 0x83, 0x3b, 0x4c, 0x09, 0x8c, 0x11, 0x54, 0x38,
+  0xa4, 0x83, 0x3c, 0xb8, 0x01, 0x3b, 0x84, 0x83, 0x3b, 0x9c, 0x43, 0x3d,
+  0x84, 0xc3, 0x39, 0x94, 0xc3, 0x2f, 0xd8, 0x43, 0x39, 0xc8, 0xc3, 0x3c,
+  0xa4, 0xc3, 0x3b, 0xb8, 0xc3, 0x94, 0x00, 0x19, 0x31, 0x85, 0x43, 0x3a,
+  0xc8, 0x83, 0x1b, 0x8c, 0xc3, 0x3b, 0xb4, 0x03, 0x3c, 0xa4, 0x03, 0x3b,
+  0x94, 0xc3, 0x2f, 0xbc, 0x03, 0x3c, 0xd0, 0x43, 0x3a, 0xbc, 0x83, 0x3b,
+  0xcc, 0xc3, 0x94, 0x41, 0x61, 0x9c, 0x11, 0x4c, 0x38, 0xa4, 0x83, 0x3c,
+  0xb8, 0x81, 0x39, 0xc8, 0x43, 0x38, 0x9c, 0x43, 0x3b, 0x94, 0x83, 0x3b,
+  0xd0, 0xc3, 0x94, 0x60, 0x0f, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74,
+  0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19,
+  0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e,
+  0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28,
+  0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81,
+  0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18,
+  0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78,
+  0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a,
+  0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01,
+  0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85,
+  0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc,
+  0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5,
+  0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a,
+  0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e,
+  0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1,
+  0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0,
+  0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc,
+  0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc,
+  0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71,
+  0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06,
+  0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e,
+  0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06,
+  0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61,
+  0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21,
+  0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20,
+  0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc,
+  0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a,
+  0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e,
+  0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e,
+  0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37,
+  0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77,
+  0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16,
+  0x10, 0x06, 0x00, 0x12, 0xf9, 0x12, 0xc0, 0x3c, 0x0b, 0xf1, 0x4f, 0xc4,
+  0x35, 0x51, 0x11, 0xf1, 0xdb, 0xc3, 0x0f, 0x44, 0x11, 0x80, 0xf9, 0x15,
+  0x5e, 0xdc, 0xb6, 0x01, 0x3c, 0xdb, 0x82, 0x4c, 0x5f, 0xe4, 0x30, 0x76,
+  0xa7, 0x45, 0x11, 0x80, 0x99, 0xc0, 0x05, 0x20, 0x91, 0x2f, 0x38, 0x4d,
+  0x45, 0x44, 0x93, 0x5f, 0xf8, 0xc5, 0x6d, 0xfb, 0x94, 0x8f, 0xdc, 0xb6,
+  0x0d, 0x5c, 0x00, 0x12, 0xf9, 0x82, 0xd3, 0x54, 0x44, 0x34, 0xf9, 0x94,
+  0x8f, 0xdc, 0xb6, 0x5f, 0xf8, 0xc5, 0x6d, 0x03, 0x00, 0x00, 0x00, 0x61,
+  0x20, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10,
+  0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc4, 0x6a, 0x80, 0xda, 0x08,
+  0x00, 0x00, 0x00, 0xe3, 0x0d, 0xc5, 0x52, 0x51, 0x40, 0xc6, 0x1b, 0x8e,
+  0xc6, 0xa2, 0x80, 0x58, 0xb0, 0xc8, 0xc7, 0x02, 0x02, 0x3e, 0xe3, 0x0d,
+  0x4b, 0x34, 0x51, 0x30, 0x46, 0x0c, 0x08, 0x22, 0xf0, 0x82, 0xf1, 0x06,
+  0x87, 0xd2, 0x28, 0x20, 0x23, 0x06, 0x04, 0x11, 0x88, 0x41, 0x30, 0x62,
+  0xb0, 0x14, 0x01, 0x19, 0x40, 0xcf, 0x41, 0x38, 0x8d, 0x13, 0x64, 0x10,
+  0x10, 0x03, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5b, 0x86, 0x20, 0x00, 0x85,
+  0x2d, 0xc3, 0x10, 0x80, 0xc2, 0x96, 0xe1, 0x08, 0x4c, 0x61, 0xcb, 0xa0,
+  0x04, 0xa7, 0xb0, 0x65, 0x60, 0x0e, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom2DArray_metallib_len = 3667;
+const unsigned char BlitFrom3D_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x2e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0b, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x33, 0x44, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01,
+  0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x78, 0x53, 0x9f, 0xfc, 0x6a, 0x9b,
+  0x5a, 0x81, 0x64, 0xb4, 0xce, 0x81, 0xaf, 0x0e, 0x37, 0x55, 0xd4, 0x37,
+  0xea, 0x09, 0x10, 0xd5, 0xa5, 0x4b, 0x22, 0x30, 0xc5, 0xd7, 0x29, 0xbb,
+  0x60, 0x58, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53,
+  0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00,
+  0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x30, 0x0d, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x49, 0x03,
+  0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00,
+  0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10,
+  0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04,
+  0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10,
+  0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a,
+  0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07,
+  0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00,
+  0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x1b, 0xc2,
+  0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x60, 0x00, 0x09, 0xa8, 0x88,
+  0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77, 0xc0, 0x87, 0x36, 0x30, 0x87,
+  0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87,
+  0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00,
+  0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0xe1, 0x1c, 0xc2,
+  0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4,
+  0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81, 0x1e, 0xd0, 0x01, 0x88, 0x03,
+  0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77, 0x68, 0x03, 0x71, 0xa8, 0x87,
+  0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77, 0x98, 0x07, 0x80, 0x70, 0x87,
+  0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70, 0x68, 0x87, 0x72, 0x68, 0x03,
+  0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a, 0x28, 0x07, 0x79, 0x68, 0x83,
+  0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c, 0xda,
+  0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e, 0xca,
+  0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0xa1, 0x0d, 0xdc,
+  0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xc2, 0xc1, 0x1c, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83,
+  0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83,
+  0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1d, 0xc2, 0xc1, 0x1d, 0xe6,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87,
+  0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77, 0x28, 0x07, 0x72, 0x68, 0x03,
+  0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2,
+  0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1, 0x1c, 0xda, 0xa0, 0x1d, 0xc2,
+  0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x88,
+  0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75, 0x68, 0x03, 0x78, 0x90, 0x87,
+  0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x03,
+  0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72, 0x90, 0x87, 0x36, 0x98, 0x87,
+  0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00, 0x20, 0xea, 0xc1, 0x1d, 0xe6,
+  0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda,
+  0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07,
+  0x60, 0x83, 0x21, 0x0c, 0xc0, 0x02, 0x54, 0x1b, 0x8c, 0xa1, 0x00, 0x16,
+  0xa0, 0xda, 0x80, 0x10, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x0c, 0x20,
+  0x01, 0xd5, 0x06, 0xa3, 0x08, 0x80, 0x05, 0xa8, 0x36, 0x18, 0x86, 0x00,
+  0x2c, 0x40, 0xb5, 0xc1, 0x38, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x24,
+  0x80, 0xda, 0x60, 0x20, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x12, 0x40,
+  0x6d, 0x40, 0x92, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x06, 0x90, 0x80,
+  0x0a, 0x00, 0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x13, 0x86,
+  0x40, 0x18, 0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09, 0x01, 0x32,
+  0x61, 0x48, 0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x27, 0x00,
+  0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22,
+  0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c,
+  0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x68, 0x33, 0x00, 0xc3, 0x08,
+  0x04, 0x30, 0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93, 0x34, 0x45,
+  0x94, 0x30, 0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06, 0xe2, 0x34,
+  0x88, 0x10, 0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4a, 0x9a, 0x22, 0x4a,
+  0x98, 0xfc, 0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0xff, 0x1e, 0xfe, 0x69,
+  0x8c, 0x00, 0x18, 0x44, 0x30, 0x82, 0x8b, 0xa4, 0x29, 0xa2, 0x84, 0xc9,
+  0xff, 0x25, 0x80, 0x79, 0x16, 0x22, 0xfa, 0xa7, 0x31, 0x02, 0x60, 0x10,
+  0x01, 0x11, 0x8a, 0x11, 0x44, 0x28, 0x27, 0x91, 0x1a, 0x46, 0x18, 0x80,
+  0x39, 0x82, 0x60, 0x18, 0x61, 0x18, 0x0a, 0x12, 0x4e, 0x62, 0xcd, 0x35,
+  0x40, 0xaf, 0x08, 0x60, 0x50, 0x1c, 0x08, 0x48, 0x81, 0x31, 0x47, 0x00,
+  0x0a, 0x83, 0x08, 0x82, 0x30, 0x88, 0x00, 0x08, 0x83, 0x08, 0x83, 0x30,
+  0x02, 0x00, 0x13, 0xb2, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68,
+  0x83, 0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x76, 0x08,
+  0x87, 0x71, 0x78, 0x87, 0x79, 0xc0, 0x87, 0x38, 0x80, 0x03, 0x37, 0x88,
+  0x83, 0x38, 0x70, 0x03, 0x38, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06, 0xf0,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78,
+  0xd0, 0x06, 0xe9, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d,
+  0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71,
+  0x60, 0x07, 0x6d, 0x90, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x60, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x60, 0x0f, 0x74, 0x80, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x6d, 0x60, 0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07, 0x7a,
+  0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d,
+  0x60, 0x0f, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78,
+  0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x79,
+  0x20, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75,
+  0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72,
+  0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6,
+  0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a,
+  0x50, 0x07, 0x71, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07, 0x72,
+  0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x71,
+  0x00, 0x07, 0x72, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71,
+  0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0x30, 0x84, 0x59, 0x00, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc2, 0x40, 0x40, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0c, 0x61, 0x24, 0x20, 0x00, 0x06, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xb2, 0x40, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e,
+  0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04,
+  0x43, 0x1a, 0x23, 0x00, 0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05, 0x53,
+  0x20, 0x85, 0x52, 0x06, 0x54, 0x0b, 0x62, 0x04, 0xa0, 0x40, 0x0a, 0x85,
+  0xe8, 0x58, 0x82, 0x23, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x3c, 0x01,
+  0x00, 0x00, 0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab,
+  0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x70, 0x4c, 0x00, 0x05,
+  0x51, 0xb9, 0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b,
+  0x62, 0x0c, 0xc4, 0x24, 0x0c, 0x06, 0xe3, 0x20, 0x08, 0x0e, 0x8e, 0xad,
+  0x0c, 0xa4, 0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e,
+  0xed, 0xcd, 0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x06, 0x26,
+  0x06, 0x04, 0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46,
+  0x06, 0x46, 0x66, 0xc6, 0x25, 0x06, 0x26, 0x26, 0x65, 0x88, 0x30, 0x11,
+  0x43, 0x8c, 0x81, 0x18, 0x8a, 0x61, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6,
+  0x36, 0x04, 0x99, 0x8e, 0x81, 0x18, 0x88, 0x61, 0xe0, 0x16, 0x96, 0x26,
+  0xe7, 0x32, 0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6,
+  0xf6, 0x26, 0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56,
+  0x36, 0x44, 0x98, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
+  0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61,
+  0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x84, 0x69,
+  0x61, 0x19, 0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1,
+  0x95, 0xb9, 0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95,
+  0xc9, 0x7d, 0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x91, 0xa5, 0xcd, 0x85,
+  0x89, 0xb1, 0x95, 0x0d, 0x11, 0xa6, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b,
+  0x5c, 0x99, 0x1b, 0x59, 0x99, 0xdc, 0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19,
+  0x1d, 0xa3, 0xb0, 0x34, 0x39, 0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c,
+  0xb8, 0xb2, 0x2f, 0xb7, 0xb0, 0xb6, 0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61,
+  0x74, 0x34, 0x43, 0x90, 0xe9, 0x19, 0x86, 0x09, 0x9a, 0xa2, 0x21, 0xc2,
+  0x24, 0x51, 0x0a, 0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b,
+  0x73, 0xa3, 0xfb, 0x4a, 0x73, 0x83, 0xab, 0xa3, 0x23, 0x75, 0x56, 0xe6,
+  0x56, 0x26, 0x17, 0x46, 0x57, 0x46, 0x86, 0x32, 0x43, 0x57, 0x86, 0x47,
+  0x64, 0x27, 0xf3, 0x65, 0x96, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac,
+  0xcc, 0x8d, 0xae, 0x4c, 0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99,
+  0xdc, 0x1c, 0x5c, 0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x0d, 0x33, 0xb6,
+  0xb7, 0x30, 0x3a, 0x19, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67,
+  0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x1c, 0xe8, 0xca, 0xf0, 0x86, 0x48, 0xc3,
+  0x30, 0x51, 0x53, 0x35, 0x59, 0xd3, 0x35, 0x41, 0x13, 0x36, 0x65, 0x93,
+  0x46, 0x26, 0x2c, 0x4d, 0xce, 0x05, 0xee, 0x6d, 0x2e, 0x8d, 0x2e, 0xed,
+  0xcd, 0x8d, 0x52, 0x58, 0x9a, 0x9c, 0x8b, 0xdb, 0xdb, 0x17, 0x5c, 0x99,
+  0xdc, 0x1c, 0x5c, 0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x07, 0xb8, 0xb7,
+  0xb9, 0x21, 0xd0, 0x40, 0x4c, 0xdc, 0x64, 0x4d, 0xdd, 0x04, 0x4d, 0xd1,
+  0x94, 0x4d, 0x1e, 0x95, 0xb0, 0x34, 0x39, 0x17, 0xb1, 0x3a, 0x33, 0xb3,
+  0x32, 0x39, 0x3e, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65,
+  0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x94, 0xc2, 0xd2, 0xe4, 0x5c, 0xd8,
+  0xde, 0xc6, 0xc2, 0xe8, 0xd2, 0xde, 0xdc, 0xbe, 0xd2, 0xdc, 0xc8, 0xca,
+  0xf0, 0x88, 0x84, 0xa5, 0xc9, 0xb9, 0xc8, 0x95, 0x85, 0x91, 0x91, 0x0a,
+  0x4b, 0x93, 0x73, 0x99, 0xa3, 0x93, 0xab, 0x1b, 0xa3, 0xfb, 0xa2, 0xcb,
+  0x83, 0x2b, 0xfb, 0x4a, 0x73, 0x33, 0x7b, 0x63, 0x52, 0x65, 0xc5, 0x54,
+  0x66, 0x46, 0x47, 0xf5, 0x06, 0x47, 0xa6, 0xca, 0x8a, 0x28, 0xad, 0xad,
+  0xcc, 0x6d, 0x2e, 0xed, 0xcd, 0x6d, 0x8e, 0x44, 0x5d, 0x9a, 0x1b, 0x1d,
+  0x91, 0xa6, 0x34, 0x38, 0xa6, 0x32, 0xbb, 0x32, 0x36, 0x16, 0x66, 0x6c,
+  0x6f, 0x61, 0x74, 0x64, 0x98, 0xc2, 0xf2, 0xca, 0xe4, 0x9e, 0xe4, 0x88,
+  0xca, 0xe0, 0xe8, 0xd0, 0x86, 0xa0, 0xc1, 0x30, 0x0c, 0xc5, 0x30, 0x4c,
+  0xd8, 0x54, 0x06, 0x43, 0x31, 0x14, 0xc3, 0x30, 0x61, 0x93, 0x19, 0x0c,
+  0xc9, 0x60, 0x0c, 0xc3, 0x74, 0x06, 0x13, 0x1a, 0x0c, 0xca, 0x60, 0x0c,
+  0xc3, 0x94, 0x06, 0x93, 0x1a, 0x30, 0x0a, 0x4b, 0x93, 0x73, 0x09, 0x93,
+  0x3b, 0xfb, 0xa2, 0xcb, 0x83, 0x2b, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0xe3,
+  0x15, 0x96, 0x26, 0xe7, 0x12, 0x26, 0x77, 0xf6, 0x45, 0x97, 0x07, 0x57,
+  0xf6, 0x15, 0xc6, 0x96, 0x76, 0xe6, 0xf6, 0x35, 0x97, 0xa6, 0x57, 0x46,
+  0x66, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x4c, 0xaa, 0xec, 0x2c, 0xed, 0xcd,
+  0x8d, 0xcc, 0xdc, 0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda,
+  0x9b, 0xdb, 0x10, 0x32, 0x18, 0x8e, 0x09, 0x0c, 0xa6, 0x30, 0x18, 0x90,
+  0x49, 0x0c, 0x86, 0x61, 0x20, 0xa6, 0x31, 0x98, 0xc8, 0x60, 0x5a, 0x83,
+  0x89, 0x0d, 0x06, 0x64, 0x6a, 0x83, 0xa1, 0x98, 0xa0, 0xc9, 0x0d, 0xa6,
+  0x6c, 0x7a, 0x03, 0x2e, 0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74,
+  0x75, 0x72, 0x65, 0x54, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0,
+  0xd8, 0xca, 0x88, 0xd1, 0x95, 0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0xcd, 0x90,
+  0xf1, 0x98, 0xb1, 0xbd, 0x85, 0xd1, 0xb1, 0x80, 0xcc, 0x85, 0xb5, 0xc1,
+  0xb1, 0x95, 0xf9, 0xb0, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0xa3, 0x2a,
+  0xc3, 0xa3, 0xab, 0x93, 0x2b, 0x1b, 0x42, 0x0d, 0xcb, 0x14, 0x07, 0x93,
+  0x18, 0x0c, 0xc3, 0x40, 0x4c, 0x72, 0x30, 0x41, 0xd3, 0x1c, 0x4c, 0xd9,
+  0x44, 0x07, 0x5c, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8,
+  0xca, 0xe4, 0x78, 0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xc9, 0xb1, 0x99,
+  0x7b, 0xab, 0x93, 0x1b, 0x2b, 0x9b, 0x0a, 0x6b, 0x83, 0x63, 0x2b, 0x93,
+  0x1b, 0x22, 0x0d, 0xc6, 0x64, 0x07, 0x93, 0x18, 0x0c, 0xc3, 0x40, 0x4c,
+  0xd0, 0x74, 0x07, 0x53, 0x36, 0xe1, 0xc1, 0x10, 0x65, 0xda, 0xa6, 0x6f,
+  0x82, 0x83, 0xa9, 0x0e, 0xa6, 0x3c, 0x18, 0x62, 0x2c, 0xc0, 0x34, 0x4d,
+  0x7a, 0xc0, 0xe7, 0xad, 0xcd, 0x2d, 0x0d, 0xee, 0x8d, 0xae, 0xcc, 0x8d,
+  0x0e, 0x64, 0x0c, 0x2d, 0x4c, 0x8e, 0xcf, 0x54, 0x5a, 0x1b, 0x1c, 0x5b,
+  0x19, 0xc8, 0xd0, 0xca, 0x0a, 0x08, 0x95, 0x50, 0x50, 0xd0, 0x10, 0x61,
+  0xea, 0x83, 0x21, 0xc6, 0xc4, 0x07, 0x93, 0x1f, 0x54, 0xcd, 0x10, 0x63,
+  0xfa, 0x83, 0xe9, 0x0f, 0xaa, 0x86, 0xd2, 0x97, 0x16, 0xd5, 0x54, 0x8c,
+  0xcc, 0xd4, 0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b,
+  0x1b, 0x87, 0x34, 0x37, 0xba, 0x21, 0xc6, 0x24, 0x0a, 0xd3, 0x1f, 0x54,
+  0xcd, 0x10, 0x63, 0x4a, 0x83, 0xe9, 0x0f, 0xaa, 0x66, 0x88, 0x34, 0x85,
+  0xc2, 0xf4, 0x07, 0x55, 0x33, 0xfd, 0x41, 0xc5, 0x4c, 0xa3, 0x50, 0x39,
+  0x13, 0x29, 0x54, 0xcf, 0x10, 0x63, 0x2a, 0x85, 0x89, 0x14, 0xaa, 0x67,
+  0x88, 0x31, 0x95, 0xc2, 0x34, 0x0a, 0x95, 0x43, 0x2e, 0x2c, 0x4d, 0xae,
+  0x25, 0x8c, 0x2d, 0x2d, 0x6c, 0xae, 0x65, 0x6e, 0xec, 0x0d, 0xae, 0x6c,
+  0x0e, 0x45, 0x88, 0x2d, 0x8d, 0xce, 0x48, 0xee, 0xad, 0x6d, 0x86, 0x28,
+  0x65, 0x08, 0x31, 0xa5, 0xc2, 0x84, 0x0a, 0xc4, 0xc2, 0xd2, 0xe4, 0x5a,
+  0xc2, 0xd8, 0xd2, 0xc2, 0xe6, 0x5a, 0xe6, 0xc6, 0xde, 0xe0, 0xca, 0x5a,
+  0xe8, 0xca, 0xf0, 0xe8, 0xea, 0xe4, 0xca, 0xe6, 0x86, 0x18, 0xd3, 0x2a,
+  0x4c, 0xa9, 0x30, 0xa9, 0x02, 0xb1, 0xb0, 0x34, 0xb9, 0x96, 0x30, 0xb6,
+  0xb4, 0xb0, 0xb9, 0x96, 0xb9, 0xb1, 0x37, 0xb8, 0xb2, 0x96, 0xb9, 0xb0,
+  0x36, 0x38, 0xb6, 0x32, 0xb9, 0xb9, 0x21, 0xc6, 0xd4, 0x0a, 0x53, 0x2a,
+  0x4c, 0xac, 0x30, 0x84, 0x98, 0x56, 0x61, 0x6a, 0x85, 0x11, 0x11, 0x3b,
+  0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0xb4, 0xc3, 0x3b, 0x90, 0x43, 0x3d,
+  0xb0, 0x43, 0x39, 0xb8, 0x81, 0x39, 0xb0, 0x43, 0x38, 0x9c, 0xc3, 0x3c,
+  0x4c, 0x11, 0x82, 0x61, 0x84, 0xc2, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0,
+  0x06, 0xe9, 0x40, 0x0e, 0xe5, 0xe0, 0x0e, 0xf4, 0x30, 0x25, 0x28, 0x46,
+  0x2c, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e, 0xf2, 0x30,
+  0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x25, 0x30, 0x46, 0x50, 0xe1, 0x90,
+  0x0e, 0xf2, 0xe0, 0x06, 0xec, 0x10, 0x0e, 0xee, 0x70, 0x0e, 0xf5, 0x10,
+  0x0e, 0xe7, 0x50, 0x0e, 0xbf, 0x60, 0x0f, 0xe5, 0x20, 0x0f, 0xf3, 0x90,
+  0x0e, 0xef, 0xe0, 0x0e, 0x53, 0x02, 0x64, 0xc4, 0x14, 0x0e, 0xe9, 0x20,
+  0x0f, 0x6e, 0x30, 0x0e, 0xef, 0xd0, 0x0e, 0xf0, 0x90, 0x0e, 0xec, 0x50,
+  0x0e, 0xbf, 0xf0, 0x0e, 0xf0, 0x40, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30,
+  0x0f, 0x53, 0x06, 0x85, 0x71, 0x46, 0x30, 0xe1, 0x90, 0x0e, 0xf2, 0xe0,
+  0x06, 0xe6, 0x20, 0x0f, 0xe1, 0x70, 0x0e, 0xed, 0x50, 0x0e, 0xee, 0x40,
+  0x0f, 0x53, 0x82, 0x3d, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5, 0x00,
+  0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01,
+  0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78,
+  0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4,
+  0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c,
+  0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03,
+  0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70,
+  0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70,
+  0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec,
+  0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0,
+  0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d,
+  0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43,
+  0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0,
+  0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68,
+  0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28,
+  0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08,
+  0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee,
+  0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62,
+  0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06,
+  0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3,
+  0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3,
+  0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68,
+  0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce,
+  0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3,
+  0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d,
+  0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e,
+  0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51,
+  0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60,
+  0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98,
+  0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e,
+  0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e,
+  0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83,
+  0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2,
+  0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a,
+  0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28,
+  0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5,
+  0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17,
+  0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83,
+  0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3,
+  0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48,
+  0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58,
+  0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0,
+  0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e,
+  0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9,
+  0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c,
+  0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d,
+  0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d,
+  0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58,
+  0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48,
+  0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0,
+  0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4,
+  0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30,
+  0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8,
+  0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x16, 0xb0,
+  0x01, 0x48, 0xe4, 0x4b, 0x00, 0xf3, 0x2c, 0xc4, 0x3f, 0x11, 0xd7, 0x44,
+  0x45, 0xc4, 0x7f, 0x0f, 0x7e, 0x85, 0x17, 0xb7, 0x6d, 0x00, 0xca, 0xb6,
+  0x20, 0xd3, 0x17, 0x39, 0xcc, 0xdd, 0x99, 0xc0, 0x05, 0x20, 0x91, 0x2f,
+  0x38, 0x4d, 0x45, 0x44, 0x93, 0x5f, 0xf8, 0xc5, 0x6d, 0xfb, 0x94, 0x8f,
+  0xdc, 0x36, 0x00, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x21, 0x00,
+  0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00,
+  0x00, 0x00, 0xe4, 0x46, 0x00, 0x68, 0xcc, 0x00, 0x50, 0xab, 0x01, 0x72,
+  0x73, 0x0c, 0x03, 0x71, 0x91, 0x98, 0x01, 0x00, 0x00, 0x00, 0xe3, 0x0d,
+  0x88, 0x83, 0x51, 0x40, 0xc6, 0x1b, 0x14, 0x28, 0xa3, 0x80, 0x58, 0xe0,
+  0xc8, 0xc7, 0x02, 0x02, 0x3e, 0x83, 0x0c, 0xc1, 0x81, 0x8c, 0x37, 0x3c,
+  0xd5, 0x45, 0xc1, 0x98, 0x63, 0x18, 0x82, 0x6e, 0xbc, 0x41, 0xc2, 0x3c,
+  0x0a, 0xc8, 0x88, 0x01, 0x41, 0x04, 0x65, 0x10, 0x8c, 0x18, 0x28, 0x45,
+  0x70, 0x06, 0xd4, 0x44, 0x40, 0x12, 0x14, 0x64, 0x10, 0x10, 0x03, 0x00,
+  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5b, 0x86, 0x20, 0x00, 0x85, 0x2d,
+  0xc3, 0x10, 0x80, 0xc2, 0x96, 0x01, 0x09, 0x4c, 0x61, 0xcb, 0xb0, 0x04,
+  0xa7, 0xb0, 0x65, 0x68, 0x0e, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFrom3D_metallib_len = 3630;
+const unsigned char BlitFromCube_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x50, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x0e, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x0d, 0x00, 0x42, 0x6c, 0x69, 0x74, 0x46, 0x72,
+  0x6f, 0x6d, 0x43, 0x75, 0x62, 0x65, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01,
+  0x00, 0x01, 0x48, 0x41, 0x53, 0x48, 0x20, 0x00, 0x1b, 0xe5, 0x11, 0x5e,
+  0x1a, 0x23, 0x9f, 0xf3, 0x1f, 0xed, 0x46, 0xa4, 0x2f, 0xf4, 0x40, 0x22,
+  0x62, 0x46, 0x11, 0x3b, 0xec, 0x2f, 0x88, 0x93, 0x5c, 0x22, 0x80, 0x12,
+  0x54, 0x70, 0x91, 0x4e, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45,
+  0x52, 0x53, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54,
+  0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b,
+  0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x50, 0x0e, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00,
+  0x91, 0x03, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24,
+  0x48, 0x0a, 0x90, 0x21, 0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72,
+  0x24, 0x07, 0xc8, 0x48, 0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0,
+  0x01, 0x00, 0x00, 0x00, 0x51, 0x18, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00,
+  0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x60, 0x00, 0x09,
+  0xa8, 0x88, 0x70, 0x80, 0x07, 0x78, 0x90, 0x87, 0x77, 0xc0, 0x87, 0x36,
+  0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36,
+  0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1,
+  0x1c, 0x00, 0xa2, 0x1d, 0xd2, 0xc1, 0x1d, 0xda, 0x80, 0x1d, 0xca, 0xe1,
+  0x1c, 0xc2, 0x81, 0x1d, 0xda, 0xc0, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0xe1,
+  0x1d, 0xe4, 0xa1, 0x0d, 0xee, 0x21, 0x1d, 0xc8, 0x81, 0x1e, 0xd0, 0x01,
+  0x88, 0x03, 0x39, 0xc0, 0x03, 0x60, 0x70, 0x87, 0x77, 0x68, 0x03, 0x71,
+  0xa8, 0x87, 0x74, 0x60, 0x07, 0x7a, 0x48, 0x07, 0x77, 0x98, 0x07, 0x80,
+  0x70, 0x87, 0x77, 0x68, 0x03, 0x73, 0x90, 0x87, 0x70, 0x68, 0x87, 0x72,
+  0x68, 0x03, 0x78, 0x78, 0x87, 0x74, 0x70, 0x07, 0x7a, 0x28, 0x07, 0x79,
+  0x68, 0x83, 0x72, 0x60, 0x87, 0x74, 0x68, 0x07, 0x80, 0x1e, 0xe4, 0xa1,
+  0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21,
+  0x1c, 0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81,
+  0x1e, 0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0xa1,
+  0x0d, 0xdc, 0xe1, 0x1d, 0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xc2, 0xc1,
+  0x1c, 0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77,
+  0x68, 0x83, 0x74, 0x70, 0x07, 0x73, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78,
+  0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1,
+  0x1e, 0xca, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1d, 0xc2, 0xc1,
+  0x1d, 0xe6, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81,
+  0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77,
+  0x78, 0x87, 0x36, 0x98, 0x87, 0x74, 0x38, 0x07, 0x77, 0x28, 0x07, 0x72,
+  0x68, 0x03, 0x7d, 0x28, 0x07, 0x79, 0x78, 0x87, 0x79, 0x68, 0x03, 0x73,
+  0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41,
+  0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe8, 0x41,
+  0x1e, 0xc2, 0x01, 0x1e, 0xe0, 0x21, 0x1d, 0xdc, 0xe1, 0x1c, 0xda, 0xa0,
+  0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72,
+  0x00, 0x88, 0x79, 0xa0, 0x87, 0x70, 0x18, 0x87, 0x75, 0x68, 0x03, 0x78,
+  0x90, 0x87, 0x77, 0xa0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79,
+  0x68, 0x03, 0x71, 0xa8, 0x07, 0x73, 0x30, 0x87, 0x72, 0x90, 0x87, 0x36,
+  0x98, 0x87, 0x74, 0xd0, 0x87, 0x72, 0x00, 0xf0, 0x00, 0x20, 0xea, 0xc1,
+  0x1d, 0xe6, 0x21, 0x1c, 0xcc, 0xa1, 0x1c, 0xda, 0xc0, 0x1c, 0xe0, 0xa1,
+  0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87, 0x7a,
+  0x28, 0x07, 0x60, 0x83, 0x21, 0x0c, 0xc0, 0x02, 0x54, 0x1b, 0x8c, 0xa1,
+  0x00, 0x16, 0xa0, 0xda, 0x80, 0x10, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+  0x0c, 0x20, 0x01, 0xd5, 0x06, 0xa3, 0x08, 0x80, 0x05, 0xa8, 0x36, 0x18,
+  0x86, 0x00, 0x2c, 0x40, 0xb5, 0xc1, 0x38, 0xfe, 0xff, 0xff, 0xff, 0x7f,
+  0x00, 0x24, 0x80, 0xda, 0x60, 0x20, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+  0x12, 0x40, 0x6d, 0x40, 0x92, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x06,
+  0x90, 0x80, 0x0a, 0x00, 0x49, 0x18, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x13, 0x86, 0x40, 0x18, 0x26, 0x0c, 0x44, 0x61, 0x4c, 0x08, 0x8e, 0x09,
+  0x01, 0x32, 0x61, 0x48, 0x0a, 0x03, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00,
+  0x29, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04,
+  0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14,
+  0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x74, 0x33, 0x00,
+  0xc3, 0x08, 0x04, 0x30, 0x8c, 0x20, 0x00, 0x73, 0x04, 0x60, 0x70, 0x93,
+  0x34, 0x45, 0x94, 0x30, 0xf9, 0xac, 0x43, 0x45, 0x02, 0xb1, 0x12, 0x06,
+  0xe2, 0x34, 0x88, 0x10, 0x62, 0x80, 0x41, 0x04, 0x42, 0x38, 0x4b, 0x9a,
+  0x22, 0x4a, 0x98, 0xfc, 0x7f, 0x22, 0xae, 0x89, 0x8a, 0x88, 0x5f, 0xa0,
+  0x02, 0xe2, 0x9f, 0xc6, 0x08, 0x80, 0x41, 0x04, 0x23, 0xb8, 0x48, 0x9a,
+  0x22, 0x4a, 0x98, 0xfc, 0x5f, 0x02, 0x98, 0x67, 0x21, 0xa2, 0x7f, 0x1a,
+  0x23, 0x00, 0x06, 0x11, 0x10, 0xa1, 0x18, 0x41, 0x84, 0x72, 0x12, 0xa9,
+  0x61, 0x84, 0x01, 0x98, 0x23, 0x08, 0x8a, 0x11, 0x4e, 0x62, 0x0d, 0x90,
+  0x2b, 0x02, 0x18, 0x04, 0x8b, 0x30, 0x00, 0xc9, 0x81, 0x80, 0x14, 0x18,
+  0x73, 0x04, 0xa0, 0x30, 0x88, 0x20, 0x08, 0x83, 0x08, 0x80, 0x30, 0x05,
+  0x30, 0x02, 0x30, 0x8c, 0x30, 0x0c, 0x83, 0x08, 0x83, 0x00, 0x00, 0x00,
+  0x13, 0xb2, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70,
+  0x80, 0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x76, 0x08, 0x87, 0x71,
+  0x78, 0x87, 0x79, 0xc0, 0x87, 0x38, 0x80, 0x03, 0x37, 0x88, 0x83, 0x38,
+  0x70, 0x03, 0x38, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06, 0xf0, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06,
+  0xe9, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d, 0x90, 0x0e,
+  0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07,
+  0x6d, 0x90, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0x60, 0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f,
+  0x74, 0x80, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0x60, 0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07, 0x7a, 0x10, 0x07,
+  0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f,
+  0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07,
+  0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x79, 0x20, 0x07,
+  0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07,
+  0x6d, 0x60, 0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07,
+  0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x50, 0x07,
+  0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07,
+  0x71, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07,
+  0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07,
+  0x72, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0x30, 0x84, 0x59, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x18, 0xc2, 0x3c, 0x40, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x0c, 0x61, 0x22, 0x20, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x86, 0x30, 0x13, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x59, 0x20, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x1a,
+  0x23, 0x00, 0x25, 0x50, 0x10, 0x85, 0x50, 0x04, 0x05, 0x53, 0x20, 0x85,
+  0x52, 0x06, 0x64, 0x0b, 0x62, 0x04, 0xa0, 0x40, 0x0a, 0x85, 0xea, 0x58,
+  0x82, 0x23, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x3d, 0x01, 0x00, 0x00,
+  0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9,
+  0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x80, 0x50, 0x40, 0x15, 0x51, 0xb9,
+  0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x0c,
+  0x05, 0x25, 0x0c, 0x07, 0xe3, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4,
+  0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd,
+  0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x06, 0x26, 0x06, 0x04,
+  0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46,
+  0x66, 0xc6, 0x25, 0x06, 0x26, 0x26, 0x65, 0x88, 0x40, 0x11, 0x43, 0x8c,
+  0xa1, 0x18, 0x8c, 0x81, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04,
+  0xa1, 0x8e, 0xa1, 0x18, 0x8a, 0x81, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32,
+  0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26,
+  0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44,
+  0xa0, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69,
+  0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68,
+  0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x6a, 0x61, 0x19,
+  0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9,
+  0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d,
+  0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x91, 0xa5, 0xcd, 0x85, 0x89, 0xb1,
+  0x95, 0x0d, 0x11, 0xa8, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99,
+  0x1b, 0x59, 0x99, 0xdc, 0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3,
+  0xb0, 0x34, 0x39, 0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2,
+  0x2f, 0xb7, 0xb0, 0xb6, 0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
+  0x43, 0x10, 0xea, 0x19, 0x08, 0x0a, 0xa2, 0xa2, 0x21, 0x02, 0x25, 0x51,
+  0x0a, 0x4b, 0x93, 0x73, 0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3,
+  0xfb, 0x4a, 0x73, 0x83, 0xab, 0xa3, 0x23, 0x75, 0x56, 0xe6, 0x56, 0x26,
+  0x17, 0x46, 0x57, 0x46, 0x86, 0x32, 0x43, 0x57, 0x86, 0x47, 0x64, 0x27,
+  0xf3, 0x65, 0x96, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d,
+  0xae, 0x4c, 0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c,
+  0x5c, 0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x0d, 0x33, 0xb6, 0xb7, 0x30,
+  0x3a, 0x19, 0x32, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e,
+  0x61, 0x6d, 0x65, 0x1c, 0xe8, 0xca, 0xf0, 0x86, 0x48, 0x03, 0x41, 0x51,
+  0x54, 0x45, 0x59, 0xd4, 0x45, 0x41, 0x14, 0x46, 0x65, 0x94, 0x46, 0x26,
+  0x2c, 0x4d, 0xce, 0x05, 0xee, 0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x8d,
+  0x52, 0x58, 0x9a, 0x9c, 0x8b, 0xdb, 0xdb, 0x17, 0x5c, 0x99, 0xdc, 0x1c,
+  0x5c, 0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x07, 0xb8, 0xb7, 0xb9, 0x21,
+  0xd0, 0x50, 0x50, 0x1c, 0x65, 0x51, 0x1d, 0x05, 0x51, 0x11, 0x95, 0x51,
+  0x1e, 0x95, 0xb0, 0x34, 0x39, 0x17, 0xb1, 0x3a, 0x33, 0xb3, 0x32, 0x39,
+  0x3e, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f,
+  0x73, 0x69, 0x7a, 0x65, 0x94, 0xc2, 0xd2, 0xe4, 0x5c, 0xd8, 0xde, 0xc6,
+  0xc2, 0xe8, 0xd2, 0xde, 0xdc, 0xbe, 0xd2, 0xdc, 0xc8, 0xca, 0xf0, 0x88,
+  0x84, 0xa5, 0xc9, 0xb9, 0xc8, 0x95, 0x85, 0x91, 0x91, 0x0a, 0x4b, 0x93,
+  0x73, 0x99, 0xa3, 0x93, 0xab, 0x1b, 0xa3, 0xfb, 0xa2, 0xcb, 0x83, 0x2b,
+  0xfb, 0x4a, 0x73, 0x33, 0x7b, 0x63, 0x52, 0x65, 0xc5, 0x54, 0x66, 0x46,
+  0x47, 0xf5, 0x06, 0x47, 0xa6, 0xca, 0x8a, 0x28, 0xad, 0xad, 0xcc, 0x6d,
+  0x2e, 0xed, 0xcd, 0x6d, 0x8e, 0x44, 0x5d, 0x9a, 0x1b, 0x1d, 0x91, 0xa6,
+  0x34, 0x38, 0xa6, 0x32, 0xbb, 0x32, 0x36, 0x16, 0x66, 0x6c, 0x6f, 0x61,
+  0x74, 0x64, 0x98, 0xc2, 0xf2, 0xca, 0xe4, 0x9e, 0xe4, 0x88, 0xca, 0xe0,
+  0xe8, 0xd0, 0x86, 0xa0, 0xc1, 0x40, 0x0c, 0xc6, 0x40, 0x50, 0x18, 0x55,
+  0x06, 0x83, 0x31, 0x18, 0x03, 0x41, 0x61, 0x94, 0x19, 0x0c, 0xca, 0x70,
+  0x0c, 0x04, 0x75, 0x06, 0x14, 0x1a, 0x0c, 0xcb, 0x70, 0x0c, 0x04, 0x95,
+  0x06, 0x94, 0x1a, 0x30, 0x0a, 0x4b, 0x93, 0x73, 0x09, 0x93, 0x3b, 0xfb,
+  0xa2, 0xcb, 0x83, 0x2b, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0xe3, 0x15, 0x96,
+  0x26, 0xe7, 0x12, 0x26, 0x77, 0xf6, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x15,
+  0xc6, 0x96, 0x76, 0xe6, 0xf6, 0x35, 0x97, 0xa6, 0x57, 0x46, 0x66, 0xea,
+  0xad, 0x4e, 0x6e, 0xac, 0x4c, 0xaa, 0xec, 0x2c, 0xed, 0xcd, 0x8d, 0xcc,
+  0xdc, 0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b, 0xdb,
+  0x10, 0x32, 0x18, 0x10, 0x0a, 0x0c, 0xa8, 0x30, 0x18, 0x12, 0x4a, 0x0c,
+  0x06, 0x62, 0x28, 0xa8, 0x31, 0xa0, 0xc8, 0x80, 0x5a, 0x03, 0x8a, 0x0d,
+  0x86, 0x84, 0x6a, 0x83, 0xc1, 0xa0, 0x20, 0xca, 0x0d, 0xa8, 0x8c, 0x7a,
+  0x03, 0x2e, 0x61, 0x69, 0x72, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
+  0x65, 0x54, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8, 0xca,
+  0xa8, 0xd1, 0x95, 0xe1, 0xd1, 0xd5, 0xc9, 0x95, 0x8d, 0xd5, 0x89, 0x95,
+  0xf1, 0x98, 0xb1, 0xbd, 0x85, 0xd1, 0xb1, 0x80, 0xcc, 0x85, 0xb5, 0xc1,
+  0xb1, 0x95, 0xf9, 0xb0, 0x99, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0xa3, 0x2a,
+  0xc3, 0xa3, 0xab, 0x93, 0x2b, 0x1b, 0x42, 0x0d, 0x0c, 0x15, 0x07, 0x94,
+  0x18, 0x0c, 0xc4, 0x50, 0x50, 0x72, 0x40, 0x41, 0xd4, 0x1c, 0x50, 0x19,
+  0x45, 0x07, 0x5c, 0xc2, 0xd2, 0xe4, 0x5c, 0xe6, 0xc2, 0xda, 0xe0, 0xd8,
+  0xca, 0xe4, 0x78, 0xcc, 0x85, 0xb5, 0xc1, 0xb1, 0x95, 0xc9, 0xb1, 0x99,
+  0x7b, 0xab, 0x93, 0x1b, 0x2b, 0x9b, 0x0a, 0x6b, 0x83, 0x63, 0x2b, 0x93,
+  0x1b, 0x22, 0x0d, 0x07, 0x65, 0x07, 0x94, 0x18, 0x0c, 0xc4, 0x50, 0x50,
+  0x10, 0x75, 0x07, 0x54, 0x46, 0xe1, 0xc1, 0x10, 0x85, 0xda, 0xa8, 0x8f,
+  0x82, 0x03, 0xaa, 0x0e, 0xa8, 0x3c, 0x18, 0x62, 0x2c, 0x00, 0x35, 0x51,
+  0x7a, 0xc0, 0xe7, 0xad, 0xcd, 0x2d, 0x0d, 0xee, 0x8d, 0xae, 0xcc, 0x8d,
+  0x0e, 0x64, 0x0c, 0x2d, 0x4c, 0x8e, 0xcf, 0x54, 0x5a, 0x1b, 0x1c, 0x5b,
+  0x19, 0xc8, 0xd0, 0xca, 0x0a, 0x08, 0x95, 0x50, 0x50, 0xd0, 0x10, 0x81,
+  0xea, 0x83, 0x21, 0x06, 0xc5, 0x07, 0x94, 0x1f, 0x58, 0xce, 0x10, 0x83,
+  0xfa, 0x03, 0xea, 0x0f, 0x2c, 0x87, 0xd2, 0x97, 0x16, 0xd5, 0x54, 0x8c,
+  0xcc, 0xd4, 0x5b, 0x9d, 0xdc, 0x58, 0x99, 0x54, 0xd9, 0x59, 0xda, 0x9b,
+  0x1b, 0x87, 0x34, 0x37, 0xba, 0x21, 0x06, 0x25, 0x0a, 0xd4, 0x1f, 0x58,
+  0xce, 0x10, 0x83, 0x4a, 0x03, 0xea, 0x0f, 0x2c, 0x67, 0x88, 0x44, 0x85,
+  0x02, 0xf5, 0x07, 0x96, 0x43, 0xfd, 0x81, 0xd5, 0x50, 0xa3, 0x60, 0x3d,
+  0x14, 0x29, 0x58, 0xd0, 0x10, 0x83, 0x2a, 0x05, 0x8a, 0x14, 0x2c, 0x68,
+  0x88, 0x41, 0x95, 0x02, 0x35, 0x0a, 0xd6, 0x43, 0x2f, 0x2c, 0x4d, 0xae,
+  0x25, 0x8c, 0x2d, 0x2d, 0x6c, 0xae, 0x65, 0x6e, 0xec, 0x0d, 0xae, 0x6c,
+  0x0e, 0x45, 0x88, 0x2d, 0x8d, 0xce, 0x48, 0xee, 0xad, 0x6d, 0xa8, 0x4e,
+  0xac, 0x2c, 0x65, 0x08, 0x41, 0xa5, 0x02, 0x85, 0x0a, 0xc4, 0xc2, 0xd2,
+  0xe4, 0x5a, 0xc2, 0xd8, 0xd2, 0xc2, 0xe6, 0x5a, 0xe6, 0xc6, 0xde, 0xe0,
+  0xca, 0x5a, 0xe8, 0xca, 0xf0, 0xe8, 0xea, 0xe4, 0xca, 0xe6, 0x86, 0x18,
+  0xd4, 0x2a, 0x50, 0xa9, 0x40, 0xa9, 0x02, 0xb1, 0xb0, 0x34, 0xb9, 0x96,
+  0x30, 0xb6, 0xb4, 0xb0, 0xb9, 0x96, 0xb9, 0xb1, 0x37, 0xb8, 0xb2, 0x96,
+  0xb9, 0xb0, 0x36, 0x38, 0xb6, 0x32, 0xb9, 0xb9, 0x21, 0x06, 0xd5, 0x0a,
+  0x54, 0x2a, 0x50, 0xac, 0x30, 0x84, 0xa0, 0x56, 0x81, 0x6a, 0x85, 0x11,
+  0x11, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0xb4, 0xc3, 0x3b, 0x90,
+  0x43, 0x3d, 0xb0, 0x43, 0x39, 0xb8, 0x81, 0x39, 0xb0, 0x43, 0x38, 0x9c,
+  0xc3, 0x3c, 0x4c, 0x11, 0x82, 0x61, 0x84, 0xc2, 0x0e, 0xec, 0x60, 0x0f,
+  0xed, 0xe0, 0x06, 0xe9, 0x40, 0x0e, 0xe5, 0xe0, 0x0e, 0xf4, 0x30, 0x25,
+  0x28, 0x46, 0x2c, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e,
+  0xf2, 0x30, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x25, 0x30, 0x46, 0x50,
+  0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xec, 0x10, 0x0e, 0xee, 0x70, 0x0e,
+  0xf5, 0x10, 0x0e, 0xe7, 0x50, 0x0e, 0xbf, 0x60, 0x0f, 0xe5, 0x20, 0x0f,
+  0xf3, 0x90, 0x0e, 0xef, 0xe0, 0x0e, 0x53, 0x02, 0x64, 0xc4, 0x14, 0x0e,
+  0xe9, 0x20, 0x0f, 0x6e, 0x30, 0x0e, 0xef, 0xd0, 0x0e, 0xf0, 0x90, 0x0e,
+  0xec, 0x50, 0x0e, 0xbf, 0xf0, 0x0e, 0xf0, 0x40, 0x0f, 0xe9, 0xf0, 0x0e,
+  0xee, 0x30, 0x0f, 0x53, 0x06, 0x85, 0x71, 0x46, 0x30, 0xe1, 0x90, 0x0e,
+  0xf2, 0xe0, 0x06, 0xe6, 0x20, 0x0f, 0xe1, 0x70, 0x0e, 0xed, 0x50, 0x0e,
+  0xee, 0x40, 0x0f, 0x53, 0x82, 0x3d, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00,
+  0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66,
+  0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10,
+  0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce,
+  0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b,
+  0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c,
+  0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07,
+  0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11,
+  0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0,
+  0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8,
+  0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b,
+  0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b,
+  0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87,
+  0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07,
+  0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87,
+  0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81,
+  0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30,
+  0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca,
+  0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b,
+  0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b,
+  0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83,
+  0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87,
+  0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90,
+  0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20,
+  0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc,
+  0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66,
+  0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24,
+  0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07,
+  0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e,
+  0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e,
+  0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54,
+  0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39,
+  0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c,
+  0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07,
+  0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0,
+  0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4,
+  0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b,
+  0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39,
+  0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c,
+  0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87,
+  0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0,
+  0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50,
+  0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0,
+  0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec,
+  0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6,
+  0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66,
+  0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39,
+  0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07,
+  0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10,
+  0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90,
+  0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07,
+  0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07,
+  0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x26, 0x70, 0x01, 0x48, 0xe4, 0x0b, 0x4e, 0x53, 0x11, 0xd1, 0xe4, 0x17,
+  0x7e, 0x71, 0xdb, 0x3e, 0xe5, 0x23, 0xb7, 0x6d, 0x03, 0x17, 0x80, 0x44,
+  0xbe, 0xe0, 0x34, 0x15, 0x11, 0x4d, 0x3e, 0xe5, 0x23, 0xb7, 0xed, 0x17,
+  0x7e, 0x71, 0xdb, 0x16, 0xd0, 0x01, 0x48, 0xe4, 0x4b, 0x00, 0xf3, 0x2c,
+  0xc4, 0x3f, 0x11, 0xd7, 0x44, 0x45, 0xc4, 0x2f, 0x50, 0x01, 0xe1, 0x57,
+  0x78, 0x71, 0xdb, 0x06, 0xc0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0x70,
+  0x54, 0x40, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00,
+  0x13, 0x04, 0x48, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+  0xb4, 0xc7, 0x1a, 0x80, 0x40, 0xa0, 0x56, 0x03, 0x34, 0x4a, 0x81, 0xc0,
+  0x18, 0x01, 0x08, 0x82, 0x20, 0xfe, 0x0b, 0x63, 0x04, 0x20, 0x08, 0x82,
+  0xf8, 0x37, 0x02, 0x30, 0x46, 0x00, 0x82, 0x20, 0x08, 0x82, 0x01, 0x85,
+  0x39, 0x88, 0x0d, 0x0d, 0xd0, 0xc0, 0x0c, 0xe6, 0x20, 0x34, 0x34, 0x40,
+  0x03, 0x33, 0x98, 0x83, 0x40, 0x03, 0x0d, 0x0d, 0xcc, 0x60, 0x0e, 0x02,
+  0x0d, 0x36, 0x34, 0x30, 0x83, 0x39, 0x08, 0x34, 0x40, 0x83, 0xcd, 0x0c,
+  0xe6, 0x20, 0xd0, 0x00, 0x0d, 0x34, 0x33, 0x98, 0x83, 0xe0, 0x38, 0xce,
+  0x0c, 0x66, 0x00, 0x08, 0xcc, 0x00, 0x8c, 0x11, 0x80, 0x20, 0x08, 0x82,
+  0xa0, 0x30, 0x03, 0x00, 0xe3, 0x0d, 0xd5, 0x56, 0x06, 0x14, 0x90, 0xf1,
+  0x86, 0xab, 0x33, 0x03, 0x0a, 0x88, 0x05, 0x9b, 0x7c, 0x2c, 0x20, 0xe0,
+  0x33, 0x86, 0x10, 0xac, 0x81, 0x05, 0x93, 0x7c, 0x2c, 0xb8, 0xe0, 0x33,
+  0x86, 0x40, 0xb4, 0x81, 0x05, 0x96, 0x7c, 0x2c, 0xd0, 0xe0, 0x33, 0xde,
+  0x10, 0x06, 0x67, 0x90, 0x06, 0x14, 0x8c, 0x11, 0x03, 0x82, 0x08, 0xe8,
+  0x20, 0x18, 0xe6, 0x19, 0x82, 0x83, 0x08, 0x0a, 0x01, 0x19, 0x18, 0xe2,
+  0x28, 0x32, 0xc3, 0x22, 0x22, 0x3e, 0x73, 0x0c, 0x5b, 0x40, 0x07, 0x36,
+  0x25, 0xf1, 0x99, 0x63, 0x10, 0x82, 0x39, 0x98, 0x25, 0x38, 0xac, 0x42,
+  0xe2, 0x33, 0xc7, 0xe0, 0x05, 0x78, 0x30, 0xc7, 0x10, 0x34, 0x76, 0x30,
+  0x4b, 0x70, 0xcc, 0x31, 0x7c, 0xce, 0x1e, 0x58, 0xc6, 0xc4, 0x67, 0x8e,
+  0x41, 0x08, 0xf2, 0x60, 0x96, 0xe0, 0x98, 0x63, 0x08, 0x83, 0xc8, 0x0f,
+  0xe6, 0x18, 0x82, 0x67, 0x0f, 0x66, 0x09, 0x0e, 0xeb, 0xa0, 0xf8, 0xcc,
+  0x31, 0x8c, 0x01, 0x15, 0x0a, 0x73, 0x0c, 0x81, 0x10, 0x0a, 0xb3, 0x04,
+  0x87, 0x81, 0x81, 0x15, 0x1f, 0x0b, 0x03, 0x2a, 0x3e, 0x73, 0x0c, 0x66,
+  0x20, 0x94, 0xc2, 0x1c, 0x43, 0x20, 0x94, 0xc2, 0x2c, 0xc1, 0x31, 0xd0,
+  0x13, 0x08, 0x86, 0x52, 0x40, 0x04, 0x35, 0x68, 0x02, 0x18, 0x04, 0xae,
+  0x00, 0x0c, 0x32, 0x04, 0x67, 0x50, 0x07, 0xe3, 0x0d, 0x79, 0xf0, 0x07,
+  0xa5, 0x40, 0x01, 0x19, 0x31, 0x20, 0x88, 0xa0, 0x15, 0x82, 0x11, 0x03,
+  0xa4, 0x08, 0x5e, 0x61, 0x0f, 0xf4, 0x80, 0xc0, 0x83, 0x20, 0x83, 0x80,
+  0x18, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x5b, 0x86, 0x20, 0x00,
+  0x85, 0x2d, 0xc3, 0x10, 0x80, 0xc2, 0x96, 0xa1, 0x09, 0x4c, 0x61, 0xcb,
+  0xc0, 0x06, 0xc1, 0x29, 0x6c, 0x19, 0xdc, 0xe0, 0x70, 0x05, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int BlitFromCube_metallib_len = 3920;
+#endif

+ 85 - 0
src/gpu/metal/Metal_Blit.metal

@@ -0,0 +1,85 @@
+#include <metal_stdlib>
+using namespace metal;
+
+struct VertexToFragment {
+    float2 tex;
+    float4 pos [[position]];
+};
+
+struct SourceRegion {
+    float2 UVLeftTop;
+    float2 UVDimensions;
+    uint MipLevel;
+    float LayerOrDepth;
+};
+
+#if COMPILE_FullscreenVert
+vertex VertexToFragment FullscreenVert(uint vI [[vertex_id]]) {
+   float2 inTex = float2((vI << 1) & 2, vI & 2);
+   VertexToFragment out;
+   out.tex = inTex;
+   out.pos = float4(inTex * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);
+   return out;
+}
+#endif
+
+#if COMPILE_BlitFrom2D
+fragment float4 BlitFrom2D(
+    VertexToFragment input [[stage_in]],
+    constant SourceRegion &sourceRegion [[buffer(0)]],
+    texture2d<float> sourceTexture [[texture(0)]],
+    sampler sourceSampler [[sampler(0)]])
+{
+    float2 newCoord = sourceRegion.UVLeftTop + sourceRegion.UVDimensions * input.tex;
+    return sourceTexture.sample(sourceSampler, newCoord, level(sourceRegion.MipLevel));
+}
+#endif
+
+#if COMPILE_BlitFrom2DArray
+fragment float4 BlitFrom2DArray(
+    VertexToFragment input [[stage_in]],
+    constant SourceRegion &sourceRegion [[buffer(0)]],
+    texture2d_array<float> sourceTexture [[texture(0)]],
+    sampler sourceSampler [[sampler(0)]])
+{
+    float2 newCoord = sourceRegion.UVLeftTop + sourceRegion.UVDimensions * input.tex;
+    return sourceTexture.sample(sourceSampler, newCoord, (uint)sourceRegion.LayerOrDepth, level(sourceRegion.MipLevel));
+}
+#endif
+
+#if COMPILE_BlitFrom3D
+fragment float4 BlitFrom3D(
+    VertexToFragment input [[stage_in]],
+    constant SourceRegion &sourceRegion [[buffer(0)]],
+    texture3d<float> sourceTexture [[texture(0)]],
+    sampler sourceSampler [[sampler(0)]])
+{
+    float2 newCoord = sourceRegion.UVLeftTop + sourceRegion.UVDimensions * input.tex;
+    return sourceTexture.sample(sourceSampler, float3(newCoord, sourceRegion.LayerOrDepth), level(sourceRegion.MipLevel));
+}
+#endif
+
+#if COMPILE_BlitFromCube
+fragment float4 BlitFromCube(
+    VertexToFragment input [[stage_in]],
+    constant SourceRegion &sourceRegion [[buffer(0)]],
+    texturecube<float> sourceTexture [[texture(0)]],
+    sampler sourceSampler [[sampler(0)]])
+{
+    // Thanks, Wikipedia! https://en.wikipedia.org/wiki/Cube_mapping
+    float2 scaledUV = sourceRegion.UVLeftTop + sourceRegion.UVDimensions * input.tex;
+    float u = 2.0 * scaledUV.x - 1.0;
+    float v = 2.0 * scaledUV.y - 1.0;
+    float3 newCoord;
+    switch ((uint)sourceRegion.LayerOrDepth) {
+        case 0: newCoord = float3(1.0, -v, -u); break; // POSITIVE X
+        case 1: newCoord = float3(-1.0, -v, u); break; // NEGATIVE X
+        case 2: newCoord = float3(u, -1.0, -v); break; // POSITIVE Y
+        case 3: newCoord = float3(u, 1.0, v); break; // NEGATIVE Y
+        case 4: newCoord = float3(u, -v, 1.0); break; // POSITIVE Z
+        case 5: newCoord = float3(-u, -v, -1.0); break; // NEGATIVE Z
+        default: newCoord = float3(0, 0, 0); break; // silences warning
+    }
+    return sourceTexture.sample(sourceSampler, newCoord, level(sourceRegion.MipLevel));
+}
+#endif

+ 3984 - 0
src/gpu/metal/SDL_gpu_metal.m

@@ -0,0 +1,3984 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_internal.h"
+
+#if SDL_GPU_METAL
+
+#include <Metal/Metal.h>
+#include <QuartzCore/CoreAnimation.h>
+
+#include "../SDL_sysgpu.h"
+
+// Defines
+
+#define METAL_MAX_BUFFER_COUNT      31
+#define WINDOW_PROPERTY_DATA        "SDL_GpuMetalWindowPropertyData"
+#define SDL_GPU_SHADERSTAGE_COMPUTE 2
+
+#define TRACK_RESOURCE(resource, type, array, count, capacity) \
+    Uint32 i;                                                  \
+                                                               \
+    for (i = 0; i < commandBuffer->count; i += 1) {            \
+        if (commandBuffer->array[i] == resource) {             \
+            return;                                            \
+        }                                                      \
+    }                                                          \
+                                                               \
+    if (commandBuffer->count == commandBuffer->capacity) {     \
+        commandBuffer->capacity += 1;                          \
+        commandBuffer->array = SDL_realloc(                    \
+            commandBuffer->array,                              \
+            commandBuffer->capacity * sizeof(type));           \
+    }                                                          \
+    commandBuffer->array[commandBuffer->count] = resource;     \
+    commandBuffer->count += 1;                                 \
+    SDL_AtomicIncRef(&resource->referenceCount);
+
+// Blit Shaders
+
+#include "Metal_Blit.h"
+
+// Forward Declarations
+
+static void METAL_Wait(SDL_GpuRenderer *driverData);
+static void METAL_UnclaimWindow(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window);
+static void METAL_INTERNAL_DestroyBlitResources(SDL_GpuRenderer *driverData);
+
+// Conversions
+
+static MTLPixelFormat SDLToMetal_SurfaceFormat[] = {
+    MTLPixelFormatRGBA8Unorm,   // R8G8B8A8_UNORM
+    MTLPixelFormatBGRA8Unorm,   // B8G8R8A8_UNORM
+    MTLPixelFormatB5G6R5Unorm,  // B5G6R5_UNORM
+    MTLPixelFormatBGR5A1Unorm,  // B5G5R5A1_UNORM
+    MTLPixelFormatABGR4Unorm,   // B4G4R4A4_UNORM
+    MTLPixelFormatRGB10A2Unorm, // A2R10G10B10_UNORM
+    MTLPixelFormatRG16Unorm,    // R16G16_UNORM
+    MTLPixelFormatRGBA16Unorm,  // R16G16B16A16_UNORM
+    MTLPixelFormatR8Unorm,      // R8_UNORM
+    MTLPixelFormatA8Unorm,      // A8_UNORM
+#ifdef SDL_PLATFORM_MACOS
+    MTLPixelFormatBC1_RGBA,      // BC1_UNORM
+    MTLPixelFormatBC2_RGBA,      // BC2_UNORM
+    MTLPixelFormatBC3_RGBA,      // BC3_UNORM
+    MTLPixelFormatBC7_RGBAUnorm, // BC7_UNORM
+#else
+    MTLPixelFormatInvalid, // BC1_UNORM
+    MTLPixelFormatInvalid, // BC2_UNORM
+    MTLPixelFormatInvalid, // BC3_UNORM
+    MTLPixelFormatInvalid, // BC7_UNORM
+#endif
+    MTLPixelFormatRG8Snorm,        // R8G8_SNORM
+    MTLPixelFormatRGBA8Snorm,      // R8G8B8A8_SNORM
+    MTLPixelFormatR16Float,        // R16_FLOAT
+    MTLPixelFormatRG16Float,       // R16G16_FLOAT
+    MTLPixelFormatRGBA16Float,     // R16G16B16A16_FLOAT
+    MTLPixelFormatR32Float,        // R32_FLOAT
+    MTLPixelFormatRG32Float,       // R32G32_FLOAT
+    MTLPixelFormatRGBA32Float,     // R32G32B32A32_FLOAT
+    MTLPixelFormatR8Uint,          // R8_UINT
+    MTLPixelFormatRG8Uint,         // R8G8_UINT
+    MTLPixelFormatRGBA8Uint,       // R8G8B8A8_UINT
+    MTLPixelFormatR16Uint,         // R16_UINT
+    MTLPixelFormatRG16Uint,        // R16G16_UINT
+    MTLPixelFormatRGBA16Uint,      // R16G16B16A16_UINT
+    MTLPixelFormatRGBA8Unorm_sRGB, // R8G8B8A8_UNORM_SRGB
+    MTLPixelFormatBGRA8Unorm_sRGB, // B8G8R8A8_UNORM_SRGB
+#ifdef SDL_PLATFORM_MACOS
+    MTLPixelFormatBC3_RGBA_sRGB,      // BC3_UNORM_SRGB
+    MTLPixelFormatBC7_RGBAUnorm_sRGB, // BC7_UNORM_SRGB
+#else
+    MTLPixelFormatInvalid, // BC3_UNORM_SRGB
+    MTLPixelFormatInvalid, // BC7_UNORM_SRGB
+#endif
+    MTLPixelFormatDepth16Unorm, // D16_UNORM
+#ifdef SDL_PLATFORM_MACOS
+    MTLPixelFormatDepth24Unorm_Stencil8, // D24_UNORM
+#else
+    MTLPixelFormatInvalid, // D24_UNORM
+#endif
+    MTLPixelFormatDepth32Float, // D32_FLOAT
+#ifdef SDL_PLATFORM_MACOS
+    MTLPixelFormatDepth24Unorm_Stencil8, // D24_UNORM_S8_UINT
+#else
+    MTLPixelFormatInvalid, // D24_UNORM_S8_UINT
+#endif
+    MTLPixelFormatDepth32Float_Stencil8, // D32_FLOAT_S8_UINT
+};
+SDL_COMPILE_TIME_ASSERT(SDLToMetal_SurfaceFormat, SDL_arraysize(SDLToMetal_SurfaceFormat) == SDL_GPU_TEXTUREFORMAT_MAX);
+
+static MTLVertexFormat SDLToMetal_VertexFormat[] = {
+    MTLVertexFormatInt,               // INT
+    MTLVertexFormatInt2,              // INT2
+    MTLVertexFormatInt3,              // INT3
+    MTLVertexFormatInt4,              // INT4
+    MTLVertexFormatUInt,              // UINT
+    MTLVertexFormatUInt2,             // UINT2
+    MTLVertexFormatUInt3,             // UINT3
+    MTLVertexFormatUInt4,             // UINT4
+    MTLVertexFormatFloat,             // FLOAT
+    MTLVertexFormatFloat2,            // FLOAT2
+    MTLVertexFormatFloat3,            // FLOAT3
+    MTLVertexFormatFloat4,            // FLOAT4
+    MTLVertexFormatChar2,             // BYTE2
+    MTLVertexFormatChar4,             // BYTE4
+    MTLVertexFormatUChar2,            // UBYTE2
+    MTLVertexFormatUChar4,            // UBYTE4
+    MTLVertexFormatChar2Normalized,   // BYTE2_NORM
+    MTLVertexFormatChar4Normalized,   // BYTE4_NORM
+    MTLVertexFormatUChar2Normalized,  // UBYTE2_NORM
+    MTLVertexFormatUChar4Normalized,  // UBYTE4_NORM
+    MTLVertexFormatShort2,            // SHORT2
+    MTLVertexFormatShort4,            // SHORT4
+    MTLVertexFormatUShort2,           // USHORT2
+    MTLVertexFormatUShort4,           // USHORT4
+    MTLVertexFormatShort2Normalized,  // SHORT2_NORM
+    MTLVertexFormatShort4Normalized,  // SHORT4_NORM
+    MTLVertexFormatUShort2Normalized, // USHORT2_NORM
+    MTLVertexFormatUShort4Normalized, // USHORT4_NORM
+    MTLVertexFormatHalf2,             // HALF2
+    MTLVertexFormatHalf4              // HALF4
+};
+
+static MTLIndexType SDLToMetal_IndexType[] = {
+    MTLIndexTypeUInt16, // 16BIT
+    MTLIndexTypeUInt32, // 32BIT
+};
+
+static MTLPrimitiveType SDLToMetal_PrimitiveType[] = {
+    MTLPrimitiveTypePoint,        // POINTLIST
+    MTLPrimitiveTypeLine,         // LINELIST
+    MTLPrimitiveTypeLineStrip,    // LINESTRIP
+    MTLPrimitiveTypeTriangle,     // TRIANGLELIST
+    MTLPrimitiveTypeTriangleStrip // TRIANGLESTRIP
+};
+
+static MTLTriangleFillMode SDLToMetal_PolygonMode[] = {
+    MTLTriangleFillModeFill,  // FILL
+    MTLTriangleFillModeLines, // LINE
+};
+
+static MTLCullMode SDLToMetal_CullMode[] = {
+    MTLCullModeNone,  // NONE
+    MTLCullModeFront, // FRONT
+    MTLCullModeBack,  // BACK
+};
+
+static MTLWinding SDLToMetal_FrontFace[] = {
+    MTLWindingCounterClockwise, // COUNTER_CLOCKWISE
+    MTLWindingClockwise,        // CLOCKWISE
+};
+
+static MTLBlendFactor SDLToMetal_BlendFactor[] = {
+    MTLBlendFactorZero,                     // ZERO
+    MTLBlendFactorOne,                      // ONE
+    MTLBlendFactorSourceColor,              // SRC_COLOR
+    MTLBlendFactorOneMinusSourceColor,      // ONE_MINUS_SRC_COLOR
+    MTLBlendFactorDestinationColor,         // DST_COLOR
+    MTLBlendFactorOneMinusDestinationColor, // ONE_MINUS_DST_COLOR
+    MTLBlendFactorSourceAlpha,              // SRC_ALPHA
+    MTLBlendFactorOneMinusSourceAlpha,      // ONE_MINUS_SRC_ALPHA
+    MTLBlendFactorDestinationAlpha,         // DST_ALPHA
+    MTLBlendFactorOneMinusDestinationAlpha, // ONE_MINUS_DST_ALPHA
+    MTLBlendFactorBlendColor,               // CONSTANT_COLOR
+    MTLBlendFactorOneMinusBlendColor,       // ONE_MINUS_CONSTANT_COLOR
+    MTLBlendFactorSourceAlphaSaturated,     // SRC_ALPHA_SATURATE
+};
+
+static MTLBlendOperation SDLToMetal_BlendOp[] = {
+    MTLBlendOperationAdd,             // ADD
+    MTLBlendOperationSubtract,        // SUBTRACT
+    MTLBlendOperationReverseSubtract, // REVERSE_SUBTRACT
+    MTLBlendOperationMin,             // MIN
+    MTLBlendOperationMax,             // MAX
+};
+
+static MTLCompareFunction SDLToMetal_CompareOp[] = {
+    MTLCompareFunctionNever,        // NEVER
+    MTLCompareFunctionLess,         // LESS
+    MTLCompareFunctionEqual,        // EQUAL
+    MTLCompareFunctionLessEqual,    // LESS_OR_EQUAL
+    MTLCompareFunctionGreater,      // GREATER
+    MTLCompareFunctionNotEqual,     // NOT_EQUAL
+    MTLCompareFunctionGreaterEqual, // GREATER_OR_EQUAL
+    MTLCompareFunctionAlways,       // ALWAYS
+};
+
+static MTLStencilOperation SDLToMetal_StencilOp[] = {
+    MTLStencilOperationKeep,           // KEEP
+    MTLStencilOperationZero,           // ZERO
+    MTLStencilOperationReplace,        // REPLACE
+    MTLStencilOperationIncrementClamp, // INCREMENT_AND_CLAMP
+    MTLStencilOperationDecrementClamp, // DECREMENT_AND_CLAMP
+    MTLStencilOperationInvert,         // INVERT
+    MTLStencilOperationIncrementWrap,  // INCREMENT_AND_WRAP
+    MTLStencilOperationDecrementWrap,  // DECREMENT_AND_WRAP
+};
+
+static MTLSamplerAddressMode SDLToMetal_SamplerAddressMode[] = {
+    MTLSamplerAddressModeRepeat,       // REPEAT
+    MTLSamplerAddressModeMirrorRepeat, // MIRRORED_REPEAT
+    MTLSamplerAddressModeClampToEdge   // CLAMP_TO_EDGE
+};
+
+static MTLSamplerMinMagFilter SDLToMetal_MinMagFilter[] = {
+    MTLSamplerMinMagFilterNearest, // NEAREST
+    MTLSamplerMinMagFilterLinear,  // LINEAR
+};
+
+static MTLSamplerMipFilter SDLToMetal_MipFilter[] = {
+    MTLSamplerMipFilterNearest, // NEAREST
+    MTLSamplerMipFilterLinear,  // LINEAR
+};
+
+static MTLLoadAction SDLToMetal_LoadOp[] = {
+    MTLLoadActionLoad,     // LOAD
+    MTLLoadActionClear,    // CLEAR
+    MTLLoadActionDontCare, // DONT_CARE
+};
+
+static MTLVertexStepFunction SDLToMetal_StepFunction[] = {
+    MTLVertexStepFunctionPerVertex,
+    MTLVertexStepFunctionPerInstance,
+};
+
+static NSUInteger SDLToMetal_SampleCount[] = {
+    1, // SDL_GPU_SAMPLECOUNT_1
+    2, // SDL_GPU_SAMPLECOUNT_2
+    4, // SDL_GPU_SAMPLECOUNT_4
+    8  // SDL_GPU_SAMPLECOUNT_8
+};
+
+static MTLTextureType SDLToMetal_TextureType[] = {
+    MTLTextureType2D,      // SDL_GPU_TEXTURETYPE_2D
+    MTLTextureType2DArray, // SDL_GPU_TEXTURETYPE_2D_ARRAY
+    MTLTextureType3D,      // SDL_GPU_TEXTURETYPE_3D
+    MTLTextureTypeCube     // SDL_GPU_TEXTURETYPE_CUBE
+};
+
+static SDL_GpuTextureFormat SwapchainCompositionToFormat[] = {
+    SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM,      // SDR
+    SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, // SDR_LINEAR
+    SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT,  // HDR_EXTENDED_LINEAR
+    SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM,   // HDR10_ST2048
+};
+
+static CFStringRef SwapchainCompositionToColorSpace[4]; // initialized on device creation
+
+static MTLStoreAction SDLToMetal_StoreOp(
+    SDL_GpuStoreOp storeOp,
+    Uint8 isMultisample)
+{
+    if (isMultisample) {
+        if (storeOp == SDL_GPU_STOREOP_STORE) {
+            return MTLStoreActionStoreAndMultisampleResolve;
+        } else {
+            return MTLStoreActionMultisampleResolve;
+        }
+    } else {
+        if (storeOp == SDL_GPU_STOREOP_STORE) {
+            return MTLStoreActionStore;
+        } else {
+            return MTLStoreActionDontCare;
+        }
+    }
+};
+
+static MTLColorWriteMask SDLToMetal_ColorWriteMask(
+    SDL_GpuColorComponentFlagBits mask)
+{
+    MTLColorWriteMask result = 0;
+    if (mask & SDL_GPU_COLORCOMPONENT_R_BIT) {
+        result |= MTLColorWriteMaskRed;
+    }
+    if (mask & SDL_GPU_COLORCOMPONENT_G_BIT) {
+        result |= MTLColorWriteMaskGreen;
+    }
+    if (mask & SDL_GPU_COLORCOMPONENT_B_BIT) {
+        result |= MTLColorWriteMaskBlue;
+    }
+    if (mask & SDL_GPU_COLORCOMPONENT_A_BIT) {
+        result |= MTLColorWriteMaskAlpha;
+    }
+    return result;
+}
+
+// Structs
+
+typedef struct MetalTexture
+{
+    id<MTLTexture> handle;
+    id<MTLTexture> msaaHandle;
+    SDL_AtomicInt referenceCount;
+} MetalTexture;
+
+typedef struct MetalTextureContainer
+{
+    TextureCommonHeader header;
+
+    MetalTexture *activeTexture;
+    Uint8 canBeCycled;
+
+    Uint32 textureCapacity;
+    Uint32 textureCount;
+    MetalTexture **textures;
+
+    char *debugName;
+} MetalTextureContainer;
+
+typedef struct MetalFence
+{
+    SDL_AtomicInt complete;
+} MetalFence;
+
+typedef struct MetalWindowData
+{
+    SDL_Window *window;
+    SDL_MetalView view;
+    CAMetalLayer *layer;
+    id<CAMetalDrawable> drawable;
+    MetalTexture texture;
+    MetalTextureContainer textureContainer;
+} MetalWindowData;
+
+typedef struct MetalShader
+{
+    id<MTLLibrary> library;
+    id<MTLFunction> function;
+
+    Uint32 samplerCount;
+    Uint32 uniformBufferCount;
+    Uint32 storageBufferCount;
+    Uint32 storageTextureCount;
+} MetalShader;
+
+typedef struct MetalGraphicsPipeline
+{
+    id<MTLRenderPipelineState> handle;
+
+    float blendConstants[4];
+    Uint32 sampleMask;
+
+    SDL_GpuRasterizerState rasterizerState;
+    SDL_GpuPrimitiveType primitiveType;
+
+    id<MTLDepthStencilState> depthStencilState;
+    Uint8 stencilReference;
+
+    Uint32 vertexSamplerCount;
+    Uint32 vertexUniformBufferCount;
+    Uint32 vertexStorageBufferCount;
+    Uint32 vertexStorageTextureCount;
+
+    Uint32 fragmentSamplerCount;
+    Uint32 fragmentUniformBufferCount;
+    Uint32 fragmentStorageBufferCount;
+    Uint32 fragmentStorageTextureCount;
+} MetalGraphicsPipeline;
+
+typedef struct MetalComputePipeline
+{
+    id<MTLComputePipelineState> handle;
+    Uint32 readOnlyStorageTextureCount;
+    Uint32 writeOnlyStorageTextureCount;
+    Uint32 readOnlyStorageBufferCount;
+    Uint32 writeOnlyStorageBufferCount;
+    Uint32 uniformBufferCount;
+    Uint32 threadCountX;
+    Uint32 threadCountY;
+    Uint32 threadCountZ;
+} MetalComputePipeline;
+
+typedef struct MetalBuffer
+{
+    id<MTLBuffer> handle;
+    SDL_AtomicInt referenceCount;
+} MetalBuffer;
+
+typedef struct MetalBufferContainer
+{
+    MetalBuffer *activeBuffer;
+    Uint32 size;
+
+    Uint32 bufferCapacity;
+    Uint32 bufferCount;
+    MetalBuffer **buffers;
+
+    SDL_bool isPrivate;
+    SDL_bool isWriteOnly;
+    char *debugName;
+} MetalBufferContainer;
+
+typedef struct MetalUniformBuffer
+{
+    id<MTLBuffer> handle;
+    Uint32 writeOffset;
+    Uint32 drawOffset;
+} MetalUniformBuffer;
+
+typedef struct MetalRenderer MetalRenderer;
+
+typedef struct MetalCommandBuffer
+{
+    CommandBufferCommonHeader common;
+    MetalRenderer *renderer;
+
+    // Native Handle
+    id<MTLCommandBuffer> handle;
+
+    // Presentation
+    MetalWindowData **windowDatas;
+    Uint32 windowDataCount;
+    Uint32 windowDataCapacity;
+
+    // Render Pass
+    id<MTLRenderCommandEncoder> renderEncoder;
+    MetalGraphicsPipeline *graphicsPipeline;
+    MetalBuffer *indexBuffer;
+    Uint32 indexBufferOffset;
+    SDL_GpuIndexElementSize indexElementSize;
+
+    // Copy Pass
+    id<MTLBlitCommandEncoder> blitEncoder;
+
+    // Compute Pass
+    id<MTLComputeCommandEncoder> computeEncoder;
+    MetalComputePipeline *computePipeline;
+
+    // Resource slot state
+    SDL_bool needVertexSamplerBind;
+    SDL_bool needVertexStorageTextureBind;
+    SDL_bool needVertexStorageBufferBind;
+    SDL_bool needVertexUniformBind;
+
+    SDL_bool needFragmentSamplerBind;
+    SDL_bool needFragmentStorageTextureBind;
+    SDL_bool needFragmentStorageBufferBind;
+    SDL_bool needFragmentUniformBind;
+
+    SDL_bool needComputeTextureBind;
+    SDL_bool needComputeBufferBind;
+    SDL_bool needComputeUniformBind;
+
+    id<MTLSamplerState> vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    id<MTLTexture> vertexTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    id<MTLTexture> vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
+    id<MTLBuffer> vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+
+    id<MTLSamplerState> fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    id<MTLTexture> fragmentTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    id<MTLTexture> fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
+    id<MTLBuffer> fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+
+    id<MTLTexture> computeReadOnlyTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
+    id<MTLBuffer> computeReadOnlyBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+    id<MTLTexture> computeWriteOnlyTextures[MAX_COMPUTE_WRITE_TEXTURES];
+    id<MTLBuffer> computeWriteOnlyBuffers[MAX_COMPUTE_WRITE_BUFFERS];
+
+    // Uniform buffers
+    MetalUniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+    MetalUniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+    MetalUniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+
+    MetalUniformBuffer **usedUniformBuffers;
+    Uint32 usedUniformBufferCount;
+    Uint32 usedUniformBufferCapacity;
+
+    // Fences
+    MetalFence *fence;
+    Uint8 autoReleaseFence;
+
+    // Reference Counting
+    MetalBuffer **usedBuffers;
+    Uint32 usedBufferCount;
+    Uint32 usedBufferCapacity;
+
+    MetalTexture **usedTextures;
+    Uint32 usedTextureCount;
+    Uint32 usedTextureCapacity;
+} MetalCommandBuffer;
+
+typedef struct MetalSampler
+{
+    id<MTLSamplerState> handle;
+} MetalSampler;
+
+typedef struct BlitPipeline
+{
+    SDL_GpuGraphicsPipeline *pipeline;
+    SDL_GpuTextureFormat format;
+} BlitPipeline;
+
+struct MetalRenderer
+{
+    // Reference to the parent device
+    SDL_GpuDevice *sdlGpuDevice;
+
+    id<MTLDevice> device;
+    id<MTLCommandQueue> queue;
+
+    SDL_bool debugMode;
+
+    MetalWindowData **claimedWindows;
+    Uint32 claimedWindowCount;
+    Uint32 claimedWindowCapacity;
+
+    MetalCommandBuffer **availableCommandBuffers;
+    Uint32 availableCommandBufferCount;
+    Uint32 availableCommandBufferCapacity;
+
+    MetalCommandBuffer **submittedCommandBuffers;
+    Uint32 submittedCommandBufferCount;
+    Uint32 submittedCommandBufferCapacity;
+
+    MetalFence **availableFences;
+    Uint32 availableFenceCount;
+    Uint32 availableFenceCapacity;
+
+    MetalUniformBuffer **uniformBufferPool;
+    Uint32 uniformBufferPoolCount;
+    Uint32 uniformBufferPoolCapacity;
+
+    MetalBufferContainer **bufferContainersToDestroy;
+    Uint32 bufferContainersToDestroyCount;
+    Uint32 bufferContainersToDestroyCapacity;
+
+    MetalTextureContainer **textureContainersToDestroy;
+    Uint32 textureContainersToDestroyCount;
+    Uint32 textureContainersToDestroyCapacity;
+
+    // Blit
+    SDL_GpuShader *blitVertexShader;
+    SDL_GpuShader *blitFrom2DShader;
+    SDL_GpuShader *blitFrom2DArrayShader;
+    SDL_GpuShader *blitFrom3DShader;
+    SDL_GpuShader *blitFromCubeShader;
+
+    SDL_GpuSampler *blitNearestSampler;
+    SDL_GpuSampler *blitLinearSampler;
+
+    BlitPipelineCacheEntry *blitPipelines;
+    Uint32 blitPipelineCount;
+    Uint32 blitPipelineCapacity;
+
+    // Mutexes
+    SDL_Mutex *submitLock;
+    SDL_Mutex *acquireCommandBufferLock;
+    SDL_Mutex *acquireUniformBufferLock;
+    SDL_Mutex *disposeLock;
+    SDL_Mutex *fenceLock;
+    SDL_Mutex *windowLock;
+};
+
+// Helper Functions
+
+static Uint32 METAL_INTERNAL_GetVertexBufferIndex(Uint32 binding)
+{
+    return METAL_MAX_BUFFER_COUNT - 1 - binding;
+}
+
+// FIXME: This should be moved into SDL_sysgpu.h
+static inline Uint32 METAL_INTERNAL_NextHighestAlignment(
+    Uint32 n,
+    Uint32 align)
+{
+    return align * ((n + align - 1) / align);
+}
+
+// Quit
+
+static void METAL_DestroyDevice(SDL_GpuDevice *device)
+{
+    MetalRenderer *renderer = (MetalRenderer *)device->driverData;
+
+    // Flush any remaining GPU work...
+    METAL_Wait(device->driverData);
+
+    // Release the window data
+    for (Sint32 i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) {
+        METAL_UnclaimWindow(device->driverData, renderer->claimedWindows[i]->window);
+    }
+    SDL_free(renderer->claimedWindows);
+
+    // Release the blit resources
+    METAL_INTERNAL_DestroyBlitResources(device->driverData);
+
+    // Release uniform buffers
+    for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
+        renderer->uniformBufferPool[i]->handle = nil;
+        SDL_free(renderer->uniformBufferPool[i]);
+    }
+    SDL_free(renderer->uniformBufferPool);
+
+    // Release destroyed resource lists
+    SDL_free(renderer->bufferContainersToDestroy);
+    SDL_free(renderer->textureContainersToDestroy);
+
+    // Release command buffer infrastructure
+    for (Uint32 i = 0; i < renderer->availableCommandBufferCount; i += 1) {
+        MetalCommandBuffer *commandBuffer = renderer->availableCommandBuffers[i];
+        SDL_free(commandBuffer->usedBuffers);
+        SDL_free(commandBuffer->usedTextures);
+        SDL_free(commandBuffer->usedUniformBuffers);
+        SDL_free(commandBuffer->windowDatas);
+        SDL_free(commandBuffer);
+    }
+    SDL_free(renderer->availableCommandBuffers);
+    SDL_free(renderer->submittedCommandBuffers);
+
+    // Release fence infrastructure
+    for (Uint32 i = 0; i < renderer->availableFenceCount; i += 1) {
+        SDL_free(renderer->availableFences[i]);
+    }
+    SDL_free(renderer->availableFences);
+
+    // Release the mutexes
+    SDL_DestroyMutex(renderer->submitLock);
+    SDL_DestroyMutex(renderer->acquireCommandBufferLock);
+    SDL_DestroyMutex(renderer->acquireUniformBufferLock);
+    SDL_DestroyMutex(renderer->disposeLock);
+    SDL_DestroyMutex(renderer->fenceLock);
+    SDL_DestroyMutex(renderer->windowLock);
+
+    // Release the command queue
+    renderer->queue = nil;
+
+    // Free the primary structures
+    SDL_free(renderer);
+    SDL_free(device);
+}
+
+// Resource tracking
+
+static void METAL_INTERNAL_TrackBuffer(
+    MetalCommandBuffer *commandBuffer,
+    MetalBuffer *buffer)
+{
+    TRACK_RESOURCE(
+        buffer,
+        MetalBuffer *,
+        usedBuffers,
+        usedBufferCount,
+        usedBufferCapacity);
+}
+
+static void METAL_INTERNAL_TrackTexture(
+    MetalCommandBuffer *commandBuffer,
+    MetalTexture *texture)
+{
+    TRACK_RESOURCE(
+        texture,
+        MetalTexture *,
+        usedTextures,
+        usedTextureCount,
+        usedTextureCapacity);
+}
+
+static void METAL_INTERNAL_TrackUniformBuffer(
+    MetalCommandBuffer *commandBuffer,
+    MetalUniformBuffer *uniformBuffer)
+{
+    Uint32 i;
+    for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
+        if (commandBuffer->usedUniformBuffers[i] == uniformBuffer) {
+            return;
+        }
+    }
+
+    if (commandBuffer->usedUniformBufferCount == commandBuffer->usedUniformBufferCapacity) {
+        commandBuffer->usedUniformBufferCapacity += 1;
+        commandBuffer->usedUniformBuffers = SDL_realloc(
+            commandBuffer->usedUniformBuffers,
+            commandBuffer->usedUniformBufferCapacity * sizeof(MetalUniformBuffer *));
+    }
+
+    commandBuffer->usedUniformBuffers[commandBuffer->usedUniformBufferCount] = uniformBuffer;
+    commandBuffer->usedUniformBufferCount += 1;
+}
+
+// Shader Compilation
+
+typedef struct MetalLibraryFunction
+{
+    id<MTLLibrary> library;
+    id<MTLFunction> function;
+} MetalLibraryFunction;
+
+// This function assumes that it's called from within an autorelease pool
+static MetalLibraryFunction METAL_INTERNAL_CompileShader(
+    MetalRenderer *renderer,
+    SDL_GpuShaderFormat format,
+    const Uint8 *code,
+    size_t codeSize,
+    const char *entryPointName)
+{
+    MetalLibraryFunction libraryFunction = { nil, nil };
+    id<MTLLibrary> library;
+    NSError *error;
+    dispatch_data_t data;
+    id<MTLFunction> function;
+
+    if (format == SDL_GPU_SHADERFORMAT_MSL) {
+        library = [renderer->device
+            newLibraryWithSource:@((const char *)code)
+                         options:nil
+                           error:&error];
+    } else if (format == SDL_GPU_SHADERFORMAT_METALLIB) {
+        data = dispatch_data_create(
+            code,
+            codeSize,
+            dispatch_get_global_queue(0, 0),
+            ^{ /* do nothing */ });
+        library = [renderer->device newLibraryWithData:data error:&error];
+    } else {
+        SDL_assert(!"SDL_gpu.c should have already validated this!");
+        return libraryFunction;
+    }
+
+    if (library == nil) {
+        SDL_LogError(
+            SDL_LOG_CATEGORY_GPU,
+            "Creating MTLLibrary failed: %s",
+            [[error description] cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+        return libraryFunction;
+    } else if (error != nil) {
+        SDL_LogWarn(
+            SDL_LOG_CATEGORY_GPU,
+            "Creating MTLLibrary failed: %s",
+            [[error description] cStringUsingEncoding:[NSString defaultCStringEncoding]]);
+    }
+
+    function = [library newFunctionWithName:@(entryPointName)];
+    if (function == nil) {
+        SDL_LogError(
+            SDL_LOG_CATEGORY_GPU,
+            "Creating MTLFunction failed");
+        return libraryFunction;
+    }
+
+    libraryFunction.library = library;
+    libraryFunction.function = function;
+    return libraryFunction;
+}
+
+// Disposal
+
+static void METAL_INTERNAL_DestroyTextureContainer(
+    MetalTextureContainer *container)
+{
+    for (Uint32 i = 0; i < container->textureCount; i += 1) {
+        container->textures[i]->handle = nil;
+        container->textures[i]->msaaHandle = nil;
+        SDL_free(container->textures[i]);
+    }
+    if (container->debugName != NULL) {
+        SDL_free(container->debugName);
+    }
+    SDL_free(container->textures);
+    SDL_free(container);
+}
+
+static void METAL_ReleaseTexture(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTexture *texture)
+{
+    MetalRenderer *renderer = (MetalRenderer *)driverData;
+    MetalTextureContainer *container = (MetalTextureContainer *)texture;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->textureContainersToDestroy,
+        MetalTextureContainer *,
+        renderer->textureContainersToDestroyCount + 1,
+        renderer->textureContainersToDestroyCapacity,
+        renderer->textureContainersToDestroyCapacity + 1);
+
+    renderer->textureContainersToDestroy[renderer->textureContainersToDestroyCount] = container;
+    renderer->textureContainersToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void METAL_ReleaseSampler(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuSampler *sampler)
+{
+    @autoreleasepool {
+        MetalSampler *metalSampler = (MetalSampler *)sampler;
+        metalSampler->handle = nil;
+        SDL_free(metalSampler);
+    }
+}
+
+static void METAL_INTERNAL_DestroyBufferContainer(
+    MetalBufferContainer *container)
+{
+    for (Uint32 i = 0; i < container->bufferCount; i += 1) {
+        container->buffers[i]->handle = nil;
+        SDL_free(container->buffers[i]);
+    }
+    if (container->debugName != NULL) {
+        SDL_free(container->debugName);
+    }
+    SDL_free(container->buffers);
+    SDL_free(container);
+}
+
+static void METAL_ReleaseBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBuffer *buffer)
+{
+    MetalRenderer *renderer = (MetalRenderer *)driverData;
+    MetalBufferContainer *container = (MetalBufferContainer *)buffer;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->bufferContainersToDestroy,
+        MetalBufferContainer *,
+        renderer->bufferContainersToDestroyCount + 1,
+        renderer->bufferContainersToDestroyCapacity,
+        renderer->bufferContainersToDestroyCapacity + 1);
+
+    renderer->bufferContainersToDestroy[renderer->bufferContainersToDestroyCount] = container;
+    renderer->bufferContainersToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void METAL_ReleaseTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer)
+{
+    METAL_ReleaseBuffer(
+        driverData,
+        (SDL_GpuBuffer *)transferBuffer);
+}
+
+static void METAL_ReleaseShader(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuShader *shader)
+{
+    @autoreleasepool {
+        MetalShader *metalShader = (MetalShader *)shader;
+        metalShader->function = nil;
+        metalShader->library = nil;
+        SDL_free(metalShader);
+    }
+}
+
+static void METAL_ReleaseComputePipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuComputePipeline *computePipeline)
+{
+    @autoreleasepool {
+        MetalComputePipeline *metalComputePipeline = (MetalComputePipeline *)computePipeline;
+        metalComputePipeline->handle = nil;
+        SDL_free(metalComputePipeline);
+    }
+}
+
+static void METAL_ReleaseGraphicsPipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuGraphicsPipeline *graphicsPipeline)
+{
+    @autoreleasepool {
+        MetalGraphicsPipeline *metalGraphicsPipeline = (MetalGraphicsPipeline *)graphicsPipeline;
+        metalGraphicsPipeline->handle = nil;
+        metalGraphicsPipeline->depthStencilState = nil;
+        SDL_free(metalGraphicsPipeline);
+    }
+}
+
+// Pipeline Creation
+
+static SDL_GpuComputePipeline *METAL_CreateComputePipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuComputePipelineCreateInfo *pipelineCreateInfo)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MetalLibraryFunction libraryFunction;
+        id<MTLComputePipelineState> handle;
+        MetalComputePipeline *pipeline;
+        NSError *error;
+
+        libraryFunction = METAL_INTERNAL_CompileShader(
+            renderer,
+            pipelineCreateInfo->format,
+            pipelineCreateInfo->code,
+            pipelineCreateInfo->codeSize,
+            pipelineCreateInfo->entryPointName);
+
+        if (libraryFunction.library == nil || libraryFunction.function == nil) {
+            return NULL;
+        }
+
+        handle = [renderer->device newComputePipelineStateWithFunction:libraryFunction.function error:&error];
+        if (error != NULL) {
+            SDL_LogError(
+                SDL_LOG_CATEGORY_GPU,
+                "Creating compute pipeline failed: %s", [[error description] UTF8String]);
+            return NULL;
+        }
+
+        pipeline = SDL_malloc(sizeof(MetalComputePipeline));
+        pipeline->handle = handle;
+        pipeline->readOnlyStorageTextureCount = pipelineCreateInfo->readOnlyStorageTextureCount;
+        pipeline->writeOnlyStorageTextureCount = pipelineCreateInfo->writeOnlyStorageTextureCount;
+        pipeline->readOnlyStorageBufferCount = pipelineCreateInfo->readOnlyStorageBufferCount;
+        pipeline->writeOnlyStorageBufferCount = pipelineCreateInfo->writeOnlyStorageBufferCount;
+        pipeline->uniformBufferCount = pipelineCreateInfo->uniformBufferCount;
+        pipeline->threadCountX = pipelineCreateInfo->threadCountX;
+        pipeline->threadCountY = pipelineCreateInfo->threadCountY;
+        pipeline->threadCountZ = pipelineCreateInfo->threadCountZ;
+
+        return (SDL_GpuComputePipeline *)pipeline;
+    }
+}
+
+static SDL_GpuGraphicsPipeline *METAL_CreateGraphicsPipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuGraphicsPipelineCreateInfo *pipelineCreateInfo)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MetalShader *vertexShader = (MetalShader *)pipelineCreateInfo->vertexShader;
+        MetalShader *fragmentShader = (MetalShader *)pipelineCreateInfo->fragmentShader;
+        MTLRenderPipelineDescriptor *pipelineDescriptor;
+        SDL_GpuColorAttachmentBlendState *blendState;
+        MTLVertexDescriptor *vertexDescriptor;
+        Uint32 binding;
+        MTLDepthStencilDescriptor *depthStencilDescriptor;
+        MTLStencilDescriptor *frontStencilDescriptor = NULL;
+        MTLStencilDescriptor *backStencilDescriptor = NULL;
+        id<MTLDepthStencilState> depthStencilState = nil;
+        id<MTLRenderPipelineState> pipelineState = nil;
+        NSError *error = NULL;
+        MetalGraphicsPipeline *result = NULL;
+
+        pipelineDescriptor = [MTLRenderPipelineDescriptor new];
+
+        // Blend
+
+        for (Uint32 i = 0; i < pipelineCreateInfo->attachmentInfo.colorAttachmentCount; i += 1) {
+            blendState = &pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].blendState;
+
+            pipelineDescriptor.colorAttachments[i].pixelFormat = SDLToMetal_SurfaceFormat[pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].format];
+            pipelineDescriptor.colorAttachments[i].writeMask = SDLToMetal_ColorWriteMask(blendState->colorWriteMask);
+            pipelineDescriptor.colorAttachments[i].blendingEnabled = blendState->blendEnable;
+            pipelineDescriptor.colorAttachments[i].rgbBlendOperation = SDLToMetal_BlendOp[blendState->colorBlendOp];
+            pipelineDescriptor.colorAttachments[i].alphaBlendOperation = SDLToMetal_BlendOp[blendState->alphaBlendOp];
+            pipelineDescriptor.colorAttachments[i].sourceRGBBlendFactor = SDLToMetal_BlendFactor[blendState->srcColorBlendFactor];
+            pipelineDescriptor.colorAttachments[i].sourceAlphaBlendFactor = SDLToMetal_BlendFactor[blendState->srcAlphaBlendFactor];
+            pipelineDescriptor.colorAttachments[i].destinationRGBBlendFactor = SDLToMetal_BlendFactor[blendState->dstColorBlendFactor];
+            pipelineDescriptor.colorAttachments[i].destinationAlphaBlendFactor = SDLToMetal_BlendFactor[blendState->dstAlphaBlendFactor];
+        }
+
+        // Multisample
+
+        pipelineDescriptor.rasterSampleCount = SDLToMetal_SampleCount[pipelineCreateInfo->multisampleState.sampleCount];
+
+        // Depth Stencil
+
+        if (pipelineCreateInfo->attachmentInfo.hasDepthStencilAttachment) {
+            pipelineDescriptor.depthAttachmentPixelFormat = SDLToMetal_SurfaceFormat[pipelineCreateInfo->attachmentInfo.depthStencilFormat];
+
+            if (pipelineCreateInfo->depthStencilState.stencilTestEnable) {
+                pipelineDescriptor.stencilAttachmentPixelFormat = SDLToMetal_SurfaceFormat[pipelineCreateInfo->attachmentInfo.depthStencilFormat];
+
+                frontStencilDescriptor = [MTLStencilDescriptor new];
+                frontStencilDescriptor.stencilCompareFunction = SDLToMetal_CompareOp[pipelineCreateInfo->depthStencilState.frontStencilState.compareOp];
+                frontStencilDescriptor.stencilFailureOperation = SDLToMetal_StencilOp[pipelineCreateInfo->depthStencilState.frontStencilState.failOp];
+                frontStencilDescriptor.depthStencilPassOperation = SDLToMetal_StencilOp[pipelineCreateInfo->depthStencilState.frontStencilState.passOp];
+                frontStencilDescriptor.depthFailureOperation = SDLToMetal_StencilOp[pipelineCreateInfo->depthStencilState.frontStencilState.depthFailOp];
+                frontStencilDescriptor.readMask = pipelineCreateInfo->depthStencilState.compareMask;
+                frontStencilDescriptor.writeMask = pipelineCreateInfo->depthStencilState.writeMask;
+
+                backStencilDescriptor = [MTLStencilDescriptor new];
+                backStencilDescriptor.stencilCompareFunction = SDLToMetal_CompareOp[pipelineCreateInfo->depthStencilState.backStencilState.compareOp];
+                backStencilDescriptor.stencilFailureOperation = SDLToMetal_StencilOp[pipelineCreateInfo->depthStencilState.backStencilState.failOp];
+                backStencilDescriptor.depthStencilPassOperation = SDLToMetal_StencilOp[pipelineCreateInfo->depthStencilState.backStencilState.passOp];
+                backStencilDescriptor.depthFailureOperation = SDLToMetal_StencilOp[pipelineCreateInfo->depthStencilState.backStencilState.depthFailOp];
+                backStencilDescriptor.readMask = pipelineCreateInfo->depthStencilState.compareMask;
+                backStencilDescriptor.writeMask = pipelineCreateInfo->depthStencilState.writeMask;
+            }
+
+            depthStencilDescriptor = [MTLDepthStencilDescriptor new];
+            depthStencilDescriptor.depthCompareFunction = pipelineCreateInfo->depthStencilState.depthTestEnable ? SDLToMetal_CompareOp[pipelineCreateInfo->depthStencilState.compareOp] : MTLCompareFunctionAlways;
+            depthStencilDescriptor.depthWriteEnabled = pipelineCreateInfo->depthStencilState.depthWriteEnable;
+            depthStencilDescriptor.frontFaceStencil = frontStencilDescriptor;
+            depthStencilDescriptor.backFaceStencil = backStencilDescriptor;
+
+            depthStencilState = [renderer->device newDepthStencilStateWithDescriptor:depthStencilDescriptor];
+        }
+
+        // Shaders
+
+        pipelineDescriptor.vertexFunction = vertexShader->function;
+        pipelineDescriptor.fragmentFunction = fragmentShader->function;
+
+        // Vertex Descriptor
+
+        if (pipelineCreateInfo->vertexInputState.vertexBindingCount > 0) {
+            vertexDescriptor = [MTLVertexDescriptor vertexDescriptor];
+
+            for (Uint32 i = 0; i < pipelineCreateInfo->vertexInputState.vertexAttributeCount; i += 1) {
+                Uint32 loc = pipelineCreateInfo->vertexInputState.vertexAttributes[i].location;
+                vertexDescriptor.attributes[loc].format = SDLToMetal_VertexFormat[pipelineCreateInfo->vertexInputState.vertexAttributes[i].format];
+                vertexDescriptor.attributes[loc].offset = pipelineCreateInfo->vertexInputState.vertexAttributes[i].offset;
+                vertexDescriptor.attributes[loc].bufferIndex = METAL_INTERNAL_GetVertexBufferIndex(pipelineCreateInfo->vertexInputState.vertexAttributes[i].binding);
+            }
+
+            for (Uint32 i = 0; i < pipelineCreateInfo->vertexInputState.vertexBindingCount; i += 1) {
+                binding = METAL_INTERNAL_GetVertexBufferIndex(pipelineCreateInfo->vertexInputState.vertexBindings[i].binding);
+                vertexDescriptor.layouts[binding].stepFunction = SDLToMetal_StepFunction[pipelineCreateInfo->vertexInputState.vertexBindings[i].inputRate];
+                vertexDescriptor.layouts[binding].stepRate = (pipelineCreateInfo->vertexInputState.vertexBindings[i].inputRate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) ? pipelineCreateInfo->vertexInputState.vertexBindings[i].instanceStepRate : 1;
+                vertexDescriptor.layouts[binding].stride = pipelineCreateInfo->vertexInputState.vertexBindings[i].stride;
+            }
+
+            pipelineDescriptor.vertexDescriptor = vertexDescriptor;
+        }
+
+        // Create the graphics pipeline
+
+        pipelineState = [renderer->device newRenderPipelineStateWithDescriptor:pipelineDescriptor error:&error];
+        if (error != NULL) {
+            SDL_LogError(
+                SDL_LOG_CATEGORY_GPU,
+                "Creating render pipeline failed: %s", [[error description] UTF8String]);
+            return NULL;
+        }
+
+        result = SDL_malloc(sizeof(MetalGraphicsPipeline));
+        result->handle = pipelineState;
+        result->blendConstants[0] = pipelineCreateInfo->blendConstants[0];
+        result->blendConstants[1] = pipelineCreateInfo->blendConstants[1];
+        result->blendConstants[2] = pipelineCreateInfo->blendConstants[2];
+        result->blendConstants[3] = pipelineCreateInfo->blendConstants[3];
+        result->sampleMask = pipelineCreateInfo->multisampleState.sampleMask;
+        result->depthStencilState = depthStencilState;
+        result->stencilReference = pipelineCreateInfo->depthStencilState.reference;
+        result->rasterizerState = pipelineCreateInfo->rasterizerState;
+        result->primitiveType = pipelineCreateInfo->primitiveType;
+        result->vertexSamplerCount = vertexShader->samplerCount;
+        result->vertexUniformBufferCount = vertexShader->uniformBufferCount;
+        result->vertexStorageBufferCount = vertexShader->storageBufferCount;
+        result->vertexStorageTextureCount = vertexShader->storageTextureCount;
+        result->fragmentSamplerCount = fragmentShader->samplerCount;
+        result->fragmentUniformBufferCount = fragmentShader->uniformBufferCount;
+        result->fragmentStorageBufferCount = fragmentShader->storageBufferCount;
+        result->fragmentStorageTextureCount = fragmentShader->storageTextureCount;
+        return (SDL_GpuGraphicsPipeline *)result;
+    }
+}
+
+// Debug Naming
+
+static void METAL_SetBufferName(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBuffer *buffer,
+    const char *text)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MetalBufferContainer *container = (MetalBufferContainer *)buffer;
+        size_t textLength = SDL_strlen(text) + 1;
+
+        if (renderer->debugMode) {
+            container->debugName = SDL_realloc(
+                container->debugName,
+                textLength);
+
+            SDL_utf8strlcpy(
+                container->debugName,
+                text,
+                textLength);
+
+            for (Uint32 i = 0; i < container->bufferCount; i += 1) {
+                container->buffers[i]->handle.label = @(text);
+            }
+        }
+    }
+}
+
+static void METAL_SetTextureName(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTexture *texture,
+    const char *text)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MetalTextureContainer *container = (MetalTextureContainer *)texture;
+        size_t textLength = SDL_strlen(text) + 1;
+
+        if (renderer->debugMode) {
+            container->debugName = SDL_realloc(
+                container->debugName,
+                textLength);
+
+            SDL_utf8strlcpy(
+                container->debugName,
+                text,
+                textLength);
+
+            for (Uint32 i = 0; i < container->textureCount; i += 1) {
+                container->textures[i]->handle.label = @(text);
+            }
+        }
+    }
+}
+
+static void METAL_InsertDebugLabel(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *text)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        NSString *label = @(text);
+
+        if (metalCommandBuffer->renderEncoder) {
+            [metalCommandBuffer->renderEncoder insertDebugSignpost:label];
+        } else if (metalCommandBuffer->blitEncoder) {
+            [metalCommandBuffer->blitEncoder insertDebugSignpost:label];
+        } else if (metalCommandBuffer->computeEncoder) {
+            [metalCommandBuffer->computeEncoder insertDebugSignpost:label];
+        } else {
+            // Metal doesn't have insertDebugSignpost for command buffers...
+            [metalCommandBuffer->handle pushDebugGroup:label];
+            [metalCommandBuffer->handle popDebugGroup];
+        }
+    }
+}
+
+static void METAL_PushDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *name)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        NSString *label = @(name);
+
+        if (metalCommandBuffer->renderEncoder) {
+            [metalCommandBuffer->renderEncoder pushDebugGroup:label];
+        } else if (metalCommandBuffer->blitEncoder) {
+            [metalCommandBuffer->blitEncoder pushDebugGroup:label];
+        } else if (metalCommandBuffer->computeEncoder) {
+            [metalCommandBuffer->computeEncoder pushDebugGroup:label];
+        } else {
+            [metalCommandBuffer->handle pushDebugGroup:label];
+        }
+    }
+}
+
+static void METAL_PopDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+
+        if (metalCommandBuffer->renderEncoder) {
+            [metalCommandBuffer->renderEncoder popDebugGroup];
+        } else if (metalCommandBuffer->blitEncoder) {
+            [metalCommandBuffer->blitEncoder popDebugGroup];
+        } else if (metalCommandBuffer->computeEncoder) {
+            [metalCommandBuffer->computeEncoder popDebugGroup];
+        } else {
+            [metalCommandBuffer->handle popDebugGroup];
+        }
+    }
+}
+
+// Resource Creation
+
+static SDL_GpuSampler *METAL_CreateSampler(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuSamplerCreateInfo *samplerCreateInfo)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MTLSamplerDescriptor *samplerDesc = [MTLSamplerDescriptor new];
+        id<MTLSamplerState> sampler;
+        MetalSampler *metalSampler;
+
+        samplerDesc.rAddressMode = SDLToMetal_SamplerAddressMode[samplerCreateInfo->addressModeU];
+        samplerDesc.sAddressMode = SDLToMetal_SamplerAddressMode[samplerCreateInfo->addressModeV];
+        samplerDesc.tAddressMode = SDLToMetal_SamplerAddressMode[samplerCreateInfo->addressModeW];
+        samplerDesc.minFilter = SDLToMetal_MinMagFilter[samplerCreateInfo->minFilter];
+        samplerDesc.magFilter = SDLToMetal_MinMagFilter[samplerCreateInfo->magFilter];
+        samplerDesc.mipFilter = SDLToMetal_MipFilter[samplerCreateInfo->mipmapMode]; // FIXME: Is this right with non-mipmapped samplers?
+        samplerDesc.lodMinClamp = samplerCreateInfo->minLod;
+        samplerDesc.lodMaxClamp = samplerCreateInfo->maxLod;
+        samplerDesc.maxAnisotropy = (NSUInteger)((samplerCreateInfo->anisotropyEnable) ? samplerCreateInfo->maxAnisotropy : 1);
+        samplerDesc.compareFunction = (samplerCreateInfo->compareEnable) ? SDLToMetal_CompareOp[samplerCreateInfo->compareOp] : MTLCompareFunctionAlways;
+        samplerDesc.borderColor = MTLSamplerBorderColorTransparentBlack; // arbitrary, unused
+
+        sampler = [renderer->device newSamplerStateWithDescriptor:samplerDesc];
+        if (sampler == NULL) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create sampler");
+            return NULL;
+        }
+
+        metalSampler = (MetalSampler *)SDL_malloc(sizeof(MetalSampler));
+        metalSampler->handle = sampler;
+        return (SDL_GpuSampler *)metalSampler;
+    }
+}
+
+static SDL_GpuShader *METAL_CreateShader(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuShaderCreateInfo *shaderCreateInfo)
+{
+    @autoreleasepool {
+        MetalLibraryFunction libraryFunction;
+        MetalShader *result;
+
+        libraryFunction = METAL_INTERNAL_CompileShader(
+            (MetalRenderer *)driverData,
+            shaderCreateInfo->format,
+            shaderCreateInfo->code,
+            shaderCreateInfo->codeSize,
+            shaderCreateInfo->entryPointName);
+
+        if (libraryFunction.library == nil || libraryFunction.function == nil) {
+            return NULL;
+        }
+
+        result = SDL_malloc(sizeof(MetalShader));
+        result->library = libraryFunction.library;
+        result->function = libraryFunction.function;
+        result->samplerCount = shaderCreateInfo->samplerCount;
+        result->storageBufferCount = shaderCreateInfo->storageBufferCount;
+        result->storageTextureCount = shaderCreateInfo->storageTextureCount;
+        result->uniformBufferCount = shaderCreateInfo->uniformBufferCount;
+        return (SDL_GpuShader *)result;
+    }
+}
+
+// This function assumes that it's called from within an autorelease pool
+static MetalTexture *METAL_INTERNAL_CreateTexture(
+    MetalRenderer *renderer,
+    SDL_GpuTextureCreateInfo *textureCreateInfo)
+{
+    MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor new];
+    id<MTLTexture> texture;
+    id<MTLTexture> msaaTexture = NULL;
+    MetalTexture *metalTexture;
+
+    textureDescriptor.textureType = SDLToMetal_TextureType[textureCreateInfo->type];
+    textureDescriptor.pixelFormat = SDLToMetal_SurfaceFormat[textureCreateInfo->format];
+    // This format isn't natively supported so let's swizzle!
+    if (textureCreateInfo->format == SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM) {
+        textureDescriptor.swizzle = MTLTextureSwizzleChannelsMake(
+            MTLTextureSwizzleBlue,
+            MTLTextureSwizzleGreen,
+            MTLTextureSwizzleRed,
+            MTLTextureSwizzleAlpha);
+    }
+
+    textureDescriptor.width = textureCreateInfo->width;
+    textureDescriptor.height = textureCreateInfo->height;
+    textureDescriptor.depth = (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_3D) ? textureCreateInfo->layerCountOrDepth : 1;
+    textureDescriptor.mipmapLevelCount = textureCreateInfo->levelCount;
+    textureDescriptor.sampleCount = 1;
+    textureDescriptor.arrayLength = (textureCreateInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) ? textureCreateInfo->layerCountOrDepth : 1;
+    textureDescriptor.storageMode = MTLStorageModePrivate;
+
+    textureDescriptor.usage = 0;
+    if (textureCreateInfo->usageFlags & (SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT |
+                                         SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT)) {
+        textureDescriptor.usage |= MTLTextureUsageRenderTarget;
+    }
+    if (textureCreateInfo->usageFlags & (SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT |
+                                         SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT |
+                                         SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT)) {
+        textureDescriptor.usage |= MTLTextureUsageShaderRead;
+    }
+    if (textureCreateInfo->usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+        textureDescriptor.usage |= MTLTextureUsageShaderWrite;
+    }
+
+    texture = [renderer->device newTextureWithDescriptor:textureDescriptor];
+    if (texture == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create MTLTexture!");
+        return NULL;
+    }
+
+    // Create the MSAA texture, if needed
+    if (textureCreateInfo->sampleCount > SDL_GPU_SAMPLECOUNT_1 && textureCreateInfo->type == SDL_GPU_TEXTURETYPE_2D) {
+        textureDescriptor.textureType = MTLTextureType2DMultisample;
+        textureDescriptor.sampleCount = SDLToMetal_SampleCount[textureCreateInfo->sampleCount];
+        textureDescriptor.usage = MTLTextureUsageRenderTarget;
+
+        msaaTexture = [renderer->device newTextureWithDescriptor:textureDescriptor];
+        if (msaaTexture == NULL) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create MSAA MTLTexture!");
+            return NULL;
+        }
+    }
+
+    metalTexture = (MetalTexture *)SDL_malloc(sizeof(MetalTexture));
+    metalTexture->handle = texture;
+    metalTexture->msaaHandle = msaaTexture;
+    SDL_AtomicSet(&metalTexture->referenceCount, 0);
+    return metalTexture;
+}
+
+static SDL_bool METAL_SupportsSampleCount(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureFormat format,
+    SDL_GpuSampleCount sampleCount)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        NSUInteger mtlSampleCount = SDLToMetal_SampleCount[sampleCount];
+        return [renderer->device supportsTextureSampleCount:mtlSampleCount];
+    }
+}
+
+static SDL_GpuTexture *METAL_CreateTexture(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureCreateInfo *textureCreateInfo)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MetalTextureContainer *container;
+        MetalTexture *texture;
+
+        texture = METAL_INTERNAL_CreateTexture(
+            renderer,
+            textureCreateInfo);
+
+        if (texture == NULL) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create texture!");
+            return NULL;
+        }
+
+        container = SDL_malloc(sizeof(MetalTextureContainer));
+        container->canBeCycled = 1;
+        container->header.info = *textureCreateInfo;
+        container->activeTexture = texture;
+        container->textureCapacity = 1;
+        container->textureCount = 1;
+        container->textures = SDL_malloc(
+            container->textureCapacity * sizeof(MetalTexture *));
+        container->textures[0] = texture;
+        container->debugName = NULL;
+
+        return (SDL_GpuTexture *)container;
+    }
+}
+
+// This function assumes that it's called from within an autorelease pool
+static MetalTexture *METAL_INTERNAL_PrepareTextureForWrite(
+    MetalRenderer *renderer,
+    MetalTextureContainer *container,
+    SDL_bool cycle)
+{
+    Uint32 i;
+
+    // Cycle the active texture handle if needed
+    if (cycle && container->canBeCycled) {
+        for (i = 0; i < container->textureCount; i += 1) {
+            if (SDL_AtomicGet(&container->textures[i]->referenceCount) == 0) {
+                container->activeTexture = container->textures[i];
+                return container->activeTexture;
+            }
+        }
+
+        EXPAND_ARRAY_IF_NEEDED(
+            container->textures,
+            MetalTexture *,
+            container->textureCount + 1,
+            container->textureCapacity,
+            container->textureCapacity + 1);
+
+        container->textures[container->textureCount] = METAL_INTERNAL_CreateTexture(
+            renderer,
+            &container->header.info);
+        container->textureCount += 1;
+
+        container->activeTexture = container->textures[container->textureCount - 1];
+
+        if (renderer->debugMode && container->debugName != NULL) {
+            container->activeTexture->handle.label = @(container->debugName);
+        }
+    }
+
+    return container->activeTexture;
+}
+
+// This function assumes that it's called from within an autorelease pool
+static MetalBuffer *METAL_INTERNAL_CreateBuffer(
+    MetalRenderer *renderer,
+    Uint32 sizeInBytes,
+    MTLResourceOptions resourceOptions)
+{
+    id<MTLBuffer> bufferHandle;
+    MetalBuffer *metalBuffer;
+
+    // Storage buffers have to be 4-aligned, so might as well align them all
+    sizeInBytes = METAL_INTERNAL_NextHighestAlignment(sizeInBytes, 4);
+
+    bufferHandle = [renderer->device newBufferWithLength:sizeInBytes options:resourceOptions];
+    if (bufferHandle == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not create buffer");
+        return NULL;
+    }
+
+    metalBuffer = SDL_malloc(sizeof(MetalBuffer));
+    metalBuffer->handle = bufferHandle;
+    SDL_AtomicSet(&metalBuffer->referenceCount, 0);
+
+    return metalBuffer;
+}
+
+// This function assumes that it's called from within an autorelease pool
+static MetalBufferContainer *METAL_INTERNAL_CreateBufferContainer(
+    MetalRenderer *renderer,
+    Uint32 sizeInBytes,
+    SDL_bool isPrivate,
+    SDL_bool isWriteOnly)
+{
+    MetalBufferContainer *container = SDL_malloc(sizeof(MetalBufferContainer));
+    MTLResourceOptions resourceOptions;
+
+    container->size = sizeInBytes;
+    container->bufferCapacity = 1;
+    container->bufferCount = 1;
+    container->buffers = SDL_malloc(
+        container->bufferCapacity * sizeof(MetalBuffer *));
+    container->isPrivate = isPrivate;
+    container->isWriteOnly = isWriteOnly;
+    container->debugName = NULL;
+
+    if (isPrivate) {
+        resourceOptions = MTLResourceStorageModePrivate;
+    } else {
+        if (isWriteOnly) {
+            resourceOptions = MTLResourceCPUCacheModeWriteCombined;
+        } else {
+            resourceOptions = MTLResourceCPUCacheModeDefaultCache;
+        }
+    }
+
+    container->buffers[0] = METAL_INTERNAL_CreateBuffer(
+        renderer,
+        sizeInBytes,
+        resourceOptions);
+    container->activeBuffer = container->buffers[0];
+
+    return container;
+}
+
+static SDL_GpuBuffer *METAL_CreateBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBufferUsageFlags usageFlags,
+    Uint32 sizeInBytes)
+{
+    @autoreleasepool {
+        return (SDL_GpuBuffer *)METAL_INTERNAL_CreateBufferContainer(
+            (MetalRenderer *)driverData,
+            sizeInBytes,
+            SDL_TRUE,
+            SDL_FALSE);
+    }
+}
+
+static SDL_GpuTransferBuffer *METAL_CreateTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBufferUsage usage,
+    Uint32 sizeInBytes)
+{
+    @autoreleasepool {
+        return (SDL_GpuTransferBuffer *)METAL_INTERNAL_CreateBufferContainer(
+            (MetalRenderer *)driverData,
+            sizeInBytes,
+            SDL_FALSE,
+            usage == SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD);
+    }
+}
+
+// This function assumes that it's called from within an autorelease pool
+static MetalUniformBuffer *METAL_INTERNAL_CreateUniformBuffer(
+    MetalRenderer *renderer,
+    Uint32 sizeInBytes)
+{
+    MetalUniformBuffer *uniformBuffer;
+    id<MTLBuffer> bufferHandle;
+
+    bufferHandle = [renderer->device newBufferWithLength:sizeInBytes options:MTLResourceCPUCacheModeWriteCombined];
+    if (bufferHandle == nil) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not create uniform buffer");
+        return NULL;
+    }
+
+    uniformBuffer = SDL_malloc(sizeof(MetalUniformBuffer));
+    uniformBuffer->handle = bufferHandle;
+    uniformBuffer->writeOffset = 0;
+    uniformBuffer->drawOffset = 0;
+
+    return uniformBuffer;
+}
+
+// This function assumes that it's called from within an autorelease pool
+static MetalBuffer *METAL_INTERNAL_PrepareBufferForWrite(
+    MetalRenderer *renderer,
+    MetalBufferContainer *container,
+    SDL_bool cycle)
+{
+    MTLResourceOptions resourceOptions;
+    Uint32 i;
+
+    // Cycle if needed
+    if (cycle && SDL_AtomicGet(&container->activeBuffer->referenceCount) > 0) {
+        for (i = 0; i < container->bufferCount; i += 1) {
+            if (SDL_AtomicGet(&container->buffers[i]->referenceCount) == 0) {
+                container->activeBuffer = container->buffers[i];
+                return container->activeBuffer;
+            }
+        }
+
+        EXPAND_ARRAY_IF_NEEDED(
+            container->buffers,
+            MetalBuffer *,
+            container->bufferCount + 1,
+            container->bufferCapacity,
+            container->bufferCapacity + 1);
+
+        if (container->isPrivate) {
+            resourceOptions = MTLResourceStorageModePrivate;
+        } else {
+            if (container->isWriteOnly) {
+                resourceOptions = MTLResourceCPUCacheModeWriteCombined;
+            } else {
+                resourceOptions = MTLResourceCPUCacheModeDefaultCache;
+            }
+        }
+
+        container->buffers[container->bufferCount] = METAL_INTERNAL_CreateBuffer(
+            renderer,
+            container->size,
+            resourceOptions);
+        container->bufferCount += 1;
+
+        container->activeBuffer = container->buffers[container->bufferCount - 1];
+
+        if (renderer->debugMode && container->debugName != NULL) {
+            container->activeBuffer->handle.label = @(container->debugName);
+        }
+    }
+
+    return container->activeBuffer;
+}
+
+// TransferBuffer Data
+
+static void *METAL_MapTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer,
+    SDL_bool cycle)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MetalBufferContainer *container = (MetalBufferContainer *)transferBuffer;
+        MetalBuffer *buffer = METAL_INTERNAL_PrepareBufferForWrite(renderer, container, cycle);
+        return [buffer->handle contents];
+    }
+}
+
+static void METAL_UnmapTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer)
+{
+#ifdef SDL_PLATFORM_MACOS
+    @autoreleasepool {
+        // FIXME: Is this necessary?
+        MetalBufferContainer *container = (MetalBufferContainer *)transferBuffer;
+        MetalBuffer *buffer = container->activeBuffer;
+        if (buffer->handle.storageMode == MTLStorageModeManaged) {
+            [buffer->handle didModifyRange:NSMakeRange(0, container->size)];
+        }
+    }
+#endif
+}
+
+// Copy Pass
+
+static void METAL_BeginCopyPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        metalCommandBuffer->blitEncoder = [metalCommandBuffer->handle blitCommandEncoder];
+    }
+}
+
+static void METAL_UploadToTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureTransferInfo *source,
+    SDL_GpuTextureRegion *destination,
+    SDL_bool cycle)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalRenderer *renderer = metalCommandBuffer->renderer;
+        MetalBufferContainer *bufferContainer = (MetalBufferContainer *)source->transferBuffer;
+        MetalTextureContainer *textureContainer = (MetalTextureContainer *)destination->texture;
+
+        MetalTexture *metalTexture = METAL_INTERNAL_PrepareTextureForWrite(renderer, textureContainer, cycle);
+
+        [metalCommandBuffer->blitEncoder
+                 copyFromBuffer:bufferContainer->activeBuffer->handle
+                   sourceOffset:source->offset
+              sourceBytesPerRow:BytesPerRow(destination->w, textureContainer->header.info.format)
+            sourceBytesPerImage:BytesPerImage(destination->w, destination->h, textureContainer->header.info.format)
+                     sourceSize:MTLSizeMake(destination->w, destination->h, destination->d)
+                      toTexture:metalTexture->handle
+               destinationSlice:destination->layer
+               destinationLevel:destination->mipLevel
+              destinationOrigin:MTLOriginMake(destination->x, destination->y, destination->z)];
+
+        METAL_INTERNAL_TrackTexture(metalCommandBuffer, metalTexture);
+        METAL_INTERNAL_TrackBuffer(metalCommandBuffer, bufferContainer->activeBuffer);
+    }
+}
+
+static void METAL_UploadToBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTransferBufferLocation *source,
+    SDL_GpuBufferRegion *destination,
+    SDL_bool cycle)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalRenderer *renderer = metalCommandBuffer->renderer;
+        MetalBufferContainer *transferContainer = (MetalBufferContainer *)source->transferBuffer;
+        MetalBufferContainer *bufferContainer = (MetalBufferContainer *)destination->buffer;
+
+        MetalBuffer *metalBuffer = METAL_INTERNAL_PrepareBufferForWrite(
+            renderer,
+            bufferContainer,
+            cycle);
+
+        [metalCommandBuffer->blitEncoder
+               copyFromBuffer:transferContainer->activeBuffer->handle
+                 sourceOffset:source->offset
+                     toBuffer:metalBuffer->handle
+            destinationOffset:destination->offset
+                         size:destination->size];
+
+        METAL_INTERNAL_TrackBuffer(metalCommandBuffer, metalBuffer);
+        METAL_INTERNAL_TrackBuffer(metalCommandBuffer, transferContainer->activeBuffer);
+    }
+}
+
+static void METAL_CopyTextureToTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureLocation *source,
+    SDL_GpuTextureLocation *destination,
+    Uint32 w,
+    Uint32 h,
+    Uint32 d,
+    SDL_bool cycle)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalRenderer *renderer = metalCommandBuffer->renderer;
+        MetalTextureContainer *srcContainer = (MetalTextureContainer *)source->texture;
+        MetalTextureContainer *dstContainer = (MetalTextureContainer *)destination->texture;
+
+        MetalTexture *srcTexture = srcContainer->activeTexture;
+        MetalTexture *dstTexture = METAL_INTERNAL_PrepareTextureForWrite(
+            renderer,
+            dstContainer,
+            cycle);
+
+        [metalCommandBuffer->blitEncoder
+              copyFromTexture:srcTexture->handle
+                  sourceSlice:source->layer
+                  sourceLevel:source->mipLevel
+                 sourceOrigin:MTLOriginMake(source->x, source->y, source->z)
+                   sourceSize:MTLSizeMake(w, h, d)
+                    toTexture:dstTexture->handle
+             destinationSlice:destination->layer
+             destinationLevel:destination->mipLevel
+            destinationOrigin:MTLOriginMake(destination->x, destination->y, destination->z)];
+
+        METAL_INTERNAL_TrackTexture(metalCommandBuffer, srcTexture);
+        METAL_INTERNAL_TrackTexture(metalCommandBuffer, dstTexture);
+    }
+}
+
+static void METAL_CopyBufferToBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferLocation *source,
+    SDL_GpuBufferLocation *destination,
+    Uint32 size,
+    SDL_bool cycle)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalRenderer *renderer = metalCommandBuffer->renderer;
+        MetalBufferContainer *srcContainer = (MetalBufferContainer *)source->buffer;
+        MetalBufferContainer *dstContainer = (MetalBufferContainer *)destination->buffer;
+
+        MetalBuffer *srcBuffer = srcContainer->activeBuffer;
+        MetalBuffer *dstBuffer = METAL_INTERNAL_PrepareBufferForWrite(
+            renderer,
+            dstContainer,
+            cycle);
+
+        [metalCommandBuffer->blitEncoder
+               copyFromBuffer:srcBuffer->handle
+                 sourceOffset:source->offset
+                     toBuffer:dstBuffer->handle
+            destinationOffset:destination->offset
+                         size:size];
+
+        METAL_INTERNAL_TrackBuffer(metalCommandBuffer, srcBuffer);
+        METAL_INTERNAL_TrackBuffer(metalCommandBuffer, dstBuffer);
+    }
+}
+
+static void METAL_DownloadFromTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureRegion *source,
+    SDL_GpuTextureTransferInfo *destination)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalRenderer *renderer = metalCommandBuffer->renderer;
+        MetalTextureContainer *textureContainer = (MetalTextureContainer *)source->texture;
+        MetalTexture *metalTexture = textureContainer->activeTexture;
+        MetalBufferContainer *bufferContainer = (MetalBufferContainer *)destination->transferBuffer;
+        Uint32 bufferStride = destination->imagePitch;
+        Uint32 bufferImageHeight = destination->imageHeight;
+        Uint32 bytesPerRow, bytesPerDepthSlice;
+
+        MetalBuffer *dstBuffer = METAL_INTERNAL_PrepareBufferForWrite(
+            renderer,
+            bufferContainer,
+            SDL_FALSE);
+
+        MTLOrigin regionOrigin = MTLOriginMake(
+            source->x,
+            source->y,
+            source->z);
+
+        MTLSize regionSize = MTLSizeMake(
+            source->w,
+            source->h,
+            source->d);
+
+        if (bufferStride == 0 || bufferImageHeight == 0) {
+            bufferStride = source->w;
+            bufferImageHeight = source->h;
+        }
+
+        bytesPerRow = BytesPerRow(bufferStride, textureContainer->header.info.format);
+        bytesPerDepthSlice = bytesPerRow * bufferImageHeight;
+
+        [metalCommandBuffer->blitEncoder
+                     copyFromTexture:metalTexture->handle
+                         sourceSlice:source->layer
+                         sourceLevel:source->mipLevel
+                        sourceOrigin:regionOrigin
+                          sourceSize:regionSize
+                            toBuffer:dstBuffer->handle
+                   destinationOffset:destination->offset
+              destinationBytesPerRow:bytesPerRow
+            destinationBytesPerImage:bytesPerDepthSlice];
+
+        METAL_INTERNAL_TrackTexture(metalCommandBuffer, metalTexture);
+        METAL_INTERNAL_TrackBuffer(metalCommandBuffer, dstBuffer);
+    }
+}
+
+static void METAL_DownloadFromBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferRegion *source,
+    SDL_GpuTransferBufferLocation *destination)
+{
+    SDL_GpuBufferLocation sourceLocation;
+    sourceLocation.buffer = source->buffer;
+    sourceLocation.offset = source->offset;
+
+    METAL_CopyBufferToBuffer(
+        commandBuffer,
+        &sourceLocation,
+        (SDL_GpuBufferLocation *)destination,
+        source->size,
+        SDL_FALSE);
+}
+
+static void METAL_EndCopyPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        [metalCommandBuffer->blitEncoder endEncoding];
+        metalCommandBuffer->blitEncoder = nil;
+    }
+}
+
+static void METAL_GenerateMipmaps(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTexture *texture)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalTextureContainer *container = (MetalTextureContainer *)texture;
+        MetalTexture *metalTexture = container->activeTexture;
+
+        METAL_BeginCopyPass(commandBuffer);
+        [metalCommandBuffer->blitEncoder
+            generateMipmapsForTexture:metalTexture->handle];
+        METAL_EndCopyPass(commandBuffer);
+
+        METAL_INTERNAL_TrackTexture(metalCommandBuffer, metalTexture);
+    }
+}
+
+// Graphics State
+
+static void METAL_INTERNAL_AllocateCommandBuffers(
+    MetalRenderer *renderer,
+    Uint32 allocateCount)
+{
+    MetalCommandBuffer *commandBuffer;
+
+    renderer->availableCommandBufferCapacity += allocateCount;
+
+    renderer->availableCommandBuffers = SDL_realloc(
+        renderer->availableCommandBuffers,
+        sizeof(MetalCommandBuffer *) * renderer->availableCommandBufferCapacity);
+
+    for (Uint32 i = 0; i < allocateCount; i += 1) {
+        commandBuffer = SDL_calloc(1, sizeof(MetalCommandBuffer));
+        commandBuffer->renderer = renderer;
+
+        // The native Metal command buffer is created in METAL_AcquireCommandBuffer
+
+        commandBuffer->windowDataCapacity = 1;
+        commandBuffer->windowDataCount = 0;
+        commandBuffer->windowDatas = SDL_malloc(
+            commandBuffer->windowDataCapacity * sizeof(MetalWindowData *));
+
+        // Reference Counting
+        commandBuffer->usedBufferCapacity = 4;
+        commandBuffer->usedBufferCount = 0;
+        commandBuffer->usedBuffers = SDL_malloc(
+            commandBuffer->usedBufferCapacity * sizeof(MetalBuffer *));
+
+        commandBuffer->usedTextureCapacity = 4;
+        commandBuffer->usedTextureCount = 0;
+        commandBuffer->usedTextures = SDL_malloc(
+            commandBuffer->usedTextureCapacity * sizeof(MetalTexture *));
+
+        renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
+        renderer->availableCommandBufferCount += 1;
+    }
+}
+
+static MetalCommandBuffer *METAL_INTERNAL_GetInactiveCommandBufferFromPool(
+    MetalRenderer *renderer)
+{
+    MetalCommandBuffer *commandBuffer;
+
+    if (renderer->availableCommandBufferCount == 0) {
+        METAL_INTERNAL_AllocateCommandBuffers(
+            renderer,
+            renderer->availableCommandBufferCapacity);
+    }
+
+    commandBuffer = renderer->availableCommandBuffers[renderer->availableCommandBufferCount - 1];
+    renderer->availableCommandBufferCount -= 1;
+
+    return commandBuffer;
+}
+
+static Uint8 METAL_INTERNAL_CreateFence(
+    MetalRenderer *renderer)
+{
+    MetalFence *fence;
+
+    fence = SDL_malloc(sizeof(MetalFence));
+    SDL_AtomicSet(&fence->complete, 0);
+
+    // Add it to the available pool
+    // FIXME: Should this be EXPAND_IF_NEEDED?
+    if (renderer->availableFenceCount >= renderer->availableFenceCapacity) {
+        renderer->availableFenceCapacity *= 2;
+
+        renderer->availableFences = SDL_realloc(
+            renderer->availableFences,
+            sizeof(MetalFence *) * renderer->availableFenceCapacity);
+    }
+
+    renderer->availableFences[renderer->availableFenceCount] = fence;
+    renderer->availableFenceCount += 1;
+
+    return 1;
+}
+
+static Uint8 METAL_INTERNAL_AcquireFence(
+    MetalRenderer *renderer,
+    MetalCommandBuffer *commandBuffer)
+{
+    MetalFence *fence;
+
+    // Acquire a fence from the pool
+    SDL_LockMutex(renderer->fenceLock);
+
+    if (renderer->availableFenceCount == 0) {
+        if (!METAL_INTERNAL_CreateFence(renderer)) {
+            SDL_UnlockMutex(renderer->fenceLock);
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create fence!");
+            return 0;
+        }
+    }
+
+    fence = renderer->availableFences[renderer->availableFenceCount - 1];
+    renderer->availableFenceCount -= 1;
+
+    SDL_UnlockMutex(renderer->fenceLock);
+
+    // Associate the fence with the command buffer
+    commandBuffer->fence = fence;
+    SDL_AtomicSet(&fence->complete, 0); // FIXME: Is this right?
+
+    return 1;
+}
+
+static SDL_GpuCommandBuffer *METAL_AcquireCommandBuffer(
+    SDL_GpuRenderer *driverData)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MetalCommandBuffer *commandBuffer;
+
+        SDL_LockMutex(renderer->acquireCommandBufferLock);
+
+        commandBuffer = METAL_INTERNAL_GetInactiveCommandBufferFromPool(renderer);
+        commandBuffer->handle = [renderer->queue commandBuffer];
+
+        commandBuffer->graphicsPipeline = NULL;
+        commandBuffer->computePipeline = NULL;
+        for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+            commandBuffer->vertexUniformBuffers[i] = NULL;
+            commandBuffer->fragmentUniformBuffers[i] = NULL;
+            commandBuffer->computeUniformBuffers[i] = NULL;
+        }
+
+        // FIXME: Do we actually need to set this?
+        commandBuffer->needVertexSamplerBind = SDL_TRUE;
+        commandBuffer->needVertexStorageTextureBind = SDL_TRUE;
+        commandBuffer->needVertexStorageBufferBind = SDL_TRUE;
+        commandBuffer->needVertexUniformBind = SDL_TRUE;
+        commandBuffer->needFragmentSamplerBind = SDL_TRUE;
+        commandBuffer->needFragmentStorageTextureBind = SDL_TRUE;
+        commandBuffer->needFragmentStorageBufferBind = SDL_TRUE;
+        commandBuffer->needFragmentUniformBind = SDL_TRUE;
+        commandBuffer->needComputeBufferBind = SDL_TRUE;
+        commandBuffer->needComputeTextureBind = SDL_TRUE;
+        commandBuffer->needComputeUniformBind = SDL_TRUE;
+
+        METAL_INTERNAL_AcquireFence(renderer, commandBuffer);
+        commandBuffer->autoReleaseFence = 1;
+
+        SDL_UnlockMutex(renderer->acquireCommandBufferLock);
+
+        return (SDL_GpuCommandBuffer *)commandBuffer;
+    }
+}
+
+// This function assumes that it's called from within an autorelease pool
+static MetalUniformBuffer *METAL_INTERNAL_AcquireUniformBufferFromPool(
+    MetalCommandBuffer *commandBuffer)
+{
+    MetalRenderer *renderer = commandBuffer->renderer;
+    MetalUniformBuffer *uniformBuffer;
+
+    SDL_LockMutex(renderer->acquireUniformBufferLock);
+
+    if (renderer->uniformBufferPoolCount > 0) {
+        uniformBuffer = renderer->uniformBufferPool[renderer->uniformBufferPoolCount - 1];
+        renderer->uniformBufferPoolCount -= 1;
+    } else {
+        uniformBuffer = METAL_INTERNAL_CreateUniformBuffer(
+            renderer,
+            UNIFORM_BUFFER_SIZE);
+    }
+
+    SDL_UnlockMutex(renderer->acquireUniformBufferLock);
+
+    METAL_INTERNAL_TrackUniformBuffer(commandBuffer, uniformBuffer);
+
+    return uniformBuffer;
+}
+
+static void METAL_INTERNAL_ReturnUniformBufferToPool(
+    MetalRenderer *renderer,
+    MetalUniformBuffer *uniformBuffer)
+{
+    if (renderer->uniformBufferPoolCount >= renderer->uniformBufferPoolCapacity) {
+        renderer->uniformBufferPoolCapacity *= 2;
+        renderer->uniformBufferPool = SDL_realloc(
+            renderer->uniformBufferPool,
+            renderer->uniformBufferPoolCapacity * sizeof(MetalUniformBuffer *));
+    }
+
+    renderer->uniformBufferPool[renderer->uniformBufferPoolCount] = uniformBuffer;
+    renderer->uniformBufferPoolCount += 1;
+
+    uniformBuffer->writeOffset = 0;
+    uniformBuffer->drawOffset = 0;
+}
+
+static void METAL_BeginRenderPass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuColorAttachmentInfo *colorAttachmentInfos,
+    Uint32 colorAttachmentCount,
+    SDL_GpuDepthStencilAttachmentInfo *depthStencilAttachmentInfo)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalRenderer *renderer = metalCommandBuffer->renderer;
+        MTLRenderPassDescriptor *passDescriptor = [MTLRenderPassDescriptor renderPassDescriptor];
+        Uint32 vpWidth = UINT_MAX;
+        Uint32 vpHeight = UINT_MAX;
+        MTLViewport viewport;
+        MTLScissorRect scissorRect;
+
+        for (Uint32 i = 0; i < colorAttachmentCount; i += 1) {
+            MetalTextureContainer *container = (MetalTextureContainer *)colorAttachmentInfos[i].texture;
+            MetalTexture *texture = METAL_INTERNAL_PrepareTextureForWrite(
+                renderer,
+                container,
+                colorAttachmentInfos[i].cycle);
+
+            if (texture->msaaHandle) {
+                passDescriptor.colorAttachments[i].texture = texture->msaaHandle;
+                passDescriptor.colorAttachments[i].resolveTexture = texture->handle;
+            } else {
+                passDescriptor.colorAttachments[i].texture = texture->handle;
+            }
+            passDescriptor.colorAttachments[i].level = colorAttachmentInfos[i].mipLevel;
+            if (container->header.info.type == SDL_GPU_TEXTURETYPE_3D) {
+                passDescriptor.colorAttachments[i].depthPlane = colorAttachmentInfos[i].layerOrDepthPlane;
+            } else {
+                passDescriptor.colorAttachments[i].slice = colorAttachmentInfos[i].layerOrDepthPlane;
+            }
+            passDescriptor.colorAttachments[i].clearColor = MTLClearColorMake(
+                colorAttachmentInfos[i].clearColor.r,
+                colorAttachmentInfos[i].clearColor.g,
+                colorAttachmentInfos[i].clearColor.b,
+                colorAttachmentInfos[i].clearColor.a);
+            passDescriptor.colorAttachments[i].loadAction = SDLToMetal_LoadOp[colorAttachmentInfos[i].loadOp];
+            passDescriptor.colorAttachments[i].storeAction = SDLToMetal_StoreOp(
+                colorAttachmentInfos[i].storeOp,
+                texture->msaaHandle ? 1 : 0);
+
+            METAL_INTERNAL_TrackTexture(metalCommandBuffer, texture);
+        }
+
+        if (depthStencilAttachmentInfo != NULL) {
+            MetalTextureContainer *container = (MetalTextureContainer *)depthStencilAttachmentInfo->texture;
+            MetalTexture *texture = METAL_INTERNAL_PrepareTextureForWrite(
+                renderer,
+                container,
+                depthStencilAttachmentInfo->cycle);
+
+            if (texture->msaaHandle) {
+                passDescriptor.depthAttachment.texture = texture->msaaHandle;
+                passDescriptor.depthAttachment.resolveTexture = texture->handle;
+            } else {
+                passDescriptor.depthAttachment.texture = texture->handle;
+            }
+            passDescriptor.depthAttachment.loadAction = SDLToMetal_LoadOp[depthStencilAttachmentInfo->loadOp];
+            passDescriptor.depthAttachment.storeAction = SDLToMetal_StoreOp(
+                depthStencilAttachmentInfo->storeOp,
+                texture->msaaHandle ? 1 : 0);
+            passDescriptor.depthAttachment.clearDepth = depthStencilAttachmentInfo->depthStencilClearValue.depth;
+
+            if (IsStencilFormat(container->header.info.format)) {
+                if (texture->msaaHandle) {
+                    passDescriptor.stencilAttachment.texture = texture->msaaHandle;
+                    passDescriptor.stencilAttachment.resolveTexture = texture->handle;
+                } else {
+                    passDescriptor.stencilAttachment.texture = texture->handle;
+                }
+                passDescriptor.stencilAttachment.loadAction = SDLToMetal_LoadOp[depthStencilAttachmentInfo->loadOp];
+                passDescriptor.stencilAttachment.storeAction = SDLToMetal_StoreOp(
+                    depthStencilAttachmentInfo->storeOp,
+                    texture->msaaHandle ? 1 : 0);
+                passDescriptor.stencilAttachment.clearStencil = depthStencilAttachmentInfo->depthStencilClearValue.stencil;
+            }
+
+            METAL_INTERNAL_TrackTexture(metalCommandBuffer, texture);
+        }
+
+        metalCommandBuffer->renderEncoder = [metalCommandBuffer->handle renderCommandEncoderWithDescriptor:passDescriptor];
+
+        // The viewport cannot be larger than the smallest attachment.
+        for (Uint32 i = 0; i < colorAttachmentCount; i += 1) {
+            MetalTextureContainer *container = (MetalTextureContainer *)colorAttachmentInfos[i].texture;
+            Uint32 w = container->header.info.width >> colorAttachmentInfos[i].mipLevel;
+            Uint32 h = container->header.info.height >> colorAttachmentInfos[i].mipLevel;
+
+            if (w < vpWidth) {
+                vpWidth = w;
+            }
+
+            if (h < vpHeight) {
+                vpHeight = h;
+            }
+        }
+
+        if (depthStencilAttachmentInfo != NULL) {
+            MetalTextureContainer *container = (MetalTextureContainer *)depthStencilAttachmentInfo->texture;
+            Uint32 w = container->header.info.width;
+            Uint32 h = container->header.info.height;
+
+            if (w < vpWidth) {
+                vpWidth = w;
+            }
+
+            if (h < vpHeight) {
+                vpHeight = h;
+            }
+        }
+
+        // Set default viewport and scissor state
+        viewport.originX = 0;
+        viewport.originY = 0;
+        viewport.width = vpWidth;
+        viewport.height = vpHeight;
+        viewport.znear = 0;
+        viewport.zfar = 1;
+        [metalCommandBuffer->renderEncoder setViewport:viewport];
+
+        scissorRect.x = 0;
+        scissorRect.y = 0;
+        scissorRect.width = vpWidth;
+        scissorRect.height = vpHeight;
+        [metalCommandBuffer->renderEncoder setScissorRect:scissorRect];
+    }
+}
+
+static void METAL_BindGraphicsPipeline(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuGraphicsPipeline *graphicsPipeline)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalGraphicsPipeline *metalGraphicsPipeline = (MetalGraphicsPipeline *)graphicsPipeline;
+        SDL_GpuRasterizerState *rast = &metalGraphicsPipeline->rasterizerState;
+
+        metalCommandBuffer->graphicsPipeline = metalGraphicsPipeline;
+
+        [metalCommandBuffer->renderEncoder setRenderPipelineState:metalGraphicsPipeline->handle];
+
+        // Apply rasterizer state
+        [metalCommandBuffer->renderEncoder setTriangleFillMode:SDLToMetal_PolygonMode[metalGraphicsPipeline->rasterizerState.fillMode]];
+        [metalCommandBuffer->renderEncoder setCullMode:SDLToMetal_CullMode[metalGraphicsPipeline->rasterizerState.cullMode]];
+        [metalCommandBuffer->renderEncoder setFrontFacingWinding:SDLToMetal_FrontFace[metalGraphicsPipeline->rasterizerState.frontFace]];
+        [metalCommandBuffer->renderEncoder
+            setDepthBias:((rast->depthBiasEnable) ? rast->depthBiasConstantFactor : 0)
+              slopeScale:((rast->depthBiasEnable) ? rast->depthBiasSlopeFactor : 0)
+              clamp:((rast->depthBiasEnable) ? rast->depthBiasClamp : 0)];
+
+        // Apply blend constants
+        [metalCommandBuffer->renderEncoder
+            setBlendColorRed:metalGraphicsPipeline->blendConstants[0]
+                       green:metalGraphicsPipeline->blendConstants[1]
+                        blue:metalGraphicsPipeline->blendConstants[2]
+                       alpha:metalGraphicsPipeline->blendConstants[3]];
+
+        // Apply depth-stencil state
+        if (metalGraphicsPipeline->depthStencilState != NULL) {
+            [metalCommandBuffer->renderEncoder
+                setDepthStencilState:metalGraphicsPipeline->depthStencilState];
+            [metalCommandBuffer->renderEncoder
+                setStencilReferenceValue:metalGraphicsPipeline->stencilReference];
+        }
+
+        for (Uint32 i = 0; i < metalGraphicsPipeline->vertexUniformBufferCount; i += 1) {
+            if (metalCommandBuffer->vertexUniformBuffers[i] == NULL) {
+                metalCommandBuffer->vertexUniformBuffers[i] = METAL_INTERNAL_AcquireUniformBufferFromPool(
+                    metalCommandBuffer);
+            }
+        }
+
+        for (Uint32 i = 0; i < metalGraphicsPipeline->fragmentUniformBufferCount; i += 1) {
+            if (metalCommandBuffer->fragmentUniformBuffers[i] == NULL) {
+                metalCommandBuffer->fragmentUniformBuffers[i] = METAL_INTERNAL_AcquireUniformBufferFromPool(
+                    metalCommandBuffer);
+            }
+        }
+
+        metalCommandBuffer->needVertexUniformBind = SDL_TRUE;
+        metalCommandBuffer->needFragmentUniformBind = SDL_TRUE;
+    }
+}
+
+static void METAL_SetViewport(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuViewport *viewport)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MTLViewport metalViewport;
+
+        metalViewport.originX = viewport->x;
+        metalViewport.originY = viewport->y;
+        metalViewport.width = viewport->w;
+        metalViewport.height = viewport->h;
+        metalViewport.znear = viewport->minDepth;
+        metalViewport.zfar = viewport->maxDepth;
+
+        [metalCommandBuffer->renderEncoder setViewport:metalViewport];
+    }
+}
+
+static void METAL_SetScissor(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_Rect *scissor)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MTLScissorRect metalScissor;
+
+        metalScissor.x = scissor->x;
+        metalScissor.y = scissor->y;
+        metalScissor.width = scissor->w;
+        metalScissor.height = scissor->h;
+
+        [metalCommandBuffer->renderEncoder setScissorRect:metalScissor];
+    }
+}
+
+static void METAL_BindVertexBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstBinding,
+    SDL_GpuBufferBinding *pBindings,
+    Uint32 bindingCount)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        id<MTLBuffer> metalBuffers[MAX_BUFFER_BINDINGS];
+        NSUInteger bufferOffsets[MAX_BUFFER_BINDINGS];
+        NSRange range = NSMakeRange(METAL_INTERNAL_GetVertexBufferIndex(firstBinding), bindingCount);
+
+        if (range.length == 0) {
+            return;
+        }
+
+        for (Uint32 i = 0; i < range.length; i += 1) {
+            MetalBuffer *currentBuffer = ((MetalBufferContainer *)pBindings[i].buffer)->activeBuffer;
+            NSUInteger bindingIndex = range.length - 1 - i;
+            metalBuffers[bindingIndex] = currentBuffer->handle;
+            bufferOffsets[bindingIndex] = pBindings[i].offset;
+            METAL_INTERNAL_TrackBuffer(metalCommandBuffer, currentBuffer);
+        }
+
+        [metalCommandBuffer->renderEncoder setVertexBuffers:metalBuffers offsets:bufferOffsets withRange:range];
+    }
+}
+
+static void METAL_BindIndexBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferBinding *pBinding,
+    SDL_GpuIndexElementSize indexElementSize)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    metalCommandBuffer->indexBuffer = ((MetalBufferContainer *)pBinding->buffer)->activeBuffer;
+    metalCommandBuffer->indexBufferOffset = pBinding->offset;
+    metalCommandBuffer->indexElementSize = indexElementSize;
+
+    METAL_INTERNAL_TrackBuffer(metalCommandBuffer, metalCommandBuffer->indexBuffer);
+}
+
+static void METAL_BindVertexSamplers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    MetalTextureContainer *textureContainer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        textureContainer = (MetalTextureContainer *)textureSamplerBindings[i].texture;
+
+        METAL_INTERNAL_TrackTexture(
+            metalCommandBuffer,
+            textureContainer->activeTexture);
+
+        metalCommandBuffer->vertexSamplers[firstSlot + i] =
+            ((MetalSampler *)textureSamplerBindings[i].sampler)->handle;
+
+        metalCommandBuffer->vertexTextures[firstSlot + i] =
+            textureContainer->activeTexture->handle;
+    }
+
+    metalCommandBuffer->needVertexSamplerBind = SDL_TRUE;
+}
+
+static void METAL_BindVertexStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    MetalTextureContainer *textureContainer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        textureContainer = (MetalTextureContainer *)storageTextures[i];
+
+        METAL_INTERNAL_TrackTexture(
+            metalCommandBuffer,
+            textureContainer->activeTexture);
+
+        metalCommandBuffer->vertexStorageTextures[firstSlot + i] =
+            textureContainer->activeTexture->handle;
+    }
+
+    metalCommandBuffer->needVertexStorageTextureBind = SDL_TRUE;
+}
+
+static void METAL_BindVertexStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    MetalBufferContainer *bufferContainer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        bufferContainer = (MetalBufferContainer *)storageBuffers[i];
+
+        METAL_INTERNAL_TrackBuffer(
+            metalCommandBuffer,
+            bufferContainer->activeBuffer);
+
+        metalCommandBuffer->vertexStorageBuffers[firstSlot + i] =
+            bufferContainer->activeBuffer->handle;
+    }
+
+    metalCommandBuffer->needVertexStorageBufferBind = SDL_TRUE;
+}
+
+static void METAL_BindFragmentSamplers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    MetalTextureContainer *textureContainer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        textureContainer = (MetalTextureContainer *)textureSamplerBindings[i].texture;
+
+        METAL_INTERNAL_TrackTexture(
+            metalCommandBuffer,
+            textureContainer->activeTexture);
+
+        metalCommandBuffer->fragmentSamplers[firstSlot + i] =
+            ((MetalSampler *)textureSamplerBindings[i].sampler)->handle;
+
+        metalCommandBuffer->fragmentTextures[firstSlot + i] =
+            textureContainer->activeTexture->handle;
+    }
+
+    metalCommandBuffer->needFragmentSamplerBind = SDL_TRUE;
+}
+
+static void METAL_BindFragmentStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    MetalTextureContainer *textureContainer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        textureContainer = (MetalTextureContainer *)storageTextures[i];
+
+        METAL_INTERNAL_TrackTexture(
+            metalCommandBuffer,
+            textureContainer->activeTexture);
+
+        metalCommandBuffer->fragmentStorageTextures[firstSlot + i] =
+            textureContainer->activeTexture->handle;
+    }
+
+    metalCommandBuffer->needFragmentStorageTextureBind = SDL_TRUE;
+}
+
+static void METAL_BindFragmentStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    MetalBufferContainer *bufferContainer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        bufferContainer = (MetalBufferContainer *)storageBuffers[i];
+
+        METAL_INTERNAL_TrackBuffer(
+            metalCommandBuffer,
+            bufferContainer->activeBuffer);
+
+        metalCommandBuffer->fragmentStorageBuffers[firstSlot + i] =
+            bufferContainer->activeBuffer->handle;
+    }
+
+    metalCommandBuffer->needFragmentStorageBufferBind = SDL_TRUE;
+}
+
+// This function assumes that it's called from within an autorelease pool
+static void METAL_INTERNAL_BindGraphicsResources(
+    MetalCommandBuffer *commandBuffer)
+{
+    MetalGraphicsPipeline *graphicsPipeline = commandBuffer->graphicsPipeline;
+    NSUInteger offsets[MAX_STORAGE_BUFFERS_PER_STAGE] = { 0 };
+
+    // Vertex Samplers+Textures
+
+    if (graphicsPipeline->vertexSamplerCount > 0 && commandBuffer->needVertexSamplerBind) {
+        [commandBuffer->renderEncoder setVertexSamplerStates:commandBuffer->vertexSamplers
+                                                   withRange:NSMakeRange(0, graphicsPipeline->vertexSamplerCount)];
+        [commandBuffer->renderEncoder setVertexTextures:commandBuffer->vertexTextures
+                                              withRange:NSMakeRange(0, graphicsPipeline->vertexSamplerCount)];
+        commandBuffer->needVertexSamplerBind = SDL_FALSE;
+    }
+
+    // Vertex Storage Textures
+
+    if (graphicsPipeline->vertexStorageTextureCount > 0 && commandBuffer->needVertexStorageTextureBind) {
+        [commandBuffer->renderEncoder setVertexTextures:commandBuffer->vertexStorageTextures
+                                              withRange:NSMakeRange(graphicsPipeline->vertexSamplerCount,
+                                                                    graphicsPipeline->vertexStorageTextureCount)];
+        commandBuffer->needVertexStorageTextureBind = SDL_FALSE;
+    }
+
+    // Vertex Storage Buffers
+
+    if (graphicsPipeline->vertexStorageBufferCount > 0 && commandBuffer->needVertexStorageBufferBind) {
+        [commandBuffer->renderEncoder setVertexBuffers:commandBuffer->vertexStorageBuffers
+                                               offsets:offsets
+                                             withRange:NSMakeRange(graphicsPipeline->vertexUniformBufferCount,
+                                                                   graphicsPipeline->vertexStorageBufferCount)];
+        commandBuffer->needVertexStorageBufferBind = SDL_FALSE;
+    }
+
+    // Vertex Uniform Buffers
+
+    if (graphicsPipeline->vertexUniformBufferCount > 0 && commandBuffer->needVertexUniformBind) {
+        for (Uint32 i = 0; i < graphicsPipeline->vertexUniformBufferCount; i += 1) {
+            [commandBuffer->renderEncoder
+                setVertexBuffer:commandBuffer->vertexUniformBuffers[i]->handle
+                         offset:commandBuffer->vertexUniformBuffers[i]->drawOffset
+                        atIndex:i];
+        }
+        commandBuffer->needVertexUniformBind = SDL_FALSE;
+    }
+
+    // Fragment Samplers+Textures
+
+    if (graphicsPipeline->fragmentSamplerCount > 0 && commandBuffer->needFragmentSamplerBind) {
+        [commandBuffer->renderEncoder setFragmentSamplerStates:commandBuffer->fragmentSamplers
+                                                     withRange:NSMakeRange(0, graphicsPipeline->fragmentSamplerCount)];
+        [commandBuffer->renderEncoder setFragmentTextures:commandBuffer->fragmentTextures
+                                                withRange:NSMakeRange(0, graphicsPipeline->fragmentSamplerCount)];
+        commandBuffer->needFragmentSamplerBind = SDL_FALSE;
+    }
+
+    // Fragment Storage Textures
+
+    if (graphicsPipeline->fragmentStorageTextureCount > 0 && commandBuffer->needFragmentStorageTextureBind) {
+        [commandBuffer->renderEncoder setFragmentTextures:commandBuffer->fragmentStorageTextures
+                                                withRange:NSMakeRange(graphicsPipeline->fragmentSamplerCount,
+                                                                      graphicsPipeline->fragmentStorageTextureCount)];
+        commandBuffer->needFragmentStorageTextureBind = SDL_FALSE;
+    }
+
+    // Fragment Storage Buffers
+
+    if (graphicsPipeline->fragmentStorageBufferCount > 0 && commandBuffer->needFragmentStorageBufferBind) {
+        [commandBuffer->renderEncoder setFragmentBuffers:commandBuffer->fragmentStorageBuffers
+                                                 offsets:offsets
+                                               withRange:NSMakeRange(graphicsPipeline->fragmentUniformBufferCount,
+                                                                     graphicsPipeline->fragmentStorageBufferCount)];
+        commandBuffer->needFragmentStorageBufferBind = SDL_FALSE;
+    }
+
+    // Fragment Uniform Buffers
+    if (graphicsPipeline->fragmentUniformBufferCount > 0 && commandBuffer->needFragmentUniformBind) {
+        for (Uint32 i = 0; i < graphicsPipeline->fragmentUniformBufferCount; i += 1) {
+            [commandBuffer->renderEncoder
+                setFragmentBuffer:commandBuffer->fragmentUniformBuffers[i]->handle
+                           offset:commandBuffer->fragmentUniformBuffers[i]->drawOffset
+                          atIndex:i];
+        }
+        commandBuffer->needFragmentUniformBind = SDL_FALSE;
+    }
+}
+
+// This function assumes that it's called from within an autorelease pool
+static void METAL_INTERNAL_BindComputeResources(
+    MetalCommandBuffer *commandBuffer)
+{
+    MetalComputePipeline *computePipeline = commandBuffer->computePipeline;
+    NSUInteger offsets[MAX_STORAGE_BUFFERS_PER_STAGE] = { 0 }; // 8 is the max for both read and write-only
+
+    if (commandBuffer->needComputeTextureBind) {
+        // Bind read-only textures
+        if (computePipeline->readOnlyStorageTextureCount > 0) {
+            [commandBuffer->computeEncoder setTextures:commandBuffer->computeReadOnlyTextures
+                                             withRange:NSMakeRange(0, computePipeline->readOnlyStorageTextureCount)];
+        }
+
+        // Bind write-only textures
+        if (computePipeline->writeOnlyStorageTextureCount > 0) {
+            [commandBuffer->computeEncoder setTextures:commandBuffer->computeWriteOnlyTextures
+                                             withRange:NSMakeRange(
+                                                           computePipeline->readOnlyStorageTextureCount,
+                                                           computePipeline->writeOnlyStorageTextureCount)];
+        }
+        commandBuffer->needComputeTextureBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needComputeBufferBind) {
+        // Bind read-only buffers
+        if (computePipeline->readOnlyStorageBufferCount > 0) {
+            [commandBuffer->computeEncoder setBuffers:commandBuffer->computeReadOnlyBuffers
+                                              offsets:offsets
+                                            withRange:NSMakeRange(computePipeline->uniformBufferCount,
+                                                                  computePipeline->readOnlyStorageBufferCount)];
+        }
+        // Bind write-only buffers
+        if (computePipeline->writeOnlyStorageBufferCount > 0) {
+            [commandBuffer->computeEncoder setBuffers:commandBuffer->computeWriteOnlyBuffers
+                                              offsets:offsets
+                                            withRange:NSMakeRange(
+                                                          computePipeline->uniformBufferCount +
+                                                              computePipeline->readOnlyStorageBufferCount,
+                                                          computePipeline->writeOnlyStorageBufferCount)];
+        }
+        commandBuffer->needComputeBufferBind = SDL_FALSE;
+    }
+
+    if (commandBuffer->needComputeUniformBind) {
+        for (Uint32 i = 0; i < computePipeline->uniformBufferCount; i += 1) {
+            [commandBuffer->computeEncoder
+                setBuffer:commandBuffer->computeUniformBuffers[i]->handle
+                   offset:commandBuffer->computeUniformBuffers[i]->drawOffset
+                  atIndex:i];
+        }
+
+        commandBuffer->needComputeUniformBind = SDL_FALSE;
+    }
+}
+
+static void METAL_DrawIndexedPrimitives(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 indexCount,
+    Uint32 instanceCount,
+    Uint32 firstIndex,
+    Sint32 vertexOffset,
+    Uint32 firstInstance)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        SDL_GpuPrimitiveType primitiveType = metalCommandBuffer->graphicsPipeline->primitiveType;
+        Uint32 indexSize = IndexSize(metalCommandBuffer->indexElementSize);
+
+        METAL_INTERNAL_BindGraphicsResources(metalCommandBuffer);
+
+        [metalCommandBuffer->renderEncoder
+            drawIndexedPrimitives:SDLToMetal_PrimitiveType[primitiveType]
+                       indexCount:indexCount
+                        indexType:SDLToMetal_IndexType[metalCommandBuffer->indexElementSize]
+                      indexBuffer:metalCommandBuffer->indexBuffer->handle
+                indexBufferOffset:metalCommandBuffer->indexBufferOffset + (firstIndex * indexSize)
+                    instanceCount:instanceCount
+                       baseVertex:vertexOffset
+                     baseInstance:firstInstance];
+    }
+}
+
+static void METAL_DrawPrimitives(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 vertexCount,
+    Uint32 instanceCount,
+    Uint32 firstVertex,
+    Uint32 firstInstance)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        SDL_GpuPrimitiveType primitiveType = metalCommandBuffer->graphicsPipeline->primitiveType;
+
+        METAL_INTERNAL_BindGraphicsResources(metalCommandBuffer);
+
+        [metalCommandBuffer->renderEncoder
+            drawPrimitives:SDLToMetal_PrimitiveType[primitiveType]
+               vertexStart:firstVertex
+               vertexCount:vertexCount
+             instanceCount:instanceCount
+              baseInstance:firstInstance];
+    }
+}
+
+static void METAL_DrawPrimitivesIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalBuffer *metalBuffer = ((MetalBufferContainer *)buffer)->activeBuffer;
+        SDL_GpuPrimitiveType primitiveType = metalCommandBuffer->graphicsPipeline->primitiveType;
+
+        METAL_INTERNAL_BindGraphicsResources(metalCommandBuffer);
+
+        /* Metal: "We have multi-draw at home!"
+         * Multi-draw at home:
+         */
+        for (Uint32 i = 0; i < drawCount; i += 1) {
+            [metalCommandBuffer->renderEncoder
+                      drawPrimitives:SDLToMetal_PrimitiveType[primitiveType]
+                      indirectBuffer:metalBuffer->handle
+                indirectBufferOffset:offsetInBytes + (stride * i)];
+        }
+
+        METAL_INTERNAL_TrackBuffer(metalCommandBuffer, metalBuffer);
+    }
+}
+
+static void METAL_DrawIndexedPrimitivesIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalBuffer *metalBuffer = ((MetalBufferContainer *)buffer)->activeBuffer;
+        SDL_GpuPrimitiveType primitiveType = metalCommandBuffer->graphicsPipeline->primitiveType;
+
+        METAL_INTERNAL_BindGraphicsResources(metalCommandBuffer);
+
+        for (Uint32 i = 0; i < drawCount; i += 1) {
+            [metalCommandBuffer->renderEncoder
+                drawIndexedPrimitives:SDLToMetal_PrimitiveType[primitiveType]
+                            indexType:SDLToMetal_IndexType[metalCommandBuffer->indexElementSize]
+                          indexBuffer:metalCommandBuffer->indexBuffer->handle
+                    indexBufferOffset:metalCommandBuffer->indexBufferOffset
+                       indirectBuffer:metalBuffer->handle
+                 indirectBufferOffset:offsetInBytes + (stride * i)];
+        }
+
+        METAL_INTERNAL_TrackBuffer(metalCommandBuffer, metalBuffer);
+    }
+}
+
+static void METAL_EndRenderPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        [metalCommandBuffer->renderEncoder endEncoding];
+        metalCommandBuffer->renderEncoder = nil;
+
+        for (Uint32 i = 0; i < MAX_TEXTURE_SAMPLERS_PER_STAGE; i += 1) {
+            metalCommandBuffer->vertexSamplers[i] = nil;
+            metalCommandBuffer->vertexTextures[i] = nil;
+            metalCommandBuffer->fragmentSamplers[i] = nil;
+            metalCommandBuffer->fragmentTextures[i] = nil;
+        }
+        for (Uint32 i = 0; i < MAX_STORAGE_TEXTURES_PER_STAGE; i += 1) {
+            metalCommandBuffer->vertexStorageTextures[i] = nil;
+            metalCommandBuffer->fragmentStorageTextures[i] = nil;
+        }
+        for (Uint32 i = 0; i < MAX_STORAGE_BUFFERS_PER_STAGE; i += 1) {
+            metalCommandBuffer->vertexStorageBuffers[i] = nil;
+            metalCommandBuffer->fragmentStorageBuffers[i] = nil;
+        }
+    }
+}
+
+// This function assumes that it's called from within an autorelease pool
+static void METAL_INTERNAL_PushUniformData(
+    MetalCommandBuffer *metalCommandBuffer,
+    SDL_GpuShaderStage shaderStage,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    MetalUniformBuffer *metalUniformBuffer;
+    Uint32 alignedDataLength;
+
+    if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
+        if (metalCommandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
+            metalCommandBuffer->vertexUniformBuffers[slotIndex] = METAL_INTERNAL_AcquireUniformBufferFromPool(
+                metalCommandBuffer);
+        }
+        metalUniformBuffer = metalCommandBuffer->vertexUniformBuffers[slotIndex];
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
+        if (metalCommandBuffer->fragmentUniformBuffers[slotIndex] == NULL) {
+            metalCommandBuffer->fragmentUniformBuffers[slotIndex] = METAL_INTERNAL_AcquireUniformBufferFromPool(
+                metalCommandBuffer);
+        }
+        metalUniformBuffer = metalCommandBuffer->fragmentUniformBuffers[slotIndex];
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
+        if (metalCommandBuffer->computeUniformBuffers[slotIndex] == NULL) {
+            metalCommandBuffer->computeUniformBuffers[slotIndex] = METAL_INTERNAL_AcquireUniformBufferFromPool(
+                metalCommandBuffer);
+        }
+        metalUniformBuffer = metalCommandBuffer->computeUniformBuffers[slotIndex];
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+        return;
+    }
+
+    alignedDataLength = METAL_INTERNAL_NextHighestAlignment(
+        dataLengthInBytes,
+        256);
+
+    if (metalUniformBuffer->writeOffset + alignedDataLength >= UNIFORM_BUFFER_SIZE) {
+        metalUniformBuffer = METAL_INTERNAL_AcquireUniformBufferFromPool(
+            metalCommandBuffer);
+
+        metalUniformBuffer->writeOffset = 0;
+        metalUniformBuffer->drawOffset = 0;
+
+        if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
+            metalCommandBuffer->vertexUniformBuffers[slotIndex] = metalUniformBuffer;
+        } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
+            metalCommandBuffer->fragmentUniformBuffers[slotIndex] = metalUniformBuffer;
+        } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
+            metalCommandBuffer->computeUniformBuffers[slotIndex] = metalUniformBuffer;
+        } else {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+            return;
+        }
+    }
+
+    metalUniformBuffer->drawOffset = metalUniformBuffer->writeOffset;
+
+    SDL_memcpy(
+        (metalUniformBuffer->handle).contents + metalUniformBuffer->writeOffset,
+        data,
+        dataLengthInBytes);
+
+    metalUniformBuffer->writeOffset += alignedDataLength;
+
+    if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) {
+        metalCommandBuffer->needVertexUniformBind = SDL_TRUE;
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) {
+        metalCommandBuffer->needFragmentUniformBind = SDL_TRUE;
+    } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) {
+        metalCommandBuffer->needComputeUniformBind = SDL_TRUE;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+    }
+}
+
+static void METAL_PushVertexUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    @autoreleasepool {
+        METAL_INTERNAL_PushUniformData(
+            (MetalCommandBuffer *)commandBuffer,
+            SDL_GPU_SHADERSTAGE_VERTEX,
+            slotIndex,
+            data,
+            dataLengthInBytes);
+    }
+}
+
+static void METAL_PushFragmentUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    @autoreleasepool {
+        METAL_INTERNAL_PushUniformData(
+            (MetalCommandBuffer *)commandBuffer,
+            SDL_GPU_SHADERSTAGE_FRAGMENT,
+            slotIndex,
+            data,
+            dataLengthInBytes);
+    }
+}
+
+// Blit
+
+static void METAL_Blit(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBlitRegion *source,
+    SDL_GpuBlitRegion *destination,
+    SDL_FlipMode flipMode,
+    SDL_GpuFilter filterMode,
+    SDL_bool cycle)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    MetalRenderer *renderer = (MetalRenderer *)metalCommandBuffer->renderer;
+
+    SDL_Gpu_BlitCommon(
+        commandBuffer,
+        source,
+        destination,
+        flipMode,
+        filterMode,
+        cycle,
+        renderer->blitLinearSampler,
+        renderer->blitNearestSampler,
+        renderer->blitVertexShader,
+        renderer->blitFrom2DShader,
+        renderer->blitFrom2DArrayShader,
+        renderer->blitFrom3DShader,
+        renderer->blitFromCubeShader,
+        &renderer->blitPipelines,
+        &renderer->blitPipelineCount,
+        &renderer->blitPipelineCapacity);
+}
+
+// Compute State
+
+static void METAL_BeginComputePass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuStorageTextureWriteOnlyBinding *storageTextureBindings,
+    Uint32 storageTextureBindingCount,
+    SDL_GpuStorageBufferWriteOnlyBinding *storageBufferBindings,
+    Uint32 storageBufferBindingCount)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalTextureContainer *textureContainer;
+        MetalTexture *texture;
+        id<MTLTexture> textureView;
+        MetalBufferContainer *bufferContainer;
+        MetalBuffer *buffer;
+
+        metalCommandBuffer->computeEncoder = [metalCommandBuffer->handle computeCommandEncoder];
+
+        for (Uint32 i = 0; i < storageTextureBindingCount; i += 1) {
+            textureContainer = (MetalTextureContainer *)storageTextureBindings[i].texture;
+
+            texture = METAL_INTERNAL_PrepareTextureForWrite(
+                metalCommandBuffer->renderer,
+                textureContainer,
+                storageTextureBindings[i].cycle);
+
+            METAL_INTERNAL_TrackTexture(metalCommandBuffer, texture);
+
+            textureView = [texture->handle newTextureViewWithPixelFormat:SDLToMetal_SurfaceFormat[textureContainer->header.info.format]
+                                                             textureType:SDLToMetal_TextureType[textureContainer->header.info.type]
+                                                                  levels:NSMakeRange(storageTextureBindings[i].mipLevel, 1)
+                                                                  slices:NSMakeRange(storageTextureBindings[i].layer, 1)];
+
+            metalCommandBuffer->computeWriteOnlyTextures[i] = textureView;
+            metalCommandBuffer->needComputeTextureBind = SDL_TRUE;
+        }
+
+        for (Uint32 i = 0; i < storageBufferBindingCount; i += 1) {
+            bufferContainer = (MetalBufferContainer *)storageBufferBindings[i].buffer;
+
+            buffer = METAL_INTERNAL_PrepareBufferForWrite(
+                metalCommandBuffer->renderer,
+                bufferContainer,
+                storageBufferBindings[i].cycle);
+
+            METAL_INTERNAL_TrackBuffer(
+                metalCommandBuffer,
+                buffer);
+
+            metalCommandBuffer->computeWriteOnlyBuffers[i] = buffer->handle;
+            metalCommandBuffer->needComputeBufferBind = SDL_TRUE;
+        }
+    }
+}
+
+static void METAL_BindComputePipeline(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuComputePipeline *computePipeline)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalComputePipeline *pipeline = (MetalComputePipeline *)computePipeline;
+
+        metalCommandBuffer->computePipeline = pipeline;
+
+        [metalCommandBuffer->computeEncoder setComputePipelineState:pipeline->handle];
+
+        for (Uint32 i = 0; i < pipeline->uniformBufferCount; i += 1) {
+            if (metalCommandBuffer->computeUniformBuffers[i] == NULL) {
+                metalCommandBuffer->computeUniformBuffers[i] = METAL_INTERNAL_AcquireUniformBufferFromPool(
+                    metalCommandBuffer);
+            }
+        }
+
+        metalCommandBuffer->needComputeUniformBind = SDL_TRUE;
+    }
+}
+
+static void METAL_BindComputeStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    MetalTextureContainer *textureContainer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        textureContainer = (MetalTextureContainer *)storageTextures[i];
+
+        METAL_INTERNAL_TrackTexture(
+            metalCommandBuffer,
+            textureContainer->activeTexture);
+
+        metalCommandBuffer->computeReadOnlyTextures[firstSlot + i] =
+            textureContainer->activeTexture->handle;
+    }
+
+    metalCommandBuffer->needComputeTextureBind = SDL_TRUE;
+}
+
+static void METAL_BindComputeStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    MetalBufferContainer *bufferContainer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        bufferContainer = (MetalBufferContainer *)storageBuffers[i];
+
+        METAL_INTERNAL_TrackBuffer(
+            metalCommandBuffer,
+            bufferContainer->activeBuffer);
+
+        metalCommandBuffer->computeReadOnlyBuffers[firstSlot + i] =
+            bufferContainer->activeBuffer->handle;
+    }
+
+    metalCommandBuffer->needComputeBufferBind = SDL_TRUE;
+}
+
+static void METAL_PushComputeUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    @autoreleasepool {
+        METAL_INTERNAL_PushUniformData(
+            (MetalCommandBuffer *)commandBuffer,
+            SDL_GPU_SHADERSTAGE_COMPUTE,
+            slotIndex,
+            data,
+            dataLengthInBytes);
+    }
+}
+
+static void METAL_DispatchCompute(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 groupCountX,
+    Uint32 groupCountY,
+    Uint32 groupCountZ)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MTLSize threadgroups = MTLSizeMake(groupCountX, groupCountY, groupCountZ);
+        MTLSize threadsPerThreadgroup = MTLSizeMake(
+            metalCommandBuffer->computePipeline->threadCountX,
+            metalCommandBuffer->computePipeline->threadCountY,
+            metalCommandBuffer->computePipeline->threadCountZ);
+
+        METAL_INTERNAL_BindComputeResources(metalCommandBuffer);
+
+        [metalCommandBuffer->computeEncoder
+             dispatchThreadgroups:threadgroups
+            threadsPerThreadgroup:threadsPerThreadgroup];
+    }
+}
+
+static void METAL_DispatchComputeIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalBuffer *metalBuffer = ((MetalBufferContainer *)buffer)->activeBuffer;
+        MTLSize threadsPerThreadgroup = MTLSizeMake(
+            metalCommandBuffer->computePipeline->threadCountX,
+            metalCommandBuffer->computePipeline->threadCountY,
+            metalCommandBuffer->computePipeline->threadCountZ);
+
+        METAL_INTERNAL_BindComputeResources(metalCommandBuffer);
+
+        [metalCommandBuffer->computeEncoder
+            dispatchThreadgroupsWithIndirectBuffer:metalBuffer->handle
+                              indirectBufferOffset:offsetInBytes
+                             threadsPerThreadgroup:threadsPerThreadgroup];
+
+        METAL_INTERNAL_TrackBuffer(metalCommandBuffer, metalBuffer);
+    }
+}
+
+static void METAL_EndComputePass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        [metalCommandBuffer->computeEncoder endEncoding];
+        metalCommandBuffer->computeEncoder = nil;
+
+        for (Uint32 i = 0; i < MAX_COMPUTE_WRITE_TEXTURES; i += 1) {
+            metalCommandBuffer->computeWriteOnlyTextures[i] = nil;
+        }
+        for (Uint32 i = 0; i < MAX_COMPUTE_WRITE_BUFFERS; i += 1) {
+            metalCommandBuffer->computeWriteOnlyBuffers[i] = nil;
+        }
+        for (Uint32 i = 0; i < MAX_STORAGE_TEXTURES_PER_STAGE; i += 1) {
+            metalCommandBuffer->computeReadOnlyTextures[i] = nil;
+        }
+        for (Uint32 i = 0; i < MAX_STORAGE_BUFFERS_PER_STAGE; i += 1) {
+            metalCommandBuffer->computeReadOnlyBuffers[i] = nil;
+        }
+    }
+}
+
+// Fence Cleanup
+
+static void METAL_INTERNAL_ReleaseFenceToPool(
+    MetalRenderer *renderer,
+    MetalFence *fence)
+{
+    SDL_LockMutex(renderer->fenceLock);
+
+    // FIXME: Should this use EXPAND_IF_NEEDED?
+    if (renderer->availableFenceCount == renderer->availableFenceCapacity) {
+        renderer->availableFenceCapacity *= 2;
+        renderer->availableFences = SDL_realloc(
+            renderer->availableFences,
+            renderer->availableFenceCapacity * sizeof(MetalFence *));
+    }
+    renderer->availableFences[renderer->availableFenceCount] = fence;
+    renderer->availableFenceCount += 1;
+
+    SDL_UnlockMutex(renderer->fenceLock);
+}
+
+static void METAL_ReleaseFence(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuFence *fence)
+{
+    METAL_INTERNAL_ReleaseFenceToPool(
+        (MetalRenderer *)driverData,
+        (MetalFence *)fence);
+}
+
+// Cleanup
+
+static void METAL_INTERNAL_CleanCommandBuffer(
+    MetalRenderer *renderer,
+    MetalCommandBuffer *commandBuffer)
+{
+    Uint32 i;
+
+    // Reference Counting
+    for (i = 0; i < commandBuffer->usedBufferCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount);
+    }
+    commandBuffer->usedBufferCount = 0;
+
+    for (i = 0; i < commandBuffer->usedTextureCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
+    }
+    commandBuffer->usedTextureCount = 0;
+
+    // Uniform buffers are now available
+
+    SDL_LockMutex(renderer->acquireUniformBufferLock);
+
+    for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
+        METAL_INTERNAL_ReturnUniformBufferToPool(
+            renderer,
+            commandBuffer->usedUniformBuffers[i]);
+    }
+    commandBuffer->usedUniformBufferCount = 0;
+
+    SDL_UnlockMutex(renderer->acquireUniformBufferLock);
+
+    // Reset presentation
+    commandBuffer->windowDataCount = 0;
+
+    // Reset bindings
+    commandBuffer->indexBuffer = NULL;
+    for (i = 0; i < MAX_TEXTURE_SAMPLERS_PER_STAGE; i += 1) {
+        commandBuffer->vertexSamplers[i] = nil;
+        commandBuffer->vertexTextures[i] = nil;
+        commandBuffer->fragmentSamplers[i] = nil;
+        commandBuffer->fragmentTextures[i] = nil;
+    }
+    for (i = 0; i < MAX_STORAGE_TEXTURES_PER_STAGE; i += 1) {
+        commandBuffer->vertexStorageTextures[i] = nil;
+        commandBuffer->fragmentStorageTextures[i] = nil;
+        commandBuffer->computeReadOnlyTextures[i] = nil;
+    }
+    for (i = 0; i < MAX_STORAGE_BUFFERS_PER_STAGE; i += 1) {
+        commandBuffer->vertexStorageBuffers[i] = nil;
+        commandBuffer->fragmentStorageBuffers[i] = nil;
+        commandBuffer->computeReadOnlyBuffers[i] = nil;
+    }
+    for (i = 0; i < MAX_COMPUTE_WRITE_TEXTURES; i += 1) {
+        commandBuffer->computeWriteOnlyTextures[i] = nil;
+    }
+    for (i = 0; i < MAX_COMPUTE_WRITE_BUFFERS; i += 1) {
+        commandBuffer->computeWriteOnlyBuffers[i] = nil;
+    }
+
+    // The fence is now available (unless SubmitAndAcquireFence was called)
+    if (commandBuffer->autoReleaseFence) {
+        METAL_ReleaseFence(
+            (SDL_GpuRenderer *)renderer,
+            (SDL_GpuFence *)commandBuffer->fence);
+    }
+
+    // Return command buffer to pool
+    SDL_LockMutex(renderer->acquireCommandBufferLock);
+    // FIXME: Should this use EXPAND_IF_NEEDED?
+    if (renderer->availableCommandBufferCount == renderer->availableCommandBufferCapacity) {
+        renderer->availableCommandBufferCapacity += 1;
+        renderer->availableCommandBuffers = SDL_realloc(
+            renderer->availableCommandBuffers,
+            renderer->availableCommandBufferCapacity * sizeof(MetalCommandBuffer *));
+    }
+    renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer;
+    renderer->availableCommandBufferCount += 1;
+    SDL_UnlockMutex(renderer->acquireCommandBufferLock);
+
+    // Remove this command buffer from the submitted list
+    for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
+        if (renderer->submittedCommandBuffers[i] == commandBuffer) {
+            renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
+            renderer->submittedCommandBufferCount -= 1;
+        }
+    }
+}
+
+// This function assumes that it's called from within an autorelease pool
+static void METAL_INTERNAL_PerformPendingDestroys(
+    MetalRenderer *renderer)
+{
+    Sint32 referenceCount = 0;
+    Sint32 i;
+    Uint32 j;
+
+    for (i = renderer->bufferContainersToDestroyCount - 1; i >= 0; i -= 1) {
+        referenceCount = 0;
+        for (j = 0; j < renderer->bufferContainersToDestroy[i]->bufferCount; j += 1) {
+            referenceCount += SDL_AtomicGet(&renderer->bufferContainersToDestroy[i]->buffers[j]->referenceCount);
+        }
+
+        if (referenceCount == 0) {
+            METAL_INTERNAL_DestroyBufferContainer(
+                renderer->bufferContainersToDestroy[i]);
+
+            renderer->bufferContainersToDestroy[i] = renderer->bufferContainersToDestroy[renderer->bufferContainersToDestroyCount - 1];
+            renderer->bufferContainersToDestroyCount -= 1;
+        }
+    }
+
+    for (i = renderer->textureContainersToDestroyCount - 1; i >= 0; i -= 1) {
+        referenceCount = 0;
+        for (j = 0; j < renderer->textureContainersToDestroy[i]->textureCount; j += 1) {
+            referenceCount += SDL_AtomicGet(&renderer->textureContainersToDestroy[i]->textures[j]->referenceCount);
+        }
+
+        if (referenceCount == 0) {
+            METAL_INTERNAL_DestroyTextureContainer(
+                renderer->textureContainersToDestroy[i]);
+
+            renderer->textureContainersToDestroy[i] = renderer->textureContainersToDestroy[renderer->textureContainersToDestroyCount - 1];
+            renderer->textureContainersToDestroyCount -= 1;
+        }
+    }
+}
+
+// Fences
+
+static void METAL_WaitForFences(
+    SDL_GpuRenderer *driverData,
+    SDL_bool waitAll,
+    SDL_GpuFence **pFences,
+    Uint32 fenceCount)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        SDL_bool waiting;
+
+        if (waitAll) {
+            for (Uint32 i = 0; i < fenceCount; i += 1) {
+                while (!SDL_AtomicGet(&((MetalFence *)pFences[i])->complete)) {
+                    // Spin!
+                }
+            }
+        } else {
+            waiting = 1;
+            while (waiting) {
+                for (Uint32 i = 0; i < fenceCount; i += 1) {
+                    if (SDL_AtomicGet(&((MetalFence *)pFences[i])->complete) > 0) {
+                        waiting = 0;
+                        break;
+                    }
+                }
+            }
+        }
+
+        METAL_INTERNAL_PerformPendingDestroys(renderer);
+    }
+}
+
+static SDL_bool METAL_QueryFence(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuFence *fence)
+{
+    MetalFence *metalFence = (MetalFence *)fence;
+    return SDL_AtomicGet(&metalFence->complete) == 1;
+}
+
+// Window and Swapchain Management
+
+static MetalWindowData *METAL_INTERNAL_FetchWindowData(SDL_Window *window)
+{
+    SDL_PropertiesID properties = SDL_GetWindowProperties(window);
+    return (MetalWindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
+}
+
+static SDL_bool METAL_SupportsSwapchainComposition(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition)
+{
+#ifndef SDL_PLATFORM_MACOS
+    if (swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2048) {
+        return SDL_FALSE;
+    }
+#endif
+
+    if (@available(macOS 11.0, *)) {
+        return SDL_TRUE;
+    } else {
+        return swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2048;
+    }
+}
+
+// This function assumes that it's called from within an autorelease pool
+static Uint8 METAL_INTERNAL_CreateSwapchain(
+    MetalRenderer *renderer,
+    MetalWindowData *windowData,
+    SDL_GpuSwapchainComposition swapchainComposition,
+    SDL_GpuPresentMode presentMode)
+{
+    CGColorSpaceRef colorspace;
+    CGSize drawableSize;
+
+    windowData->view = SDL_Metal_CreateView(windowData->window);
+    windowData->drawable = nil;
+
+    windowData->layer = (__bridge CAMetalLayer *)(SDL_Metal_GetLayer(windowData->view));
+    windowData->layer.device = renderer->device;
+#ifdef SDL_PLATFORM_MACOS
+    windowData->layer.displaySyncEnabled = (presentMode != SDL_GPU_PRESENTMODE_IMMEDIATE);
+#endif
+    windowData->layer.pixelFormat = SDLToMetal_SurfaceFormat[SwapchainCompositionToFormat[swapchainComposition]];
+#ifndef SDL_PLATFORM_TVOS
+    windowData->layer.wantsExtendedDynamicRangeContent = (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR);
+#endif
+
+    colorspace = CGColorSpaceCreateWithName(SwapchainCompositionToColorSpace[swapchainComposition]);
+    windowData->layer.colorspace = colorspace;
+    CGColorSpaceRelease(colorspace);
+
+    windowData->texture.handle = nil; // This will be set in AcquireSwapchainTexture.
+
+    // Precache blit pipelines for the swapchain format
+    for (Uint32 i = 0; i < 4; i += 1) {
+        SDL_Gpu_FetchBlitPipeline(
+            renderer->sdlGpuDevice,
+            (SDL_GpuTextureType)i,
+            SwapchainCompositionToFormat[swapchainComposition],
+            renderer->blitVertexShader,
+            renderer->blitFrom2DShader,
+            renderer->blitFrom2DArrayShader,
+            renderer->blitFrom3DShader,
+            renderer->blitFromCubeShader,
+            &renderer->blitPipelines,
+            &renderer->blitPipelineCount,
+            &renderer->blitPipelineCapacity);
+    }
+
+    // Set up the texture container
+    SDL_zero(windowData->textureContainer);
+    windowData->textureContainer.canBeCycled = 0;
+    windowData->textureContainer.activeTexture = &windowData->texture;
+    windowData->textureContainer.textureCapacity = 1;
+    windowData->textureContainer.textureCount = 1;
+    windowData->textureContainer.header.info.format = SwapchainCompositionToFormat[swapchainComposition];
+    windowData->textureContainer.header.info.levelCount = 1;
+    windowData->textureContainer.header.info.layerCountOrDepth = 1;
+    windowData->textureContainer.header.info.type = SDL_GPU_TEXTURETYPE_2D;
+    windowData->textureContainer.header.info.usageFlags = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT;
+
+    drawableSize = windowData->layer.drawableSize;
+    windowData->textureContainer.header.info.width = (Uint32)drawableSize.width;
+    windowData->textureContainer.header.info.height = (Uint32)drawableSize.height;
+
+    return 1;
+}
+
+static SDL_bool METAL_SupportsPresentMode(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuPresentMode presentMode)
+{
+    switch (presentMode) {
+#ifdef SDL_PLATFORM_MACOS
+    case SDL_GPU_PRESENTMODE_IMMEDIATE:
+#endif
+    case SDL_GPU_PRESENTMODE_VSYNC:
+        return SDL_TRUE;
+    default:
+        return SDL_FALSE;
+    }
+}
+
+static SDL_bool METAL_ClaimWindow(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window);
+
+        if (windowData == NULL) {
+            windowData = (MetalWindowData *)SDL_malloc(sizeof(MetalWindowData));
+            windowData->window = window;
+
+            if (METAL_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
+                SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
+
+                SDL_LockMutex(renderer->windowLock);
+
+                if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
+                    renderer->claimedWindowCapacity *= 2;
+                    renderer->claimedWindows = SDL_realloc(
+                        renderer->claimedWindows,
+                        renderer->claimedWindowCapacity * sizeof(MetalWindowData *));
+                }
+                renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
+                renderer->claimedWindowCount += 1;
+
+                SDL_UnlockMutex(renderer->windowLock);
+
+                return SDL_TRUE;
+            } else {
+                SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not create swapchain, failed to claim window!");
+                SDL_free(windowData);
+                return SDL_FALSE;
+            }
+        } else {
+            SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Window already claimed!");
+            return SDL_FALSE;
+        }
+    }
+}
+
+static void METAL_UnclaimWindow(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window);
+
+        if (windowData == NULL) {
+            return;
+        }
+
+        METAL_Wait(driverData);
+        SDL_Metal_DestroyView(windowData->view);
+
+        SDL_LockMutex(renderer->windowLock);
+        for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
+            if (renderer->claimedWindows[i]->window == window) {
+                renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1];
+                renderer->claimedWindowCount -= 1;
+                break;
+            }
+        }
+        SDL_UnlockMutex(renderer->windowLock);
+
+        SDL_free(windowData);
+
+        SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
+    }
+}
+
+static SDL_GpuTexture *METAL_AcquireSwapchainTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_Window *window,
+    Uint32 *pWidth,
+    Uint32 *pHeight)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalWindowData *windowData;
+        CGSize drawableSize;
+
+        windowData = METAL_INTERNAL_FetchWindowData(window);
+        if (windowData == NULL) {
+            return NULL;
+        }
+
+        // Get the drawable and its underlying texture
+        windowData->drawable = [windowData->layer nextDrawable];
+        windowData->texture.handle = [windowData->drawable texture];
+
+        // Update the window size
+        drawableSize = windowData->layer.drawableSize;
+        windowData->textureContainer.header.info.width = (Uint32)drawableSize.width;
+        windowData->textureContainer.header.info.height = (Uint32)drawableSize.height;
+
+        // Send the dimensions to the out parameters.
+        *pWidth = (Uint32)drawableSize.width;
+        *pHeight = (Uint32)drawableSize.height;
+
+        // Set up presentation
+        if (metalCommandBuffer->windowDataCount == metalCommandBuffer->windowDataCapacity) {
+            metalCommandBuffer->windowDataCapacity += 1;
+            metalCommandBuffer->windowDatas = SDL_realloc(
+                metalCommandBuffer->windowDatas,
+                metalCommandBuffer->windowDataCapacity * sizeof(MetalWindowData *));
+        }
+        metalCommandBuffer->windowDatas[metalCommandBuffer->windowDataCount] = windowData;
+        metalCommandBuffer->windowDataCount += 1;
+
+        // Return the swapchain texture
+        return (SDL_GpuTexture *)&windowData->textureContainer;
+    }
+}
+
+static SDL_GpuTextureFormat METAL_GetSwapchainTextureFormat(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Cannot get swapchain format, window has not been claimed!");
+        return 0;
+    }
+
+    return windowData->textureContainer.header.info.format;
+}
+
+static SDL_bool METAL_SetSwapchainParameters(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition,
+    SDL_GpuPresentMode presentMode)
+{
+    @autoreleasepool {
+        MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window);
+        CGColorSpaceRef colorspace;
+
+        if (windowData == NULL) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Cannot set swapchain parameters, window has not been claimed!");
+            return SDL_FALSE;
+        }
+
+        if (!METAL_SupportsSwapchainComposition(driverData, window, swapchainComposition)) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Swapchain composition not supported!");
+            return SDL_FALSE;
+        }
+
+        if (!METAL_SupportsPresentMode(driverData, window, presentMode)) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Present mode not supported!");
+            return SDL_FALSE;
+        }
+
+        METAL_Wait(driverData);
+
+#ifdef SDL_PLATFORM_MACOS
+        windowData->layer.displaySyncEnabled = (presentMode != SDL_GPU_PRESENTMODE_IMMEDIATE);
+#endif
+        windowData->layer.pixelFormat = SDLToMetal_SurfaceFormat[SwapchainCompositionToFormat[swapchainComposition]];
+#ifndef SDL_PLATFORM_TVOS
+        windowData->layer.wantsExtendedDynamicRangeContent = (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR);
+#endif
+
+        colorspace = CGColorSpaceCreateWithName(SwapchainCompositionToColorSpace[swapchainComposition]);
+        windowData->layer.colorspace = colorspace;
+        CGColorSpaceRelease(colorspace);
+
+        windowData->textureContainer.header.info.format = SwapchainCompositionToFormat[swapchainComposition];
+
+        return SDL_TRUE;
+    }
+}
+
+// Submission
+
+static void METAL_Submit(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    @autoreleasepool {
+        MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+        MetalRenderer *renderer = metalCommandBuffer->renderer;
+
+        SDL_LockMutex(renderer->submitLock);
+
+        // Enqueue present requests, if applicable
+        for (Uint32 i = 0; i < metalCommandBuffer->windowDataCount; i += 1) {
+            [metalCommandBuffer->handle presentDrawable:metalCommandBuffer->windowDatas[i]->drawable];
+            metalCommandBuffer->windowDatas[i]->drawable = nil;
+        }
+
+        // Notify the fence when the command buffer has completed
+        [metalCommandBuffer->handle addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
+          SDL_AtomicIncRef(&metalCommandBuffer->fence->complete);
+        }];
+
+        // Submit the command buffer
+        [metalCommandBuffer->handle commit];
+        metalCommandBuffer->handle = nil;
+
+        // Mark the command buffer as submitted
+        if (renderer->submittedCommandBufferCount >= renderer->submittedCommandBufferCapacity) {
+            renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1;
+
+            renderer->submittedCommandBuffers = SDL_realloc(
+                renderer->submittedCommandBuffers,
+                sizeof(MetalCommandBuffer *) * renderer->submittedCommandBufferCapacity);
+        }
+        renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = metalCommandBuffer;
+        renderer->submittedCommandBufferCount += 1;
+
+        // Check if we can perform any cleanups
+        for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+            if (SDL_AtomicGet(&renderer->submittedCommandBuffers[i]->fence->complete)) {
+                METAL_INTERNAL_CleanCommandBuffer(
+                    renderer,
+                    renderer->submittedCommandBuffers[i]);
+            }
+        }
+
+        METAL_INTERNAL_PerformPendingDestroys(renderer);
+
+        SDL_UnlockMutex(renderer->submitLock);
+    }
+}
+
+static SDL_GpuFence *METAL_SubmitAndAcquireFence(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    MetalCommandBuffer *metalCommandBuffer = (MetalCommandBuffer *)commandBuffer;
+    MetalFence *fence = metalCommandBuffer->fence;
+
+    metalCommandBuffer->autoReleaseFence = 0;
+    METAL_Submit(commandBuffer);
+
+    return (SDL_GpuFence *)fence;
+}
+
+static void METAL_Wait(
+    SDL_GpuRenderer *driverData)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+        MetalCommandBuffer *commandBuffer;
+
+        /*
+         * Wait for all submitted command buffers to complete.
+         * Sort of equivalent to vkDeviceWaitIdle.
+         */
+        for (Uint32 i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
+            while (!SDL_AtomicGet(&renderer->submittedCommandBuffers[i]->fence->complete)) {
+                // Spin!
+            }
+        }
+
+        SDL_LockMutex(renderer->submitLock);
+
+        for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+            commandBuffer = renderer->submittedCommandBuffers[i];
+            METAL_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
+        }
+
+        METAL_INTERNAL_PerformPendingDestroys(renderer);
+
+        SDL_UnlockMutex(renderer->submitLock);
+    }
+}
+
+// Format Info
+
+static SDL_bool METAL_SupportsTextureFormat(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureFormat format,
+    SDL_GpuTextureType type,
+    SDL_GpuTextureUsageFlags usage)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer = (MetalRenderer *)driverData;
+
+        // Only depth textures can be used as... depth textures
+        if ((usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT)) {
+            if (!IsDepthFormat(format)) {
+                return SDL_FALSE;
+            }
+        }
+
+        switch (format) {
+        // Apple GPU exclusive
+        case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM:
+        case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM:
+        case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM:
+            return [renderer->device supportsFamily:MTLGPUFamilyApple1];
+
+        // Requires BC compression support
+        case SDL_GPU_TEXTUREFORMAT_BC1_UNORM:
+        case SDL_GPU_TEXTUREFORMAT_BC2_UNORM:
+        case SDL_GPU_TEXTUREFORMAT_BC3_UNORM:
+        case SDL_GPU_TEXTUREFORMAT_BC7_UNORM:
+        case SDL_GPU_TEXTUREFORMAT_BC3_UNORM_SRGB:
+        case SDL_GPU_TEXTUREFORMAT_BC7_UNORM_SRGB:
+#ifdef SDL_PLATFORM_MACOS
+            if (@available(macOS 11.0, *)) {
+                return (
+                    [renderer->device supportsBCTextureCompression] &&
+                    !(usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT));
+            } else {
+                return SDL_FALSE;
+            }
+#else
+            // FIXME: iOS 16.4+ allows these formats!
+            return SDL_FALSE;
+#endif
+
+        // Requires D24S8 support
+        case SDL_GPU_TEXTUREFORMAT_D24_UNORM:
+        case SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT:
+#ifdef SDL_PLATFORM_MACOS
+            return [renderer->device isDepth24Stencil8PixelFormatSupported];
+#else
+            return SDL_FALSE;
+#endif
+
+        default:
+            return SDL_TRUE;
+        }
+    }
+}
+
+// Device Creation
+
+static SDL_bool METAL_PrepareDriver(SDL_VideoDevice *_this)
+{
+    // FIXME: Add a macOS / iOS version check! Maybe support >= 10.14?
+    return (_this->Metal_CreateView != NULL);
+}
+
+static void METAL_INTERNAL_InitBlitResources(
+    MetalRenderer *renderer)
+{
+    SDL_GpuShaderCreateInfo shaderModuleCreateInfo;
+    SDL_GpuSamplerCreateInfo samplerCreateInfo;
+
+    // Allocate the dynamic blit pipeline list
+    renderer->blitPipelineCapacity = 2;
+    renderer->blitPipelineCount = 0;
+    renderer->blitPipelines = SDL_malloc(
+        renderer->blitPipelineCapacity * sizeof(BlitPipelineCacheEntry));
+
+    // Fullscreen vertex shader
+    SDL_zero(shaderModuleCreateInfo);
+    shaderModuleCreateInfo.code = FullscreenVert_metallib;
+    shaderModuleCreateInfo.codeSize = FullscreenVert_metallib_len;
+    shaderModuleCreateInfo.stage = SDL_GPU_SHADERSTAGE_VERTEX;
+    shaderModuleCreateInfo.format = SDL_GPU_SHADERFORMAT_METALLIB;
+    shaderModuleCreateInfo.entryPointName = "FullscreenVert";
+
+    renderer->blitVertexShader = METAL_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderModuleCreateInfo);
+
+    if (renderer->blitVertexShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile vertex shader for blit!");
+    }
+
+    // BlitFrom2D fragment shader
+    shaderModuleCreateInfo.code = BlitFrom2D_metallib;
+    shaderModuleCreateInfo.codeSize = BlitFrom2D_metallib_len;
+    shaderModuleCreateInfo.stage = SDL_GPU_SHADERSTAGE_FRAGMENT;
+    shaderModuleCreateInfo.entryPointName = "BlitFrom2D";
+    shaderModuleCreateInfo.samplerCount = 1;
+    shaderModuleCreateInfo.uniformBufferCount = 1;
+
+    renderer->blitFrom2DShader = METAL_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderModuleCreateInfo);
+
+    if (renderer->blitFrom2DShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2D fragment shader!");
+    }
+
+    // BlitFrom2DArray fragment shader
+    shaderModuleCreateInfo.code = BlitFrom2DArray_metallib;
+    shaderModuleCreateInfo.codeSize = BlitFrom2DArray_metallib_len;
+    shaderModuleCreateInfo.entryPointName = "BlitFrom2DArray";
+
+    renderer->blitFrom2DArrayShader = METAL_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderModuleCreateInfo);
+
+    if (renderer->blitFrom2DArrayShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2DArray fragment shader!");
+    }
+
+    // BlitFrom3D fragment shader
+    shaderModuleCreateInfo.code = BlitFrom3D_metallib;
+    shaderModuleCreateInfo.codeSize = BlitFrom3D_metallib_len;
+    shaderModuleCreateInfo.entryPointName = "BlitFrom3D";
+
+    renderer->blitFrom3DShader = METAL_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderModuleCreateInfo);
+
+    if (renderer->blitFrom3DShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom3D fragment shader!");
+    }
+
+    // BlitFromCube fragment shader
+    shaderModuleCreateInfo.code = BlitFromCube_metallib;
+    shaderModuleCreateInfo.codeSize = BlitFromCube_metallib_len;
+    shaderModuleCreateInfo.entryPointName = "BlitFromCube";
+
+    renderer->blitFromCubeShader = METAL_CreateShader(
+        (SDL_GpuRenderer *)renderer,
+        &shaderModuleCreateInfo);
+
+    if (renderer->blitFromCubeShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCube fragment shader!");
+    }
+
+    // Create samplers
+    samplerCreateInfo.addressModeU = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.addressModeV = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.addressModeW = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
+    samplerCreateInfo.anisotropyEnable = 0;
+    samplerCreateInfo.compareEnable = 0;
+    samplerCreateInfo.magFilter = SDL_GPU_FILTER_NEAREST;
+    samplerCreateInfo.minFilter = SDL_GPU_FILTER_NEAREST;
+    samplerCreateInfo.mipmapMode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST;
+    samplerCreateInfo.mipLodBias = 0.0f;
+    samplerCreateInfo.minLod = 0;
+    samplerCreateInfo.maxLod = 1000;
+    samplerCreateInfo.maxAnisotropy = 1.0f;
+    samplerCreateInfo.compareOp = SDL_GPU_COMPAREOP_ALWAYS;
+
+    renderer->blitNearestSampler = METAL_CreateSampler(
+        (SDL_GpuRenderer *)renderer,
+        &samplerCreateInfo);
+
+    if (renderer->blitNearestSampler == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit nearest sampler!");
+    }
+
+    samplerCreateInfo.magFilter = SDL_GPU_FILTER_LINEAR;
+    samplerCreateInfo.minFilter = SDL_GPU_FILTER_LINEAR;
+    samplerCreateInfo.mipmapMode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR;
+
+    renderer->blitLinearSampler = METAL_CreateSampler(
+        (SDL_GpuRenderer *)renderer,
+        &samplerCreateInfo);
+
+    if (renderer->blitLinearSampler == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit linear sampler!");
+    }
+}
+
+static void METAL_INTERNAL_DestroyBlitResources(
+    SDL_GpuRenderer *driverData)
+{
+    MetalRenderer *renderer = (MetalRenderer *)driverData;
+    METAL_ReleaseSampler(driverData, renderer->blitLinearSampler);
+    METAL_ReleaseSampler(driverData, renderer->blitNearestSampler);
+    METAL_ReleaseShader(driverData, renderer->blitVertexShader);
+    METAL_ReleaseShader(driverData, renderer->blitFrom2DShader);
+    METAL_ReleaseShader(driverData, renderer->blitFrom2DArrayShader);
+    METAL_ReleaseShader(driverData, renderer->blitFrom3DShader);
+    METAL_ReleaseShader(driverData, renderer->blitFromCubeShader);
+
+    for (Uint32 i = 0; i < renderer->blitPipelineCount; i += 1) {
+        METAL_ReleaseGraphicsPipeline(driverData, renderer->blitPipelines[i].pipeline);
+    }
+    SDL_free(renderer->blitPipelines);
+}
+
+static SDL_GpuDevice *METAL_CreateDevice(SDL_bool debugMode, SDL_bool preferLowPower, SDL_PropertiesID props)
+{
+    @autoreleasepool {
+        MetalRenderer *renderer;
+
+        // Allocate and zero out the renderer
+        renderer = (MetalRenderer *)SDL_calloc(1, sizeof(MetalRenderer));
+
+        // Create the Metal device and command queue
+#ifdef SDL_PLATFORM_MACOS
+        if (preferLowPower) {
+            NSArray<id<MTLDevice>> *devices = MTLCopyAllDevices();
+            for (id<MTLDevice> device in devices) {
+                if (device.isLowPower) {
+                    renderer->device = device;
+                    break;
+                }
+            }
+        }
+#endif
+        if (renderer->device == NULL) {
+            renderer->device = MTLCreateSystemDefaultDevice();
+        }
+        renderer->queue = [renderer->device newCommandQueue];
+
+        // Print driver info
+        SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_Gpu Driver: Metal");
+        SDL_LogInfo(
+            SDL_LOG_CATEGORY_GPU,
+            "Metal Device: %s",
+            [renderer->device.name UTF8String]);
+
+        // Remember debug mode
+        renderer->debugMode = debugMode;
+
+        // Set up colorspace array
+        SwapchainCompositionToColorSpace[0] = kCGColorSpaceSRGB;
+        SwapchainCompositionToColorSpace[1] = kCGColorSpaceSRGB;
+        SwapchainCompositionToColorSpace[2] = kCGColorSpaceExtendedLinearSRGB;
+        if (@available(macOS 11.0, *)) {
+            SwapchainCompositionToColorSpace[3] = kCGColorSpaceITUR_2100_PQ;
+        } else {
+            SwapchainCompositionToColorSpace[3] = NULL;
+        }
+
+        // Create mutexes
+        renderer->submitLock = SDL_CreateMutex();
+        renderer->acquireCommandBufferLock = SDL_CreateMutex();
+        renderer->acquireUniformBufferLock = SDL_CreateMutex();
+        renderer->disposeLock = SDL_CreateMutex();
+        renderer->fenceLock = SDL_CreateMutex();
+        renderer->windowLock = SDL_CreateMutex();
+
+        // Create command buffer pool
+        METAL_INTERNAL_AllocateCommandBuffers(renderer, 2);
+
+        // Create fence pool
+        renderer->availableFenceCapacity = 2;
+        renderer->availableFences = SDL_malloc(
+            sizeof(MetalFence *) * renderer->availableFenceCapacity);
+
+        // Create uniform buffer pool
+        renderer->uniformBufferPoolCapacity = 32;
+        renderer->uniformBufferPoolCount = 32;
+        renderer->uniformBufferPool = SDL_malloc(
+            renderer->uniformBufferPoolCapacity * sizeof(MetalUniformBuffer *));
+
+        for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
+            renderer->uniformBufferPool[i] = METAL_INTERNAL_CreateUniformBuffer(
+                renderer,
+                UNIFORM_BUFFER_SIZE);
+        }
+
+        // Create deferred destroy arrays
+        renderer->bufferContainersToDestroyCapacity = 2;
+        renderer->bufferContainersToDestroyCount = 0;
+        renderer->bufferContainersToDestroy = SDL_malloc(
+            renderer->bufferContainersToDestroyCapacity * sizeof(MetalBufferContainer *));
+
+        renderer->textureContainersToDestroyCapacity = 2;
+        renderer->textureContainersToDestroyCount = 0;
+        renderer->textureContainersToDestroy = SDL_malloc(
+            renderer->textureContainersToDestroyCapacity * sizeof(MetalTextureContainer *));
+
+        // Create claimed window list
+        renderer->claimedWindowCapacity = 1;
+        renderer->claimedWindows = SDL_malloc(
+            sizeof(MetalWindowData *) * renderer->claimedWindowCapacity);
+
+        // Initialize blit resources
+        METAL_INTERNAL_InitBlitResources(renderer);
+
+        SDL_GpuDevice *result = SDL_malloc(sizeof(SDL_GpuDevice));
+        ASSIGN_DRIVER(METAL)
+        result->driverData = (SDL_GpuRenderer *)renderer;
+        renderer->sdlGpuDevice = result;
+
+        return result;
+    }
+}
+
+SDL_GpuBootstrap MetalDriver = {
+    "Metal",
+    SDL_GPU_DRIVER_METAL,
+    SDL_GPU_SHADERFORMAT_MSL | SDL_GPU_SHADERFORMAT_METALLIB,
+    METAL_PrepareDriver,
+    METAL_CreateDevice
+};
+
+#endif // SDL_GPU_METAL

+ 68 - 0
src/gpu/metal/compile_shaders.sh

@@ -0,0 +1,68 @@
+#!/bin/bash
+
+set -x
+set -e
+cd `dirname "$0"`
+
+shadernames=(FullscreenVert BlitFrom2D BlitFrom2DArray BlitFrom3D BlitFromCube)
+
+generate_shaders()
+{
+        fileplatform=$1
+        compileplatform=$2
+        sdkplatform=$3
+        minversion=$4
+
+        for shadername in "${shadernames[@]}"; do
+            xcrun -sdk $sdkplatform metal -c -std=$compileplatform-metal1.1 -m$sdkplatform-version-min=$minversion -Wall -O3 -D COMPILE_$shadername -o ./$shadername.air ./Metal_Blit.metal || exit $?
+            xcrun -sdk $sdkplatform metallib -o $shadername.metallib $shadername.air || exit $?
+            xxd -i $shadername.metallib | perl -w -p -e 's/\Aunsigned /const unsigned /;' >./${shadername}_$fileplatform.h
+            rm -f $shadername.air $shadername.metallib
+        done
+}
+
+generate_shaders macos macos macosx 10.11
+generate_shaders ios ios iphoneos 8.0
+generate_shaders iphonesimulator ios iphonesimulator 8.0
+generate_shaders tvos ios appletvos 9.0
+generate_shaders tvsimulator ios appletvsimulator 9.0
+
+# Bundle together one mega-header
+catShaders()
+{
+    target=$1
+    for shadername in "${shadernames[@]}"; do
+        cat ${shadername}_$target.h >> Metal_Blit.h
+    done
+}
+
+rm -f Metal_Blit.h
+echo "#if defined(SDL_PLATFORM_IOS)" >> Metal_Blit.h
+    echo "#if TARGET_OS_SIMULATOR" >> Metal_Blit.h
+        catShaders iphonesimulator
+    echo "#else" >> Metal_Blit.h
+        catShaders ios
+    echo "#endif" >> Metal_Blit.h
+echo "#elif defined(SDL_PLATFORM_TVOS)" >> Metal_Blit.h
+    echo "#if TARGET_OS_SIMULATOR" >> Metal_Blit.h
+        catShaders tvsimulator
+    echo "#else" >> Metal_Blit.h
+        catShaders tvos
+    echo "#endif" >> Metal_Blit.h
+echo "#else" >> Metal_Blit.h
+    catShaders macos
+echo "#endif" >> Metal_Blit.h
+
+# Clean up
+cleanupShaders()
+{
+    target=$1
+    for shadername in "${shadernames[@]}"; do
+        rm -f ${shadername}_$target.h
+    done
+}
+cleanupShaders iphonesimulator
+cleanupShaders ios
+cleanupShaders tvsimulator
+cleanupShaders tvos
+cleanupShaders macos

+ 11797 - 0
src/gpu/vulkan/SDL_gpu_vulkan.c

@@ -0,0 +1,11797 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_internal.h"
+
+#if SDL_GPU_VULKAN
+
+// Needed for VK_KHR_portability_subset
+#define VK_ENABLE_BETA_EXTENSIONS
+
+#define VK_NO_PROTOTYPES
+#include "../../video/khronos/vulkan/vulkan.h"
+
+#include "SDL_hashtable.h"
+#include <SDL3/SDL_vulkan.h>
+
+#include "../SDL_sysgpu.h"
+
+#define VULKAN_INTERNAL_clamp(val, min, max) SDL_max(min, SDL_min(val, max))
+
+// Global Vulkan Loader Entry Points
+
+static PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
+
+#define VULKAN_GLOBAL_FUNCTION(name) \
+    static PFN_##name name = NULL;
+#include "SDL_gpu_vulkan_vkfuncs.h"
+
+typedef struct VulkanExtensions
+{
+    // These extensions are required!
+
+    // Globally supported
+    Uint8 KHR_swapchain;
+    // Core since 1.1, needed for negative VkViewport::height
+    Uint8 KHR_maintenance1;
+
+    // These extensions are optional!
+
+    // Core since 1.2, but requires annoying paperwork to implement
+    Uint8 KHR_driver_properties;
+    // EXT, probably not going to be Core
+    Uint8 EXT_vertex_attribute_divisor;
+    // Only required for special implementations (i.e. MoltenVK)
+    Uint8 KHR_portability_subset;
+} VulkanExtensions;
+
+// Defines
+
+#define SMALL_ALLOCATION_THRESHOLD    2097152  // 2   MiB
+#define SMALL_ALLOCATION_SIZE         16777216 // 16  MiB
+#define LARGE_ALLOCATION_INCREMENT    67108864 // 64  MiB
+#define MAX_UBO_SECTION_SIZE          4096     // 4   KiB
+#define DESCRIPTOR_POOL_STARTING_SIZE 128
+#define WINDOW_PROPERTY_DATA          "SDL_GpuVulkanWindowPropertyData"
+
+#define IDENTITY_SWIZZLE               \
+    {                                  \
+        VK_COMPONENT_SWIZZLE_IDENTITY, \
+        VK_COMPONENT_SWIZZLE_IDENTITY, \
+        VK_COMPONENT_SWIZZLE_IDENTITY, \
+        VK_COMPONENT_SWIZZLE_IDENTITY  \
+    }
+
+#define NULL_DESC_LAYOUT     (VkDescriptorSetLayout)0
+#define NULL_PIPELINE_LAYOUT (VkPipelineLayout)0
+#define NULL_RENDER_PASS     (SDL_GpuRenderPass *)0
+
+#define EXPAND_ELEMENTS_IF_NEEDED(arr, initialValue, type) \
+    if (arr->count == arr->capacity) {                     \
+        if (arr->capacity == 0) {                          \
+            arr->capacity = initialValue;                  \
+        } else {                                           \
+            arr->capacity *= 2;                            \
+        }                                                  \
+        arr->elements = (type *)SDL_realloc(               \
+            arr->elements,                                 \
+            arr->capacity * sizeof(type));                 \
+    }
+
+#define EXPAND_ARRAY_IF_NEEDED(arr, elementType, newCount, capacity, newCapacity) \
+    if (newCount >= capacity) {                                                   \
+        capacity = newCapacity;                                                   \
+        arr = (elementType *)SDL_realloc(                                         \
+            arr,                                                                  \
+            sizeof(elementType) * capacity);                                      \
+    }
+
+#define MOVE_ARRAY_CONTENTS_AND_RESET(i, dstArr, dstCount, srcArr, srcCount) \
+    for (i = 0; i < srcCount; i += 1) {                                      \
+        dstArr[i] = srcArr[i];                                               \
+    }                                                                        \
+    dstCount = srcCount;                                                     \
+    srcCount = 0;
+
+// Conversions
+
+static const Uint8 DEVICE_PRIORITY_HIGHPERFORMANCE[] = {
+    0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
+    3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
+    4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
+    2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
+    1  // VK_PHYSICAL_DEVICE_TYPE_CPU
+};
+
+static const Uint8 DEVICE_PRIORITY_LOWPOWER[] = {
+    0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
+    4, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
+    3, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
+    2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
+    1  // VK_PHYSICAL_DEVICE_TYPE_CPU
+};
+
+static VkPresentModeKHR SDLToVK_PresentMode[] = {
+    VK_PRESENT_MODE_FIFO_KHR,
+    VK_PRESENT_MODE_IMMEDIATE_KHR,
+    VK_PRESENT_MODE_MAILBOX_KHR
+};
+
+static VkFormat SDLToVK_SurfaceFormat[] = {
+    VK_FORMAT_R8G8B8A8_UNORM,           // R8G8B8A8_UNORM
+    VK_FORMAT_B8G8R8A8_UNORM,           // B8G8R8A8_UNORM
+    VK_FORMAT_R5G6B5_UNORM_PACK16,      // B5G6R5_UNORM
+    VK_FORMAT_A1R5G5B5_UNORM_PACK16,    // B5G5R5A1_UNORM
+    VK_FORMAT_B4G4R4A4_UNORM_PACK16,    // B4G4R4A4_UNORM
+    VK_FORMAT_A2B10G10R10_UNORM_PACK32, // R10G10B10A2_UNORM
+    VK_FORMAT_R16G16_UNORM,             // R16G16_UNORM
+    VK_FORMAT_R16G16B16A16_UNORM,       // R16G16B16A16_UNORM
+    VK_FORMAT_R8_UNORM,                 // R8_UNORM
+    VK_FORMAT_R8_UNORM,                 // A8_UNORM
+    VK_FORMAT_BC1_RGBA_UNORM_BLOCK,     // BC1_UNORM
+    VK_FORMAT_BC2_UNORM_BLOCK,          // BC2_UNORM
+    VK_FORMAT_BC3_UNORM_BLOCK,          // BC3_UNORM
+    VK_FORMAT_BC7_UNORM_BLOCK,          // BC7_UNORM
+    VK_FORMAT_R8G8_SNORM,               // R8G8_SNORM
+    VK_FORMAT_R8G8B8A8_SNORM,           // R8G8B8A8_SNORM
+    VK_FORMAT_R16_SFLOAT,               // R16_FLOAT
+    VK_FORMAT_R16G16_SFLOAT,            // R16G16_FLOAT
+    VK_FORMAT_R16G16B16A16_SFLOAT,      // R16G16B16A16_FLOAT
+    VK_FORMAT_R32_SFLOAT,               // R32_FLOAT
+    VK_FORMAT_R32G32_SFLOAT,            // R32G32_FLOAT
+    VK_FORMAT_R32G32B32A32_SFLOAT,      // R32G32B32A32_FLOAT
+    VK_FORMAT_R8_UINT,                  // R8_UINT
+    VK_FORMAT_R8G8_UINT,                // R8G8_UINT
+    VK_FORMAT_R8G8B8A8_UINT,            // R8G8B8A8_UINT
+    VK_FORMAT_R16_UINT,                 // R16_UINT
+    VK_FORMAT_R16G16_UINT,              // R16G16_UINT
+    VK_FORMAT_R16G16B16A16_UINT,        // R16G16B16A16_UINT
+    VK_FORMAT_R8G8B8A8_SRGB,            // R8G8B8A8_UNORM_SRGB
+    VK_FORMAT_B8G8R8A8_SRGB,            // B8G8R8A8_UNORM_SRGB
+    VK_FORMAT_BC3_SRGB_BLOCK,           // BC3_UNORM_SRGB
+    VK_FORMAT_BC7_SRGB_BLOCK,           // BC7_UNORM_SRGB
+    VK_FORMAT_D16_UNORM,                // D16_UNORM
+    VK_FORMAT_X8_D24_UNORM_PACK32,      // D24_UNORM
+    VK_FORMAT_D32_SFLOAT,               // D32_FLOAT
+    VK_FORMAT_D24_UNORM_S8_UINT,        // D24_UNORM_S8_UINT
+    VK_FORMAT_D32_SFLOAT_S8_UINT,       // D32_FLOAT_S8_UINT
+};
+SDL_COMPILE_TIME_ASSERT(SDLToVK_SurfaceFormat, SDL_arraysize(SDLToVK_SurfaceFormat) == SDL_GPU_TEXTUREFORMAT_MAX);
+
+static VkComponentMapping SDLToVK_SurfaceSwizzle[] = {
+    IDENTITY_SWIZZLE, // R8G8B8A8
+    IDENTITY_SWIZZLE, // B8G8R8A8
+    {
+        // B5G6R5
+        VK_COMPONENT_SWIZZLE_B,
+        VK_COMPONENT_SWIZZLE_G,
+        VK_COMPONENT_SWIZZLE_R,
+        VK_COMPONENT_SWIZZLE_ONE,
+    },
+    {
+        // B5G5R5A1
+        VK_COMPONENT_SWIZZLE_B,
+        VK_COMPONENT_SWIZZLE_G,
+        VK_COMPONENT_SWIZZLE_R,
+        VK_COMPONENT_SWIZZLE_A,
+    },
+    IDENTITY_SWIZZLE, // B4G4R4A4
+    {
+        // R10G10B10A2
+        VK_COMPONENT_SWIZZLE_R,
+        VK_COMPONENT_SWIZZLE_G,
+        VK_COMPONENT_SWIZZLE_B,
+        VK_COMPONENT_SWIZZLE_A,
+    },
+    IDENTITY_SWIZZLE, // R16G16
+    IDENTITY_SWIZZLE, // R16G16B16A16
+    IDENTITY_SWIZZLE, // R8
+    {
+        // A8
+        VK_COMPONENT_SWIZZLE_ZERO,
+        VK_COMPONENT_SWIZZLE_ZERO,
+        VK_COMPONENT_SWIZZLE_ZERO,
+        VK_COMPONENT_SWIZZLE_R,
+    },
+    IDENTITY_SWIZZLE, // BC1
+    IDENTITY_SWIZZLE, // BC2
+    IDENTITY_SWIZZLE, // BC3
+    IDENTITY_SWIZZLE, // BC7
+    IDENTITY_SWIZZLE, // R8G8_SNORM
+    IDENTITY_SWIZZLE, // R8G8B8A8_SNORM
+    IDENTITY_SWIZZLE, // R16_SFLOAT
+    IDENTITY_SWIZZLE, // R16G16_SFLOAT
+    IDENTITY_SWIZZLE, // R16G16B16A16_SFLOAT
+    IDENTITY_SWIZZLE, // R32_SFLOAT
+    IDENTITY_SWIZZLE, // R32G32_SFLOAT
+    IDENTITY_SWIZZLE, // R32G32B32A32_SFLOAT
+    IDENTITY_SWIZZLE, // R8_UINT
+    IDENTITY_SWIZZLE, // R8G8_UINT
+    IDENTITY_SWIZZLE, // R8G8B8A8_UINT
+    IDENTITY_SWIZZLE, // R16_UINT
+    IDENTITY_SWIZZLE, // R16G16_UINT
+    IDENTITY_SWIZZLE, // R16G16B16A16_UINT
+    IDENTITY_SWIZZLE, // R8G8B8A8_SRGB
+    IDENTITY_SWIZZLE, // B8G8R8A8_SRGB
+    IDENTITY_SWIZZLE, // BC3_SRGB
+    IDENTITY_SWIZZLE, // BC7_SRGB
+    IDENTITY_SWIZZLE, // D16_UNORM
+    IDENTITY_SWIZZLE, // D24_UNORM
+    IDENTITY_SWIZZLE, // D32_SFLOAT
+    IDENTITY_SWIZZLE, // D24_UNORM_S8_UINT
+    IDENTITY_SWIZZLE, // D32_SFLOAT_S8_UINT
+};
+
+static VkFormat SwapchainCompositionToFormat[] = {
+    VK_FORMAT_B8G8R8A8_UNORM,          // SDR
+    VK_FORMAT_B8G8R8A8_SRGB,           // SDR_LINEAR
+    VK_FORMAT_R16G16B16A16_SFLOAT,     // HDR_EXTENDED_LINEAR
+    VK_FORMAT_A2B10G10R10_UNORM_PACK32 // HDR10_ST2048
+};
+
+static VkFormat SwapchainCompositionToFallbackFormat[] = {
+    VK_FORMAT_R8G8B8A8_UNORM,
+    VK_FORMAT_R8G8B8A8_SRGB,
+    VK_FORMAT_UNDEFINED, // no fallback
+    VK_FORMAT_UNDEFINED  // no fallback
+};
+
+static SDL_GpuTextureFormat SwapchainCompositionToSDLFormat(
+    SDL_GpuSwapchainComposition composition,
+    SDL_bool usingFallback)
+{
+    switch (composition) {
+    case SDL_GPU_SWAPCHAINCOMPOSITION_SDR:
+        return usingFallback ? SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM : SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM;
+    case SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR:
+        return usingFallback ? SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB : SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB;
+    case SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR:
+        return SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT;
+    case SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2048:
+        return SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM;
+    default:
+        return SDL_GPU_TEXTUREFORMAT_INVALID;
+    }
+}
+
+static VkColorSpaceKHR SwapchainCompositionToColorSpace[] = {
+    VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+    VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+    VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT,
+    VK_COLOR_SPACE_HDR10_ST2084_EXT
+};
+
+static VkComponentMapping SwapchainCompositionSwizzle[] = {
+    IDENTITY_SWIZZLE, // SDR
+    IDENTITY_SWIZZLE, // SDR_SRGB
+    IDENTITY_SWIZZLE, // HDR
+    {
+        // HDR_ADVANCED
+        VK_COMPONENT_SWIZZLE_R,
+        VK_COMPONENT_SWIZZLE_G,
+        VK_COMPONENT_SWIZZLE_B,
+        VK_COMPONENT_SWIZZLE_A,
+    }
+};
+
+static VkFormat SDLToVK_VertexFormat[] = {
+    VK_FORMAT_R32_SINT,            // INT
+    VK_FORMAT_R32G32_SINT,         // INT2
+    VK_FORMAT_R32G32B32_SINT,      // INT3
+    VK_FORMAT_R32G32B32A32_SINT,   // INT4
+    VK_FORMAT_R32_UINT,            // UINT
+    VK_FORMAT_R32G32_UINT,         // UINT2
+    VK_FORMAT_R32G32B32_UINT,      // UINT3
+    VK_FORMAT_R32G32B32A32_UINT,   // UINT4
+    VK_FORMAT_R32_SFLOAT,          // FLOAT
+    VK_FORMAT_R32G32_SFLOAT,       // FLOAT2
+    VK_FORMAT_R32G32B32_SFLOAT,    // FLOAT3
+    VK_FORMAT_R32G32B32A32_SFLOAT, // FLOAT4
+    VK_FORMAT_R8G8_SINT,           // BYTE2
+    VK_FORMAT_R8G8B8A8_SINT,       // BYTE4
+    VK_FORMAT_R8G8_UINT,           // UBYTE2
+    VK_FORMAT_R8G8B8A8_UINT,       // UBYTE4
+    VK_FORMAT_R8G8_SNORM,          // BYTE2_NORM
+    VK_FORMAT_R8G8B8A8_SNORM,      // BYTE4_NORM
+    VK_FORMAT_R8G8_UNORM,          // UBYTE2_NORM
+    VK_FORMAT_R8G8B8A8_UNORM,      // UBYTE4_NORM
+    VK_FORMAT_R16G16_SINT,         // SHORT2
+    VK_FORMAT_R16G16B16A16_SINT,   // SHORT4
+    VK_FORMAT_R16G16_UINT,         // USHORT2
+    VK_FORMAT_R16G16B16A16_UINT,   // USHORT4
+    VK_FORMAT_R16G16_SNORM,        // SHORT2_NORM
+    VK_FORMAT_R16G16B16A16_SNORM,  // SHORT4_NORM
+    VK_FORMAT_R16G16_UNORM,        // USHORT2_NORM
+    VK_FORMAT_R16G16B16A16_UNORM,  // USHORT4_NORM
+    VK_FORMAT_R16G16_SFLOAT,       // HALF2
+    VK_FORMAT_R16G16B16A16_SFLOAT  // HALF4
+};
+
+static VkIndexType SDLToVK_IndexType[] = {
+    VK_INDEX_TYPE_UINT16,
+    VK_INDEX_TYPE_UINT32
+};
+
+static VkPrimitiveTopology SDLToVK_PrimitiveType[] = {
+    VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
+    VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
+    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
+};
+
+static VkCullModeFlags SDLToVK_CullMode[] = {
+    VK_CULL_MODE_NONE,
+    VK_CULL_MODE_FRONT_BIT,
+    VK_CULL_MODE_BACK_BIT,
+    VK_CULL_MODE_FRONT_AND_BACK
+};
+
+static VkFrontFace SDLToVK_FrontFace[] = {
+    VK_FRONT_FACE_COUNTER_CLOCKWISE,
+    VK_FRONT_FACE_CLOCKWISE
+};
+
+static VkBlendFactor SDLToVK_BlendFactor[] = {
+    VK_BLEND_FACTOR_ZERO,
+    VK_BLEND_FACTOR_ONE,
+    VK_BLEND_FACTOR_SRC_COLOR,
+    VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR,
+    VK_BLEND_FACTOR_DST_COLOR,
+    VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
+    VK_BLEND_FACTOR_SRC_ALPHA,
+    VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
+    VK_BLEND_FACTOR_DST_ALPHA,
+    VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA,
+    VK_BLEND_FACTOR_CONSTANT_COLOR,
+    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR,
+    VK_BLEND_FACTOR_CONSTANT_ALPHA,
+    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA,
+    VK_BLEND_FACTOR_SRC_ALPHA_SATURATE
+};
+
+static VkBlendOp SDLToVK_BlendOp[] = {
+    VK_BLEND_OP_ADD,
+    VK_BLEND_OP_SUBTRACT,
+    VK_BLEND_OP_REVERSE_SUBTRACT,
+    VK_BLEND_OP_MIN,
+    VK_BLEND_OP_MAX
+};
+
+static VkCompareOp SDLToVK_CompareOp[] = {
+    VK_COMPARE_OP_NEVER,
+    VK_COMPARE_OP_LESS,
+    VK_COMPARE_OP_EQUAL,
+    VK_COMPARE_OP_LESS_OR_EQUAL,
+    VK_COMPARE_OP_GREATER,
+    VK_COMPARE_OP_NOT_EQUAL,
+    VK_COMPARE_OP_GREATER_OR_EQUAL,
+    VK_COMPARE_OP_ALWAYS
+};
+
+static VkStencilOp SDLToVK_StencilOp[] = {
+    VK_STENCIL_OP_KEEP,
+    VK_STENCIL_OP_ZERO,
+    VK_STENCIL_OP_REPLACE,
+    VK_STENCIL_OP_INCREMENT_AND_CLAMP,
+    VK_STENCIL_OP_DECREMENT_AND_CLAMP,
+    VK_STENCIL_OP_INVERT,
+    VK_STENCIL_OP_INCREMENT_AND_WRAP,
+    VK_STENCIL_OP_DECREMENT_AND_WRAP
+};
+
+static VkAttachmentLoadOp SDLToVK_LoadOp[] = {
+    VK_ATTACHMENT_LOAD_OP_LOAD,
+    VK_ATTACHMENT_LOAD_OP_CLEAR,
+    VK_ATTACHMENT_LOAD_OP_DONT_CARE
+};
+
+static VkAttachmentStoreOp SDLToVK_StoreOp[] = {
+    VK_ATTACHMENT_STORE_OP_STORE,
+    VK_ATTACHMENT_STORE_OP_DONT_CARE
+};
+
+static VkSampleCountFlagBits SDLToVK_SampleCount[] = {
+    VK_SAMPLE_COUNT_1_BIT,
+    VK_SAMPLE_COUNT_2_BIT,
+    VK_SAMPLE_COUNT_4_BIT,
+    VK_SAMPLE_COUNT_8_BIT
+};
+
+static VkVertexInputRate SDLToVK_VertexInputRate[] = {
+    VK_VERTEX_INPUT_RATE_VERTEX,
+    VK_VERTEX_INPUT_RATE_INSTANCE
+};
+
+static VkFilter SDLToVK_Filter[] = {
+    VK_FILTER_NEAREST,
+    VK_FILTER_LINEAR
+};
+
+static VkSamplerMipmapMode SDLToVK_SamplerMipmapMode[] = {
+    VK_SAMPLER_MIPMAP_MODE_NEAREST,
+    VK_SAMPLER_MIPMAP_MODE_LINEAR
+};
+
+static VkSamplerAddressMode SDLToVK_SamplerAddressMode[] = {
+    VK_SAMPLER_ADDRESS_MODE_REPEAT,
+    VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
+    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
+};
+
+// Structures
+
+typedef struct VulkanMemoryAllocation VulkanMemoryAllocation;
+typedef struct VulkanBuffer VulkanBuffer;
+typedef struct VulkanBufferContainer VulkanBufferContainer;
+typedef struct VulkanTexture VulkanTexture;
+typedef struct VulkanTextureContainer VulkanTextureContainer;
+
+typedef struct VulkanFenceHandle
+{
+    VkFence fence;
+    SDL_AtomicInt referenceCount;
+} VulkanFenceHandle;
+
+// Memory Allocation
+
+typedef struct VulkanMemoryFreeRegion
+{
+    VulkanMemoryAllocation *allocation;
+    VkDeviceSize offset;
+    VkDeviceSize size;
+    Uint32 allocationIndex;
+    Uint32 sortedIndex;
+} VulkanMemoryFreeRegion;
+
+typedef struct VulkanMemoryUsedRegion
+{
+    VulkanMemoryAllocation *allocation;
+    VkDeviceSize offset;
+    VkDeviceSize size;
+    VkDeviceSize resourceOffset; // differs from offset based on alignment
+    VkDeviceSize resourceSize;   // differs from size based on alignment
+    VkDeviceSize alignment;
+    Uint8 isBuffer;
+    union
+    {
+        VulkanBuffer *vulkanBuffer;
+        VulkanTexture *vulkanTexture;
+    };
+} VulkanMemoryUsedRegion;
+
+typedef struct VulkanMemorySubAllocator
+{
+    Uint32 memoryTypeIndex;
+    VulkanMemoryAllocation **allocations;
+    Uint32 allocationCount;
+    VulkanMemoryFreeRegion **sortedFreeRegions;
+    Uint32 sortedFreeRegionCount;
+    Uint32 sortedFreeRegionCapacity;
+} VulkanMemorySubAllocator;
+
+struct VulkanMemoryAllocation
+{
+    VulkanMemorySubAllocator *allocator;
+    VkDeviceMemory memory;
+    VkDeviceSize size;
+    VulkanMemoryUsedRegion **usedRegions;
+    Uint32 usedRegionCount;
+    Uint32 usedRegionCapacity;
+    VulkanMemoryFreeRegion **freeRegions;
+    Uint32 freeRegionCount;
+    Uint32 freeRegionCapacity;
+    Uint8 availableForAllocation;
+    VkDeviceSize freeSpace;
+    VkDeviceSize usedSpace;
+    Uint8 *mapPointer;
+    SDL_Mutex *memoryLock;
+};
+
+typedef struct VulkanMemoryAllocator
+{
+    VulkanMemorySubAllocator subAllocators[VK_MAX_MEMORY_TYPES];
+} VulkanMemoryAllocator;
+
+// Memory structures
+
+/* We use pointer indirection so that defrag can occur without objects
+ * needing to be aware of the backing buffers changing.
+ */
+typedef struct VulkanBufferHandle
+{
+    VulkanBuffer *vulkanBuffer;
+    VulkanBufferContainer *container;
+} VulkanBufferHandle;
+
+typedef enum VulkanBufferType
+{
+    VULKAN_BUFFER_TYPE_GPU,
+    VULKAN_BUFFER_TYPE_UNIFORM,
+    VULKAN_BUFFER_TYPE_TRANSFER
+} VulkanBufferType;
+
+struct VulkanBuffer
+{
+    VkBuffer buffer;
+    VkDeviceSize size;
+    VulkanMemoryUsedRegion *usedRegion;
+
+    VulkanBufferType type;
+    SDL_GpuBufferUsageFlags usageFlags;
+
+    SDL_AtomicInt referenceCount; // Tracks command buffer usage
+
+    VulkanBufferHandle *handle;
+
+    SDL_bool transitioned;
+    Uint8 markedForDestroy; // so that defrag doesn't double-free
+};
+
+/* Buffer resources consist of multiple backing buffer handles so that data transfers
+ * can occur without blocking or the client having to manage extra resources.
+ *
+ * Cast from SDL_GpuBuffer or SDL_GpuTransferBuffer.
+ */
+struct VulkanBufferContainer
+{
+    VulkanBufferHandle *activeBufferHandle;
+
+    /* These are all the buffer handles that have been used by this container.
+     * If the resource is bound and then updated with a cycle parameter, a new resource
+     * will be added to this list.
+     * These can be reused after they are submitted and command processing is complete.
+     */
+    Uint32 bufferCapacity;
+    Uint32 bufferCount;
+    VulkanBufferHandle **bufferHandles;
+
+    char *debugName;
+};
+
+// Renderer Structure
+
+typedef struct QueueFamilyIndices
+{
+    Uint32 graphicsFamily;
+    Uint32 presentFamily;
+    Uint32 computeFamily;
+    Uint32 transferFamily;
+} QueueFamilyIndices;
+
+typedef struct VulkanSampler
+{
+    VkSampler sampler;
+    SDL_AtomicInt referenceCount;
+} VulkanSampler;
+
+typedef struct VulkanShader
+{
+    VkShaderModule shaderModule;
+    const char *entryPointName;
+    Uint32 samplerCount;
+    Uint32 storageTextureCount;
+    Uint32 storageBufferCount;
+    Uint32 uniformBufferCount;
+    SDL_AtomicInt referenceCount;
+} VulkanShader;
+
+typedef struct VulkanTextureHandle
+{
+    VulkanTexture *vulkanTexture;
+    VulkanTextureContainer *container;
+} VulkanTextureHandle;
+
+/* Textures are made up of individual subresources.
+ * This helps us barrier the resource efficiently.
+ */
+typedef struct VulkanTextureSubresource
+{
+    VulkanTexture *parent;
+    Uint32 layer;
+    Uint32 level;
+
+    VkImageView *renderTargetViews; // One render target view per depth slice
+    VkImageView computeWriteView;
+    VkImageView depthStencilView;
+
+    VulkanTextureHandle *msaaTexHandle; // NULL if parent sample count is 1 or is depth target
+
+    SDL_bool transitioned; // used for layout tracking
+} VulkanTextureSubresource;
+
+struct VulkanTexture
+{
+    VulkanMemoryUsedRegion *usedRegion;
+
+    VkImage image;
+    VkImageView fullView; // used for samplers and storage reads
+    VkExtent2D dimensions;
+
+    SDL_GpuTextureType type;
+    Uint8 isMSAAColorTarget;
+
+    Uint32 depth;
+    Uint32 layerCount;
+    Uint32 levelCount;
+    VkSampleCountFlagBits sampleCount; // NOTE: This refers to the sample count of a render target pass using this texture, not the actual sample count of the texture
+    VkFormat format;
+    VkComponentMapping swizzle;
+    SDL_GpuTextureUsageFlags usageFlags;
+    VkImageAspectFlags aspectFlags;
+
+    Uint32 subresourceCount;
+    VulkanTextureSubresource *subresources;
+
+    VulkanTextureHandle *handle;
+
+    Uint8 markedForDestroy; // so that defrag doesn't double-free
+    SDL_AtomicInt referenceCount;
+};
+
+/* Texture resources consist of multiple backing texture handles so that data transfers
+ * can occur without blocking or the client having to manage extra resources.
+ *
+ * Cast from SDL_GpuTexture.
+ */
+struct VulkanTextureContainer
+{
+    TextureCommonHeader header; // FIXME: Use this instead of passing so many args to CreateTexture
+
+    VulkanTextureHandle *activeTextureHandle;
+
+    /* These are all the texture handles that have been used by this container.
+     * If the resource is bound and then updated with CYCLE, a new resource
+     * will be added to this list.
+     * These can be reused after they are submitted and command processing is complete.
+     */
+    Uint32 textureCapacity;
+    Uint32 textureCount;
+    VulkanTextureHandle **textureHandles;
+
+    // Swapchain images cannot be cycled
+    Uint8 canBeCycled;
+
+    char *debugName;
+};
+
+typedef enum VulkanBufferUsageMode
+{
+    VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
+    VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
+    VULKAN_BUFFER_USAGE_MODE_VERTEX_READ,
+    VULKAN_BUFFER_USAGE_MODE_INDEX_READ,
+    VULKAN_BUFFER_USAGE_MODE_INDIRECT,
+    VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ,
+    VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
+    VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
+} VulkanBufferUsageMode;
+
+typedef enum VulkanTextureUsageMode
+{
+    VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
+    VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
+    VULKAN_TEXTURE_USAGE_MODE_SAMPLER,
+    VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ,
+    VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
+    VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
+    VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT,
+    VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT,
+    VULKAN_TEXTURE_USAGE_MODE_PRESENT
+} VulkanTextureUsageMode;
+
+typedef enum VulkanUniformBufferStage
+{
+    VULKAN_UNIFORM_BUFFER_STAGE_VERTEX,
+    VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT,
+    VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE
+} VulkanUniformBufferStage;
+
+typedef struct VulkanFramebuffer
+{
+    VkFramebuffer framebuffer;
+    SDL_AtomicInt referenceCount;
+} VulkanFramebuffer;
+
+typedef struct VulkanSwapchainData
+{
+    // Window surface
+    VkSurfaceKHR surface;
+
+    // Swapchain for window surface
+    VkSwapchainKHR swapchain;
+    VkFormat format;
+    VkColorSpaceKHR colorSpace;
+    VkComponentMapping swapchainSwizzle;
+    VkPresentModeKHR presentMode;
+    SDL_bool usingFallbackFormat;
+
+    // Swapchain images
+    VulkanTextureContainer *textureContainers; // use containers so that swapchain textures can use the same API as other textures
+    Uint32 imageCount;
+
+    // Synchronization primitives
+    VkSemaphore imageAvailableSemaphore[MAX_FRAMES_IN_FLIGHT];
+    VkSemaphore renderFinishedSemaphore[MAX_FRAMES_IN_FLIGHT];
+    VulkanFenceHandle *inFlightFences[MAX_FRAMES_IN_FLIGHT];
+
+    Uint32 frameCounter;
+} VulkanSwapchainData;
+
+typedef struct WindowData
+{
+    SDL_Window *window;
+    SDL_GpuSwapchainComposition swapchainComposition;
+    SDL_GpuPresentMode presentMode;
+    VulkanSwapchainData *swapchainData;
+    SDL_bool needsSwapchainRecreate;
+} WindowData;
+
+typedef struct SwapchainSupportDetails
+{
+    VkSurfaceCapabilitiesKHR capabilities;
+    VkSurfaceFormatKHR *formats;
+    Uint32 formatsLength;
+    VkPresentModeKHR *presentModes;
+    Uint32 presentModesLength;
+} SwapchainSupportDetails;
+
+typedef struct VulkanPresentData
+{
+    WindowData *windowData;
+    Uint32 swapchainImageIndex;
+} VulkanPresentData;
+
+typedef struct VulkanUniformBuffer
+{
+    VulkanBufferHandle *bufferHandle;
+    Uint32 drawOffset;
+    Uint32 writeOffset;
+} VulkanUniformBuffer;
+
+typedef struct VulkanDescriptorInfo
+{
+    VkDescriptorType descriptorType;
+    VkShaderStageFlagBits stageFlag;
+} VulkanDescriptorInfo;
+
+typedef struct DescriptorSetPool
+{
+    SDL_Mutex *lock;
+
+    VkDescriptorSetLayout descriptorSetLayout;
+
+    VulkanDescriptorInfo *descriptorInfos;
+    Uint32 descriptorInfoCount;
+
+    // This is actually a descriptor set and descriptor pool simultaneously
+    VkDescriptorPool *descriptorPools;
+    Uint32 descriptorPoolCount;
+    Uint32 nextPoolSize;
+
+    // We just manage a pool ourselves instead of freeing the sets
+    VkDescriptorSet *inactiveDescriptorSets;
+    Uint32 inactiveDescriptorSetCount;
+    Uint32 inactiveDescriptorSetCapacity;
+} DescriptorSetPool;
+
+typedef struct VulkanGraphicsPipelineResourceLayout
+{
+    VkPipelineLayout pipelineLayout;
+
+    /*
+     * Descriptor set layout is as follows:
+     * 0: vertex resources
+     * 1: vertex uniform buffers
+     * 2: fragment resources
+     * 3: fragment uniform buffers
+     */
+    DescriptorSetPool descriptorSetPools[4];
+
+    Uint32 vertexSamplerCount;
+    Uint32 vertexStorageBufferCount;
+    Uint32 vertexStorageTextureCount;
+    Uint32 vertexUniformBufferCount;
+
+    Uint32 fragmentSamplerCount;
+    Uint32 fragmentStorageBufferCount;
+    Uint32 fragmentStorageTextureCount;
+    Uint32 fragmentUniformBufferCount;
+} VulkanGraphicsPipelineResourceLayout;
+
+typedef struct VulkanGraphicsPipeline
+{
+    VkPipeline pipeline;
+    SDL_GpuPrimitiveType primitiveType;
+
+    VulkanGraphicsPipelineResourceLayout resourceLayout;
+
+    VulkanShader *vertexShader;
+    VulkanShader *fragmentShader;
+
+    SDL_AtomicInt referenceCount;
+} VulkanGraphicsPipeline;
+
+typedef struct VulkanComputePipelineResourceLayout
+{
+    VkPipelineLayout pipelineLayout;
+
+    /*
+     * Descriptor set layout is as follows:
+     * 0: read-only textures, then read-only buffers
+     * 1: write-only textures, then write-only buffers
+     * 2: uniform buffers
+     */
+    DescriptorSetPool descriptorSetPools[3];
+
+    Uint32 readOnlyStorageTextureCount;
+    Uint32 readOnlyStorageBufferCount;
+    Uint32 writeOnlyStorageTextureCount;
+    Uint32 writeOnlyStorageBufferCount;
+    Uint32 uniformBufferCount;
+} VulkanComputePipelineResourceLayout;
+
+typedef struct VulkanComputePipeline
+{
+    VkShaderModule shaderModule;
+    VkPipeline pipeline;
+    VulkanComputePipelineResourceLayout resourceLayout;
+    SDL_AtomicInt referenceCount;
+} VulkanComputePipeline;
+
+typedef struct RenderPassColorTargetDescription
+{
+    VkFormat format;
+    SDL_GpuLoadOp loadOp;
+    SDL_GpuStoreOp storeOp;
+} RenderPassColorTargetDescription;
+
+typedef struct RenderPassDepthStencilTargetDescription
+{
+    VkFormat format;
+    SDL_GpuLoadOp loadOp;
+    SDL_GpuStoreOp storeOp;
+    SDL_GpuLoadOp stencilLoadOp;
+    SDL_GpuStoreOp stencilStoreOp;
+} RenderPassDepthStencilTargetDescription;
+
+typedef struct CommandPoolHashTableKey
+{
+    SDL_ThreadID threadID;
+} CommandPoolHashTableKey;
+
+typedef struct RenderPassHashTableKey
+{
+    RenderPassColorTargetDescription colorTargetDescriptions[MAX_COLOR_TARGET_BINDINGS];
+    Uint32 colorAttachmentCount;
+    RenderPassDepthStencilTargetDescription depthStencilTargetDescription;
+    VkSampleCountFlagBits colorAttachmentSampleCount;
+} RenderPassHashTableKey;
+
+typedef struct VulkanRenderPassHashTableValue
+{
+    VkRenderPass handle;
+} VulkanRenderPassHashTableValue;
+
+typedef struct FramebufferHashTableKey
+{
+    VkImageView colorAttachmentViews[MAX_COLOR_TARGET_BINDINGS];
+    VkImageView colorMultiSampleAttachmentViews[MAX_COLOR_TARGET_BINDINGS];
+    Uint32 colorAttachmentCount;
+    VkImageView depthStencilAttachmentView;
+    Uint32 width;
+    Uint32 height;
+} FramebufferHashTableKey;
+
+// Command structures
+
+typedef struct DescriptorSetData
+{
+    DescriptorSetPool *descriptorSetPool;
+    VkDescriptorSet descriptorSet;
+} DescriptorSetData;
+
+typedef struct VulkanFencePool
+{
+    SDL_Mutex *lock;
+
+    VulkanFenceHandle **availableFences;
+    Uint32 availableFenceCount;
+    Uint32 availableFenceCapacity;
+} VulkanFencePool;
+
+typedef struct VulkanCommandPool VulkanCommandPool;
+
+typedef struct VulkanRenderer VulkanRenderer;
+
+typedef struct VulkanCommandBuffer
+{
+    CommandBufferCommonHeader common;
+    VulkanRenderer *renderer;
+
+    VkCommandBuffer commandBuffer;
+    VulkanCommandPool *commandPool;
+
+    VulkanPresentData *presentDatas;
+    Uint32 presentDataCount;
+    Uint32 presentDataCapacity;
+
+    VkSemaphore *waitSemaphores;
+    Uint32 waitSemaphoreCount;
+    Uint32 waitSemaphoreCapacity;
+
+    VkSemaphore *signalSemaphores;
+    Uint32 signalSemaphoreCount;
+    Uint32 signalSemaphoreCapacity;
+
+    VulkanComputePipeline *currentComputePipeline;
+    VulkanGraphicsPipeline *currentGraphicsPipeline;
+
+    // Keep track of resources transitioned away from their default state to barrier them on pass end
+
+    VulkanTextureSubresource *colorAttachmentSubresources[MAX_COLOR_TARGET_BINDINGS];
+    Uint32 colorAttachmentSubresourceCount;
+
+    VulkanTextureSubresource *depthStencilAttachmentSubresource; // may be NULL
+
+    // Viewport/scissor state
+
+    VkViewport currentViewport;
+    VkRect2D currentScissor;
+
+    // Resource bind state
+
+    SDL_bool needNewVertexResourceDescriptorSet;
+    SDL_bool needNewVertexUniformDescriptorSet;
+    SDL_bool needNewVertexUniformOffsets;
+    SDL_bool needNewFragmentResourceDescriptorSet;
+    SDL_bool needNewFragmentUniformDescriptorSet;
+    SDL_bool needNewFragmentUniformOffsets;
+
+    SDL_bool needNewComputeReadOnlyDescriptorSet;
+    SDL_bool needNewComputeWriteOnlyDescriptorSet;
+    SDL_bool needNewComputeUniformDescriptorSet;
+    SDL_bool needNewComputeUniformOffsets;
+
+    VkDescriptorSet vertexResourceDescriptorSet;
+    VkDescriptorSet vertexUniformDescriptorSet;
+    VkDescriptorSet fragmentResourceDescriptorSet;
+    VkDescriptorSet fragmentUniformDescriptorSet;
+
+    VkDescriptorSet computeReadOnlyDescriptorSet;
+    VkDescriptorSet computeWriteOnlyDescriptorSet;
+    VkDescriptorSet computeUniformDescriptorSet;
+
+    DescriptorSetData *boundDescriptorSetDatas;
+    Uint32 boundDescriptorSetDataCount;
+    Uint32 boundDescriptorSetDataCapacity;
+
+    VulkanTexture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    VulkanSampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    VulkanTexture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
+    VulkanBuffer *vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+
+    VulkanTexture *fragmentSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    VulkanSampler *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    VulkanTexture *fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
+    VulkanBuffer *fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+
+    VulkanTextureSubresource *writeOnlyComputeStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
+    Uint32 writeOnlyComputeStorageTextureSubresourceCount;
+    VulkanBuffer *writeOnlyComputeStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
+
+    VulkanTexture *readOnlyComputeStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
+    VulkanBuffer *readOnlyComputeStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+
+    // Uniform buffers
+
+    VulkanUniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+    VulkanUniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+    VulkanUniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
+
+    // Track used resources
+
+    VulkanBuffer **usedBuffers;
+    Uint32 usedBufferCount;
+    Uint32 usedBufferCapacity;
+
+    VulkanTexture **usedTextures;
+    Uint32 usedTextureCount;
+    Uint32 usedTextureCapacity;
+
+    VulkanSampler **usedSamplers;
+    Uint32 usedSamplerCount;
+    Uint32 usedSamplerCapacity;
+
+    VulkanGraphicsPipeline **usedGraphicsPipelines;
+    Uint32 usedGraphicsPipelineCount;
+    Uint32 usedGraphicsPipelineCapacity;
+
+    VulkanComputePipeline **usedComputePipelines;
+    Uint32 usedComputePipelineCount;
+    Uint32 usedComputePipelineCapacity;
+
+    VulkanFramebuffer **usedFramebuffers;
+    Uint32 usedFramebufferCount;
+    Uint32 usedFramebufferCapacity;
+
+    VulkanUniformBuffer **usedUniformBuffers;
+    Uint32 usedUniformBufferCount;
+    Uint32 usedUniformBufferCapacity;
+
+    VulkanFenceHandle *inFlightFence;
+    Uint8 autoReleaseFence;
+
+    Uint8 isDefrag; // Whether this CB was created for defragging
+} VulkanCommandBuffer;
+
+struct VulkanCommandPool
+{
+    SDL_ThreadID threadID;
+    VkCommandPool commandPool;
+
+    VulkanCommandBuffer **inactiveCommandBuffers;
+    Uint32 inactiveCommandBufferCapacity;
+    Uint32 inactiveCommandBufferCount;
+};
+
+// Context
+
+struct VulkanRenderer
+{
+    VkInstance instance;
+    VkPhysicalDevice physicalDevice;
+    VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
+    VkPhysicalDeviceDriverPropertiesKHR physicalDeviceDriverProperties;
+    VkDevice logicalDevice;
+    Uint8 integratedMemoryNotification;
+    Uint8 outOfDeviceLocalMemoryWarning;
+    Uint8 outofBARMemoryWarning;
+    Uint8 fillModeOnlyWarning;
+
+    SDL_bool debugMode;
+    SDL_bool preferLowPower;
+    VulkanExtensions supports;
+    SDL_bool supportsDebugUtils;
+    SDL_bool supportsColorspace;
+    SDL_bool supportsFillModeNonSolid;
+    SDL_bool supportsMultiDrawIndirect;
+
+    VulkanMemoryAllocator *memoryAllocator;
+    VkPhysicalDeviceMemoryProperties memoryProperties;
+
+    WindowData **claimedWindows;
+    Uint32 claimedWindowCount;
+    Uint32 claimedWindowCapacity;
+
+    Uint32 queueFamilyIndex;
+    VkQueue unifiedQueue;
+
+    VulkanCommandBuffer **submittedCommandBuffers;
+    Uint32 submittedCommandBufferCount;
+    Uint32 submittedCommandBufferCapacity;
+
+    VulkanFencePool fencePool;
+
+    SDL_HashTable *commandPoolHashTable;
+    SDL_HashTable *renderPassHashTable;
+    SDL_HashTable *framebufferHashTable;
+
+    VulkanUniformBuffer **uniformBufferPool;
+    Uint32 uniformBufferPoolCount;
+    Uint32 uniformBufferPoolCapacity;
+
+    Uint32 minUBOAlignment;
+
+    // Some drivers don't support D16 for some reason. Fun!
+    VkFormat D16Format;
+    VkFormat D16S8Format;
+
+    // Deferred resource destruction
+
+    VulkanTexture **texturesToDestroy;
+    Uint32 texturesToDestroyCount;
+    Uint32 texturesToDestroyCapacity;
+
+    VulkanBuffer **buffersToDestroy;
+    Uint32 buffersToDestroyCount;
+    Uint32 buffersToDestroyCapacity;
+
+    VulkanSampler **samplersToDestroy;
+    Uint32 samplersToDestroyCount;
+    Uint32 samplersToDestroyCapacity;
+
+    VulkanGraphicsPipeline **graphicsPipelinesToDestroy;
+    Uint32 graphicsPipelinesToDestroyCount;
+    Uint32 graphicsPipelinesToDestroyCapacity;
+
+    VulkanComputePipeline **computePipelinesToDestroy;
+    Uint32 computePipelinesToDestroyCount;
+    Uint32 computePipelinesToDestroyCapacity;
+
+    VulkanShader **shadersToDestroy;
+    Uint32 shadersToDestroyCount;
+    Uint32 shadersToDestroyCapacity;
+
+    VulkanFramebuffer **framebuffersToDestroy;
+    Uint32 framebuffersToDestroyCount;
+    Uint32 framebuffersToDestroyCapacity;
+
+    SDL_Mutex *allocatorLock;
+    SDL_Mutex *disposeLock;
+    SDL_Mutex *submitLock;
+    SDL_Mutex *acquireCommandBufferLock;
+    SDL_Mutex *acquireUniformBufferLock;
+    SDL_Mutex *renderPassFetchLock;
+    SDL_Mutex *framebufferFetchLock;
+
+    Uint8 defragInProgress;
+
+    VulkanMemoryAllocation **allocationsToDefrag;
+    Uint32 allocationsToDefragCount;
+    Uint32 allocationsToDefragCapacity;
+
+#define VULKAN_INSTANCE_FUNCTION(func) \
+    PFN_##func func;
+#define VULKAN_DEVICE_FUNCTION(func) \
+    PFN_##func func;
+#include "SDL_gpu_vulkan_vkfuncs.h"
+};
+
+// Forward declarations
+
+static Uint8 VULKAN_INTERNAL_DefragmentMemory(VulkanRenderer *renderer);
+static void VULKAN_INTERNAL_BeginCommandBuffer(VulkanRenderer *renderer, VulkanCommandBuffer *commandBuffer);
+static void VULKAN_UnclaimWindow(SDL_GpuRenderer *driverData, SDL_Window *window);
+static void VULKAN_Wait(SDL_GpuRenderer *driverData);
+static void VULKAN_WaitForFences(SDL_GpuRenderer *driverData, SDL_bool waitAll, SDL_GpuFence **pFences, Uint32 fenceCount);
+static void VULKAN_Submit(SDL_GpuCommandBuffer *commandBuffer);
+static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
+    VulkanRenderer *renderer,
+    Uint32 width,
+    Uint32 height,
+    Uint32 depth,
+    SDL_GpuTextureType type,
+    Uint32 layerCount,
+    Uint32 levelCount,
+    VkSampleCountFlagBits sampleCount,
+    VkFormat format,
+    VkComponentMapping swizzle,
+    VkImageAspectFlags aspectMask,
+    SDL_GpuTextureUsageFlags textureUsageFlags,
+    SDL_bool isMSAAColorTarget);
+
+// Error Handling
+
+static inline const char *VkErrorMessages(VkResult code)
+{
+#define ERR_TO_STR(e) \
+    case e:           \
+        return #e;
+    switch (code) {
+        ERR_TO_STR(VK_ERROR_OUT_OF_HOST_MEMORY)
+        ERR_TO_STR(VK_ERROR_OUT_OF_DEVICE_MEMORY)
+        ERR_TO_STR(VK_ERROR_FRAGMENTED_POOL)
+        ERR_TO_STR(VK_ERROR_OUT_OF_POOL_MEMORY)
+        ERR_TO_STR(VK_ERROR_INITIALIZATION_FAILED)
+        ERR_TO_STR(VK_ERROR_LAYER_NOT_PRESENT)
+        ERR_TO_STR(VK_ERROR_EXTENSION_NOT_PRESENT)
+        ERR_TO_STR(VK_ERROR_FEATURE_NOT_PRESENT)
+        ERR_TO_STR(VK_ERROR_TOO_MANY_OBJECTS)
+        ERR_TO_STR(VK_ERROR_DEVICE_LOST)
+        ERR_TO_STR(VK_ERROR_INCOMPATIBLE_DRIVER)
+        ERR_TO_STR(VK_ERROR_OUT_OF_DATE_KHR)
+        ERR_TO_STR(VK_ERROR_SURFACE_LOST_KHR)
+        ERR_TO_STR(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT)
+        ERR_TO_STR(VK_SUBOPTIMAL_KHR)
+    default:
+        return "Unhandled VkResult!";
+    }
+#undef ERR_TO_STR
+}
+
+static inline void LogVulkanResultAsError(
+    const char *vulkanFunctionName,
+    VkResult result)
+{
+    if (result != VK_SUCCESS) {
+        SDL_LogError(
+            SDL_LOG_CATEGORY_GPU,
+            "%s: %s",
+            vulkanFunctionName,
+            VkErrorMessages(result));
+    }
+}
+
+#define VULKAN_ERROR_CHECK(res, fn, ret)                                        \
+    if (res != VK_SUCCESS) {                                                    \
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s %s", #fn, VkErrorMessages(res)); \
+        return ret;                                                             \
+    }
+
+// Utility
+
+static inline SDL_bool VULKAN_INTERNAL_IsVulkanDepthFormat(VkFormat format)
+{
+    // FIXME: Can we refactor and use the regular IsDepthFormat for this?
+    return (
+        format == SDLToVK_SurfaceFormat[SDL_GPU_TEXTUREFORMAT_D16_UNORM] ||
+        format == SDLToVK_SurfaceFormat[SDL_GPU_TEXTUREFORMAT_D24_UNORM] ||
+        format == SDLToVK_SurfaceFormat[SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT] ||
+        format == SDLToVK_SurfaceFormat[SDL_GPU_TEXTUREFORMAT_D32_FLOAT] ||
+        format == SDLToVK_SurfaceFormat[SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT]);
+}
+
+static inline VkSampleCountFlagBits VULKAN_INTERNAL_GetMaxMultiSampleCount(
+    VulkanRenderer *renderer,
+    VkSampleCountFlagBits multiSampleCount)
+{
+    VkSampleCountFlags flags = renderer->physicalDeviceProperties.properties.limits.framebufferColorSampleCounts;
+    VkSampleCountFlagBits maxSupported = VK_SAMPLE_COUNT_1_BIT;
+
+    if (flags & VK_SAMPLE_COUNT_8_BIT) {
+        maxSupported = VK_SAMPLE_COUNT_8_BIT;
+    } else if (flags & VK_SAMPLE_COUNT_4_BIT) {
+        maxSupported = VK_SAMPLE_COUNT_4_BIT;
+    } else if (flags & VK_SAMPLE_COUNT_2_BIT) {
+        maxSupported = VK_SAMPLE_COUNT_2_BIT;
+    }
+
+    return SDL_min(multiSampleCount, maxSupported);
+}
+
+static inline VkPolygonMode SDLToVK_PolygonMode(
+    VulkanRenderer *renderer,
+    SDL_GpuFillMode mode)
+{
+    if (mode == SDL_GPU_FILLMODE_FILL) {
+        return VK_POLYGON_MODE_FILL; // always available!
+    }
+
+    if (renderer->supportsFillModeNonSolid && mode == SDL_GPU_FILLMODE_LINE) {
+        return VK_POLYGON_MODE_LINE;
+    }
+
+    if (!renderer->fillModeOnlyWarning) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Unsupported fill mode requested, using FILL!");
+        renderer->fillModeOnlyWarning = 1;
+    }
+    return VK_POLYGON_MODE_FILL;
+}
+
+// Memory Management
+
+// Vulkan: Memory Allocation
+
+static inline VkDeviceSize VULKAN_INTERNAL_NextHighestAlignment(
+    VkDeviceSize n,
+    VkDeviceSize align)
+{
+    return align * ((n + align - 1) / align);
+}
+
+static inline Uint32 VULKAN_INTERNAL_NextHighestAlignment32(
+    Uint32 n,
+    Uint32 align)
+{
+    return align * ((n + align - 1) / align);
+}
+
+static void VULKAN_INTERNAL_MakeMemoryUnavailable(
+    VulkanRenderer *renderer,
+    VulkanMemoryAllocation *allocation)
+{
+    Uint32 i, j;
+    VulkanMemoryFreeRegion *freeRegion;
+
+    allocation->availableForAllocation = 0;
+
+    for (i = 0; i < allocation->freeRegionCount; i += 1) {
+        freeRegion = allocation->freeRegions[i];
+
+        // close the gap in the sorted list
+        if (allocation->allocator->sortedFreeRegionCount > 1) {
+            for (j = freeRegion->sortedIndex; j < allocation->allocator->sortedFreeRegionCount - 1; j += 1) {
+                allocation->allocator->sortedFreeRegions[j] =
+                    allocation->allocator->sortedFreeRegions[j + 1];
+
+                allocation->allocator->sortedFreeRegions[j]->sortedIndex = j;
+            }
+        }
+
+        allocation->allocator->sortedFreeRegionCount -= 1;
+    }
+}
+
+static void VULKAN_INTERNAL_MarkAllocationsForDefrag(
+    VulkanRenderer *renderer)
+{
+    Uint32 memoryType, allocationIndex;
+    VulkanMemorySubAllocator *currentAllocator;
+
+    for (memoryType = 0; memoryType < VK_MAX_MEMORY_TYPES; memoryType += 1) {
+        currentAllocator = &renderer->memoryAllocator->subAllocators[memoryType];
+
+        for (allocationIndex = 0; allocationIndex < currentAllocator->allocationCount; allocationIndex += 1) {
+            if (currentAllocator->allocations[allocationIndex]->availableForAllocation == 1) {
+                if (currentAllocator->allocations[allocationIndex]->freeRegionCount > 1) {
+                    EXPAND_ARRAY_IF_NEEDED(
+                        renderer->allocationsToDefrag,
+                        VulkanMemoryAllocation *,
+                        renderer->allocationsToDefragCount + 1,
+                        renderer->allocationsToDefragCapacity,
+                        renderer->allocationsToDefragCapacity * 2);
+
+                    renderer->allocationsToDefrag[renderer->allocationsToDefragCount] =
+                        currentAllocator->allocations[allocationIndex];
+
+                    renderer->allocationsToDefragCount += 1;
+
+                    VULKAN_INTERNAL_MakeMemoryUnavailable(
+                        renderer,
+                        currentAllocator->allocations[allocationIndex]);
+                }
+            }
+        }
+    }
+}
+
+static void VULKAN_INTERNAL_RemoveMemoryFreeRegion(
+    VulkanRenderer *renderer,
+    VulkanMemoryFreeRegion *freeRegion)
+{
+    Uint32 i;
+
+    SDL_LockMutex(renderer->allocatorLock);
+
+    if (freeRegion->allocation->availableForAllocation) {
+        // close the gap in the sorted list
+        if (freeRegion->allocation->allocator->sortedFreeRegionCount > 1) {
+            for (i = freeRegion->sortedIndex; i < freeRegion->allocation->allocator->sortedFreeRegionCount - 1; i += 1) {
+                freeRegion->allocation->allocator->sortedFreeRegions[i] =
+                    freeRegion->allocation->allocator->sortedFreeRegions[i + 1];
+
+                freeRegion->allocation->allocator->sortedFreeRegions[i]->sortedIndex = i;
+            }
+        }
+
+        freeRegion->allocation->allocator->sortedFreeRegionCount -= 1;
+    }
+
+    // close the gap in the buffer list
+    if (freeRegion->allocation->freeRegionCount > 1 && freeRegion->allocationIndex != freeRegion->allocation->freeRegionCount - 1) {
+        freeRegion->allocation->freeRegions[freeRegion->allocationIndex] =
+            freeRegion->allocation->freeRegions[freeRegion->allocation->freeRegionCount - 1];
+
+        freeRegion->allocation->freeRegions[freeRegion->allocationIndex]->allocationIndex =
+            freeRegion->allocationIndex;
+    }
+
+    freeRegion->allocation->freeRegionCount -= 1;
+
+    freeRegion->allocation->freeSpace -= freeRegion->size;
+
+    SDL_free(freeRegion);
+
+    SDL_UnlockMutex(renderer->allocatorLock);
+}
+
+static void VULKAN_INTERNAL_NewMemoryFreeRegion(
+    VulkanRenderer *renderer,
+    VulkanMemoryAllocation *allocation,
+    VkDeviceSize offset,
+    VkDeviceSize size)
+{
+    VulkanMemoryFreeRegion *newFreeRegion;
+    VkDeviceSize newOffset, newSize;
+    Sint32 insertionIndex = 0;
+
+    SDL_LockMutex(renderer->allocatorLock);
+
+    // look for an adjacent region to merge
+    for (Sint32 i = allocation->freeRegionCount - 1; i >= 0; i -= 1) {
+        // check left side
+        if (allocation->freeRegions[i]->offset + allocation->freeRegions[i]->size == offset) {
+            newOffset = allocation->freeRegions[i]->offset;
+            newSize = allocation->freeRegions[i]->size + size;
+
+            VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, allocation->freeRegions[i]);
+            VULKAN_INTERNAL_NewMemoryFreeRegion(renderer, allocation, newOffset, newSize);
+
+            SDL_UnlockMutex(renderer->allocatorLock);
+            return;
+        }
+
+        // check right side
+        if (allocation->freeRegions[i]->offset == offset + size) {
+            newOffset = offset;
+            newSize = allocation->freeRegions[i]->size + size;
+
+            VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, allocation->freeRegions[i]);
+            VULKAN_INTERNAL_NewMemoryFreeRegion(renderer, allocation, newOffset, newSize);
+
+            SDL_UnlockMutex(renderer->allocatorLock);
+            return;
+        }
+    }
+
+    // region is not contiguous with another free region, make a new one
+    allocation->freeRegionCount += 1;
+    if (allocation->freeRegionCount > allocation->freeRegionCapacity) {
+        allocation->freeRegionCapacity *= 2;
+        allocation->freeRegions = SDL_realloc(
+            allocation->freeRegions,
+            sizeof(VulkanMemoryFreeRegion *) * allocation->freeRegionCapacity);
+    }
+
+    newFreeRegion = SDL_malloc(sizeof(VulkanMemoryFreeRegion));
+    newFreeRegion->offset = offset;
+    newFreeRegion->size = size;
+    newFreeRegion->allocation = allocation;
+
+    allocation->freeSpace += size;
+
+    allocation->freeRegions[allocation->freeRegionCount - 1] = newFreeRegion;
+    newFreeRegion->allocationIndex = allocation->freeRegionCount - 1;
+
+    if (allocation->availableForAllocation) {
+        for (Uint32 i = 0; i < allocation->allocator->sortedFreeRegionCount; i += 1) {
+            if (allocation->allocator->sortedFreeRegions[i]->size < size) {
+                // this is where the new region should go
+                break;
+            }
+
+            insertionIndex += 1;
+        }
+
+        if (allocation->allocator->sortedFreeRegionCount + 1 > allocation->allocator->sortedFreeRegionCapacity) {
+            allocation->allocator->sortedFreeRegionCapacity *= 2;
+            allocation->allocator->sortedFreeRegions = SDL_realloc(
+                allocation->allocator->sortedFreeRegions,
+                sizeof(VulkanMemoryFreeRegion *) * allocation->allocator->sortedFreeRegionCapacity);
+        }
+
+        // perform insertion sort
+        if (allocation->allocator->sortedFreeRegionCount > 0 && insertionIndex != allocation->allocator->sortedFreeRegionCount) {
+            for (Sint32 i = allocation->allocator->sortedFreeRegionCount; i > insertionIndex && i > 0; i -= 1) {
+                allocation->allocator->sortedFreeRegions[i] = allocation->allocator->sortedFreeRegions[i - 1];
+                allocation->allocator->sortedFreeRegions[i]->sortedIndex = i;
+            }
+        }
+
+        allocation->allocator->sortedFreeRegionCount += 1;
+        allocation->allocator->sortedFreeRegions[insertionIndex] = newFreeRegion;
+        newFreeRegion->sortedIndex = insertionIndex;
+    }
+
+    SDL_UnlockMutex(renderer->allocatorLock);
+}
+
+static VulkanMemoryUsedRegion *VULKAN_INTERNAL_NewMemoryUsedRegion(
+    VulkanRenderer *renderer,
+    VulkanMemoryAllocation *allocation,
+    VkDeviceSize offset,
+    VkDeviceSize size,
+    VkDeviceSize resourceOffset,
+    VkDeviceSize resourceSize,
+    VkDeviceSize alignment)
+{
+    VulkanMemoryUsedRegion *memoryUsedRegion;
+
+    SDL_LockMutex(renderer->allocatorLock);
+
+    if (allocation->usedRegionCount == allocation->usedRegionCapacity) {
+        allocation->usedRegionCapacity *= 2;
+        allocation->usedRegions = SDL_realloc(
+            allocation->usedRegions,
+            allocation->usedRegionCapacity * sizeof(VulkanMemoryUsedRegion *));
+    }
+
+    memoryUsedRegion = SDL_malloc(sizeof(VulkanMemoryUsedRegion));
+    memoryUsedRegion->allocation = allocation;
+    memoryUsedRegion->offset = offset;
+    memoryUsedRegion->size = size;
+    memoryUsedRegion->resourceOffset = resourceOffset;
+    memoryUsedRegion->resourceSize = resourceSize;
+    memoryUsedRegion->alignment = alignment;
+
+    allocation->usedSpace += size;
+
+    allocation->usedRegions[allocation->usedRegionCount] = memoryUsedRegion;
+    allocation->usedRegionCount += 1;
+
+    SDL_UnlockMutex(renderer->allocatorLock);
+
+    return memoryUsedRegion;
+}
+
+static void VULKAN_INTERNAL_RemoveMemoryUsedRegion(
+    VulkanRenderer *renderer,
+    VulkanMemoryUsedRegion *usedRegion)
+{
+    Uint32 i;
+
+    SDL_LockMutex(renderer->allocatorLock);
+
+    for (i = 0; i < usedRegion->allocation->usedRegionCount; i += 1) {
+        if (usedRegion->allocation->usedRegions[i] == usedRegion) {
+            // plug the hole
+            if (i != usedRegion->allocation->usedRegionCount - 1) {
+                usedRegion->allocation->usedRegions[i] = usedRegion->allocation->usedRegions[usedRegion->allocation->usedRegionCount - 1];
+            }
+
+            break;
+        }
+    }
+
+    usedRegion->allocation->usedSpace -= usedRegion->size;
+
+    usedRegion->allocation->usedRegionCount -= 1;
+
+    VULKAN_INTERNAL_NewMemoryFreeRegion(
+        renderer,
+        usedRegion->allocation,
+        usedRegion->offset,
+        usedRegion->size);
+
+    SDL_free(usedRegion);
+
+    SDL_UnlockMutex(renderer->allocatorLock);
+}
+
+static SDL_bool VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
+    Uint32 memoryTypeIndex,
+    Uint32 *memoryTypeIndexArray,
+    Uint32 count)
+{
+    Uint32 i = 0;
+
+    for (i = 0; i < count; i += 1) {
+        if (memoryTypeIndexArray[i] == memoryTypeIndex) {
+            return SDL_FALSE;
+        }
+    }
+
+    return SDL_TRUE;
+}
+
+/* Returns an array of memory type indices in order of preference.
+ * Memory types are requested with the following three guidelines:
+ *
+ * Required: Absolutely necessary
+ * Preferred: Nice to have, but not necessary
+ * Tolerable: Can be allowed if there are no other options
+ *
+ * We return memory types in this order:
+ * 1. Required and preferred. This is the best category.
+ * 2. Required only.
+ * 3. Required, preferred, and tolerable.
+ * 4. Required and tolerable. This is the worst category.
+ */
+static Uint32 *VULKAN_INTERNAL_FindBestMemoryTypes(
+    VulkanRenderer *renderer,
+    Uint32 typeFilter,
+    VkMemoryPropertyFlags requiredProperties,
+    VkMemoryPropertyFlags preferredProperties,
+    VkMemoryPropertyFlags tolerableProperties,
+    Uint32 *pCount)
+{
+    Uint32 i;
+    Uint32 index = 0;
+    Uint32 *result = SDL_malloc(sizeof(Uint32) * renderer->memoryProperties.memoryTypeCount);
+
+    // required + preferred + !tolerable
+    for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
+        if ((typeFilter & (1 << i)) &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == preferredProperties &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == 0) {
+            if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
+                    i,
+                    result,
+                    index)) {
+                result[index] = i;
+                index += 1;
+            }
+        }
+    }
+
+    // required + !preferred + !tolerable
+    for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
+        if ((typeFilter & (1 << i)) &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == 0 &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == 0) {
+            if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
+                    i,
+                    result,
+                    index)) {
+                result[index] = i;
+                index += 1;
+            }
+        }
+    }
+
+    // required + preferred + tolerable
+    for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
+        if ((typeFilter & (1 << i)) &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == preferredProperties &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == tolerableProperties) {
+            if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
+                    i,
+                    result,
+                    index)) {
+                result[index] = i;
+                index += 1;
+            }
+        }
+    }
+
+    // required + !preferred + tolerable
+    for (i = 0; i < renderer->memoryProperties.memoryTypeCount; i += 1) {
+        if ((typeFilter & (1 << i)) &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & preferredProperties) == 0 &&
+            (renderer->memoryProperties.memoryTypes[i].propertyFlags & tolerableProperties) == tolerableProperties) {
+            if (VULKAN_INTERNAL_CheckMemoryTypeArrayUnique(
+                    i,
+                    result,
+                    index)) {
+                result[index] = i;
+                index += 1;
+            }
+        }
+    }
+
+    *pCount = index;
+    return result;
+}
+
+static Uint32 *VULKAN_INTERNAL_FindBestBufferMemoryTypes(
+    VulkanRenderer *renderer,
+    VkBuffer buffer,
+    VkMemoryPropertyFlags requiredMemoryProperties,
+    VkMemoryPropertyFlags preferredMemoryProperties,
+    VkMemoryPropertyFlags tolerableMemoryProperties,
+    VkMemoryRequirements *pMemoryRequirements,
+    Uint32 *pCount)
+{
+    renderer->vkGetBufferMemoryRequirements(
+        renderer->logicalDevice,
+        buffer,
+        pMemoryRequirements);
+
+    return VULKAN_INTERNAL_FindBestMemoryTypes(
+        renderer,
+        pMemoryRequirements->memoryTypeBits,
+        requiredMemoryProperties,
+        preferredMemoryProperties,
+        tolerableMemoryProperties,
+        pCount);
+}
+
+static Uint32 *VULKAN_INTERNAL_FindBestImageMemoryTypes(
+    VulkanRenderer *renderer,
+    VkImage image,
+    VkMemoryPropertyFlags preferredMemoryPropertyFlags,
+    VkMemoryRequirements *pMemoryRequirements,
+    Uint32 *pCount)
+{
+    renderer->vkGetImageMemoryRequirements(
+        renderer->logicalDevice,
+        image,
+        pMemoryRequirements);
+
+    return VULKAN_INTERNAL_FindBestMemoryTypes(
+        renderer,
+        pMemoryRequirements->memoryTypeBits,
+        0,
+        preferredMemoryPropertyFlags,
+        0,
+        pCount);
+}
+
+static void VULKAN_INTERNAL_DeallocateMemory(
+    VulkanRenderer *renderer,
+    VulkanMemorySubAllocator *allocator,
+    Uint32 allocationIndex)
+{
+    Uint32 i;
+
+    VulkanMemoryAllocation *allocation = allocator->allocations[allocationIndex];
+
+    SDL_LockMutex(renderer->allocatorLock);
+
+    // If this allocation was marked for defrag, cancel that
+    for (i = 0; i < renderer->allocationsToDefragCount; i += 1) {
+        if (allocation == renderer->allocationsToDefrag[i]) {
+            renderer->allocationsToDefrag[i] = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
+            renderer->allocationsToDefragCount -= 1;
+
+            break;
+        }
+    }
+
+    for (i = 0; i < allocation->freeRegionCount; i += 1) {
+        VULKAN_INTERNAL_RemoveMemoryFreeRegion(
+            renderer,
+            allocation->freeRegions[i]);
+    }
+    SDL_free(allocation->freeRegions);
+
+    /* no need to iterate used regions because deallocate
+     * only happens when there are 0 used regions
+     */
+    SDL_free(allocation->usedRegions);
+
+    renderer->vkFreeMemory(
+        renderer->logicalDevice,
+        allocation->memory,
+        NULL);
+
+    SDL_DestroyMutex(allocation->memoryLock);
+    SDL_free(allocation);
+
+    if (allocationIndex != allocator->allocationCount - 1) {
+        allocator->allocations[allocationIndex] = allocator->allocations[allocator->allocationCount - 1];
+    }
+
+    allocator->allocationCount -= 1;
+
+    SDL_UnlockMutex(renderer->allocatorLock);
+}
+
+static Uint8 VULKAN_INTERNAL_AllocateMemory(
+    VulkanRenderer *renderer,
+    VkBuffer buffer,
+    VkImage image,
+    Uint32 memoryTypeIndex,
+    VkDeviceSize allocationSize,
+    Uint8 isHostVisible,
+    VulkanMemoryAllocation **pMemoryAllocation)
+{
+    VulkanMemoryAllocation *allocation;
+    VulkanMemorySubAllocator *allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex];
+    VkMemoryAllocateInfo allocInfo;
+    VkResult result;
+
+    allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+    allocInfo.pNext = NULL;
+    allocInfo.memoryTypeIndex = memoryTypeIndex;
+    allocInfo.allocationSize = allocationSize;
+
+    allocation = SDL_malloc(sizeof(VulkanMemoryAllocation));
+    allocation->size = allocationSize;
+    allocation->freeSpace = 0; // added by FreeRegions
+    allocation->usedSpace = 0; // added by UsedRegions
+    allocation->memoryLock = SDL_CreateMutex();
+
+    allocator->allocationCount += 1;
+    allocator->allocations = SDL_realloc(
+        allocator->allocations,
+        sizeof(VulkanMemoryAllocation *) * allocator->allocationCount);
+
+    allocator->allocations[allocator->allocationCount - 1] = allocation;
+
+    allocInfo.pNext = NULL;
+    allocation->availableForAllocation = 1;
+
+    allocation->usedRegions = SDL_malloc(sizeof(VulkanMemoryUsedRegion *));
+    allocation->usedRegionCount = 0;
+    allocation->usedRegionCapacity = 1;
+
+    allocation->freeRegions = SDL_malloc(sizeof(VulkanMemoryFreeRegion *));
+    allocation->freeRegionCount = 0;
+    allocation->freeRegionCapacity = 1;
+
+    allocation->allocator = allocator;
+
+    result = renderer->vkAllocateMemory(
+        renderer->logicalDevice,
+        &allocInfo,
+        NULL,
+        &allocation->memory);
+
+    if (result != VK_SUCCESS) {
+        // Uh oh, we couldn't allocate, time to clean up
+        SDL_free(allocation->freeRegions);
+
+        allocator->allocationCount -= 1;
+        allocator->allocations = SDL_realloc(
+            allocator->allocations,
+            sizeof(VulkanMemoryAllocation *) * allocator->allocationCount);
+
+        SDL_free(allocation);
+
+        return 0;
+    }
+
+    // Persistent mapping for host-visible memory
+    if (isHostVisible) {
+        result = renderer->vkMapMemory(
+            renderer->logicalDevice,
+            allocation->memory,
+            0,
+            VK_WHOLE_SIZE,
+            0,
+            (void **)&allocation->mapPointer);
+        VULKAN_ERROR_CHECK(result, vkMapMemory, 0)
+    } else {
+        allocation->mapPointer = NULL;
+    }
+
+    VULKAN_INTERNAL_NewMemoryFreeRegion(
+        renderer,
+        allocation,
+        0,
+        allocation->size);
+
+    *pMemoryAllocation = allocation;
+    return 1;
+}
+
+static Uint8 VULKAN_INTERNAL_BindBufferMemory(
+    VulkanRenderer *renderer,
+    VulkanMemoryUsedRegion *usedRegion,
+    VkDeviceSize alignedOffset,
+    VkBuffer buffer)
+{
+    VkResult vulkanResult;
+
+    SDL_LockMutex(usedRegion->allocation->memoryLock);
+
+    vulkanResult = renderer->vkBindBufferMemory(
+        renderer->logicalDevice,
+        buffer,
+        usedRegion->allocation->memory,
+        alignedOffset);
+
+    SDL_UnlockMutex(usedRegion->allocation->memoryLock);
+
+    VULKAN_ERROR_CHECK(vulkanResult, vkBindBufferMemory, 0)
+
+    return 1;
+}
+
+static Uint8 VULKAN_INTERNAL_BindImageMemory(
+    VulkanRenderer *renderer,
+    VulkanMemoryUsedRegion *usedRegion,
+    VkDeviceSize alignedOffset,
+    VkImage image)
+{
+    VkResult vulkanResult;
+
+    SDL_LockMutex(usedRegion->allocation->memoryLock);
+
+    vulkanResult = renderer->vkBindImageMemory(
+        renderer->logicalDevice,
+        image,
+        usedRegion->allocation->memory,
+        alignedOffset);
+
+    SDL_UnlockMutex(usedRegion->allocation->memoryLock);
+
+    VULKAN_ERROR_CHECK(vulkanResult, vkBindBufferMemory, 0)
+
+    return 1;
+}
+
+static Uint8 VULKAN_INTERNAL_BindResourceMemory(
+    VulkanRenderer *renderer,
+    Uint32 memoryTypeIndex,
+    VkMemoryRequirements *memoryRequirements,
+    VkDeviceSize resourceSize, // may be different from requirements size!
+    VkBuffer buffer,           // may be VK_NULL_HANDLE
+    VkImage image,             // may be VK_NULL_HANDLE
+    VulkanMemoryUsedRegion **pMemoryUsedRegion)
+{
+    VulkanMemoryAllocation *allocation;
+    VulkanMemorySubAllocator *allocator;
+    VulkanMemoryFreeRegion *region;
+    VulkanMemoryFreeRegion *selectedRegion;
+    VulkanMemoryUsedRegion *usedRegion;
+
+    VkDeviceSize requiredSize, allocationSize;
+    VkDeviceSize alignedOffset;
+    VkDeviceSize newRegionSize, newRegionOffset;
+    Uint8 isHostVisible, smallAllocation, allocationResult;
+    Sint32 i;
+
+    isHostVisible =
+        (renderer->memoryProperties.memoryTypes[memoryTypeIndex].propertyFlags &
+         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
+
+    allocator = &renderer->memoryAllocator->subAllocators[memoryTypeIndex];
+    requiredSize = memoryRequirements->size;
+    smallAllocation = requiredSize <= SMALL_ALLOCATION_THRESHOLD;
+
+    if ((buffer == VK_NULL_HANDLE && image == VK_NULL_HANDLE) ||
+        (buffer != VK_NULL_HANDLE && image != VK_NULL_HANDLE)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "BindResourceMemory must be given either a VulkanBuffer or a VulkanTexture");
+        return 0;
+    }
+
+    SDL_LockMutex(renderer->allocatorLock);
+
+    selectedRegion = NULL;
+
+    for (i = allocator->sortedFreeRegionCount - 1; i >= 0; i -= 1) {
+        region = allocator->sortedFreeRegions[i];
+
+        if (smallAllocation && region->allocation->size != SMALL_ALLOCATION_SIZE) {
+            // region is not in a small allocation
+            continue;
+        }
+
+        if (!smallAllocation && region->allocation->size == SMALL_ALLOCATION_SIZE) {
+            // allocation is not small and current region is in a small allocation
+            continue;
+        }
+
+        alignedOffset = VULKAN_INTERNAL_NextHighestAlignment(
+            region->offset,
+            memoryRequirements->alignment);
+
+        if (alignedOffset + requiredSize <= region->offset + region->size) {
+            selectedRegion = region;
+            break;
+        }
+    }
+
+    if (selectedRegion != NULL) {
+        region = selectedRegion;
+        allocation = region->allocation;
+
+        usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion(
+            renderer,
+            allocation,
+            region->offset,
+            requiredSize + (alignedOffset - region->offset),
+            alignedOffset,
+            resourceSize,
+            memoryRequirements->alignment);
+
+        usedRegion->isBuffer = buffer != VK_NULL_HANDLE;
+
+        newRegionSize = region->size - ((alignedOffset - region->offset) + requiredSize);
+        newRegionOffset = alignedOffset + requiredSize;
+
+        // remove and add modified region to re-sort
+        VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region);
+
+        // if size is 0, no need to re-insert
+        if (newRegionSize != 0) {
+            VULKAN_INTERNAL_NewMemoryFreeRegion(
+                renderer,
+                allocation,
+                newRegionOffset,
+                newRegionSize);
+        }
+
+        SDL_UnlockMutex(renderer->allocatorLock);
+
+        if (buffer != VK_NULL_HANDLE) {
+            if (!VULKAN_INTERNAL_BindBufferMemory(
+                    renderer,
+                    usedRegion,
+                    alignedOffset,
+                    buffer)) {
+                VULKAN_INTERNAL_RemoveMemoryUsedRegion(
+                    renderer,
+                    usedRegion);
+
+                return 0;
+            }
+        } else if (image != VK_NULL_HANDLE) {
+            if (!VULKAN_INTERNAL_BindImageMemory(
+                    renderer,
+                    usedRegion,
+                    alignedOffset,
+                    image)) {
+                VULKAN_INTERNAL_RemoveMemoryUsedRegion(
+                    renderer,
+                    usedRegion);
+
+                return 0;
+            }
+        }
+
+        *pMemoryUsedRegion = usedRegion;
+        return 1;
+    }
+
+    // No suitable free regions exist, allocate a new memory region
+    if (
+        renderer->allocationsToDefragCount == 0 &&
+        !renderer->defragInProgress) {
+        // Mark currently fragmented allocations for defrag
+        VULKAN_INTERNAL_MarkAllocationsForDefrag(renderer);
+    }
+
+    if (requiredSize > SMALL_ALLOCATION_THRESHOLD) {
+        // allocate a page of required size aligned to LARGE_ALLOCATION_INCREMENT increments
+        allocationSize =
+            VULKAN_INTERNAL_NextHighestAlignment(requiredSize, LARGE_ALLOCATION_INCREMENT);
+    } else {
+        allocationSize = SMALL_ALLOCATION_SIZE;
+    }
+
+    allocationResult = VULKAN_INTERNAL_AllocateMemory(
+        renderer,
+        buffer,
+        image,
+        memoryTypeIndex,
+        allocationSize,
+        isHostVisible,
+        &allocation);
+
+    // Uh oh, we're out of memory
+    if (allocationResult == 0) {
+        SDL_UnlockMutex(renderer->allocatorLock);
+
+        // Responsibility of the caller to handle being out of memory
+        return 2;
+    }
+
+    usedRegion = VULKAN_INTERNAL_NewMemoryUsedRegion(
+        renderer,
+        allocation,
+        0,
+        requiredSize,
+        0,
+        resourceSize,
+        memoryRequirements->alignment);
+
+    usedRegion->isBuffer = buffer != VK_NULL_HANDLE;
+
+    region = allocation->freeRegions[0];
+
+    newRegionOffset = region->offset + requiredSize;
+    newRegionSize = region->size - requiredSize;
+
+    VULKAN_INTERNAL_RemoveMemoryFreeRegion(renderer, region);
+
+    if (newRegionSize != 0) {
+        VULKAN_INTERNAL_NewMemoryFreeRegion(
+            renderer,
+            allocation,
+            newRegionOffset,
+            newRegionSize);
+    }
+
+    SDL_UnlockMutex(renderer->allocatorLock);
+
+    if (buffer != VK_NULL_HANDLE) {
+        if (!VULKAN_INTERNAL_BindBufferMemory(
+                renderer,
+                usedRegion,
+                0,
+                buffer)) {
+            VULKAN_INTERNAL_RemoveMemoryUsedRegion(
+                renderer,
+                usedRegion);
+
+            return 0;
+        }
+    } else if (image != VK_NULL_HANDLE) {
+        if (!VULKAN_INTERNAL_BindImageMemory(
+                renderer,
+                usedRegion,
+                0,
+                image)) {
+            VULKAN_INTERNAL_RemoveMemoryUsedRegion(
+                renderer,
+                usedRegion);
+
+            return 0;
+        }
+    }
+
+    *pMemoryUsedRegion = usedRegion;
+    return 1;
+}
+
+static Uint8 VULKAN_INTERNAL_BindMemoryForImage(
+    VulkanRenderer *renderer,
+    VkImage image,
+    VulkanMemoryUsedRegion **usedRegion)
+{
+    Uint8 bindResult = 0;
+    Uint32 memoryTypeCount = 0;
+    Uint32 *memoryTypesToTry = NULL;
+    Uint32 selectedMemoryTypeIndex = 0;
+    Uint32 i;
+    VkMemoryPropertyFlags preferredMemoryPropertyFlags;
+    VkMemoryRequirements memoryRequirements;
+
+    /* Vulkan memory types have several memory properties.
+     *
+     * Unlike buffers, images are always optimally stored device-local,
+     * so that is the only property we prefer here.
+     *
+     * If memory is constrained, it is fine for the texture to not
+     * be device-local.
+     */
+    preferredMemoryPropertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+
+    memoryTypesToTry = VULKAN_INTERNAL_FindBestImageMemoryTypes(
+        renderer,
+        image,
+        preferredMemoryPropertyFlags,
+        &memoryRequirements,
+        &memoryTypeCount);
+
+    for (i = 0; i < memoryTypeCount; i += 1) {
+        bindResult = VULKAN_INTERNAL_BindResourceMemory(
+            renderer,
+            memoryTypesToTry[i],
+            &memoryRequirements,
+            memoryRequirements.size,
+            VK_NULL_HANDLE,
+            image,
+            usedRegion);
+
+        if (bindResult == 1) {
+            selectedMemoryTypeIndex = memoryTypesToTry[i];
+            break;
+        }
+    }
+
+    SDL_free(memoryTypesToTry);
+
+    // Check for warnings on success
+    if (bindResult == 1) {
+        if (!renderer->outOfDeviceLocalMemoryWarning) {
+            if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) {
+                SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Out of device-local memory, allocating textures on host-local memory!");
+                renderer->outOfDeviceLocalMemoryWarning = 1;
+            }
+        }
+    }
+
+    return bindResult;
+}
+
+static Uint8 VULKAN_INTERNAL_BindMemoryForBuffer(
+    VulkanRenderer *renderer,
+    VkBuffer buffer,
+    VkDeviceSize size,
+    VulkanBufferType type,
+    VulkanMemoryUsedRegion **usedRegion)
+{
+    Uint8 bindResult = 0;
+    Uint32 memoryTypeCount = 0;
+    Uint32 *memoryTypesToTry = NULL;
+    Uint32 selectedMemoryTypeIndex = 0;
+    Uint32 i;
+    VkMemoryPropertyFlags requiredMemoryPropertyFlags = 0;
+    VkMemoryPropertyFlags preferredMemoryPropertyFlags = 0;
+    VkMemoryPropertyFlags tolerableMemoryPropertyFlags = 0;
+    VkMemoryRequirements memoryRequirements;
+
+    /* Buffers need to be optimally bound to a memory type
+     * based on their use case and the architecture of the system.
+     *
+     * It is important to understand the distinction between device and host.
+     *
+     * On a traditional high-performance desktop computer,
+     * the "device" would be the GPU, and the "host" would be the CPU.
+     * Memory being copied between these two must cross the PCI bus.
+     * On these systems we have to be concerned about bandwidth limitations
+     * and causing memory stalls, so we have taken a great deal of care
+     * to structure this API to guide the client towards optimal usage.
+     *
+     * Other kinds of devices do not necessarily have this distinction.
+     * On an iPhone or Nintendo Switch, all memory is accessible both to the
+     * GPU and the CPU at all times. These kinds of systems are known as
+     * UMA, or Unified Memory Architecture. A desktop computer using the
+     * CPU's integrated graphics can also be thought of as UMA.
+     *
+     * Vulkan memory types have several memory properties.
+     * The relevant memory properties are as follows:
+     *
+     * DEVICE_LOCAL:
+     *   This memory is on-device and most efficient for device access.
+     *   On UMA systems all memory is device-local.
+     *   If memory is not device-local, then it is host-local.
+     *
+     * HOST_VISIBLE:
+     *   This memory can be mapped for host access, meaning we can obtain
+     *   a pointer to directly access the memory.
+     *
+     * HOST_COHERENT:
+     *   Host-coherent memory does not require cache management operations
+     *   when mapped, so we always set this alongside HOST_VISIBLE
+     *   to avoid extra record keeping.
+     *
+     * HOST_CACHED:
+     *   Host-cached memory is faster to access than uncached memory
+     *   but memory of this type might not always be available.
+     *
+     * GPU buffers, like vertex buffers, indirect buffers, etc
+     * are optimally stored in device-local memory.
+     * However, if device-local memory is low, these buffers
+     * can be accessed from host-local memory with a performance penalty.
+     *
+     * Uniform buffers must be host-visible and coherent because
+     * the client uses them to quickly push small amounts of data.
+     * We prefer uniform buffers to also be device-local because
+     * they are accessed by shaders, but the amount of memory
+     * that is both device-local and host-visible
+     * is often constrained, particularly on low-end devices.
+     *
+     * Transfer buffers must be host-visible and coherent because
+     * the client uses them to stage data to be transferred
+     * to device-local memory, or to read back data transferred
+     * from the device. We prefer the cache bit for performance
+     * but it isn't strictly necessary. We tolerate device-local
+     * memory in this situation because, as mentioned above,
+     * on certain devices all memory is device-local, and even
+     * though the transfer isn't strictly necessary it is still
+     * useful for correctly timelining data.
+     */
+    if (type == VULKAN_BUFFER_TYPE_GPU) {
+        preferredMemoryPropertyFlags |=
+            VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+    } else if (type == VULKAN_BUFFER_TYPE_UNIFORM) {
+        requiredMemoryPropertyFlags |=
+            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+            VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+
+        preferredMemoryPropertyFlags |=
+            VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+    } else if (type == VULKAN_BUFFER_TYPE_TRANSFER) {
+        requiredMemoryPropertyFlags |=
+            VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+            VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+
+        preferredMemoryPropertyFlags |=
+            VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+
+        tolerableMemoryPropertyFlags |=
+            VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized buffer type!");
+        return 0;
+    }
+
+    memoryTypesToTry = VULKAN_INTERNAL_FindBestBufferMemoryTypes(
+        renderer,
+        buffer,
+        requiredMemoryPropertyFlags,
+        preferredMemoryPropertyFlags,
+        tolerableMemoryPropertyFlags,
+        &memoryRequirements,
+        &memoryTypeCount);
+
+    for (i = 0; i < memoryTypeCount; i += 1) {
+        bindResult = VULKAN_INTERNAL_BindResourceMemory(
+            renderer,
+            memoryTypesToTry[i],
+            &memoryRequirements,
+            size,
+            buffer,
+            VK_NULL_HANDLE,
+            usedRegion);
+
+        if (bindResult == 1) {
+            selectedMemoryTypeIndex = memoryTypesToTry[i];
+            break;
+        }
+    }
+
+    SDL_free(memoryTypesToTry);
+
+    // Check for warnings on success
+    if (bindResult == 1) {
+        if (type == VULKAN_BUFFER_TYPE_GPU) {
+            if (!renderer->outOfDeviceLocalMemoryWarning) {
+                if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) {
+                    SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Out of device-local memory, allocating buffers on host-local memory, expect degraded performance!");
+                    renderer->outOfDeviceLocalMemoryWarning = 1;
+                }
+            }
+        } else if (type == VULKAN_BUFFER_TYPE_UNIFORM) {
+            if (!renderer->outofBARMemoryWarning) {
+                if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == 0) {
+                    SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Out of BAR memory, allocating uniform buffers on host-local memory, expect degraded performance!");
+                    renderer->outofBARMemoryWarning = 1;
+                }
+            }
+        } else if (type == VULKAN_BUFFER_TYPE_TRANSFER) {
+            if (!renderer->integratedMemoryNotification) {
+                if ((renderer->memoryProperties.memoryTypes[selectedMemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) == VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
+                    SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Integrated memory detected, allocating TransferBuffers on device-local memory!");
+                    renderer->integratedMemoryNotification = 1;
+                }
+            }
+        }
+    }
+
+    return bindResult;
+}
+
+// Resource tracking
+
+#define ADD_TO_ARRAY_UNIQUE(resource, type, array, count, capacity) \
+    Uint32 i;                                                       \
+                                                                    \
+    for (i = 0; i < commandBuffer->count; i += 1) {                 \
+        if (commandBuffer->array[i] == resource) {                  \
+            return;                                                 \
+        }                                                           \
+    }                                                               \
+                                                                    \
+    if (commandBuffer->count == commandBuffer->capacity) {          \
+        commandBuffer->capacity += 1;                               \
+        commandBuffer->array = SDL_realloc(                         \
+            commandBuffer->array,                                   \
+            commandBuffer->capacity * sizeof(type));                \
+    }                                                               \
+    commandBuffer->array[commandBuffer->count] = resource;          \
+    commandBuffer->count += 1;
+
+#define TRACK_RESOURCE(resource, type, array, count, capacity) \
+    Uint32 i;                                                  \
+                                                               \
+    for (i = 0; i < commandBuffer->count; i += 1) {            \
+        if (commandBuffer->array[i] == resource) {             \
+            return;                                            \
+        }                                                      \
+    }                                                          \
+                                                               \
+    if (commandBuffer->count == commandBuffer->capacity) {     \
+        commandBuffer->capacity += 1;                          \
+        commandBuffer->array = SDL_realloc(                    \
+            commandBuffer->array,                              \
+            commandBuffer->capacity * sizeof(type));           \
+    }                                                          \
+    commandBuffer->array[commandBuffer->count] = resource;     \
+    commandBuffer->count += 1;                                 \
+    SDL_AtomicIncRef(&resource->referenceCount);
+
+static void VULKAN_INTERNAL_TrackBuffer(
+    VulkanCommandBuffer *commandBuffer,
+    VulkanBuffer *buffer)
+{
+    TRACK_RESOURCE(
+        buffer,
+        VulkanBuffer *,
+        usedBuffers,
+        usedBufferCount,
+        usedBufferCapacity)
+}
+
+static void VULKAN_INTERNAL_TrackTexture(
+    VulkanCommandBuffer *commandBuffer,
+    VulkanTexture *texture)
+{
+    TRACK_RESOURCE(
+        texture,
+        VulkanTexture *,
+        usedTextures,
+        usedTextureCount,
+        usedTextureCapacity)
+}
+
+static void VULKAN_INTERNAL_TrackSampler(
+    VulkanCommandBuffer *commandBuffer,
+    VulkanSampler *sampler)
+{
+    TRACK_RESOURCE(
+        sampler,
+        VulkanSampler *,
+        usedSamplers,
+        usedSamplerCount,
+        usedSamplerCapacity)
+}
+
+static void VULKAN_INTERNAL_TrackGraphicsPipeline(
+    VulkanCommandBuffer *commandBuffer,
+    VulkanGraphicsPipeline *graphicsPipeline)
+{
+    TRACK_RESOURCE(
+        graphicsPipeline,
+        VulkanGraphicsPipeline *,
+        usedGraphicsPipelines,
+        usedGraphicsPipelineCount,
+        usedGraphicsPipelineCapacity)
+}
+
+static void VULKAN_INTERNAL_TrackComputePipeline(
+    VulkanCommandBuffer *commandBuffer,
+    VulkanComputePipeline *computePipeline)
+{
+    TRACK_RESOURCE(
+        computePipeline,
+        VulkanComputePipeline *,
+        usedComputePipelines,
+        usedComputePipelineCount,
+        usedComputePipelineCapacity)
+}
+
+static void VULKAN_INTERNAL_TrackFramebuffer(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanFramebuffer *framebuffer)
+{
+    TRACK_RESOURCE(
+        framebuffer,
+        VulkanFramebuffer *,
+        usedFramebuffers,
+        usedFramebufferCount,
+        usedFramebufferCapacity);
+}
+
+static void VULKAN_INTERNAL_TrackUniformBuffer(
+    VulkanCommandBuffer *commandBuffer,
+    VulkanUniformBuffer *uniformBuffer)
+{
+    Uint32 i;
+    for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
+        if (commandBuffer->usedUniformBuffers[i] == uniformBuffer) {
+            return;
+        }
+    }
+
+    if (commandBuffer->usedUniformBufferCount == commandBuffer->usedUniformBufferCapacity) {
+        commandBuffer->usedUniformBufferCapacity += 1;
+        commandBuffer->usedUniformBuffers = SDL_realloc(
+            commandBuffer->usedUniformBuffers,
+            commandBuffer->usedUniformBufferCapacity * sizeof(VulkanUniformBuffer *));
+    }
+    commandBuffer->usedUniformBuffers[commandBuffer->usedUniformBufferCount] = uniformBuffer;
+    commandBuffer->usedUniformBufferCount += 1;
+
+    VULKAN_INTERNAL_TrackBuffer(
+        commandBuffer,
+        uniformBuffer->bufferHandle->vulkanBuffer);
+}
+
+#undef TRACK_RESOURCE
+
+// Memory Barriers
+
+/*
+ * In Vulkan, we must manually synchronize operations that write to resources on the GPU
+ * so that read-after-write, write-after-read, and write-after-write hazards do not occur.
+ * Additionally, textures are required to be in specific layouts for specific use cases.
+ * Both of these tasks are accomplished with vkCmdPipelineBarrier.
+ *
+ * To insert the correct barriers, we keep track of "usage modes" for buffers and textures.
+ * These indicate the current usage of that resource on the command buffer.
+ * The transition from one usage mode to another indicates how the barrier should be constructed.
+ *
+ * Pipeline barriers cannot be inserted during a render pass, but they can be inserted
+ * during a compute or copy pass.
+ *
+ * This means that the "default" usage mode of any given resource should be that it should be
+ * ready for a graphics-read operation, because we cannot barrier during a render pass.
+ * In the case where a resource is only used in compute, its default usage mode can be compute-read.
+ * This strategy allows us to avoid expensive record keeping of command buffer/resource usage mode pairs,
+ * and it fully covers synchronization between all combinations of stages.
+ *
+ * In Upload and Copy functions, we transition the resource immediately before and after the copy command.
+ *
+ * When binding a resource for compute, we transition when the Bind functions are called.
+ * If a bind slot containing a resource is overwritten, we transition the resource in that slot back to its default.
+ * When EndComputePass is called we transition all bound resources back to their default state.
+ *
+ * When binding a texture as a render pass attachment, we transition the resource on BeginRenderPass
+ * and transition it back to its default on EndRenderPass.
+ *
+ * This strategy imposes certain limitations on resource usage flags.
+ * For example, a texture cannot have both the SAMPLER and GRAPHICS_STORAGE usage flags,
+ * because then it is imposible for the backend to infer which default usage mode the texture should use.
+ *
+ * Sync hazards can be detected by setting VK_KHRONOS_VALIDATION_VALIDATE_SYNC=1 when using validation layers.
+ */
+
+static void VULKAN_INTERNAL_BufferMemoryBarrier(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanBufferUsageMode sourceUsageMode,
+    VulkanBufferUsageMode destinationUsageMode,
+    VulkanBuffer *buffer)
+{
+    VkPipelineStageFlags srcStages = 0;
+    VkPipelineStageFlags dstStages = 0;
+    VkBufferMemoryBarrier memoryBarrier;
+
+    memoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+    memoryBarrier.pNext = NULL;
+    memoryBarrier.srcAccessMask = 0;
+    memoryBarrier.dstAccessMask = 0;
+    memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    memoryBarrier.buffer = buffer->buffer;
+    memoryBarrier.offset = 0;
+    memoryBarrier.size = buffer->size;
+
+    if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE) {
+        srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+    } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION) {
+        srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+    } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_VERTEX_READ) {
+        srcStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
+    } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_INDEX_READ) {
+        srcStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_INDEX_READ_BIT;
+    } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_INDIRECT) {
+        srcStages = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
+    } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ) {
+        srcStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
+    } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ) {
+        srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
+    } else if (sourceUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
+        srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized buffer source barrier type!");
+        return;
+    }
+
+    if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE) {
+        dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+    } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION) {
+        dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+    } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_VERTEX_READ) {
+        dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
+    } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_INDEX_READ) {
+        dstStages = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_INDEX_READ_BIT;
+    } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_INDIRECT) {
+        dstStages = VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_INDIRECT_COMMAND_READ_BIT;
+    } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ) {
+        dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+    } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ) {
+        dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+    } else if (destinationUsageMode == VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
+        dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized buffer destination barrier type!");
+        return;
+    }
+
+    renderer->vkCmdPipelineBarrier(
+        commandBuffer->commandBuffer,
+        srcStages,
+        dstStages,
+        0,
+        0,
+        NULL,
+        1,
+        &memoryBarrier,
+        0,
+        NULL);
+
+    buffer->transitioned = SDL_TRUE;
+}
+
+static void VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanTextureUsageMode sourceUsageMode,
+    VulkanTextureUsageMode destinationUsageMode,
+    VulkanTextureSubresource *textureSubresource)
+{
+    VkPipelineStageFlags srcStages = 0;
+    VkPipelineStageFlags dstStages = 0;
+    VkImageMemoryBarrier memoryBarrier;
+
+    memoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+    memoryBarrier.pNext = NULL;
+    memoryBarrier.srcAccessMask = 0;
+    memoryBarrier.dstAccessMask = 0;
+    memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    memoryBarrier.newLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    memoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    memoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    memoryBarrier.image = textureSubresource->parent->image;
+    memoryBarrier.subresourceRange.aspectMask = textureSubresource->parent->aspectFlags;
+    memoryBarrier.subresourceRange.baseArrayLayer = textureSubresource->layer;
+    memoryBarrier.subresourceRange.layerCount = 1;
+    memoryBarrier.subresourceRange.baseMipLevel = textureSubresource->level;
+    memoryBarrier.subresourceRange.levelCount = 1;
+
+    if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE) {
+        srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+        memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+    } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION) {
+        srcStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+        memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+    } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_SAMPLER) {
+        srcStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
+        memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+    } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ) {
+        srcStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
+        memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
+    } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ) {
+        srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
+        memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
+    } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
+        srcStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+        memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
+    } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT) {
+        srcStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+        memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+    } else if (sourceUsageMode == VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT) {
+        srcStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+        memoryBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+        memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized texture source barrier type!");
+        return;
+    }
+
+    if (!textureSubresource->transitioned) {
+        memoryBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    }
+
+    if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE) {
+        dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+        memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+    } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION) {
+        dstStages = VK_PIPELINE_STAGE_TRANSFER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+        memoryBarrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+    } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_SAMPLER) {
+        dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+        memoryBarrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+    } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ) {
+        dstStages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+        memoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
+    } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ) {
+        dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+        memoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
+    } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE) {
+        dstStages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
+        memoryBarrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
+    } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT) {
+        dstStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+        memoryBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+    } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT) {
+        dstStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+        memoryBarrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+        memoryBarrier.newLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+    } else if (destinationUsageMode == VULKAN_TEXTURE_USAGE_MODE_PRESENT) {
+        dstStages = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+        memoryBarrier.dstAccessMask = 0;
+        memoryBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized texture destination barrier type!");
+        return;
+    }
+
+    renderer->vkCmdPipelineBarrier(
+        commandBuffer->commandBuffer,
+        srcStages,
+        dstStages,
+        0,
+        0,
+        NULL,
+        0,
+        NULL,
+        1,
+        &memoryBarrier);
+
+    textureSubresource->transitioned = SDL_TRUE;
+}
+
+static VulkanBufferUsageMode VULKAN_INTERNAL_DefaultBufferUsageMode(
+    VulkanBuffer *buffer)
+{
+    // NOTE: order matters here!
+
+    if (buffer->usageFlags & SDL_GPU_BUFFERUSAGE_VERTEX_BIT) {
+        return VULKAN_BUFFER_USAGE_MODE_VERTEX_READ;
+    } else if (buffer->usageFlags & SDL_GPU_BUFFERUSAGE_INDEX_BIT) {
+        return VULKAN_BUFFER_USAGE_MODE_INDEX_READ;
+    } else if (buffer->usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT_BIT) {
+        return VULKAN_BUFFER_USAGE_MODE_INDIRECT;
+    } else if (buffer->usageFlags & SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT) {
+        return VULKAN_BUFFER_USAGE_MODE_GRAPHICS_STORAGE_READ;
+    } else if (buffer->usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ_BIT) {
+        return VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ;
+    } else if (buffer->usageFlags & SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+        return VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Buffer has no default usage mode!");
+        return VULKAN_BUFFER_USAGE_MODE_VERTEX_READ;
+    }
+}
+
+static VulkanTextureUsageMode VULKAN_INTERNAL_DefaultTextureUsageMode(
+    VulkanTexture *texture)
+{
+    // NOTE: order matters here!
+    // NOTE: graphics storage bits and sampler bit are mutually exclusive!
+
+    if (texture->usageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) {
+        return VULKAN_TEXTURE_USAGE_MODE_SAMPLER;
+    } else if (texture->usageFlags & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT) {
+        return VULKAN_TEXTURE_USAGE_MODE_GRAPHICS_STORAGE_READ;
+    } else if (texture->usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) {
+        return VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT;
+    } else if (texture->usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) {
+        return VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT;
+    } else if (texture->usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT) {
+        return VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ;
+    } else if (texture->usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+        return VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Texture has no default usage mode!");
+        return VULKAN_TEXTURE_USAGE_MODE_SAMPLER;
+    }
+}
+
+static void VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanBufferUsageMode destinationUsageMode,
+    VulkanBuffer *buffer)
+{
+    VULKAN_INTERNAL_BufferMemoryBarrier(
+        renderer,
+        commandBuffer,
+        VULKAN_INTERNAL_DefaultBufferUsageMode(buffer),
+        destinationUsageMode,
+        buffer);
+}
+
+static void VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanBufferUsageMode sourceUsageMode,
+    VulkanBuffer *buffer)
+{
+    VULKAN_INTERNAL_BufferMemoryBarrier(
+        renderer,
+        commandBuffer,
+        sourceUsageMode,
+        VULKAN_INTERNAL_DefaultBufferUsageMode(buffer),
+        buffer);
+}
+
+static void VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanTextureUsageMode destinationUsageMode,
+    VulkanTextureSubresource *textureSubresource)
+{
+    VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
+        renderer,
+        commandBuffer,
+        VULKAN_INTERNAL_DefaultTextureUsageMode(textureSubresource->parent),
+        destinationUsageMode,
+        textureSubresource);
+}
+
+static void VULKAN_INTERNAL_TextureTransitionFromDefaultUsage(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanTextureUsageMode destinationUsageMode,
+    VulkanTexture *texture)
+{
+    for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
+        VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+            renderer,
+            commandBuffer,
+            destinationUsageMode,
+            &texture->subresources[i]);
+    }
+}
+
+static void VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanTextureUsageMode sourceUsageMode,
+    VulkanTextureSubresource *textureSubresource)
+{
+    VULKAN_INTERNAL_TextureSubresourceMemoryBarrier(
+        renderer,
+        commandBuffer,
+        sourceUsageMode,
+        VULKAN_INTERNAL_DefaultTextureUsageMode(textureSubresource->parent),
+        textureSubresource);
+}
+
+static void VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanTextureUsageMode sourceUsageMode,
+    VulkanTexture *texture)
+{
+    // FIXME: could optimize this barrier
+    for (Uint32 i = 0; i < texture->subresourceCount; i += 1) {
+        VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+            renderer,
+            commandBuffer,
+            sourceUsageMode,
+            &texture->subresources[i]);
+    }
+}
+
+// Resource Disposal
+
+static void VULKAN_INTERNAL_ReleaseFramebuffer(
+    VulkanRenderer *renderer,
+    VulkanFramebuffer *framebuffer)
+{
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->framebuffersToDestroy,
+        VulkanFramebuffer *,
+        renderer->framebuffersToDestroyCount + 1,
+        renderer->framebuffersToDestroyCapacity,
+        renderer->framebuffersToDestroyCapacity * 2)
+
+    renderer->framebuffersToDestroy[renderer->framebuffersToDestroyCount] = framebuffer;
+    renderer->framebuffersToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void VULKAN_INTERNAL_DestroyFramebuffer(
+    VulkanRenderer *renderer,
+    VulkanFramebuffer *framebuffer)
+{
+    renderer->vkDestroyFramebuffer(
+        renderer->logicalDevice,
+        framebuffer->framebuffer,
+        NULL);
+
+    SDL_free(framebuffer);
+}
+
+static void VULKAN_INTERNAL_RemoveFramebuffersContainingView(
+    VulkanRenderer *renderer,
+    VkImageView view)
+{
+    FramebufferHashTableKey *key;
+    VulkanFramebuffer *value;
+    void *iter = NULL;
+
+    // Can't remove while iterating!
+    Uint32 keysToRemoveCapacity = 8;
+    Uint32 keysToRemoveCount = 0;
+    FramebufferHashTableKey **keysToRemove = SDL_malloc(keysToRemoveCapacity * sizeof(FramebufferHashTableKey *));
+
+    SDL_LockMutex(renderer->framebufferFetchLock);
+
+    while (SDL_IterateHashTable(renderer->framebufferHashTable, (const void **)&key, (const void **)&value, &iter)) {
+        SDL_bool remove = SDL_FALSE;
+        for (Uint32 i = 0; i < key->colorAttachmentCount; i += 1) {
+            if (key->colorAttachmentViews[i] == view) {
+                remove = SDL_TRUE;
+            }
+        }
+        if (key->depthStencilAttachmentView == view) {
+            remove = SDL_TRUE;
+        }
+
+        if (remove) {
+            if (keysToRemoveCount == keysToRemoveCapacity) {
+                keysToRemoveCapacity *= 2;
+                keysToRemove = SDL_realloc(
+                    keysToRemove,
+                    keysToRemoveCapacity * sizeof(FramebufferHashTableKey *));
+            }
+
+            keysToRemove[keysToRemoveCount] = key;
+            keysToRemoveCount += 1;
+        }
+    }
+
+    for (Uint32 i = 0; i < keysToRemoveCount; i += 1) {
+        SDL_RemoveFromHashTable(renderer->framebufferHashTable, (void *)keysToRemove[i]);
+    }
+
+    SDL_UnlockMutex(renderer->framebufferFetchLock);
+
+    SDL_free(keysToRemove);
+}
+
+static void VULKAN_INTERNAL_DestroyTexture(
+    VulkanRenderer *renderer,
+    VulkanTexture *texture)
+{
+    // Clean up subresources
+    for (Uint32 subresourceIndex = 0; subresourceIndex < texture->subresourceCount; subresourceIndex += 1) {
+        if (texture->usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) {
+            for (Uint32 depthIndex = 0; depthIndex < texture->depth; depthIndex += 1) {
+                VULKAN_INTERNAL_RemoveFramebuffersContainingView(
+                    renderer,
+                    texture->subresources[subresourceIndex].renderTargetViews[depthIndex]);
+            }
+
+            if (texture->subresources[subresourceIndex].msaaTexHandle != NULL) {
+                VULKAN_INTERNAL_DestroyTexture(
+                    renderer,
+                    texture->subresources[subresourceIndex].msaaTexHandle->vulkanTexture);
+                SDL_free(texture->subresources[subresourceIndex].msaaTexHandle);
+            }
+
+            for (Uint32 depthIndex = 0; depthIndex < texture->depth; depthIndex += 1) {
+                renderer->vkDestroyImageView(
+                    renderer->logicalDevice,
+                    texture->subresources[subresourceIndex].renderTargetViews[depthIndex],
+                    NULL);
+            }
+            SDL_free(texture->subresources[subresourceIndex].renderTargetViews);
+        }
+
+        if (texture->usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+            renderer->vkDestroyImageView(
+                renderer->logicalDevice,
+                texture->subresources[subresourceIndex].computeWriteView,
+                NULL);
+        }
+
+        if (texture->usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) {
+            renderer->vkDestroyImageView(
+                renderer->logicalDevice,
+                texture->subresources[subresourceIndex].depthStencilView,
+                NULL);
+        }
+    }
+
+    SDL_free(texture->subresources);
+
+    renderer->vkDestroyImageView(
+        renderer->logicalDevice,
+        texture->fullView,
+        NULL);
+
+    renderer->vkDestroyImage(
+        renderer->logicalDevice,
+        texture->image,
+        NULL);
+
+    VULKAN_INTERNAL_RemoveMemoryUsedRegion(
+        renderer,
+        texture->usedRegion);
+
+    SDL_free(texture);
+}
+
+static void VULKAN_INTERNAL_DestroyBuffer(
+    VulkanRenderer *renderer,
+    VulkanBuffer *buffer)
+{
+    renderer->vkDestroyBuffer(
+        renderer->logicalDevice,
+        buffer->buffer,
+        NULL);
+
+    VULKAN_INTERNAL_RemoveMemoryUsedRegion(
+        renderer,
+        buffer->usedRegion);
+
+    SDL_free(buffer);
+}
+
+static void VULKAN_INTERNAL_DestroyCommandPool(
+    VulkanRenderer *renderer,
+    VulkanCommandPool *commandPool)
+{
+    Uint32 i;
+    VulkanCommandBuffer *commandBuffer;
+
+    renderer->vkDestroyCommandPool(
+        renderer->logicalDevice,
+        commandPool->commandPool,
+        NULL);
+
+    for (i = 0; i < commandPool->inactiveCommandBufferCount; i += 1) {
+        commandBuffer = commandPool->inactiveCommandBuffers[i];
+
+        SDL_free(commandBuffer->presentDatas);
+        SDL_free(commandBuffer->waitSemaphores);
+        SDL_free(commandBuffer->signalSemaphores);
+        SDL_free(commandBuffer->boundDescriptorSetDatas);
+        SDL_free(commandBuffer->usedBuffers);
+        SDL_free(commandBuffer->usedTextures);
+        SDL_free(commandBuffer->usedSamplers);
+        SDL_free(commandBuffer->usedGraphicsPipelines);
+        SDL_free(commandBuffer->usedComputePipelines);
+        SDL_free(commandBuffer->usedFramebuffers);
+        SDL_free(commandBuffer->usedUniformBuffers);
+
+        SDL_free(commandBuffer);
+    }
+
+    SDL_free(commandPool->inactiveCommandBuffers);
+    SDL_free(commandPool);
+}
+
+static void VULKAN_INTERNAL_DestroyDescriptorSetPool(
+    VulkanRenderer *renderer,
+    DescriptorSetPool *pool)
+{
+    Uint32 i;
+
+    if (pool == NULL) {
+        return;
+    }
+
+    for (i = 0; i < pool->descriptorPoolCount; i += 1) {
+        renderer->vkDestroyDescriptorPool(
+            renderer->logicalDevice,
+            pool->descriptorPools[i],
+            NULL);
+    }
+
+    renderer->vkDestroyDescriptorSetLayout(
+        renderer->logicalDevice,
+        pool->descriptorSetLayout,
+        NULL);
+
+    SDL_free(pool->descriptorInfos);
+    SDL_free(pool->descriptorPools);
+    SDL_free(pool->inactiveDescriptorSets);
+    SDL_DestroyMutex(pool->lock);
+}
+
+static void VULKAN_INTERNAL_DestroyGraphicsPipeline(
+    VulkanRenderer *renderer,
+    VulkanGraphicsPipeline *graphicsPipeline)
+{
+    Uint32 i;
+
+    renderer->vkDestroyPipeline(
+        renderer->logicalDevice,
+        graphicsPipeline->pipeline,
+        NULL);
+
+    renderer->vkDestroyPipelineLayout(
+        renderer->logicalDevice,
+        graphicsPipeline->resourceLayout.pipelineLayout,
+        NULL);
+
+    for (i = 0; i < 4; i += 1) {
+        VULKAN_INTERNAL_DestroyDescriptorSetPool(
+            renderer,
+            &graphicsPipeline->resourceLayout.descriptorSetPools[i]);
+    }
+
+    (void)SDL_AtomicDecRef(&graphicsPipeline->vertexShader->referenceCount);
+    (void)SDL_AtomicDecRef(&graphicsPipeline->fragmentShader->referenceCount);
+
+    SDL_free(graphicsPipeline);
+}
+
+static void VULKAN_INTERNAL_DestroyComputePipeline(
+    VulkanRenderer *renderer,
+    VulkanComputePipeline *computePipeline)
+{
+    Uint32 i;
+
+    renderer->vkDestroyPipeline(
+        renderer->logicalDevice,
+        computePipeline->pipeline,
+        NULL);
+
+    renderer->vkDestroyPipelineLayout(
+        renderer->logicalDevice,
+        computePipeline->resourceLayout.pipelineLayout,
+        NULL);
+
+    for (i = 0; i < 3; i += 1) {
+        VULKAN_INTERNAL_DestroyDescriptorSetPool(
+            renderer,
+            &computePipeline->resourceLayout.descriptorSetPools[i]);
+    }
+
+    renderer->vkDestroyShaderModule(
+        renderer->logicalDevice,
+        computePipeline->shaderModule,
+        NULL);
+
+    SDL_free(computePipeline);
+}
+
+static void VULKAN_INTERNAL_DestroyShader(
+    VulkanRenderer *renderer,
+    VulkanShader *vulkanShader)
+{
+    renderer->vkDestroyShaderModule(
+        renderer->logicalDevice,
+        vulkanShader->shaderModule,
+        NULL);
+
+    SDL_free((void *)vulkanShader->entryPointName);
+    SDL_free(vulkanShader);
+}
+
+static void VULKAN_INTERNAL_DestroySampler(
+    VulkanRenderer *renderer,
+    VulkanSampler *vulkanSampler)
+{
+    renderer->vkDestroySampler(
+        renderer->logicalDevice,
+        vulkanSampler->sampler,
+        NULL);
+
+    SDL_free(vulkanSampler);
+}
+
+static void VULKAN_INTERNAL_DestroySwapchain(
+    VulkanRenderer *renderer,
+    WindowData *windowData)
+{
+    Uint32 i;
+    VulkanSwapchainData *swapchainData;
+
+    if (windowData == NULL) {
+        return;
+    }
+
+    swapchainData = windowData->swapchainData;
+
+    if (swapchainData == NULL) {
+        return;
+    }
+
+    for (i = 0; i < swapchainData->imageCount; i += 1) {
+        VULKAN_INTERNAL_RemoveFramebuffersContainingView(
+            renderer,
+            swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources[0].renderTargetViews[0]);
+        renderer->vkDestroyImageView(
+            renderer->logicalDevice,
+            swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources[0].renderTargetViews[0],
+            NULL);
+        SDL_free(swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources[0].renderTargetViews);
+        SDL_free(swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources);
+
+        SDL_free(swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture);
+        SDL_free(swapchainData->textureContainers[i].activeTextureHandle);
+    }
+
+    SDL_free(swapchainData->textureContainers);
+
+    renderer->vkDestroySwapchainKHR(
+        renderer->logicalDevice,
+        swapchainData->swapchain,
+        NULL);
+
+    renderer->vkDestroySurfaceKHR(
+        renderer->instance,
+        swapchainData->surface,
+        NULL);
+
+    for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+        renderer->vkDestroySemaphore(
+            renderer->logicalDevice,
+            swapchainData->imageAvailableSemaphore[i],
+            NULL);
+
+        renderer->vkDestroySemaphore(
+            renderer->logicalDevice,
+            swapchainData->renderFinishedSemaphore[i],
+            NULL);
+    }
+
+    windowData->swapchainData = NULL;
+    SDL_free(swapchainData);
+}
+
+// Hashtable functions
+
+static Uint32 VULKAN_INTERNAL_CommandPoolHashFunction(const void *key, void *data)
+{
+    return (Uint32)((CommandPoolHashTableKey *)key)->threadID;
+}
+
+static bool VULKAN_INTERNAL_CommandPoolHashKeyMatch(const void *aKey, const void *bKey, void *data)
+{
+    CommandPoolHashTableKey *a = (CommandPoolHashTableKey *)aKey;
+    CommandPoolHashTableKey *b = (CommandPoolHashTableKey *)bKey;
+    return a->threadID == b->threadID;
+}
+
+static void VULKAN_INTERNAL_CommandPoolHashNuke(const void *key, const void *value, void *data)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)data;
+    VulkanCommandPool *pool = (VulkanCommandPool *)value;
+    VULKAN_INTERNAL_DestroyCommandPool(renderer, pool);
+    SDL_free((void *)key);
+}
+
+static Uint32 VULKAN_INTERNAL_RenderPassHashFunction(
+    const void *key,
+    void *data)
+{
+    RenderPassHashTableKey *hashTableKey = (RenderPassHashTableKey *)key;
+
+    /* The algorithm for this hashing function
+     * is taken from Josh Bloch's "Effective Java".
+     * (https://stackoverflow.com/a/113600/12492383)
+     */
+    const Uint32 HASH_FACTOR = 31;
+    Uint32 result = 1;
+
+    for (Uint32 i = 0; i < hashTableKey->colorAttachmentCount; i += 1) {
+        result = result * HASH_FACTOR + hashTableKey->colorTargetDescriptions[i].loadOp;
+        result = result * HASH_FACTOR + hashTableKey->colorTargetDescriptions[i].storeOp;
+        result = result * HASH_FACTOR + hashTableKey->colorTargetDescriptions[i].format;
+    }
+
+    result = result * HASH_FACTOR + hashTableKey->depthStencilTargetDescription.loadOp;
+    result = result * HASH_FACTOR + hashTableKey->depthStencilTargetDescription.storeOp;
+    result = result * HASH_FACTOR + hashTableKey->depthStencilTargetDescription.stencilLoadOp;
+    result = result * HASH_FACTOR + hashTableKey->depthStencilTargetDescription.stencilStoreOp;
+    result = result * HASH_FACTOR + hashTableKey->depthStencilTargetDescription.format;
+
+    result = result * HASH_FACTOR + hashTableKey->colorAttachmentSampleCount;
+
+    return result;
+}
+
+static bool VULKAN_INTERNAL_RenderPassHashKeyMatch(
+    const void *aKey,
+    const void *bKey,
+    void *data)
+{
+    RenderPassHashTableKey *a = (RenderPassHashTableKey *)aKey;
+    RenderPassHashTableKey *b = (RenderPassHashTableKey *)bKey;
+
+    if (a->colorAttachmentCount != b->colorAttachmentCount) {
+        return 0;
+    }
+
+    if (a->colorAttachmentSampleCount != b->colorAttachmentSampleCount) {
+        return 0;
+    }
+
+    for (Uint32 i = 0; i < a->colorAttachmentCount; i += 1) {
+        if (a->colorTargetDescriptions[i].format != b->colorTargetDescriptions[i].format) {
+            return 0;
+        }
+
+        if (a->colorTargetDescriptions[i].loadOp != b->colorTargetDescriptions[i].loadOp) {
+            return 0;
+        }
+
+        if (a->colorTargetDescriptions[i].storeOp != b->colorTargetDescriptions[i].storeOp) {
+            return 0;
+        }
+    }
+
+    if (a->depthStencilTargetDescription.format != b->depthStencilTargetDescription.format) {
+        return 0;
+    }
+
+    if (a->depthStencilTargetDescription.loadOp != b->depthStencilTargetDescription.loadOp) {
+        return 0;
+    }
+
+    if (a->depthStencilTargetDescription.storeOp != b->depthStencilTargetDescription.storeOp) {
+        return 0;
+    }
+
+    if (a->depthStencilTargetDescription.stencilLoadOp != b->depthStencilTargetDescription.stencilLoadOp) {
+        return 0;
+    }
+
+    if (a->depthStencilTargetDescription.stencilStoreOp != b->depthStencilTargetDescription.stencilStoreOp) {
+        return 0;
+    }
+
+    return 1;
+}
+
+static void VULKAN_INTERNAL_RenderPassHashNuke(const void *key, const void *value, void *data)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)data;
+    VulkanRenderPassHashTableValue *renderPassWrapper = (VulkanRenderPassHashTableValue *)value;
+    renderer->vkDestroyRenderPass(
+        renderer->logicalDevice,
+        renderPassWrapper->handle,
+        NULL);
+    SDL_free(renderPassWrapper);
+    SDL_free((void *)key);
+}
+
+static Uint32 VULKAN_INTERNAL_FramebufferHashFunction(
+    const void *key,
+    void *data)
+{
+    FramebufferHashTableKey *hashTableKey = (FramebufferHashTableKey *)key;
+
+    /* The algorithm for this hashing function
+     * is taken from Josh Bloch's "Effective Java".
+     * (https://stackoverflow.com/a/113600/12492383)
+     */
+    const Uint32 HASH_FACTOR = 31;
+    Uint32 result = 1;
+
+    for (Uint32 i = 0; i < hashTableKey->colorAttachmentCount; i += 1) {
+        result = result * HASH_FACTOR + (Uint32)(uintptr_t)hashTableKey->colorAttachmentViews[i];
+        result = result * HASH_FACTOR + (Uint32)(uintptr_t)hashTableKey->colorMultiSampleAttachmentViews[i];
+    }
+
+    result = result * HASH_FACTOR + (Uint32)(uintptr_t)hashTableKey->depthStencilAttachmentView;
+    result = result * HASH_FACTOR + hashTableKey->width;
+    result = result * HASH_FACTOR + hashTableKey->height;
+
+    return result;
+}
+
+static bool VULKAN_INTERNAL_FramebufferHashKeyMatch(
+    const void *aKey,
+    const void *bKey,
+    void *data)
+{
+    FramebufferHashTableKey *a = (FramebufferHashTableKey *)aKey;
+    FramebufferHashTableKey *b = (FramebufferHashTableKey *)bKey;
+
+    if (a->colorAttachmentCount != b->colorAttachmentCount) {
+        return 0;
+    }
+
+    for (Uint32 i = 0; i < a->colorAttachmentCount; i += 1) {
+        if (a->colorAttachmentViews[i] != b->colorAttachmentViews[i]) {
+            return 0;
+        }
+
+        if (a->colorMultiSampleAttachmentViews[i] != b->colorMultiSampleAttachmentViews[i]) {
+            return 0;
+        }
+    }
+
+    if (a->depthStencilAttachmentView != b->depthStencilAttachmentView) {
+        return 0;
+    }
+
+    if (a->width != b->width) {
+        return 0;
+    }
+
+    if (a->height != b->height) {
+        return 0;
+    }
+
+    return 1;
+}
+
+static void VULKAN_INTERNAL_FramebufferHashNuke(const void *key, const void *value, void *data)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)data;
+    VulkanFramebuffer *framebuffer = (VulkanFramebuffer *)value;
+    VULKAN_INTERNAL_ReleaseFramebuffer(renderer, framebuffer);
+    SDL_free((void *)key);
+}
+
+// Descriptor pool stuff
+
+static SDL_bool VULKAN_INTERNAL_CreateDescriptorPool(
+    VulkanRenderer *renderer,
+    VulkanDescriptorInfo *descriptorInfos,
+    Uint32 descriptorInfoCount,
+    Uint32 descriptorSetPoolSize,
+    VkDescriptorPool *pDescriptorPool)
+{
+    VkDescriptorPoolSize *descriptorPoolSizes;
+    VkDescriptorPoolCreateInfo descriptorPoolInfo;
+    VkResult vulkanResult;
+    Uint32 i;
+
+    descriptorPoolSizes = NULL;
+
+    if (descriptorInfoCount > 0) {
+        descriptorPoolSizes = SDL_stack_alloc(VkDescriptorPoolSize, descriptorInfoCount);
+
+        for (i = 0; i < descriptorInfoCount; i += 1) {
+            descriptorPoolSizes[i].type = descriptorInfos[i].descriptorType;
+            descriptorPoolSizes[i].descriptorCount = descriptorSetPoolSize;
+        }
+    }
+
+    descriptorPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+    descriptorPoolInfo.pNext = NULL;
+    descriptorPoolInfo.flags = 0;
+    descriptorPoolInfo.maxSets = descriptorSetPoolSize;
+    descriptorPoolInfo.poolSizeCount = descriptorInfoCount;
+    descriptorPoolInfo.pPoolSizes = descriptorPoolSizes;
+
+    vulkanResult = renderer->vkCreateDescriptorPool(
+        renderer->logicalDevice,
+        &descriptorPoolInfo,
+        NULL,
+        pDescriptorPool);
+
+    SDL_stack_free(descriptorPoolSizes);
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkCreateDescriptorPool", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    return SDL_TRUE;
+}
+
+static SDL_bool VULKAN_INTERNAL_AllocateDescriptorSets(
+    VulkanRenderer *renderer,
+    VkDescriptorPool descriptorPool,
+    VkDescriptorSetLayout descriptorSetLayout,
+    Uint32 descriptorSetCount,
+    VkDescriptorSet *descriptorSetArray)
+{
+    VkDescriptorSetAllocateInfo descriptorSetAllocateInfo;
+    VkDescriptorSetLayout *descriptorSetLayouts = SDL_stack_alloc(VkDescriptorSetLayout, descriptorSetCount);
+    VkResult vulkanResult;
+    Uint32 i;
+
+    for (i = 0; i < descriptorSetCount; i += 1) {
+        descriptorSetLayouts[i] = descriptorSetLayout;
+    }
+
+    descriptorSetAllocateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+    descriptorSetAllocateInfo.pNext = NULL;
+    descriptorSetAllocateInfo.descriptorPool = descriptorPool;
+    descriptorSetAllocateInfo.descriptorSetCount = descriptorSetCount;
+    descriptorSetAllocateInfo.pSetLayouts = descriptorSetLayouts;
+
+    vulkanResult = renderer->vkAllocateDescriptorSets(
+        renderer->logicalDevice,
+        &descriptorSetAllocateInfo,
+        descriptorSetArray);
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkAllocateDescriptorSets", vulkanResult);
+        SDL_stack_free(descriptorSetLayouts);
+        return SDL_FALSE;
+    }
+
+    SDL_stack_free(descriptorSetLayouts);
+    return SDL_TRUE;
+}
+
+static void VULKAN_INTERNAL_InitializeDescriptorSetPool(
+    VulkanRenderer *renderer,
+    DescriptorSetPool *descriptorSetPool)
+{
+    descriptorSetPool->lock = SDL_CreateMutex();
+
+    // Descriptor set layout and descriptor infos are already set when this function is called
+
+    descriptorSetPool->descriptorPoolCount = 1;
+    descriptorSetPool->descriptorPools = SDL_malloc(sizeof(VkDescriptorPool));
+    descriptorSetPool->nextPoolSize = DESCRIPTOR_POOL_STARTING_SIZE * 2;
+
+    VULKAN_INTERNAL_CreateDescriptorPool(
+        renderer,
+        descriptorSetPool->descriptorInfos,
+        descriptorSetPool->descriptorInfoCount,
+        DESCRIPTOR_POOL_STARTING_SIZE,
+        &descriptorSetPool->descriptorPools[0]);
+
+    descriptorSetPool->inactiveDescriptorSetCapacity = DESCRIPTOR_POOL_STARTING_SIZE;
+    descriptorSetPool->inactiveDescriptorSetCount = DESCRIPTOR_POOL_STARTING_SIZE;
+    descriptorSetPool->inactiveDescriptorSets = SDL_malloc(
+        sizeof(VkDescriptorSet) * DESCRIPTOR_POOL_STARTING_SIZE);
+
+    VULKAN_INTERNAL_AllocateDescriptorSets(
+        renderer,
+        descriptorSetPool->descriptorPools[0],
+        descriptorSetPool->descriptorSetLayout,
+        DESCRIPTOR_POOL_STARTING_SIZE,
+        descriptorSetPool->inactiveDescriptorSets);
+}
+
+static SDL_bool VULKAN_INTERNAL_InitializeGraphicsPipelineResourceLayout(
+    VulkanRenderer *renderer,
+    VulkanShader *vertexShader,
+    VulkanShader *fragmentShader,
+    VulkanGraphicsPipelineResourceLayout *pipelineResourceLayout)
+{
+    VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE + MAX_STORAGE_TEXTURES_PER_STAGE + MAX_STORAGE_BUFFERS_PER_STAGE];
+    VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo;
+    VkDescriptorSetLayout descriptorSetLayouts[4];
+    VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo;
+    DescriptorSetPool *descriptorSetPool;
+    VkResult vulkanResult;
+    Uint32 i;
+
+    pipelineResourceLayout->vertexSamplerCount = vertexShader->samplerCount;
+    pipelineResourceLayout->vertexStorageTextureCount = vertexShader->storageTextureCount;
+    pipelineResourceLayout->vertexStorageBufferCount = vertexShader->storageBufferCount;
+    pipelineResourceLayout->vertexUniformBufferCount = vertexShader->uniformBufferCount;
+
+    pipelineResourceLayout->fragmentSamplerCount = fragmentShader->samplerCount;
+    pipelineResourceLayout->fragmentStorageTextureCount = fragmentShader->storageTextureCount;
+    pipelineResourceLayout->fragmentStorageBufferCount = fragmentShader->storageBufferCount;
+    pipelineResourceLayout->fragmentUniformBufferCount = fragmentShader->uniformBufferCount;
+
+    // Vertex Resources
+
+    descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+    descriptorSetLayoutCreateInfo.pNext = NULL;
+    descriptorSetLayoutCreateInfo.flags = 0;
+    descriptorSetLayoutCreateInfo.pBindings = NULL;
+    descriptorSetLayoutCreateInfo.bindingCount =
+        vertexShader->samplerCount +
+        vertexShader->storageTextureCount +
+        vertexShader->storageBufferCount;
+
+    descriptorSetPool = &pipelineResourceLayout->descriptorSetPools[0];
+
+    descriptorSetPool->descriptorInfoCount = descriptorSetLayoutCreateInfo.bindingCount;
+    descriptorSetPool->descriptorInfos = NULL;
+
+    if (descriptorSetLayoutCreateInfo.bindingCount > 0) {
+        descriptorSetPool->descriptorInfos = SDL_malloc(
+            descriptorSetPool->descriptorInfoCount * sizeof(VulkanDescriptorInfo));
+
+        for (i = 0; i < vertexShader->samplerCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_VERTEX_BIT;
+        }
+
+        for (i = vertexShader->samplerCount; i < vertexShader->samplerCount + vertexShader->storageTextureCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_VERTEX_BIT;
+        }
+
+        for (i = vertexShader->samplerCount + vertexShader->storageTextureCount; i < descriptorSetLayoutCreateInfo.bindingCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_VERTEX_BIT;
+        }
+
+        descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings;
+    }
+
+    vulkanResult = renderer->vkCreateDescriptorSetLayout(
+        renderer->logicalDevice,
+        &descriptorSetLayoutCreateInfo,
+        NULL,
+        &descriptorSetPool->descriptorSetLayout);
+
+    descriptorSetLayouts[0] = descriptorSetPool->descriptorSetLayout;
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkCreateDescriptorSetLayout", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    // Vertex UBOs
+
+    descriptorSetPool = &pipelineResourceLayout->descriptorSetPools[1];
+
+    descriptorSetLayoutCreateInfo.bindingCount = pipelineResourceLayout->vertexUniformBufferCount;
+    descriptorSetLayoutCreateInfo.pBindings = NULL;
+
+    descriptorSetPool->descriptorInfoCount = descriptorSetLayoutCreateInfo.bindingCount;
+    descriptorSetPool->descriptorInfos = NULL;
+
+    if (descriptorSetLayoutCreateInfo.bindingCount > 0) {
+        descriptorSetPool->descriptorInfos = SDL_malloc(
+            descriptorSetPool->descriptorInfoCount * sizeof(VulkanDescriptorInfo));
+
+        for (i = 0; i < vertexShader->uniformBufferCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_VERTEX_BIT;
+        }
+
+        descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings;
+    }
+
+    vulkanResult = renderer->vkCreateDescriptorSetLayout(
+        renderer->logicalDevice,
+        &descriptorSetLayoutCreateInfo,
+        NULL,
+        &descriptorSetPool->descriptorSetLayout);
+
+    descriptorSetLayouts[1] = descriptorSetPool->descriptorSetLayout;
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkCreateDescriptorSetLayout", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    // Fragment resources
+
+    descriptorSetPool = &pipelineResourceLayout->descriptorSetPools[2];
+
+    descriptorSetLayoutCreateInfo.bindingCount =
+        fragmentShader->samplerCount +
+        fragmentShader->storageTextureCount +
+        fragmentShader->storageBufferCount;
+
+    descriptorSetLayoutCreateInfo.pBindings = NULL;
+
+    descriptorSetPool->descriptorInfoCount = descriptorSetLayoutCreateInfo.bindingCount;
+    descriptorSetPool->descriptorInfos = NULL;
+
+    if (descriptorSetLayoutCreateInfo.bindingCount > 0) {
+        descriptorSetPool->descriptorInfos = SDL_malloc(
+            descriptorSetPool->descriptorInfoCount * sizeof(VulkanDescriptorInfo));
+
+        for (i = 0; i < fragmentShader->samplerCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_FRAGMENT_BIT;
+        }
+
+        for (i = fragmentShader->samplerCount; i < fragmentShader->samplerCount + fragmentShader->storageTextureCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_FRAGMENT_BIT;
+        }
+
+        for (i = fragmentShader->samplerCount + fragmentShader->storageTextureCount; i < descriptorSetLayoutCreateInfo.bindingCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_FRAGMENT_BIT;
+        }
+
+        descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings;
+    }
+
+    vulkanResult = renderer->vkCreateDescriptorSetLayout(
+        renderer->logicalDevice,
+        &descriptorSetLayoutCreateInfo,
+        NULL,
+        &descriptorSetPool->descriptorSetLayout);
+
+    descriptorSetLayouts[2] = descriptorSetPool->descriptorSetLayout;
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkCreateDescriptorSetLayout", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    // Fragment UBOs
+
+    descriptorSetPool = &pipelineResourceLayout->descriptorSetPools[3];
+
+    descriptorSetLayoutCreateInfo.bindingCount =
+        pipelineResourceLayout->fragmentUniformBufferCount;
+
+    descriptorSetLayoutCreateInfo.pBindings = NULL;
+
+    descriptorSetPool->descriptorInfoCount = descriptorSetLayoutCreateInfo.bindingCount;
+    descriptorSetPool->descriptorInfos = NULL;
+
+    if (descriptorSetLayoutCreateInfo.bindingCount > 0) {
+        descriptorSetPool->descriptorInfos = SDL_malloc(
+            descriptorSetPool->descriptorInfoCount * sizeof(VulkanDescriptorInfo));
+
+        for (i = 0; i < fragmentShader->uniformBufferCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_FRAGMENT_BIT;
+        }
+
+        descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings;
+    }
+
+    vulkanResult = renderer->vkCreateDescriptorSetLayout(
+        renderer->logicalDevice,
+        &descriptorSetLayoutCreateInfo,
+        NULL,
+        &descriptorSetPool->descriptorSetLayout);
+
+    descriptorSetLayouts[3] = descriptorSetPool->descriptorSetLayout;
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkCreateDescriptorSetLayout", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    // Create the pipeline layout
+
+    pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+    pipelineLayoutCreateInfo.pNext = NULL;
+    pipelineLayoutCreateInfo.flags = 0;
+    pipelineLayoutCreateInfo.setLayoutCount = 4;
+    pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts;
+    pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
+    pipelineLayoutCreateInfo.pPushConstantRanges = NULL;
+
+    vulkanResult = renderer->vkCreatePipelineLayout(
+        renderer->logicalDevice,
+        &pipelineLayoutCreateInfo,
+        NULL,
+        &pipelineResourceLayout->pipelineLayout);
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkCreatePipelineLayout", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    for (i = 0; i < 4; i += 1) {
+        VULKAN_INTERNAL_InitializeDescriptorSetPool(
+            renderer,
+            &pipelineResourceLayout->descriptorSetPools[i]);
+    }
+
+    return SDL_TRUE;
+}
+
+static SDL_bool VULKAN_INTERNAL_InitializeComputePipelineResourceLayout(
+    VulkanRenderer *renderer,
+    SDL_GpuComputePipelineCreateInfo *pipelineCreateInfo,
+    VulkanComputePipelineResourceLayout *pipelineResourceLayout)
+{
+    VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[MAX_UNIFORM_BUFFERS_PER_STAGE];
+    VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo;
+    VkDescriptorSetLayout descriptorSetLayouts[3];
+    VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo;
+    DescriptorSetPool *descriptorSetPool;
+    VkResult vulkanResult;
+    Uint32 i;
+
+    pipelineResourceLayout->readOnlyStorageTextureCount = pipelineCreateInfo->readOnlyStorageTextureCount;
+    pipelineResourceLayout->readOnlyStorageBufferCount = pipelineCreateInfo->readOnlyStorageBufferCount;
+    pipelineResourceLayout->writeOnlyStorageTextureCount = pipelineCreateInfo->writeOnlyStorageTextureCount;
+    pipelineResourceLayout->writeOnlyStorageBufferCount = pipelineCreateInfo->writeOnlyStorageBufferCount;
+    pipelineResourceLayout->uniformBufferCount = pipelineCreateInfo->uniformBufferCount;
+
+    // Read-only resources
+
+    descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+    descriptorSetLayoutCreateInfo.pNext = NULL;
+    descriptorSetLayoutCreateInfo.flags = 0;
+    descriptorSetLayoutCreateInfo.pBindings = NULL;
+    descriptorSetLayoutCreateInfo.bindingCount =
+        pipelineCreateInfo->readOnlyStorageTextureCount +
+        pipelineCreateInfo->readOnlyStorageBufferCount;
+
+    descriptorSetPool = &pipelineResourceLayout->descriptorSetPools[0];
+
+    descriptorSetPool->descriptorInfoCount = descriptorSetLayoutCreateInfo.bindingCount;
+    descriptorSetPool->descriptorInfos = NULL;
+
+    if (descriptorSetLayoutCreateInfo.bindingCount > 0) {
+        descriptorSetPool->descriptorInfos = SDL_malloc(
+            descriptorSetPool->descriptorInfoCount * sizeof(VulkanDescriptorInfo));
+
+        for (i = 0; i < pipelineCreateInfo->readOnlyStorageTextureCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_COMPUTE_BIT;
+        }
+
+        for (i = pipelineCreateInfo->readOnlyStorageTextureCount; i < descriptorSetLayoutCreateInfo.bindingCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_COMPUTE_BIT;
+        }
+
+        descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings;
+    }
+
+    vulkanResult = renderer->vkCreateDescriptorSetLayout(
+        renderer->logicalDevice,
+        &descriptorSetLayoutCreateInfo,
+        NULL,
+        &descriptorSetPool->descriptorSetLayout);
+
+    descriptorSetLayouts[0] = descriptorSetPool->descriptorSetLayout;
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkCreateDescriptorSetLayout", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    // Write-only resources
+
+    descriptorSetLayoutCreateInfo.bindingCount =
+        pipelineCreateInfo->writeOnlyStorageTextureCount +
+        pipelineCreateInfo->writeOnlyStorageBufferCount;
+
+    descriptorSetLayoutCreateInfo.pBindings = NULL;
+
+    descriptorSetPool = &pipelineResourceLayout->descriptorSetPools[1];
+
+    descriptorSetPool->descriptorInfoCount = descriptorSetLayoutCreateInfo.bindingCount;
+    descriptorSetPool->descriptorInfos = NULL;
+
+    if (descriptorSetLayoutCreateInfo.bindingCount > 0) {
+        descriptorSetPool->descriptorInfos = SDL_malloc(
+            descriptorSetPool->descriptorInfoCount * sizeof(VulkanDescriptorInfo));
+
+        for (i = 0; i < pipelineCreateInfo->writeOnlyStorageTextureCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_COMPUTE_BIT;
+        }
+
+        for (i = pipelineCreateInfo->writeOnlyStorageTextureCount; i < descriptorSetLayoutCreateInfo.bindingCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_COMPUTE_BIT;
+        }
+
+        descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings;
+    }
+
+    vulkanResult = renderer->vkCreateDescriptorSetLayout(
+        renderer->logicalDevice,
+        &descriptorSetLayoutCreateInfo,
+        NULL,
+        &descriptorSetPool->descriptorSetLayout);
+
+    descriptorSetLayouts[1] = descriptorSetPool->descriptorSetLayout;
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkCreateDescriptorSetLayout", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    // Uniform buffers
+
+    descriptorSetPool = &pipelineResourceLayout->descriptorSetPools[2];
+
+    descriptorSetLayoutCreateInfo.bindingCount = pipelineCreateInfo->uniformBufferCount;
+    descriptorSetLayoutCreateInfo.pBindings = NULL;
+
+    descriptorSetPool->descriptorInfoCount = descriptorSetLayoutCreateInfo.bindingCount;
+    descriptorSetPool->descriptorInfos = NULL;
+
+    if (descriptorSetLayoutCreateInfo.bindingCount > 0) {
+        descriptorSetPool->descriptorInfos = SDL_malloc(
+            descriptorSetPool->descriptorInfoCount * sizeof(VulkanDescriptorInfo));
+
+        for (i = 0; i < pipelineCreateInfo->uniformBufferCount; i += 1) {
+            descriptorSetLayoutBindings[i].binding = i;
+            descriptorSetLayoutBindings[i].descriptorCount = 1;
+            descriptorSetLayoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+            descriptorSetLayoutBindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
+            descriptorSetLayoutBindings[i].pImmutableSamplers = NULL;
+
+            descriptorSetPool->descriptorInfos[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+            descriptorSetPool->descriptorInfos[i].stageFlag = VK_SHADER_STAGE_COMPUTE_BIT;
+        }
+
+        descriptorSetLayoutCreateInfo.pBindings = descriptorSetLayoutBindings;
+    }
+
+    vulkanResult = renderer->vkCreateDescriptorSetLayout(
+        renderer->logicalDevice,
+        &descriptorSetLayoutCreateInfo,
+        NULL,
+        &descriptorSetPool->descriptorSetLayout);
+
+    descriptorSetLayouts[2] = descriptorSetPool->descriptorSetLayout;
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkCreateDescriptorSetLayout", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    // Create the pipeline layout
+
+    pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+    pipelineLayoutCreateInfo.pNext = NULL;
+    pipelineLayoutCreateInfo.flags = 0;
+    pipelineLayoutCreateInfo.setLayoutCount = 3;
+    pipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayouts;
+    pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
+    pipelineLayoutCreateInfo.pPushConstantRanges = NULL;
+
+    vulkanResult = renderer->vkCreatePipelineLayout(
+        renderer->logicalDevice,
+        &pipelineLayoutCreateInfo,
+        NULL,
+        &pipelineResourceLayout->pipelineLayout);
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkCreatePipelineLayout", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    for (i = 0; i < 3; i += 1) {
+        VULKAN_INTERNAL_InitializeDescriptorSetPool(
+            renderer,
+            &pipelineResourceLayout->descriptorSetPools[i]);
+    }
+
+    return SDL_TRUE;
+}
+
+// Data Buffer
+
+static VulkanBuffer *VULKAN_INTERNAL_CreateBuffer(
+    VulkanRenderer *renderer,
+    VkDeviceSize size,
+    SDL_GpuBufferUsageFlags usageFlags,
+    VulkanBufferType type)
+{
+    VulkanBuffer *buffer;
+    VkResult vulkanResult;
+    VkBufferCreateInfo bufferCreateInfo;
+    VkBufferUsageFlags vulkanUsageFlags = 0;
+    Uint8 bindResult;
+
+    if (usageFlags & SDL_GPU_BUFFERUSAGE_VERTEX_BIT) {
+        vulkanUsageFlags |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+    }
+
+    if (usageFlags & SDL_GPU_BUFFERUSAGE_INDEX_BIT) {
+        vulkanUsageFlags |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
+    }
+
+    if (usageFlags & (SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ_BIT |
+                      SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ_BIT |
+                      SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE_BIT)) {
+        vulkanUsageFlags |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
+    }
+
+    if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT_BIT) {
+        vulkanUsageFlags |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT;
+    }
+
+    if (type == VULKAN_BUFFER_TYPE_UNIFORM) {
+        vulkanUsageFlags |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+    } else {
+        // GPU buffers need transfer bits for defrag, transfer buffers need them for transfers
+        vulkanUsageFlags |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+    }
+
+    buffer = SDL_malloc(sizeof(VulkanBuffer));
+
+    buffer->size = size;
+    buffer->usageFlags = usageFlags;
+    buffer->type = type;
+    buffer->markedForDestroy = 0;
+    buffer->transitioned = SDL_FALSE;
+
+    bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+    bufferCreateInfo.pNext = NULL;
+    bufferCreateInfo.flags = 0;
+    bufferCreateInfo.size = size;
+    bufferCreateInfo.usage = vulkanUsageFlags;
+    bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    bufferCreateInfo.queueFamilyIndexCount = 1;
+    bufferCreateInfo.pQueueFamilyIndices = &renderer->queueFamilyIndex;
+
+    // Set transfer bits so we can defrag
+    bufferCreateInfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+    vulkanResult = renderer->vkCreateBuffer(
+        renderer->logicalDevice,
+        &bufferCreateInfo,
+        NULL,
+        &buffer->buffer);
+    VULKAN_ERROR_CHECK(vulkanResult, vkCreateBuffer, 0)
+
+    bindResult = VULKAN_INTERNAL_BindMemoryForBuffer(
+        renderer,
+        buffer->buffer,
+        buffer->size,
+        buffer->type,
+        &buffer->usedRegion);
+
+    if (bindResult != 1) {
+        renderer->vkDestroyBuffer(
+            renderer->logicalDevice,
+            buffer->buffer,
+            NULL);
+
+        return NULL;
+    }
+
+    buffer->usedRegion->vulkanBuffer = buffer; // lol
+    buffer->handle = NULL;
+
+    SDL_AtomicSet(&buffer->referenceCount, 0);
+
+    return buffer;
+}
+
+// Indirection so we can cleanly defrag buffers
+static VulkanBufferHandle *VULKAN_INTERNAL_CreateBufferHandle(
+    VulkanRenderer *renderer,
+    VkDeviceSize sizeInBytes,
+    SDL_GpuBufferUsageFlags usageFlags,
+    VulkanBufferType type)
+{
+    VulkanBufferHandle *bufferHandle;
+    VulkanBuffer *buffer;
+
+    buffer = VULKAN_INTERNAL_CreateBuffer(
+        renderer,
+        sizeInBytes,
+        usageFlags,
+        type);
+
+    if (buffer == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create buffer!");
+        return NULL;
+    }
+
+    bufferHandle = SDL_malloc(sizeof(VulkanBufferHandle));
+    bufferHandle->vulkanBuffer = buffer;
+    bufferHandle->container = NULL;
+
+    buffer->handle = bufferHandle;
+
+    return bufferHandle;
+}
+
+static VulkanBufferContainer *VULKAN_INTERNAL_CreateBufferContainer(
+    VulkanRenderer *renderer,
+    VkDeviceSize sizeInBytes,
+    SDL_GpuBufferUsageFlags usageFlags,
+    VulkanBufferType type)
+{
+    VulkanBufferContainer *bufferContainer;
+    VulkanBufferHandle *bufferHandle;
+
+    bufferHandle = VULKAN_INTERNAL_CreateBufferHandle(
+        renderer,
+        sizeInBytes,
+        usageFlags,
+        type);
+
+    if (bufferHandle == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create buffer container!");
+        return NULL;
+    }
+
+    bufferContainer = SDL_malloc(sizeof(VulkanBufferContainer));
+
+    bufferContainer->activeBufferHandle = bufferHandle;
+    bufferHandle->container = bufferContainer;
+
+    bufferContainer->bufferCapacity = 1;
+    bufferContainer->bufferCount = 1;
+    bufferContainer->bufferHandles = SDL_malloc(
+        bufferContainer->bufferCapacity * sizeof(VulkanBufferHandle *));
+    bufferContainer->bufferHandles[0] = bufferContainer->activeBufferHandle;
+    bufferContainer->debugName = NULL;
+
+    return bufferContainer;
+}
+
+// Texture Subresource Utilities
+
+static Uint32 VULKAN_INTERNAL_GetTextureSubresourceIndex(
+    Uint32 mipLevel,
+    Uint32 layer,
+    Uint32 numLevels)
+{
+    return mipLevel + (layer * numLevels);
+}
+
+static VulkanTextureSubresource *VULKAN_INTERNAL_FetchTextureSubresource(
+    VulkanTextureContainer *textureContainer,
+    Uint32 layer,
+    Uint32 level)
+{
+    Uint32 index = VULKAN_INTERNAL_GetTextureSubresourceIndex(
+        level,
+        layer,
+        textureContainer->header.info.levelCount);
+
+    return &textureContainer->activeTextureHandle->vulkanTexture->subresources[index];
+}
+
+static void VULKAN_INTERNAL_CreateRenderTargetView(
+    VulkanRenderer *renderer,
+    VulkanTexture *texture,
+    Uint32 layerOrDepth,
+    Uint32 level,
+    VkComponentMapping swizzle,
+    VkImageView *pView)
+{
+    VkResult vulkanResult;
+    VkImageViewCreateInfo imageViewCreateInfo;
+
+    // create framebuffer compatible views for RenderTarget
+    imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+    imageViewCreateInfo.pNext = NULL;
+    imageViewCreateInfo.flags = 0;
+    imageViewCreateInfo.image = texture->image;
+    imageViewCreateInfo.format = texture->format;
+    imageViewCreateInfo.components = swizzle;
+    imageViewCreateInfo.subresourceRange.aspectMask = texture->aspectFlags;
+    imageViewCreateInfo.subresourceRange.baseMipLevel = level;
+    imageViewCreateInfo.subresourceRange.levelCount = 1;
+    imageViewCreateInfo.subresourceRange.baseArrayLayer = layerOrDepth;
+    imageViewCreateInfo.subresourceRange.layerCount = 1;
+    imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+
+    vulkanResult = renderer->vkCreateImageView(
+        renderer->logicalDevice,
+        &imageViewCreateInfo,
+        NULL,
+        pView);
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError(
+            "vkCreateImageView",
+            vulkanResult);
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create color attachment image view");
+        *pView = (VkImageView)VK_NULL_HANDLE;
+        return;
+    }
+}
+
+static void VULKAN_INTERNAL_CreateSubresourceView(
+    VulkanRenderer *renderer,
+    VulkanTexture *texture,
+    Uint32 layer,
+    Uint32 level,
+    VkComponentMapping swizzle,
+    VkImageView *pView)
+{
+    VkResult vulkanResult;
+    VkImageViewCreateInfo imageViewCreateInfo;
+
+    // create framebuffer compatible views for RenderTarget
+    imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+    imageViewCreateInfo.pNext = NULL;
+    imageViewCreateInfo.flags = 0;
+    imageViewCreateInfo.image = texture->image;
+    imageViewCreateInfo.format = texture->format;
+    imageViewCreateInfo.components = swizzle;
+    imageViewCreateInfo.subresourceRange.aspectMask = texture->aspectFlags;
+    imageViewCreateInfo.subresourceRange.baseMipLevel = level;
+    imageViewCreateInfo.subresourceRange.levelCount = 1;
+    imageViewCreateInfo.subresourceRange.baseArrayLayer = layer;
+    imageViewCreateInfo.subresourceRange.layerCount = 1;
+    imageViewCreateInfo.viewType = texture->depth > 1 ? VK_IMAGE_VIEW_TYPE_3D : VK_IMAGE_VIEW_TYPE_2D;
+
+    vulkanResult = renderer->vkCreateImageView(
+        renderer->logicalDevice,
+        &imageViewCreateInfo,
+        NULL,
+        pView);
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError(
+            "vkCreateImageView",
+            vulkanResult);
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create color attachment image view");
+        *pView = (VkImageView)VK_NULL_HANDLE;
+        return;
+    }
+}
+
+// Swapchain
+
+static Uint8 VULKAN_INTERNAL_QuerySwapchainSupport(
+    VulkanRenderer *renderer,
+    VkPhysicalDevice physicalDevice,
+    VkSurfaceKHR surface,
+    SwapchainSupportDetails *outputDetails)
+{
+    VkResult result;
+    VkBool32 supportsPresent;
+
+    renderer->vkGetPhysicalDeviceSurfaceSupportKHR(
+        physicalDevice,
+        renderer->queueFamilyIndex,
+        surface,
+        &supportsPresent);
+
+    // Initialize these in case anything fails
+    outputDetails->formatsLength = 0;
+    outputDetails->presentModesLength = 0;
+
+    if (!supportsPresent) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "This surface does not support presenting!");
+        return 0;
+    }
+
+    // Run the device surface queries
+    result = renderer->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
+        physicalDevice,
+        surface,
+        &outputDetails->capabilities);
+    VULKAN_ERROR_CHECK(result, vkGetPhysicalDeviceSurfaceCapabilitiesKHR, 0)
+
+    if (!(outputDetails->capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Opaque presentation unsupported! Expect weird transparency bugs!");
+    }
+
+    result = renderer->vkGetPhysicalDeviceSurfaceFormatsKHR(
+        physicalDevice,
+        surface,
+        &outputDetails->formatsLength,
+        NULL);
+    VULKAN_ERROR_CHECK(result, vkGetPhysicalDeviceSurfaceFormatsKHR, 0)
+    result = renderer->vkGetPhysicalDeviceSurfacePresentModesKHR(
+        physicalDevice,
+        surface,
+        &outputDetails->presentModesLength,
+        NULL);
+    VULKAN_ERROR_CHECK(result, vkGetPhysicalDeviceSurfacePresentModesKHR, 0)
+
+    // Generate the arrays, if applicable
+
+    outputDetails->formats = NULL;
+    if (outputDetails->formatsLength != 0) {
+        outputDetails->formats = (VkSurfaceFormatKHR *)SDL_malloc(
+            sizeof(VkSurfaceFormatKHR) * outputDetails->formatsLength);
+
+        if (!outputDetails->formats) {
+            return 0;
+        }
+
+        result = renderer->vkGetPhysicalDeviceSurfaceFormatsKHR(
+            physicalDevice,
+            surface,
+            &outputDetails->formatsLength,
+            outputDetails->formats);
+        if (result != VK_SUCCESS) {
+            SDL_LogError(
+                SDL_LOG_CATEGORY_GPU,
+                "vkGetPhysicalDeviceSurfaceFormatsKHR: %s",
+                VkErrorMessages(result));
+
+            SDL_free(outputDetails->formats);
+            return 0;
+        }
+    }
+
+    outputDetails->presentModes = NULL;
+    if (outputDetails->presentModesLength != 0) {
+        outputDetails->presentModes = (VkPresentModeKHR *)SDL_malloc(
+            sizeof(VkPresentModeKHR) * outputDetails->presentModesLength);
+
+        if (!outputDetails->presentModes) {
+            SDL_free(outputDetails->formats);
+            return 0;
+        }
+
+        result = renderer->vkGetPhysicalDeviceSurfacePresentModesKHR(
+            physicalDevice,
+            surface,
+            &outputDetails->presentModesLength,
+            outputDetails->presentModes);
+        if (result != VK_SUCCESS) {
+            SDL_LogError(
+                SDL_LOG_CATEGORY_GPU,
+                "vkGetPhysicalDeviceSurfacePresentModesKHR: %s",
+                VkErrorMessages(result));
+
+            SDL_free(outputDetails->formats);
+            SDL_free(outputDetails->presentModes);
+            return 0;
+        }
+    }
+
+    /* If we made it here, all the queries were successful. This does NOT
+     * necessarily mean there are any supported formats or present modes!
+     */
+    return 1;
+}
+
+static SDL_bool VULKAN_INTERNAL_VerifySwapSurfaceFormat(
+    VkFormat desiredFormat,
+    VkColorSpaceKHR desiredColorSpace,
+    VkSurfaceFormatKHR *availableFormats,
+    Uint32 availableFormatsLength)
+{
+    Uint32 i;
+    for (i = 0; i < availableFormatsLength; i += 1) {
+        if (availableFormats[i].format == desiredFormat &&
+            availableFormats[i].colorSpace == desiredColorSpace) {
+            return SDL_TRUE;
+        }
+    }
+    return SDL_FALSE;
+}
+
+static SDL_bool VULKAN_INTERNAL_VerifySwapPresentMode(
+    VkPresentModeKHR presentMode,
+    VkPresentModeKHR *availablePresentModes,
+    Uint32 availablePresentModesLength)
+{
+    Uint32 i;
+    for (i = 0; i < availablePresentModesLength; i += 1) {
+        if (availablePresentModes[i] == presentMode) {
+            return SDL_TRUE;
+        }
+    }
+    return SDL_FALSE;
+}
+
+static SDL_bool VULKAN_INTERNAL_CreateSwapchain(
+    VulkanRenderer *renderer,
+    WindowData *windowData)
+{
+    VkResult vulkanResult;
+    VulkanSwapchainData *swapchainData;
+    VkSwapchainCreateInfoKHR swapchainCreateInfo;
+    VkImage *swapchainImages;
+    VkSemaphoreCreateInfo semaphoreCreateInfo;
+    SwapchainSupportDetails swapchainSupportDetails;
+    SDL_bool hasValidSwapchainComposition, hasValidPresentMode;
+    Sint32 drawableWidth, drawableHeight;
+    Uint32 i;
+    SDL_VideoDevice *_this = SDL_GetVideoDevice();
+
+    SDL_assert(_this && _this->Vulkan_CreateSurface);
+
+    swapchainData = SDL_malloc(sizeof(VulkanSwapchainData));
+    swapchainData->frameCounter = 0;
+
+    // Each swapchain must have its own surface.
+
+    if (!_this->Vulkan_CreateSurface(
+            _this,
+            windowData->window,
+            renderer->instance,
+            NULL, // FIXME: VAllocationCallbacks
+            &swapchainData->surface)) {
+        SDL_free(swapchainData);
+        SDL_LogError(
+            SDL_LOG_CATEGORY_GPU,
+            "Vulkan_CreateSurface failed: %s",
+            SDL_GetError());
+        return SDL_FALSE;
+    }
+
+    if (!VULKAN_INTERNAL_QuerySwapchainSupport(
+            renderer,
+            renderer->physicalDevice,
+            swapchainData->surface,
+            &swapchainSupportDetails)) {
+        renderer->vkDestroySurfaceKHR(
+            renderer->instance,
+            swapchainData->surface,
+            NULL);
+        if (swapchainSupportDetails.formatsLength > 0) {
+            SDL_free(swapchainSupportDetails.formats);
+        }
+        if (swapchainSupportDetails.presentModesLength > 0) {
+            SDL_free(swapchainSupportDetails.presentModes);
+        }
+        SDL_free(swapchainData);
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Device does not support swap chain creation");
+        return SDL_FALSE;
+    }
+
+    if (swapchainSupportDetails.capabilities.currentExtent.width == 0 ||
+        swapchainSupportDetails.capabilities.currentExtent.height == 0) {
+        // Not an error, just minimize behavior!
+        renderer->vkDestroySurfaceKHR(
+            renderer->instance,
+            swapchainData->surface,
+            NULL);
+        if (swapchainSupportDetails.formatsLength > 0) {
+            SDL_free(swapchainSupportDetails.formats);
+        }
+        if (swapchainSupportDetails.presentModesLength > 0) {
+            SDL_free(swapchainSupportDetails.presentModes);
+        }
+        SDL_free(swapchainData);
+        return SDL_FALSE;
+    }
+
+    // Verify that we can use the requested composition and present mode
+
+    swapchainData->format = SwapchainCompositionToFormat[windowData->swapchainComposition];
+    swapchainData->colorSpace = SwapchainCompositionToColorSpace[windowData->swapchainComposition];
+    swapchainData->swapchainSwizzle = SwapchainCompositionSwizzle[windowData->swapchainComposition];
+    swapchainData->usingFallbackFormat = SDL_FALSE;
+
+    hasValidSwapchainComposition = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
+        swapchainData->format,
+        swapchainData->colorSpace,
+        swapchainSupportDetails.formats,
+        swapchainSupportDetails.formatsLength);
+
+    if (!hasValidSwapchainComposition) {
+        // Let's try again with the fallback format...
+        swapchainData->format = SwapchainCompositionToFallbackFormat[windowData->swapchainComposition];
+        swapchainData->usingFallbackFormat = SDL_TRUE;
+        hasValidSwapchainComposition = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
+            swapchainData->format,
+            swapchainData->colorSpace,
+            swapchainSupportDetails.formats,
+            swapchainSupportDetails.formatsLength);
+    }
+
+    swapchainData->presentMode = SDLToVK_PresentMode[windowData->presentMode];
+    hasValidPresentMode = VULKAN_INTERNAL_VerifySwapPresentMode(
+        swapchainData->presentMode,
+        swapchainSupportDetails.presentModes,
+        swapchainSupportDetails.presentModesLength);
+
+    if (!hasValidSwapchainComposition || !hasValidPresentMode) {
+        renderer->vkDestroySurfaceKHR(
+            renderer->instance,
+            swapchainData->surface,
+            NULL);
+
+        if (swapchainSupportDetails.formatsLength > 0) {
+            SDL_free(swapchainSupportDetails.formats);
+        }
+
+        if (swapchainSupportDetails.presentModesLength > 0) {
+            SDL_free(swapchainSupportDetails.presentModes);
+        }
+
+        SDL_free(swapchainData);
+
+        if (!hasValidSwapchainComposition) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Device does not support requested swapchain composition!");
+        }
+        if (!hasValidPresentMode) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Device does not support requested presentMode!");
+        }
+        return SDL_FALSE;
+    }
+
+    // Sync now to be sure that our swapchain size is correct
+    SDL_SyncWindow(windowData->window);
+    SDL_GetWindowSizeInPixels(
+        windowData->window,
+        &drawableWidth,
+        &drawableHeight);
+
+    if (drawableWidth < (Sint32)swapchainSupportDetails.capabilities.minImageExtent.width ||
+        drawableWidth > (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.width ||
+        drawableHeight < (Sint32)swapchainSupportDetails.capabilities.minImageExtent.height ||
+        drawableHeight > (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.height) {
+        if (swapchainSupportDetails.capabilities.currentExtent.width != UINT32_MAX) {
+            drawableWidth = VULKAN_INTERNAL_clamp(
+                drawableWidth,
+                (Sint32)swapchainSupportDetails.capabilities.minImageExtent.width,
+                (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.width);
+            drawableHeight = VULKAN_INTERNAL_clamp(
+                drawableHeight,
+                (Sint32)swapchainSupportDetails.capabilities.minImageExtent.height,
+                (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.height);
+        } else {
+            renderer->vkDestroySurfaceKHR(
+                renderer->instance,
+                swapchainData->surface,
+                NULL);
+            if (swapchainSupportDetails.formatsLength > 0) {
+                SDL_free(swapchainSupportDetails.formats);
+            }
+            if (swapchainSupportDetails.presentModesLength > 0) {
+                SDL_free(swapchainSupportDetails.presentModes);
+            }
+            SDL_free(swapchainData);
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "No fallback swapchain size available!");
+            return SDL_FALSE;
+        }
+    }
+
+    swapchainData->imageCount = MAX_FRAMES_IN_FLIGHT;
+
+    if (swapchainSupportDetails.capabilities.maxImageCount > 0 &&
+        swapchainData->imageCount > swapchainSupportDetails.capabilities.maxImageCount) {
+        swapchainData->imageCount = swapchainSupportDetails.capabilities.maxImageCount;
+    }
+
+    if (swapchainData->presentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
+        /* Required for proper triple-buffering.
+         * Note that this is below the above maxImageCount check!
+         * If the driver advertises MAILBOX but does not support 3 swap
+         * images, it's not real mailbox support, so let it fail hard.
+         * -flibit
+         */
+        swapchainData->imageCount = SDL_max(swapchainData->imageCount, 3);
+    }
+
+    swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+    swapchainCreateInfo.pNext = NULL;
+    swapchainCreateInfo.flags = 0;
+    swapchainCreateInfo.surface = swapchainData->surface;
+    swapchainCreateInfo.minImageCount = swapchainData->imageCount;
+    swapchainCreateInfo.imageFormat = swapchainData->format;
+    swapchainCreateInfo.imageColorSpace = swapchainData->colorSpace;
+    swapchainCreateInfo.imageExtent.width = drawableWidth;
+    swapchainCreateInfo.imageExtent.height = drawableHeight;
+    swapchainCreateInfo.imageArrayLayers = 1;
+    swapchainCreateInfo.imageUsage =
+        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+        VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+    swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    swapchainCreateInfo.queueFamilyIndexCount = 0;
+    swapchainCreateInfo.pQueueFamilyIndices = NULL;
+    swapchainCreateInfo.preTransform = swapchainSupportDetails.capabilities.currentTransform;
+    swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+    swapchainCreateInfo.presentMode = swapchainData->presentMode;
+    swapchainCreateInfo.clipped = VK_TRUE;
+    swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
+
+    vulkanResult = renderer->vkCreateSwapchainKHR(
+        renderer->logicalDevice,
+        &swapchainCreateInfo,
+        NULL,
+        &swapchainData->swapchain);
+
+    if (swapchainSupportDetails.formatsLength > 0) {
+        SDL_free(swapchainSupportDetails.formats);
+    }
+    if (swapchainSupportDetails.presentModesLength > 0) {
+        SDL_free(swapchainSupportDetails.presentModes);
+    }
+
+    if (vulkanResult != VK_SUCCESS) {
+        renderer->vkDestroySurfaceKHR(
+            renderer->instance,
+            swapchainData->surface,
+            NULL);
+        SDL_free(swapchainData);
+        LogVulkanResultAsError("vkCreateSwapchainKHR", vulkanResult);
+        return SDL_FALSE;
+    }
+
+    renderer->vkGetSwapchainImagesKHR(
+        renderer->logicalDevice,
+        swapchainData->swapchain,
+        &swapchainData->imageCount,
+        NULL);
+
+    swapchainData->textureContainers = SDL_malloc(
+        sizeof(VulkanTextureContainer) * swapchainData->imageCount);
+
+    if (!swapchainData->textureContainers) {
+        renderer->vkDestroySurfaceKHR(
+            renderer->instance,
+            swapchainData->surface,
+            NULL);
+        SDL_free(swapchainData);
+        return SDL_FALSE;
+    }
+
+    swapchainImages = SDL_stack_alloc(VkImage, swapchainData->imageCount);
+
+    renderer->vkGetSwapchainImagesKHR(
+        renderer->logicalDevice,
+        swapchainData->swapchain,
+        &swapchainData->imageCount,
+        swapchainImages);
+
+    for (i = 0; i < swapchainData->imageCount; i += 1) {
+
+        // Initialize dummy container
+        SDL_zero(swapchainData->textureContainers[i]);
+        swapchainData->textureContainers[i].canBeCycled = SDL_FALSE;
+        swapchainData->textureContainers[i].header.info.width = drawableWidth;
+        swapchainData->textureContainers[i].header.info.height = drawableHeight;
+        swapchainData->textureContainers[i].header.info.layerCountOrDepth = 1;
+        swapchainData->textureContainers[i].header.info.format = SwapchainCompositionToSDLFormat(
+            windowData->swapchainComposition,
+            swapchainData->usingFallbackFormat);
+        swapchainData->textureContainers[i].header.info.type = SDL_GPU_TEXTURETYPE_2D;
+        swapchainData->textureContainers[i].header.info.levelCount = 1;
+        swapchainData->textureContainers[i].header.info.sampleCount = SDL_GPU_SAMPLECOUNT_1;
+        swapchainData->textureContainers[i].header.info.usageFlags = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT;
+
+        swapchainData->textureContainers[i].activeTextureHandle = SDL_malloc(sizeof(VulkanTextureHandle));
+
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture = SDL_malloc(sizeof(VulkanTexture));
+
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->image = swapchainImages[i];
+
+        // Swapchain memory is managed by the driver
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->usedRegion = NULL;
+
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->dimensions.width = drawableWidth;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->dimensions.height = drawableHeight;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->format = swapchainData->format;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->swizzle = swapchainData->swapchainSwizzle;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->type = SDL_GPU_TEXTURETYPE_2D;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->depth = 1;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->layerCount = 1;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->levelCount = 1;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->sampleCount = VK_SAMPLE_COUNT_1_BIT;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->usageFlags =
+            SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
+        SDL_AtomicSet(&swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->referenceCount, 0);
+
+        swapchainData->textureContainers[i].activeTextureHandle->container = NULL;
+
+        // Create slice
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresourceCount = 1;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources = SDL_malloc(sizeof(VulkanTextureSubresource));
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources[0].parent = swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources[0].layer = 0;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources[0].level = 0;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources[0].transitioned = SDL_TRUE;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources[0].msaaTexHandle = NULL;
+        swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources[0].renderTargetViews = SDL_malloc(sizeof(VkImageView));
+        VULKAN_INTERNAL_CreateRenderTargetView(
+            renderer,
+            swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture,
+            0,
+            0,
+            swapchainData->swapchainSwizzle,
+            &swapchainData->textureContainers[i].activeTextureHandle->vulkanTexture->subresources[0].renderTargetViews[0]);
+    }
+
+    SDL_stack_free(swapchainImages);
+
+    semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+    semaphoreCreateInfo.pNext = NULL;
+    semaphoreCreateInfo.flags = 0;
+
+    for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+        renderer->vkCreateSemaphore(
+            renderer->logicalDevice,
+            &semaphoreCreateInfo,
+            NULL,
+            &swapchainData->imageAvailableSemaphore[i]);
+
+        renderer->vkCreateSemaphore(
+            renderer->logicalDevice,
+            &semaphoreCreateInfo,
+            NULL,
+            &swapchainData->renderFinishedSemaphore[i]);
+
+        swapchainData->inFlightFences[i] = NULL;
+    }
+
+    windowData->swapchainData = swapchainData;
+    windowData->needsSwapchainRecreate = SDL_FALSE;
+    return SDL_TRUE;
+}
+
+// Command Buffers
+
+static void VULKAN_INTERNAL_BeginCommandBuffer(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer)
+{
+    VkCommandBufferBeginInfo beginInfo;
+    VkResult result;
+
+    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+    beginInfo.pNext = NULL;
+    beginInfo.flags = 0;
+    beginInfo.pInheritanceInfo = NULL;
+    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+
+    result = renderer->vkBeginCommandBuffer(
+        commandBuffer->commandBuffer,
+        &beginInfo);
+
+    if (result != VK_SUCCESS) {
+        LogVulkanResultAsError("vkBeginCommandBuffer", result);
+    }
+}
+
+static void VULKAN_INTERNAL_EndCommandBuffer(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer)
+{
+    VkResult result;
+
+    result = renderer->vkEndCommandBuffer(
+        commandBuffer->commandBuffer);
+
+    if (result != VK_SUCCESS) {
+        LogVulkanResultAsError("vkEndCommandBuffer", result);
+    }
+}
+
+static void VULKAN_DestroyDevice(
+    SDL_GpuDevice *device)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)device->driverData;
+    VulkanMemorySubAllocator *allocator;
+
+    VULKAN_Wait(device->driverData);
+
+    for (Sint32 i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) {
+        VULKAN_UnclaimWindow(device->driverData, renderer->claimedWindows[i]->window);
+    }
+
+    SDL_free(renderer->claimedWindows);
+
+    VULKAN_Wait(device->driverData);
+
+    SDL_free(renderer->submittedCommandBuffers);
+
+    for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
+        VULKAN_INTERNAL_DestroyBuffer(
+            renderer,
+            renderer->uniformBufferPool[i]->bufferHandle->vulkanBuffer);
+        SDL_free(renderer->uniformBufferPool[i]->bufferHandle);
+        SDL_free(renderer->uniformBufferPool[i]);
+    }
+    SDL_free(renderer->uniformBufferPool);
+
+    for (Uint32 i = 0; i < renderer->fencePool.availableFenceCount; i += 1) {
+        renderer->vkDestroyFence(
+            renderer->logicalDevice,
+            renderer->fencePool.availableFences[i]->fence,
+            NULL);
+
+        SDL_free(renderer->fencePool.availableFences[i]);
+    }
+
+    SDL_free(renderer->fencePool.availableFences);
+    SDL_DestroyMutex(renderer->fencePool.lock);
+
+    SDL_DestroyHashTable(renderer->commandPoolHashTable);
+    SDL_DestroyHashTable(renderer->renderPassHashTable);
+    SDL_DestroyHashTable(renderer->framebufferHashTable);
+
+    for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
+        allocator = &renderer->memoryAllocator->subAllocators[i];
+
+        for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
+            for (Sint32 k = allocator->allocations[j]->usedRegionCount - 1; k >= 0; k -= 1) {
+                VULKAN_INTERNAL_RemoveMemoryUsedRegion(
+                    renderer,
+                    allocator->allocations[j]->usedRegions[k]);
+            }
+
+            VULKAN_INTERNAL_DeallocateMemory(
+                renderer,
+                allocator,
+                j);
+        }
+
+        if (renderer->memoryAllocator->subAllocators[i].allocations != NULL) {
+            SDL_free(renderer->memoryAllocator->subAllocators[i].allocations);
+        }
+
+        SDL_free(renderer->memoryAllocator->subAllocators[i].sortedFreeRegions);
+    }
+
+    SDL_free(renderer->memoryAllocator);
+
+    SDL_free(renderer->texturesToDestroy);
+    SDL_free(renderer->buffersToDestroy);
+    SDL_free(renderer->graphicsPipelinesToDestroy);
+    SDL_free(renderer->computePipelinesToDestroy);
+    SDL_free(renderer->shadersToDestroy);
+    SDL_free(renderer->samplersToDestroy);
+    SDL_free(renderer->framebuffersToDestroy);
+
+    SDL_DestroyMutex(renderer->allocatorLock);
+    SDL_DestroyMutex(renderer->disposeLock);
+    SDL_DestroyMutex(renderer->submitLock);
+    SDL_DestroyMutex(renderer->acquireCommandBufferLock);
+    SDL_DestroyMutex(renderer->acquireUniformBufferLock);
+    SDL_DestroyMutex(renderer->renderPassFetchLock);
+    SDL_DestroyMutex(renderer->framebufferFetchLock);
+
+    renderer->vkDestroyDevice(renderer->logicalDevice, NULL);
+    renderer->vkDestroyInstance(renderer->instance, NULL);
+
+    SDL_free(renderer);
+    SDL_free(device);
+    SDL_Vulkan_UnloadLibrary();
+}
+
+static VkDescriptorSet VULKAN_INTERNAL_FetchDescriptorSet(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *vulkanCommandBuffer,
+    DescriptorSetPool *descriptorSetPool)
+{
+    VkDescriptorSet descriptorSet;
+
+    SDL_LockMutex(descriptorSetPool->lock);
+
+    // If no inactive descriptor sets remain, create a new pool and allocate new inactive sets
+
+    if (descriptorSetPool->inactiveDescriptorSetCount == 0) {
+        descriptorSetPool->descriptorPoolCount += 1;
+        descriptorSetPool->descriptorPools = SDL_realloc(
+            descriptorSetPool->descriptorPools,
+            sizeof(VkDescriptorPool) * descriptorSetPool->descriptorPoolCount);
+
+        if (!VULKAN_INTERNAL_CreateDescriptorPool(
+                renderer,
+                descriptorSetPool->descriptorInfos,
+                descriptorSetPool->descriptorInfoCount,
+                descriptorSetPool->nextPoolSize,
+                &descriptorSetPool->descriptorPools[descriptorSetPool->descriptorPoolCount - 1])) {
+            SDL_UnlockMutex(descriptorSetPool->lock);
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create descriptor pool!");
+            return VK_NULL_HANDLE;
+        }
+
+        descriptorSetPool->inactiveDescriptorSetCapacity += descriptorSetPool->nextPoolSize;
+
+        descriptorSetPool->inactiveDescriptorSets = SDL_realloc(
+            descriptorSetPool->inactiveDescriptorSets,
+            sizeof(VkDescriptorSet) * descriptorSetPool->inactiveDescriptorSetCapacity);
+
+        if (!VULKAN_INTERNAL_AllocateDescriptorSets(
+                renderer,
+                descriptorSetPool->descriptorPools[descriptorSetPool->descriptorPoolCount - 1],
+                descriptorSetPool->descriptorSetLayout,
+                descriptorSetPool->nextPoolSize,
+                descriptorSetPool->inactiveDescriptorSets)) {
+            SDL_UnlockMutex(descriptorSetPool->lock);
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to allocate descriptor sets!");
+            return VK_NULL_HANDLE;
+        }
+
+        descriptorSetPool->inactiveDescriptorSetCount = descriptorSetPool->nextPoolSize;
+
+        descriptorSetPool->nextPoolSize *= 2;
+    }
+
+    descriptorSet = descriptorSetPool->inactiveDescriptorSets[descriptorSetPool->inactiveDescriptorSetCount - 1];
+    descriptorSetPool->inactiveDescriptorSetCount -= 1;
+
+    SDL_UnlockMutex(descriptorSetPool->lock);
+
+    if (vulkanCommandBuffer->boundDescriptorSetDataCount == vulkanCommandBuffer->boundDescriptorSetDataCapacity) {
+        vulkanCommandBuffer->boundDescriptorSetDataCapacity *= 2;
+        vulkanCommandBuffer->boundDescriptorSetDatas = SDL_realloc(
+            vulkanCommandBuffer->boundDescriptorSetDatas,
+            vulkanCommandBuffer->boundDescriptorSetDataCapacity * sizeof(DescriptorSetData));
+    }
+
+    vulkanCommandBuffer->boundDescriptorSetDatas[vulkanCommandBuffer->boundDescriptorSetDataCount].descriptorSet = descriptorSet;
+    vulkanCommandBuffer->boundDescriptorSetDatas[vulkanCommandBuffer->boundDescriptorSetDataCount].descriptorSetPool = descriptorSetPool;
+    vulkanCommandBuffer->boundDescriptorSetDataCount += 1;
+
+    return descriptorSet;
+}
+
+static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer)
+{
+    VulkanGraphicsPipelineResourceLayout *resourceLayout;
+    VkWriteDescriptorSet *writeDescriptorSets;
+    VkWriteDescriptorSet *currentWriteDescriptorSet;
+    DescriptorSetPool *descriptorSetPool;
+    VkDescriptorBufferInfo bufferInfos[MAX_STORAGE_BUFFERS_PER_STAGE];
+    VkDescriptorImageInfo imageInfos[MAX_TEXTURE_SAMPLERS_PER_STAGE + MAX_STORAGE_TEXTURES_PER_STAGE];
+    Uint32 dynamicOffsets[MAX_UNIFORM_BUFFERS_PER_STAGE];
+    Uint32 bufferInfoCount = 0;
+    Uint32 imageInfoCount = 0;
+    Uint32 i;
+
+    resourceLayout = &commandBuffer->currentGraphicsPipeline->resourceLayout;
+
+    if (commandBuffer->needNewVertexResourceDescriptorSet) {
+        descriptorSetPool = &resourceLayout->descriptorSetPools[0];
+
+        commandBuffer->vertexResourceDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
+            renderer,
+            commandBuffer,
+            descriptorSetPool);
+
+        writeDescriptorSets = SDL_stack_alloc(
+            VkWriteDescriptorSet,
+            resourceLayout->vertexSamplerCount +
+                resourceLayout->vertexStorageTextureCount +
+                resourceLayout->vertexStorageBufferCount);
+
+        for (i = 0; i < resourceLayout->vertexSamplerCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[i];
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->vertexResourceDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pBufferInfo = NULL;
+
+            imageInfos[imageInfoCount].sampler = commandBuffer->vertexSamplers[i]->sampler;
+            imageInfos[imageInfoCount].imageView = commandBuffer->vertexSamplerTextures[i]->fullView;
+            imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+            currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
+
+            imageInfoCount += 1;
+        }
+
+        for (i = 0; i < resourceLayout->vertexStorageTextureCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[resourceLayout->vertexSamplerCount + i];
+
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = resourceLayout->vertexSamplerCount + i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->vertexResourceDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pBufferInfo = NULL;
+
+            imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
+            imageInfos[imageInfoCount].imageView = commandBuffer->vertexStorageTextures[i]->fullView;
+            imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+
+            currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
+
+            imageInfoCount += 1;
+        }
+
+        for (i = 0; i < resourceLayout->vertexStorageBufferCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[resourceLayout->vertexSamplerCount + resourceLayout->vertexStorageTextureCount + i];
+
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = resourceLayout->vertexSamplerCount + resourceLayout->vertexStorageTextureCount + i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->vertexResourceDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pImageInfo = NULL;
+
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->vertexStorageBuffers[i]->buffer;
+            bufferInfos[bufferInfoCount].offset = 0;
+            bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
+
+            currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
+
+            bufferInfoCount += 1;
+        }
+
+        renderer->vkUpdateDescriptorSets(
+            renderer->logicalDevice,
+            resourceLayout->vertexSamplerCount + resourceLayout->vertexStorageTextureCount + resourceLayout->vertexStorageBufferCount,
+            writeDescriptorSets,
+            0,
+            NULL);
+
+        renderer->vkCmdBindDescriptorSets(
+            commandBuffer->commandBuffer,
+            VK_PIPELINE_BIND_POINT_GRAPHICS,
+            resourceLayout->pipelineLayout,
+            0,
+            1,
+            &commandBuffer->vertexResourceDescriptorSet,
+            0,
+            NULL);
+
+        SDL_stack_free(writeDescriptorSets);
+        bufferInfoCount = 0;
+        imageInfoCount = 0;
+
+        commandBuffer->needNewVertexResourceDescriptorSet = SDL_FALSE;
+    }
+
+    if (commandBuffer->needNewVertexUniformDescriptorSet) {
+        descriptorSetPool = &resourceLayout->descriptorSetPools[1];
+
+        commandBuffer->vertexUniformDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
+            renderer,
+            commandBuffer,
+            descriptorSetPool);
+
+        writeDescriptorSets = SDL_stack_alloc(
+            VkWriteDescriptorSet,
+            resourceLayout->vertexUniformBufferCount);
+
+        for (i = 0; i < resourceLayout->vertexUniformBufferCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[i];
+
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->vertexUniformDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pImageInfo = NULL;
+
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->vertexUniformBuffers[i]->bufferHandle->vulkanBuffer->buffer;
+            bufferInfos[bufferInfoCount].offset = 0;
+            bufferInfos[bufferInfoCount].range = MAX_UBO_SECTION_SIZE;
+
+            currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
+
+            bufferInfoCount += 1;
+        }
+
+        renderer->vkUpdateDescriptorSets(
+            renderer->logicalDevice,
+            resourceLayout->vertexUniformBufferCount,
+            writeDescriptorSets,
+            0,
+            NULL);
+
+        SDL_stack_free(writeDescriptorSets);
+        bufferInfoCount = 0;
+        imageInfoCount = 0;
+
+        commandBuffer->needNewVertexUniformDescriptorSet = SDL_FALSE;
+        commandBuffer->needNewVertexUniformOffsets = SDL_TRUE;
+    }
+
+    if (commandBuffer->needNewVertexUniformOffsets) {
+        for (i = 0; i < resourceLayout->vertexUniformBufferCount; i += 1) {
+            dynamicOffsets[i] = commandBuffer->vertexUniformBuffers[i]->drawOffset;
+        }
+
+        renderer->vkCmdBindDescriptorSets(
+            commandBuffer->commandBuffer,
+            VK_PIPELINE_BIND_POINT_GRAPHICS,
+            resourceLayout->pipelineLayout,
+            1,
+            1,
+            &commandBuffer->vertexUniformDescriptorSet,
+            resourceLayout->vertexUniformBufferCount,
+            dynamicOffsets);
+
+        commandBuffer->needNewVertexUniformOffsets = SDL_FALSE;
+    }
+
+    if (commandBuffer->needNewFragmentResourceDescriptorSet) {
+        descriptorSetPool = &resourceLayout->descriptorSetPools[2];
+
+        commandBuffer->fragmentResourceDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
+            renderer,
+            commandBuffer,
+            descriptorSetPool);
+
+        writeDescriptorSets = SDL_stack_alloc(
+            VkWriteDescriptorSet,
+            resourceLayout->fragmentSamplerCount +
+                resourceLayout->fragmentStorageTextureCount +
+                resourceLayout->fragmentStorageBufferCount);
+
+        for (i = 0; i < resourceLayout->fragmentSamplerCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[i];
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->fragmentResourceDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pBufferInfo = NULL;
+
+            imageInfos[imageInfoCount].sampler = commandBuffer->fragmentSamplers[i]->sampler;
+            imageInfos[imageInfoCount].imageView = commandBuffer->fragmentSamplerTextures[i]->fullView;
+            imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+            currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
+
+            imageInfoCount += 1;
+        }
+
+        for (i = 0; i < resourceLayout->fragmentStorageTextureCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[resourceLayout->fragmentSamplerCount + i];
+
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = resourceLayout->fragmentSamplerCount + i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->fragmentResourceDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pBufferInfo = NULL;
+
+            imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
+            imageInfos[imageInfoCount].imageView = commandBuffer->fragmentStorageTextures[i]->fullView;
+            imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+
+            currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
+
+            imageInfoCount += 1;
+        }
+
+        for (i = 0; i < resourceLayout->fragmentStorageBufferCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[resourceLayout->fragmentSamplerCount + resourceLayout->fragmentStorageTextureCount + i];
+
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = resourceLayout->fragmentSamplerCount + resourceLayout->fragmentStorageTextureCount + i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->fragmentResourceDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pImageInfo = NULL;
+
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->fragmentStorageBuffers[i]->buffer;
+            bufferInfos[bufferInfoCount].offset = 0;
+            bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
+
+            currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
+
+            bufferInfoCount += 1;
+        }
+
+        renderer->vkUpdateDescriptorSets(
+            renderer->logicalDevice,
+            resourceLayout->fragmentSamplerCount + resourceLayout->fragmentStorageTextureCount + resourceLayout->fragmentStorageBufferCount,
+            writeDescriptorSets,
+            0,
+            NULL);
+
+        renderer->vkCmdBindDescriptorSets(
+            commandBuffer->commandBuffer,
+            VK_PIPELINE_BIND_POINT_GRAPHICS,
+            resourceLayout->pipelineLayout,
+            2,
+            1,
+            &commandBuffer->fragmentResourceDescriptorSet,
+            0,
+            NULL);
+
+        SDL_stack_free(writeDescriptorSets);
+        bufferInfoCount = 0;
+        imageInfoCount = 0;
+
+        commandBuffer->needNewFragmentResourceDescriptorSet = SDL_FALSE;
+    }
+
+    if (commandBuffer->needNewFragmentUniformDescriptorSet) {
+        descriptorSetPool = &resourceLayout->descriptorSetPools[3];
+
+        commandBuffer->fragmentUniformDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
+            renderer,
+            commandBuffer,
+            descriptorSetPool);
+
+        writeDescriptorSets = SDL_stack_alloc(
+            VkWriteDescriptorSet,
+            resourceLayout->fragmentUniformBufferCount);
+
+        for (i = 0; i < resourceLayout->fragmentUniformBufferCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[i];
+
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->fragmentUniformDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pImageInfo = NULL;
+
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->fragmentUniformBuffers[i]->bufferHandle->vulkanBuffer->buffer;
+            bufferInfos[bufferInfoCount].offset = 0;
+            bufferInfos[bufferInfoCount].range = MAX_UBO_SECTION_SIZE;
+
+            currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
+
+            bufferInfoCount += 1;
+        }
+
+        renderer->vkUpdateDescriptorSets(
+            renderer->logicalDevice,
+            resourceLayout->fragmentUniformBufferCount,
+            writeDescriptorSets,
+            0,
+            NULL);
+
+        SDL_stack_free(writeDescriptorSets);
+        bufferInfoCount = 0;
+        imageInfoCount = 0;
+
+        commandBuffer->needNewFragmentUniformDescriptorSet = SDL_FALSE;
+        commandBuffer->needNewFragmentUniformOffsets = SDL_TRUE;
+    }
+
+    if (commandBuffer->needNewFragmentUniformOffsets) {
+        for (i = 0; i < resourceLayout->fragmentUniformBufferCount; i += 1) {
+            dynamicOffsets[i] = commandBuffer->fragmentUniformBuffers[i]->drawOffset;
+        }
+
+        renderer->vkCmdBindDescriptorSets(
+            commandBuffer->commandBuffer,
+            VK_PIPELINE_BIND_POINT_GRAPHICS,
+            resourceLayout->pipelineLayout,
+            3,
+            1,
+            &commandBuffer->fragmentUniformDescriptorSet,
+            resourceLayout->fragmentUniformBufferCount,
+            dynamicOffsets);
+
+        commandBuffer->needNewFragmentUniformOffsets = SDL_FALSE;
+    }
+}
+
+static void VULKAN_DrawIndexedPrimitives(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 indexCount,
+    Uint32 instanceCount,
+    Uint32 firstIndex,
+    Sint32 vertexOffset,
+    Uint32 firstInstance)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+
+    VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
+
+    renderer->vkCmdDrawIndexed(
+        vulkanCommandBuffer->commandBuffer,
+        indexCount,
+        instanceCount,
+        firstIndex,
+        vertexOffset,
+        firstInstance);
+}
+
+static void VULKAN_DrawPrimitives(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 vertexCount,
+    Uint32 instanceCount,
+    Uint32 firstVertex,
+    Uint32 firstInstance)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+
+    VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
+
+    renderer->vkCmdDraw(
+        vulkanCommandBuffer->commandBuffer,
+        vertexCount,
+        instanceCount,
+        firstVertex,
+        firstInstance);
+}
+
+static void VULKAN_DrawPrimitivesIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)buffer)->activeBufferHandle->vulkanBuffer;
+    Uint32 i;
+
+    VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
+
+    if (renderer->supportsMultiDrawIndirect) {
+        // Real multi-draw!
+        renderer->vkCmdDrawIndirect(
+            vulkanCommandBuffer->commandBuffer,
+            vulkanBuffer->buffer,
+            offsetInBytes,
+            drawCount,
+            stride);
+    } else {
+        // Fake multi-draw...
+        for (i = 0; i < drawCount; i += 1) {
+            renderer->vkCmdDrawIndirect(
+                vulkanCommandBuffer->commandBuffer,
+                vulkanBuffer->buffer,
+                offsetInBytes + (stride * i),
+                1,
+                stride);
+        }
+    }
+
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
+}
+
+static void VULKAN_DrawIndexedPrimitivesIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes,
+    Uint32 drawCount,
+    Uint32 stride)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)buffer)->activeBufferHandle->vulkanBuffer;
+    Uint32 i;
+
+    VULKAN_INTERNAL_BindGraphicsDescriptorSets(renderer, vulkanCommandBuffer);
+
+    if (renderer->supportsMultiDrawIndirect) {
+        // Real multi-draw!
+        renderer->vkCmdDrawIndexedIndirect(
+            vulkanCommandBuffer->commandBuffer,
+            vulkanBuffer->buffer,
+            offsetInBytes,
+            drawCount,
+            stride);
+    } else {
+        // Fake multi-draw...
+        for (i = 0; i < drawCount; i += 1) {
+            renderer->vkCmdDrawIndexedIndirect(
+                vulkanCommandBuffer->commandBuffer,
+                vulkanBuffer->buffer,
+                offsetInBytes + (stride * i),
+                1,
+                stride);
+        }
+    }
+
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
+}
+
+// Debug Naming
+
+static void VULKAN_INTERNAL_SetBufferName(
+    VulkanRenderer *renderer,
+    VulkanBuffer *buffer,
+    const char *text)
+{
+    VkDebugUtilsObjectNameInfoEXT nameInfo;
+
+    if (renderer->debugMode && renderer->supportsDebugUtils) {
+        nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+        nameInfo.pNext = NULL;
+        nameInfo.pObjectName = text;
+        nameInfo.objectType = VK_OBJECT_TYPE_BUFFER;
+        nameInfo.objectHandle = (uint64_t)buffer->buffer;
+
+        renderer->vkSetDebugUtilsObjectNameEXT(
+            renderer->logicalDevice,
+            &nameInfo);
+    }
+}
+
+static void VULKAN_SetBufferName(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBuffer *buffer,
+    const char *text)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanBufferContainer *container = (VulkanBufferContainer *)buffer;
+    size_t textLength = SDL_strlen(text) + 1;
+
+    if (renderer->debugMode && renderer->supportsDebugUtils) {
+        container->debugName = SDL_realloc(
+            container->debugName,
+            textLength);
+
+        SDL_utf8strlcpy(
+            container->debugName,
+            text,
+            textLength);
+
+        for (Uint32 i = 0; i < container->bufferCount; i += 1) {
+            VULKAN_INTERNAL_SetBufferName(
+                renderer,
+                container->bufferHandles[i]->vulkanBuffer,
+                text);
+        }
+    }
+}
+
+static void VULKAN_INTERNAL_SetTextureName(
+    VulkanRenderer *renderer,
+    VulkanTexture *texture,
+    const char *text)
+{
+    VkDebugUtilsObjectNameInfoEXT nameInfo;
+
+    if (renderer->debugMode && renderer->supportsDebugUtils) {
+        nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+        nameInfo.pNext = NULL;
+        nameInfo.pObjectName = text;
+        nameInfo.objectType = VK_OBJECT_TYPE_IMAGE;
+        nameInfo.objectHandle = (uint64_t)texture->image;
+
+        renderer->vkSetDebugUtilsObjectNameEXT(
+            renderer->logicalDevice,
+            &nameInfo);
+    }
+}
+
+static void VULKAN_SetTextureName(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTexture *texture,
+    const char *text)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanTextureContainer *container = (VulkanTextureContainer *)texture;
+    size_t textLength = SDL_strlen(text) + 1;
+
+    if (renderer->debugMode && renderer->supportsDebugUtils) {
+        container->debugName = SDL_realloc(
+            container->debugName,
+            textLength);
+
+        SDL_utf8strlcpy(
+            container->debugName,
+            text,
+            textLength);
+
+        for (Uint32 i = 0; i < container->textureCount; i += 1) {
+            VULKAN_INTERNAL_SetTextureName(
+                renderer,
+                container->textureHandles[i]->vulkanTexture,
+                text);
+        }
+    }
+}
+
+static void VULKAN_InsertDebugLabel(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *text)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VkDebugUtilsLabelEXT labelInfo;
+
+    if (renderer->supportsDebugUtils) {
+        labelInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+        labelInfo.pNext = NULL;
+        labelInfo.pLabelName = text;
+
+        renderer->vkCmdInsertDebugUtilsLabelEXT(
+            vulkanCommandBuffer->commandBuffer,
+            &labelInfo);
+    }
+}
+
+static void VULKAN_PushDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer,
+    const char *name)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VkDebugUtilsLabelEXT labelInfo;
+
+    if (renderer->supportsDebugUtils) {
+        labelInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+        labelInfo.pNext = NULL;
+        labelInfo.pLabelName = name;
+
+        renderer->vkCmdBeginDebugUtilsLabelEXT(
+            vulkanCommandBuffer->commandBuffer,
+            &labelInfo);
+    }
+}
+
+static void VULKAN_PopDebugGroup(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+
+    if (renderer->supportsDebugUtils) {
+        renderer->vkCmdEndDebugUtilsLabelEXT(vulkanCommandBuffer->commandBuffer);
+    }
+}
+
+static VulkanTextureHandle *VULKAN_INTERNAL_CreateTextureHandle(
+    VulkanRenderer *renderer,
+    Uint32 width,
+    Uint32 height,
+    Uint32 depth,
+    SDL_GpuTextureType type,
+    Uint32 layerCount,
+    Uint32 levelCount,
+    VkSampleCountFlagBits sampleCount,
+    VkFormat format,
+    VkComponentMapping swizzle,
+    VkImageAspectFlags aspectMask,
+    SDL_GpuTextureUsageFlags textureUsageFlags,
+    SDL_bool isMSAAColorTarget)
+{
+    VulkanTextureHandle *textureHandle;
+    VulkanTexture *texture;
+
+    texture = VULKAN_INTERNAL_CreateTexture(
+        renderer,
+        width,
+        height,
+        depth,
+        type,
+        layerCount,
+        levelCount,
+        sampleCount,
+        format,
+        swizzle,
+        aspectMask,
+        textureUsageFlags,
+        isMSAAColorTarget);
+
+    if (texture == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create texture!");
+        return NULL;
+    }
+
+    textureHandle = SDL_malloc(sizeof(VulkanTextureHandle));
+    textureHandle->vulkanTexture = texture;
+    textureHandle->container = NULL;
+
+    texture->handle = textureHandle;
+
+    return textureHandle;
+}
+
+static VulkanTexture *VULKAN_INTERNAL_CreateTexture(
+    VulkanRenderer *renderer,
+    Uint32 width,
+    Uint32 height,
+    Uint32 depth,
+    SDL_GpuTextureType type,
+    Uint32 layerCount,
+    Uint32 levelCount,
+    VkSampleCountFlagBits sampleCount,
+    VkFormat format,
+    VkComponentMapping swizzle,
+    VkImageAspectFlags aspectMask,
+    SDL_GpuTextureUsageFlags textureUsageFlags,
+    SDL_bool isMSAAColorTarget)
+{
+    VkResult vulkanResult;
+    VkImageCreateInfo imageCreateInfo;
+    VkImageCreateFlags imageCreateFlags = 0;
+    VkImageViewCreateInfo imageViewCreateInfo;
+    Uint8 bindResult;
+    Uint8 isRenderTarget =
+        ((textureUsageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) != 0) ||
+        ((textureUsageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) != 0);
+    VkImageUsageFlags vkUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+    VulkanTexture *texture = SDL_malloc(sizeof(VulkanTexture));
+
+    texture->type = type;
+    texture->isMSAAColorTarget = isMSAAColorTarget;
+    texture->markedForDestroy = 0;
+
+    if (type == SDL_GPU_TEXTURETYPE_CUBE) {
+        imageCreateFlags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+    } else if (type == SDL_GPU_TEXTURETYPE_3D) {
+        imageCreateFlags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
+    }
+
+    if (textureUsageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) {
+        vkUsageFlags |= VK_IMAGE_USAGE_SAMPLED_BIT;
+    }
+    if (textureUsageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) {
+        vkUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+    }
+    if (textureUsageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) {
+        vkUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+    }
+    if (textureUsageFlags & (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT |
+                             SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT |
+                             SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT)) {
+        vkUsageFlags |= VK_IMAGE_USAGE_STORAGE_BIT;
+    }
+
+    imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+    imageCreateInfo.pNext = NULL;
+    imageCreateInfo.flags = imageCreateFlags;
+    imageCreateInfo.imageType = type == SDL_GPU_TEXTURETYPE_3D ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D;
+    imageCreateInfo.format = format;
+    imageCreateInfo.extent.width = width;
+    imageCreateInfo.extent.height = height;
+    imageCreateInfo.extent.depth = depth;
+    imageCreateInfo.mipLevels = levelCount;
+    imageCreateInfo.arrayLayers = layerCount;
+    imageCreateInfo.samples = isMSAAColorTarget || VULKAN_INTERNAL_IsVulkanDepthFormat(format) ? sampleCount : VK_SAMPLE_COUNT_1_BIT;
+    imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+    imageCreateInfo.usage = vkUsageFlags;
+    imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+    imageCreateInfo.queueFamilyIndexCount = 0;
+    imageCreateInfo.pQueueFamilyIndices = NULL;
+    imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+
+    vulkanResult = renderer->vkCreateImage(
+        renderer->logicalDevice,
+        &imageCreateInfo,
+        NULL,
+        &texture->image);
+    VULKAN_ERROR_CHECK(vulkanResult, vkCreateImage, 0)
+
+    bindResult = VULKAN_INTERNAL_BindMemoryForImage(
+        renderer,
+        texture->image,
+        &texture->usedRegion);
+
+    if (bindResult != 1) {
+        renderer->vkDestroyImage(
+            renderer->logicalDevice,
+            texture->image,
+            NULL);
+
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unable to bind memory for texture!");
+        return NULL;
+    }
+
+    texture->usedRegion->vulkanTexture = texture; // lol
+
+    texture->fullView = VK_NULL_HANDLE;
+
+    if (
+        (textureUsageFlags & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) ||
+        (textureUsageFlags & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT) ||
+        (textureUsageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT)) {
+
+        imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+        imageViewCreateInfo.pNext = NULL;
+        imageViewCreateInfo.flags = 0;
+        imageViewCreateInfo.image = texture->image;
+        imageViewCreateInfo.format = format;
+        imageViewCreateInfo.components = swizzle;
+        imageViewCreateInfo.subresourceRange.aspectMask = aspectMask;
+        imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
+        imageViewCreateInfo.subresourceRange.levelCount = levelCount;
+        imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
+        imageViewCreateInfo.subresourceRange.layerCount = layerCount;
+
+        if (type == SDL_GPU_TEXTURETYPE_CUBE) {
+            imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_CUBE;
+        } else if (type == SDL_GPU_TEXTURETYPE_3D) {
+            imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
+        } else if (type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
+            imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
+        } else {
+            imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+        }
+
+        vulkanResult = renderer->vkCreateImageView(
+            renderer->logicalDevice,
+            &imageViewCreateInfo,
+            NULL,
+            &texture->fullView);
+
+        if (vulkanResult != VK_SUCCESS) {
+            LogVulkanResultAsError("vkCreateImageView", vulkanResult);
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create texture image view");
+            return NULL;
+        }
+    }
+
+    texture->dimensions.width = width;
+    texture->dimensions.height = height;
+    texture->depth = depth;
+    texture->format = format;
+    texture->swizzle = swizzle;
+    texture->levelCount = levelCount;
+    texture->layerCount = layerCount;
+    texture->sampleCount = sampleCount;
+    texture->usageFlags = textureUsageFlags;
+    texture->aspectFlags = aspectMask;
+    SDL_AtomicSet(&texture->referenceCount, 0);
+
+    // Define slices
+    texture->subresourceCount =
+        texture->layerCount *
+        texture->levelCount;
+
+    texture->subresources = SDL_malloc(
+        texture->subresourceCount * sizeof(VulkanTextureSubresource));
+
+    for (Uint32 i = 0; i < texture->layerCount; i += 1) {
+        for (Uint32 j = 0; j < texture->levelCount; j += 1) {
+            Uint32 subresourceIndex = VULKAN_INTERNAL_GetTextureSubresourceIndex(
+                j,
+                i,
+                texture->levelCount);
+
+            texture->subresources[subresourceIndex].renderTargetViews = NULL;
+            texture->subresources[subresourceIndex].computeWriteView = VK_NULL_HANDLE;
+            texture->subresources[subresourceIndex].depthStencilView = VK_NULL_HANDLE;
+
+            if (textureUsageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) {
+                texture->subresources[subresourceIndex].renderTargetViews = SDL_malloc(
+                    texture->depth * sizeof(VkImageView));
+
+                if (texture->depth > 1) {
+                    for (Uint32 k = 0; k < texture->depth; k += 1) {
+                        VULKAN_INTERNAL_CreateRenderTargetView(
+                            renderer,
+                            texture,
+                            k,
+                            j,
+                            swizzle,
+                            &texture->subresources[subresourceIndex].renderTargetViews[k]);
+                    }
+                } else {
+                    VULKAN_INTERNAL_CreateRenderTargetView(
+                        renderer,
+                        texture,
+                        i,
+                        j,
+                        swizzle,
+                        &texture->subresources[subresourceIndex].renderTargetViews[0]);
+                }
+            }
+
+            if (textureUsageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT) {
+                VULKAN_INTERNAL_CreateSubresourceView(
+                    renderer,
+                    texture,
+                    i,
+                    j,
+                    swizzle,
+                    &texture->subresources[subresourceIndex].computeWriteView);
+            }
+
+            if (textureUsageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) {
+                VULKAN_INTERNAL_CreateSubresourceView(
+                    renderer,
+                    texture,
+                    i,
+                    j,
+                    swizzle,
+                    &texture->subresources[subresourceIndex].depthStencilView);
+            }
+
+            texture->subresources[subresourceIndex].parent = texture;
+            texture->subresources[subresourceIndex].layer = i;
+            texture->subresources[subresourceIndex].level = j;
+            texture->subresources[subresourceIndex].msaaTexHandle = NULL;
+            texture->subresources[subresourceIndex].transitioned = SDL_FALSE;
+
+            if (
+                sampleCount > VK_SAMPLE_COUNT_1_BIT &&
+                isRenderTarget &&
+                !isMSAAColorTarget &&
+                !VULKAN_INTERNAL_IsVulkanDepthFormat(texture->format)) {
+                texture->subresources[subresourceIndex].msaaTexHandle = VULKAN_INTERNAL_CreateTextureHandle(
+                    renderer,
+                    texture->dimensions.width >> j,
+                    texture->dimensions.height >> j,
+                    1,
+                    0,
+                    1,
+                    1,
+                    sampleCount,
+                    texture->format,
+                    texture->swizzle,
+                    aspectMask,
+                    SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT,
+                    SDL_TRUE);
+            }
+        }
+    }
+
+    return texture;
+}
+
+static void VULKAN_INTERNAL_CycleActiveBuffer(
+    VulkanRenderer *renderer,
+    VulkanBufferContainer *bufferContainer)
+{
+    VulkanBufferHandle *bufferHandle;
+    Uint32 i;
+
+    // If a previously-cycled buffer is available, we can use that.
+    for (i = 0; i < bufferContainer->bufferCount; i += 1) {
+        bufferHandle = bufferContainer->bufferHandles[i];
+        if (SDL_AtomicGet(&bufferHandle->vulkanBuffer->referenceCount) == 0) {
+            bufferContainer->activeBufferHandle = bufferHandle;
+            return;
+        }
+    }
+
+    // No buffer handle is available, generate a new one.
+    bufferContainer->activeBufferHandle = VULKAN_INTERNAL_CreateBufferHandle(
+        renderer,
+        bufferContainer->activeBufferHandle->vulkanBuffer->size,
+        bufferContainer->activeBufferHandle->vulkanBuffer->usageFlags,
+        bufferContainer->activeBufferHandle->vulkanBuffer->type);
+
+    bufferContainer->activeBufferHandle->container = bufferContainer;
+
+    EXPAND_ARRAY_IF_NEEDED(
+        bufferContainer->bufferHandles,
+        VulkanBufferHandle *,
+        bufferContainer->bufferCount + 1,
+        bufferContainer->bufferCapacity,
+        bufferContainer->bufferCapacity * 2);
+
+    bufferContainer->bufferHandles[bufferContainer->bufferCount] = bufferContainer->activeBufferHandle;
+    bufferContainer->bufferCount += 1;
+
+    if (
+        renderer->debugMode &&
+        renderer->supportsDebugUtils &&
+        bufferContainer->debugName != NULL) {
+        VULKAN_INTERNAL_SetBufferName(
+            renderer,
+            bufferContainer->activeBufferHandle->vulkanBuffer,
+            bufferContainer->debugName);
+    }
+}
+
+static void VULKAN_INTERNAL_CycleActiveTexture(
+    VulkanRenderer *renderer,
+    VulkanTextureContainer *textureContainer)
+{
+    // If a previously-cycled texture is available, we can use that.
+    for (Uint32 i = 0; i < textureContainer->textureCount; i += 1) {
+        VulkanTextureHandle *textureHandle = textureContainer->textureHandles[i];
+
+        if (SDL_AtomicGet(&textureHandle->vulkanTexture->referenceCount) == 0) {
+            textureContainer->activeTextureHandle = textureHandle;
+            return;
+        }
+    }
+
+    // No texture handle is available, generate a new one.
+    textureContainer->activeTextureHandle = VULKAN_INTERNAL_CreateTextureHandle(
+        renderer,
+        textureContainer->activeTextureHandle->vulkanTexture->dimensions.width,
+        textureContainer->activeTextureHandle->vulkanTexture->dimensions.height,
+        textureContainer->activeTextureHandle->vulkanTexture->depth,
+        textureContainer->activeTextureHandle->vulkanTexture->type,
+        textureContainer->activeTextureHandle->vulkanTexture->layerCount,
+        textureContainer->activeTextureHandle->vulkanTexture->levelCount,
+        textureContainer->activeTextureHandle->vulkanTexture->sampleCount,
+        textureContainer->activeTextureHandle->vulkanTexture->format,
+        textureContainer->activeTextureHandle->vulkanTexture->swizzle,
+        textureContainer->activeTextureHandle->vulkanTexture->aspectFlags,
+        textureContainer->activeTextureHandle->vulkanTexture->usageFlags,
+        SDL_FALSE);
+
+    textureContainer->activeTextureHandle->container = textureContainer;
+
+    EXPAND_ARRAY_IF_NEEDED(
+        textureContainer->textureHandles,
+        VulkanTextureHandle *,
+        textureContainer->textureCount + 1,
+        textureContainer->textureCapacity,
+        textureContainer->textureCapacity * 2);
+
+    textureContainer->textureHandles[textureContainer->textureCount] = textureContainer->activeTextureHandle;
+    textureContainer->textureCount += 1;
+
+    if (
+        renderer->debugMode &&
+        renderer->supportsDebugUtils &&
+        textureContainer->debugName != NULL) {
+        VULKAN_INTERNAL_SetTextureName(
+            renderer,
+            textureContainer->activeTextureHandle->vulkanTexture,
+            textureContainer->debugName);
+    }
+}
+
+static VulkanBuffer *VULKAN_INTERNAL_PrepareBufferForWrite(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanBufferContainer *bufferContainer,
+    SDL_bool cycle,
+    VulkanBufferUsageMode destinationUsageMode)
+{
+    if (
+        cycle &&
+        SDL_AtomicGet(&bufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) {
+        VULKAN_INTERNAL_CycleActiveBuffer(
+            renderer,
+            bufferContainer);
+    }
+
+    VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
+        renderer,
+        commandBuffer,
+        destinationUsageMode,
+        bufferContainer->activeBufferHandle->vulkanBuffer);
+
+    return bufferContainer->activeBufferHandle->vulkanBuffer;
+}
+
+static VulkanTextureSubresource *VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    VulkanTextureContainer *textureContainer,
+    Uint32 layer,
+    Uint32 level,
+    SDL_bool cycle,
+    VulkanTextureUsageMode destinationUsageMode)
+{
+    VulkanTextureSubresource *textureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
+        textureContainer,
+        layer,
+        level);
+
+    if (
+        cycle &&
+        textureContainer->canBeCycled &&
+        SDL_AtomicGet(&textureContainer->activeTextureHandle->vulkanTexture->referenceCount) > 0) {
+        VULKAN_INTERNAL_CycleActiveTexture(
+            renderer,
+            textureContainer);
+
+        textureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
+            textureContainer,
+            layer,
+            level);
+    }
+
+    // always do barrier because of layout transitions
+    VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+        renderer,
+        commandBuffer,
+        destinationUsageMode,
+        textureSubresource);
+
+    return textureSubresource;
+}
+
+static VkRenderPass VULKAN_INTERNAL_CreateRenderPass(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    SDL_GpuColorAttachmentInfo *colorAttachmentInfos,
+    Uint32 colorAttachmentCount,
+    SDL_GpuDepthStencilAttachmentInfo *depthStencilAttachmentInfo)
+{
+    VkResult vulkanResult;
+    VkAttachmentDescription attachmentDescriptions[2 * MAX_COLOR_TARGET_BINDINGS + 1];
+    VkAttachmentReference colorAttachmentReferences[MAX_COLOR_TARGET_BINDINGS];
+    VkAttachmentReference resolveReferences[MAX_COLOR_TARGET_BINDINGS + 1];
+    VkAttachmentReference depthStencilAttachmentReference;
+    VkRenderPassCreateInfo renderPassCreateInfo;
+    VkSubpassDescription subpass;
+    VkRenderPass renderPass;
+    Uint32 i;
+
+    Uint32 attachmentDescriptionCount = 0;
+    Uint32 colorAttachmentReferenceCount = 0;
+    Uint32 resolveReferenceCount = 0;
+
+    VulkanTexture *texture = NULL;
+
+    for (i = 0; i < colorAttachmentCount; i += 1) {
+        texture = ((VulkanTextureContainer *)colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture;
+
+        if (texture->sampleCount > VK_SAMPLE_COUNT_1_BIT) {
+            // Resolve attachment and multisample attachment
+
+            attachmentDescriptions[attachmentDescriptionCount].flags = 0;
+            attachmentDescriptions[attachmentDescriptionCount].format = texture->format;
+            attachmentDescriptions[attachmentDescriptionCount].samples =
+                VK_SAMPLE_COUNT_1_BIT;
+            attachmentDescriptions[attachmentDescriptionCount].loadOp = SDLToVK_LoadOp[colorAttachmentInfos[i].loadOp];
+            attachmentDescriptions[attachmentDescriptionCount].storeOp =
+                VK_ATTACHMENT_STORE_OP_STORE; // Always store the resolve texture
+            attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp =
+                VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp =
+                VK_ATTACHMENT_STORE_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].initialLayout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+            attachmentDescriptions[attachmentDescriptionCount].finalLayout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            resolveReferences[resolveReferenceCount].attachment =
+                attachmentDescriptionCount;
+            resolveReferences[resolveReferenceCount].layout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            attachmentDescriptionCount += 1;
+            resolveReferenceCount += 1;
+
+            attachmentDescriptions[attachmentDescriptionCount].flags = 0;
+            attachmentDescriptions[attachmentDescriptionCount].format = texture->format;
+            attachmentDescriptions[attachmentDescriptionCount].samples = texture->sampleCount;
+            attachmentDescriptions[attachmentDescriptionCount].loadOp = SDLToVK_LoadOp[colorAttachmentInfos[i].loadOp];
+            attachmentDescriptions[attachmentDescriptionCount].storeOp = SDLToVK_StoreOp[colorAttachmentInfos[i].storeOp];
+            attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp =
+                VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp =
+                VK_ATTACHMENT_STORE_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].initialLayout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+            attachmentDescriptions[attachmentDescriptionCount].finalLayout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            colorAttachmentReferences[colorAttachmentReferenceCount].attachment =
+                attachmentDescriptionCount;
+            colorAttachmentReferences[colorAttachmentReferenceCount].layout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            attachmentDescriptionCount += 1;
+            colorAttachmentReferenceCount += 1;
+        } else {
+            attachmentDescriptions[attachmentDescriptionCount].flags = 0;
+            attachmentDescriptions[attachmentDescriptionCount].format = texture->format;
+            attachmentDescriptions[attachmentDescriptionCount].samples =
+                VK_SAMPLE_COUNT_1_BIT;
+            attachmentDescriptions[attachmentDescriptionCount].loadOp = SDLToVK_LoadOp[colorAttachmentInfos[i].loadOp];
+            attachmentDescriptions[attachmentDescriptionCount].storeOp =
+                VK_ATTACHMENT_STORE_OP_STORE; // Always store non-MSAA textures
+            attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp =
+                VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp =
+                VK_ATTACHMENT_STORE_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].initialLayout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+            attachmentDescriptions[attachmentDescriptionCount].finalLayout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            colorAttachmentReferences[colorAttachmentReferenceCount].attachment = attachmentDescriptionCount;
+            colorAttachmentReferences[colorAttachmentReferenceCount].layout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            attachmentDescriptionCount += 1;
+            colorAttachmentReferenceCount += 1;
+        }
+    }
+
+    subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+    subpass.flags = 0;
+    subpass.inputAttachmentCount = 0;
+    subpass.pInputAttachments = NULL;
+    subpass.colorAttachmentCount = colorAttachmentCount;
+    subpass.pColorAttachments = colorAttachmentReferences;
+    subpass.preserveAttachmentCount = 0;
+    subpass.pPreserveAttachments = NULL;
+
+    if (depthStencilAttachmentInfo == NULL) {
+        subpass.pDepthStencilAttachment = NULL;
+    } else {
+        texture = ((VulkanTextureContainer *)depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture;
+
+        attachmentDescriptions[attachmentDescriptionCount].flags = 0;
+        attachmentDescriptions[attachmentDescriptionCount].format = texture->format;
+        attachmentDescriptions[attachmentDescriptionCount].samples = texture->sampleCount;
+
+        attachmentDescriptions[attachmentDescriptionCount].loadOp = SDLToVK_LoadOp[depthStencilAttachmentInfo->loadOp];
+        attachmentDescriptions[attachmentDescriptionCount].storeOp = SDLToVK_StoreOp[depthStencilAttachmentInfo->storeOp];
+        attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = SDLToVK_LoadOp[depthStencilAttachmentInfo->stencilLoadOp];
+        attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = SDLToVK_StoreOp[depthStencilAttachmentInfo->stencilStoreOp];
+        attachmentDescriptions[attachmentDescriptionCount].initialLayout =
+            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+        attachmentDescriptions[attachmentDescriptionCount].finalLayout =
+            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+        depthStencilAttachmentReference.attachment =
+            attachmentDescriptionCount;
+        depthStencilAttachmentReference.layout =
+            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+        subpass.pDepthStencilAttachment =
+            &depthStencilAttachmentReference;
+
+        attachmentDescriptionCount += 1;
+    }
+
+    if (texture != NULL && texture->sampleCount > VK_SAMPLE_COUNT_1_BIT) {
+        subpass.pResolveAttachments = resolveReferences;
+    } else {
+        subpass.pResolveAttachments = NULL;
+    }
+
+    renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+    renderPassCreateInfo.pNext = NULL;
+    renderPassCreateInfo.flags = 0;
+    renderPassCreateInfo.pAttachments = attachmentDescriptions;
+    renderPassCreateInfo.attachmentCount = attachmentDescriptionCount;
+    renderPassCreateInfo.subpassCount = 1;
+    renderPassCreateInfo.pSubpasses = &subpass;
+    renderPassCreateInfo.dependencyCount = 0;
+    renderPassCreateInfo.pDependencies = NULL;
+
+    vulkanResult = renderer->vkCreateRenderPass(
+        renderer->logicalDevice,
+        &renderPassCreateInfo,
+        NULL,
+        &renderPass);
+
+    if (vulkanResult != VK_SUCCESS) {
+        renderPass = VK_NULL_HANDLE;
+        LogVulkanResultAsError("vkCreateRenderPass", vulkanResult);
+    }
+
+    return renderPass;
+}
+
+static VkRenderPass VULKAN_INTERNAL_CreateTransientRenderPass(
+    VulkanRenderer *renderer,
+    SDL_GpuGraphicsPipelineAttachmentInfo attachmentInfo,
+    VkSampleCountFlagBits sampleCount)
+{
+    VkAttachmentDescription attachmentDescriptions[2 * MAX_COLOR_TARGET_BINDINGS + 1];
+    VkAttachmentReference colorAttachmentReferences[MAX_COLOR_TARGET_BINDINGS];
+    VkAttachmentReference resolveReferences[MAX_COLOR_TARGET_BINDINGS + 1];
+    VkAttachmentReference depthStencilAttachmentReference;
+    SDL_GpuColorAttachmentDescription attachmentDescription;
+    VkSubpassDescription subpass;
+    VkRenderPassCreateInfo renderPassCreateInfo;
+    VkRenderPass renderPass;
+    VkResult result;
+
+    Uint32 multisampling = 0;
+    Uint32 attachmentDescriptionCount = 0;
+    Uint32 colorAttachmentReferenceCount = 0;
+    Uint32 resolveReferenceCount = 0;
+    Uint32 i;
+
+    for (i = 0; i < attachmentInfo.colorAttachmentCount; i += 1) {
+        attachmentDescription = attachmentInfo.colorAttachmentDescriptions[i];
+
+        if (sampleCount > VK_SAMPLE_COUNT_1_BIT) {
+            multisampling = 1;
+
+            // Resolve attachment and multisample attachment
+
+            attachmentDescriptions[attachmentDescriptionCount].flags = 0;
+            attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_SurfaceFormat[attachmentDescription.format];
+            attachmentDescriptions[attachmentDescriptionCount].samples = VK_SAMPLE_COUNT_1_BIT;
+            attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+            attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            resolveReferences[resolveReferenceCount].attachment = attachmentDescriptionCount;
+            resolveReferences[resolveReferenceCount].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            attachmentDescriptionCount += 1;
+            resolveReferenceCount += 1;
+
+            attachmentDescriptions[attachmentDescriptionCount].flags = 0;
+            attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_SurfaceFormat[attachmentDescription.format];
+            attachmentDescriptions[attachmentDescriptionCount].samples = sampleCount;
+
+            attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+            attachmentDescriptions[attachmentDescriptionCount].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            colorAttachmentReferences[colorAttachmentReferenceCount].attachment =
+                attachmentDescriptionCount;
+            colorAttachmentReferences[colorAttachmentReferenceCount].layout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            attachmentDescriptionCount += 1;
+            colorAttachmentReferenceCount += 1;
+        } else {
+            attachmentDescriptions[attachmentDescriptionCount].flags = 0;
+            attachmentDescriptions[attachmentDescriptionCount].format = SDLToVK_SurfaceFormat[attachmentDescription.format];
+            attachmentDescriptions[attachmentDescriptionCount].samples =
+                VK_SAMPLE_COUNT_1_BIT;
+            attachmentDescriptions[attachmentDescriptionCount].loadOp =
+                VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].storeOp =
+                VK_ATTACHMENT_STORE_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp =
+                VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp =
+                VK_ATTACHMENT_STORE_OP_DONT_CARE;
+            attachmentDescriptions[attachmentDescriptionCount].initialLayout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+            attachmentDescriptions[attachmentDescriptionCount].finalLayout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            colorAttachmentReferences[colorAttachmentReferenceCount].attachment = attachmentDescriptionCount;
+            colorAttachmentReferences[colorAttachmentReferenceCount].layout =
+                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+
+            attachmentDescriptionCount += 1;
+            colorAttachmentReferenceCount += 1;
+        }
+    }
+
+    subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+    subpass.flags = 0;
+    subpass.inputAttachmentCount = 0;
+    subpass.pInputAttachments = NULL;
+    subpass.colorAttachmentCount = attachmentInfo.colorAttachmentCount;
+    subpass.pColorAttachments = colorAttachmentReferences;
+    subpass.preserveAttachmentCount = 0;
+    subpass.pPreserveAttachments = NULL;
+
+    if (attachmentInfo.hasDepthStencilAttachment) {
+        attachmentDescriptions[attachmentDescriptionCount].flags = 0;
+        attachmentDescriptions[attachmentDescriptionCount].format =
+            SDLToVK_SurfaceFormat[attachmentInfo.depthStencilFormat];
+        attachmentDescriptions[attachmentDescriptionCount].samples = sampleCount;
+
+        attachmentDescriptions[attachmentDescriptionCount].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+        attachmentDescriptions[attachmentDescriptionCount].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+        attachmentDescriptions[attachmentDescriptionCount].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+        attachmentDescriptions[attachmentDescriptionCount].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+        attachmentDescriptions[attachmentDescriptionCount].initialLayout =
+            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+        attachmentDescriptions[attachmentDescriptionCount].finalLayout =
+            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+        depthStencilAttachmentReference.attachment =
+            attachmentDescriptionCount;
+        depthStencilAttachmentReference.layout =
+            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+        subpass.pDepthStencilAttachment =
+            &depthStencilAttachmentReference;
+
+        attachmentDescriptionCount += 1;
+    } else {
+        subpass.pDepthStencilAttachment = NULL;
+    }
+
+    if (multisampling) {
+        subpass.pResolveAttachments = resolveReferences;
+    } else {
+        subpass.pResolveAttachments = NULL;
+    }
+
+    renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+    renderPassCreateInfo.pNext = NULL;
+    renderPassCreateInfo.flags = 0;
+    renderPassCreateInfo.pAttachments = attachmentDescriptions;
+    renderPassCreateInfo.attachmentCount = attachmentDescriptionCount;
+    renderPassCreateInfo.subpassCount = 1;
+    renderPassCreateInfo.pSubpasses = &subpass;
+    renderPassCreateInfo.dependencyCount = 0;
+    renderPassCreateInfo.pDependencies = NULL;
+
+    result = renderer->vkCreateRenderPass(
+        renderer->logicalDevice,
+        &renderPassCreateInfo,
+        NULL,
+        &renderPass);
+
+    if (result != VK_SUCCESS) {
+        renderPass = VK_NULL_HANDLE;
+        LogVulkanResultAsError("vkCreateRenderPass", result);
+    }
+
+    return renderPass;
+}
+
+static SDL_GpuGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuGraphicsPipelineCreateInfo *pipelineCreateInfo)
+{
+    VkResult vulkanResult;
+    Uint32 i;
+    VkSampleCountFlagBits actualSampleCount;
+
+    VulkanGraphicsPipeline *graphicsPipeline = (VulkanGraphicsPipeline *)SDL_malloc(sizeof(VulkanGraphicsPipeline));
+    VkGraphicsPipelineCreateInfo vkPipelineCreateInfo;
+
+    VkPipelineShaderStageCreateInfo shaderStageCreateInfos[2];
+
+    VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo;
+    VkPipelineVertexInputDivisorStateCreateInfoEXT divisorStateCreateInfo;
+    VkVertexInputBindingDescription *vertexInputBindingDescriptions = SDL_stack_alloc(VkVertexInputBindingDescription, pipelineCreateInfo->vertexInputState.vertexBindingCount);
+    VkVertexInputAttributeDescription *vertexInputAttributeDescriptions = SDL_stack_alloc(VkVertexInputAttributeDescription, pipelineCreateInfo->vertexInputState.vertexAttributeCount);
+    VkVertexInputBindingDivisorDescriptionEXT *divisorDescriptions = SDL_stack_alloc(VkVertexInputBindingDivisorDescriptionEXT, pipelineCreateInfo->vertexInputState.vertexBindingCount);
+    Uint32 divisorDescriptionCount = 0;
+
+    VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo;
+
+    VkPipelineViewportStateCreateInfo viewportStateCreateInfo;
+
+    VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo;
+
+    VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo;
+
+    VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo;
+    VkStencilOpState frontStencilState;
+    VkStencilOpState backStencilState;
+
+    VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo;
+    VkPipelineColorBlendAttachmentState *colorBlendAttachmentStates = SDL_stack_alloc(
+        VkPipelineColorBlendAttachmentState,
+        pipelineCreateInfo->attachmentInfo.colorAttachmentCount);
+
+    static const VkDynamicState dynamicStates[] = {
+        VK_DYNAMIC_STATE_VIEWPORT,
+        VK_DYNAMIC_STATE_SCISSOR
+    };
+    VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo;
+
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+
+    // Find a compatible sample count to use
+
+    actualSampleCount = VULKAN_INTERNAL_GetMaxMultiSampleCount(
+        renderer,
+        SDLToVK_SampleCount[pipelineCreateInfo->multisampleState.sampleCount]);
+
+    // Create a "compatible" render pass
+
+    VkRenderPass transientRenderPass = VULKAN_INTERNAL_CreateTransientRenderPass(
+        renderer,
+        pipelineCreateInfo->attachmentInfo,
+        actualSampleCount);
+
+    // Dynamic state
+
+    dynamicStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+    dynamicStateCreateInfo.pNext = NULL;
+    dynamicStateCreateInfo.flags = 0;
+    dynamicStateCreateInfo.dynamicStateCount = SDL_arraysize(dynamicStates);
+    dynamicStateCreateInfo.pDynamicStates = dynamicStates;
+
+    // Shader stages
+
+    graphicsPipeline->vertexShader = (VulkanShader *)pipelineCreateInfo->vertexShader;
+    SDL_AtomicIncRef(&graphicsPipeline->vertexShader->referenceCount);
+
+    shaderStageCreateInfos[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+    shaderStageCreateInfos[0].pNext = NULL;
+    shaderStageCreateInfos[0].flags = 0;
+    shaderStageCreateInfos[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
+    shaderStageCreateInfos[0].module = graphicsPipeline->vertexShader->shaderModule;
+    shaderStageCreateInfos[0].pName = graphicsPipeline->vertexShader->entryPointName;
+    shaderStageCreateInfos[0].pSpecializationInfo = NULL;
+
+    graphicsPipeline->fragmentShader = (VulkanShader *)pipelineCreateInfo->fragmentShader;
+    SDL_AtomicIncRef(&graphicsPipeline->fragmentShader->referenceCount);
+
+    shaderStageCreateInfos[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+    shaderStageCreateInfos[1].pNext = NULL;
+    shaderStageCreateInfos[1].flags = 0;
+    shaderStageCreateInfos[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
+    shaderStageCreateInfos[1].module = graphicsPipeline->fragmentShader->shaderModule;
+    shaderStageCreateInfos[1].pName = graphicsPipeline->fragmentShader->entryPointName;
+    shaderStageCreateInfos[1].pSpecializationInfo = NULL;
+
+    // Vertex input
+
+    for (i = 0; i < pipelineCreateInfo->vertexInputState.vertexBindingCount; i += 1) {
+        vertexInputBindingDescriptions[i].binding = pipelineCreateInfo->vertexInputState.vertexBindings[i].binding;
+        vertexInputBindingDescriptions[i].inputRate = SDLToVK_VertexInputRate[pipelineCreateInfo->vertexInputState.vertexBindings[i].inputRate];
+        vertexInputBindingDescriptions[i].stride = pipelineCreateInfo->vertexInputState.vertexBindings[i].stride;
+
+        if (pipelineCreateInfo->vertexInputState.vertexBindings[i].inputRate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) {
+            divisorDescriptionCount += 1;
+        }
+    }
+
+    for (i = 0; i < pipelineCreateInfo->vertexInputState.vertexAttributeCount; i += 1) {
+        vertexInputAttributeDescriptions[i].binding = pipelineCreateInfo->vertexInputState.vertexAttributes[i].binding;
+        vertexInputAttributeDescriptions[i].format = SDLToVK_VertexFormat[pipelineCreateInfo->vertexInputState.vertexAttributes[i].format];
+        vertexInputAttributeDescriptions[i].location = pipelineCreateInfo->vertexInputState.vertexAttributes[i].location;
+        vertexInputAttributeDescriptions[i].offset = pipelineCreateInfo->vertexInputState.vertexAttributes[i].offset;
+    }
+
+    vertexInputStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+    vertexInputStateCreateInfo.pNext = NULL;
+    vertexInputStateCreateInfo.flags = 0;
+    vertexInputStateCreateInfo.vertexBindingDescriptionCount = pipelineCreateInfo->vertexInputState.vertexBindingCount;
+    vertexInputStateCreateInfo.pVertexBindingDescriptions = vertexInputBindingDescriptions;
+    vertexInputStateCreateInfo.vertexAttributeDescriptionCount = pipelineCreateInfo->vertexInputState.vertexAttributeCount;
+    vertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescriptions;
+
+    if (divisorDescriptionCount > 0) {
+        divisorDescriptionCount = 0;
+
+        for (i = 0; i < pipelineCreateInfo->vertexInputState.vertexBindingCount; i += 1) {
+            if (pipelineCreateInfo->vertexInputState.vertexBindings[i].inputRate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) {
+                divisorDescriptions[divisorDescriptionCount].binding = pipelineCreateInfo->vertexInputState.vertexBindings[i].binding;
+                divisorDescriptions[divisorDescriptionCount].divisor = pipelineCreateInfo->vertexInputState.vertexBindings[i].instanceStepRate;
+
+                divisorDescriptionCount += 1;
+            }
+        }
+
+        divisorStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
+        divisorStateCreateInfo.pNext = NULL;
+        divisorStateCreateInfo.vertexBindingDivisorCount = divisorDescriptionCount;
+        divisorStateCreateInfo.pVertexBindingDivisors = divisorDescriptions;
+
+        vertexInputStateCreateInfo.pNext = &divisorStateCreateInfo;
+    }
+
+    // Topology
+
+    inputAssemblyStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+    inputAssemblyStateCreateInfo.pNext = NULL;
+    inputAssemblyStateCreateInfo.flags = 0;
+    inputAssemblyStateCreateInfo.primitiveRestartEnable = VK_FALSE;
+    inputAssemblyStateCreateInfo.topology = SDLToVK_PrimitiveType[pipelineCreateInfo->primitiveType];
+
+    graphicsPipeline->primitiveType = pipelineCreateInfo->primitiveType;
+
+    // Viewport
+
+    // NOTE: viewport and scissor are dynamic, and must be set using the command buffer
+
+    viewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+    viewportStateCreateInfo.pNext = NULL;
+    viewportStateCreateInfo.flags = 0;
+    viewportStateCreateInfo.viewportCount = 1;
+    viewportStateCreateInfo.pViewports = NULL;
+    viewportStateCreateInfo.scissorCount = 1;
+    viewportStateCreateInfo.pScissors = NULL;
+
+    // Rasterization
+
+    rasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+    rasterizationStateCreateInfo.pNext = NULL;
+    rasterizationStateCreateInfo.flags = 0;
+    rasterizationStateCreateInfo.depthClampEnable = VK_FALSE;
+    rasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE;
+    rasterizationStateCreateInfo.polygonMode = SDLToVK_PolygonMode(
+        renderer,
+        pipelineCreateInfo->rasterizerState.fillMode);
+    rasterizationStateCreateInfo.cullMode = SDLToVK_CullMode[pipelineCreateInfo->rasterizerState.cullMode];
+    rasterizationStateCreateInfo.frontFace = SDLToVK_FrontFace[pipelineCreateInfo->rasterizerState.frontFace];
+    rasterizationStateCreateInfo.depthBiasEnable =
+        pipelineCreateInfo->rasterizerState.depthBiasEnable;
+    rasterizationStateCreateInfo.depthBiasConstantFactor =
+        pipelineCreateInfo->rasterizerState.depthBiasConstantFactor;
+    rasterizationStateCreateInfo.depthBiasClamp =
+        pipelineCreateInfo->rasterizerState.depthBiasClamp;
+    rasterizationStateCreateInfo.depthBiasSlopeFactor =
+        pipelineCreateInfo->rasterizerState.depthBiasSlopeFactor;
+    rasterizationStateCreateInfo.lineWidth = 1.0f;
+
+    // Multisample
+
+    multisampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+    multisampleStateCreateInfo.pNext = NULL;
+    multisampleStateCreateInfo.flags = 0;
+    multisampleStateCreateInfo.rasterizationSamples = actualSampleCount;
+    multisampleStateCreateInfo.sampleShadingEnable = VK_FALSE;
+    multisampleStateCreateInfo.minSampleShading = 1.0f;
+    multisampleStateCreateInfo.pSampleMask =
+        &pipelineCreateInfo->multisampleState.sampleMask;
+    multisampleStateCreateInfo.alphaToCoverageEnable = VK_FALSE;
+    multisampleStateCreateInfo.alphaToOneEnable = VK_FALSE;
+
+    // Depth Stencil State
+
+    frontStencilState.failOp = SDLToVK_StencilOp[pipelineCreateInfo->depthStencilState.frontStencilState.failOp];
+    frontStencilState.passOp = SDLToVK_StencilOp[pipelineCreateInfo->depthStencilState.frontStencilState.passOp];
+    frontStencilState.depthFailOp = SDLToVK_StencilOp[pipelineCreateInfo->depthStencilState.frontStencilState.depthFailOp];
+    frontStencilState.compareOp = SDLToVK_CompareOp[pipelineCreateInfo->depthStencilState.frontStencilState.compareOp];
+    frontStencilState.compareMask =
+        pipelineCreateInfo->depthStencilState.compareMask;
+    frontStencilState.writeMask =
+        pipelineCreateInfo->depthStencilState.writeMask;
+    frontStencilState.reference =
+        pipelineCreateInfo->depthStencilState.reference;
+
+    backStencilState.failOp = SDLToVK_StencilOp[pipelineCreateInfo->depthStencilState.backStencilState.failOp];
+    backStencilState.passOp = SDLToVK_StencilOp[pipelineCreateInfo->depthStencilState.backStencilState.passOp];
+    backStencilState.depthFailOp = SDLToVK_StencilOp[pipelineCreateInfo->depthStencilState.backStencilState.depthFailOp];
+    backStencilState.compareOp = SDLToVK_CompareOp[pipelineCreateInfo->depthStencilState.backStencilState.compareOp];
+    backStencilState.compareMask =
+        pipelineCreateInfo->depthStencilState.compareMask;
+    backStencilState.writeMask =
+        pipelineCreateInfo->depthStencilState.writeMask;
+    backStencilState.reference =
+        pipelineCreateInfo->depthStencilState.reference;
+
+    depthStencilStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+    depthStencilStateCreateInfo.pNext = NULL;
+    depthStencilStateCreateInfo.flags = 0;
+    depthStencilStateCreateInfo.depthTestEnable =
+        pipelineCreateInfo->depthStencilState.depthTestEnable;
+    depthStencilStateCreateInfo.depthWriteEnable =
+        pipelineCreateInfo->depthStencilState.depthWriteEnable;
+    depthStencilStateCreateInfo.depthCompareOp = SDLToVK_CompareOp[pipelineCreateInfo->depthStencilState.compareOp];
+    depthStencilStateCreateInfo.depthBoundsTestEnable = VK_FALSE;
+    depthStencilStateCreateInfo.stencilTestEnable =
+        pipelineCreateInfo->depthStencilState.stencilTestEnable;
+    depthStencilStateCreateInfo.front = frontStencilState;
+    depthStencilStateCreateInfo.back = backStencilState;
+    depthStencilStateCreateInfo.minDepthBounds = 0; // unused
+    depthStencilStateCreateInfo.maxDepthBounds = 0; // unused
+
+    // Color Blend
+
+    for (i = 0; i < pipelineCreateInfo->attachmentInfo.colorAttachmentCount; i += 1) {
+        SDL_GpuColorAttachmentBlendState blendState = pipelineCreateInfo->attachmentInfo.colorAttachmentDescriptions[i].blendState;
+
+        colorBlendAttachmentStates[i].blendEnable =
+            blendState.blendEnable;
+        colorBlendAttachmentStates[i].srcColorBlendFactor = SDLToVK_BlendFactor[blendState.srcColorBlendFactor];
+        colorBlendAttachmentStates[i].dstColorBlendFactor = SDLToVK_BlendFactor[blendState.dstColorBlendFactor];
+        colorBlendAttachmentStates[i].colorBlendOp = SDLToVK_BlendOp[blendState.colorBlendOp];
+        colorBlendAttachmentStates[i].srcAlphaBlendFactor = SDLToVK_BlendFactor[blendState.srcAlphaBlendFactor];
+        colorBlendAttachmentStates[i].dstAlphaBlendFactor = SDLToVK_BlendFactor[blendState.dstAlphaBlendFactor];
+        colorBlendAttachmentStates[i].alphaBlendOp = SDLToVK_BlendOp[blendState.alphaBlendOp];
+        colorBlendAttachmentStates[i].colorWriteMask =
+            blendState.colorWriteMask;
+    }
+
+    colorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+    colorBlendStateCreateInfo.pNext = NULL;
+    colorBlendStateCreateInfo.flags = 0;
+    colorBlendStateCreateInfo.attachmentCount =
+        pipelineCreateInfo->attachmentInfo.colorAttachmentCount;
+    colorBlendStateCreateInfo.pAttachments =
+        colorBlendAttachmentStates;
+    colorBlendStateCreateInfo.blendConstants[0] =
+        pipelineCreateInfo->blendConstants[0];
+    colorBlendStateCreateInfo.blendConstants[1] =
+        pipelineCreateInfo->blendConstants[1];
+    colorBlendStateCreateInfo.blendConstants[2] =
+        pipelineCreateInfo->blendConstants[2];
+    colorBlendStateCreateInfo.blendConstants[3] =
+        pipelineCreateInfo->blendConstants[3];
+
+    // We don't support LogicOp, so this is easy.
+    colorBlendStateCreateInfo.logicOpEnable = VK_FALSE;
+    colorBlendStateCreateInfo.logicOp = 0;
+
+    // Pipeline Layout
+
+    if (!VULKAN_INTERNAL_InitializeGraphicsPipelineResourceLayout(
+            renderer,
+            graphicsPipeline->vertexShader,
+            graphicsPipeline->fragmentShader,
+            &graphicsPipeline->resourceLayout)) {
+        SDL_stack_free(vertexInputBindingDescriptions);
+        SDL_stack_free(vertexInputAttributeDescriptions);
+        SDL_stack_free(colorBlendAttachmentStates);
+        SDL_stack_free(divisorDescriptions);
+        SDL_free(graphicsPipeline);
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to initialize pipeline resource layout!");
+        return NULL;
+    }
+
+    // Pipeline
+
+    vkPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+    vkPipelineCreateInfo.pNext = NULL;
+    vkPipelineCreateInfo.flags = 0;
+    vkPipelineCreateInfo.stageCount = 2;
+    vkPipelineCreateInfo.pStages = shaderStageCreateInfos;
+    vkPipelineCreateInfo.pVertexInputState = &vertexInputStateCreateInfo;
+    vkPipelineCreateInfo.pInputAssemblyState = &inputAssemblyStateCreateInfo;
+    vkPipelineCreateInfo.pTessellationState = VK_NULL_HANDLE;
+    vkPipelineCreateInfo.pViewportState = &viewportStateCreateInfo;
+    vkPipelineCreateInfo.pRasterizationState = &rasterizationStateCreateInfo;
+    vkPipelineCreateInfo.pMultisampleState = &multisampleStateCreateInfo;
+    vkPipelineCreateInfo.pDepthStencilState = &depthStencilStateCreateInfo;
+    vkPipelineCreateInfo.pColorBlendState = &colorBlendStateCreateInfo;
+    vkPipelineCreateInfo.pDynamicState = &dynamicStateCreateInfo;
+    vkPipelineCreateInfo.layout = graphicsPipeline->resourceLayout.pipelineLayout;
+    vkPipelineCreateInfo.renderPass = transientRenderPass;
+    vkPipelineCreateInfo.subpass = 0;
+    vkPipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
+    vkPipelineCreateInfo.basePipelineIndex = 0;
+
+    // TODO: enable pipeline caching
+    vulkanResult = renderer->vkCreateGraphicsPipelines(
+        renderer->logicalDevice,
+        VK_NULL_HANDLE,
+        1,
+        &vkPipelineCreateInfo,
+        NULL,
+        &graphicsPipeline->pipeline);
+
+    SDL_stack_free(vertexInputBindingDescriptions);
+    SDL_stack_free(vertexInputAttributeDescriptions);
+    SDL_stack_free(colorBlendAttachmentStates);
+    SDL_stack_free(divisorDescriptions);
+
+    renderer->vkDestroyRenderPass(
+        renderer->logicalDevice,
+        transientRenderPass,
+        NULL);
+
+    if (vulkanResult != VK_SUCCESS) {
+        SDL_free(graphicsPipeline);
+        LogVulkanResultAsError("vkCreateGraphicsPipelines", vulkanResult);
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create graphics pipeline!");
+        return NULL;
+    }
+
+    SDL_AtomicSet(&graphicsPipeline->referenceCount, 0);
+
+    return (SDL_GpuGraphicsPipeline *)graphicsPipeline;
+}
+
+static SDL_GpuComputePipeline *VULKAN_CreateComputePipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuComputePipelineCreateInfo *pipelineCreateInfo)
+{
+    VkShaderModuleCreateInfo shaderModuleCreateInfo;
+    VkComputePipelineCreateInfo computePipelineCreateInfo;
+    VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo;
+    VkResult vulkanResult;
+    Uint32 i;
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanComputePipeline *vulkanComputePipeline;
+
+    if (pipelineCreateInfo->format != SDL_GPU_SHADERFORMAT_SPIRV) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Incompatible shader format for Vulkan!");
+        return NULL;
+    }
+
+    vulkanComputePipeline = SDL_malloc(sizeof(VulkanComputePipeline));
+    shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+    shaderModuleCreateInfo.pNext = NULL;
+    shaderModuleCreateInfo.flags = 0;
+    shaderModuleCreateInfo.codeSize = pipelineCreateInfo->codeSize;
+    shaderModuleCreateInfo.pCode = (Uint32 *)pipelineCreateInfo->code;
+
+    vulkanResult = renderer->vkCreateShaderModule(
+        renderer->logicalDevice,
+        &shaderModuleCreateInfo,
+        NULL,
+        &vulkanComputePipeline->shaderModule);
+
+    if (vulkanResult != VK_SUCCESS) {
+        SDL_free(vulkanComputePipeline);
+        LogVulkanResultAsError("vkCreateShaderModule", vulkanResult);
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create compute pipeline!");
+        return NULL;
+    }
+
+    pipelineShaderStageCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+    pipelineShaderStageCreateInfo.pNext = NULL;
+    pipelineShaderStageCreateInfo.flags = 0;
+    pipelineShaderStageCreateInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
+    pipelineShaderStageCreateInfo.module = vulkanComputePipeline->shaderModule;
+    pipelineShaderStageCreateInfo.pName = pipelineCreateInfo->entryPointName;
+    pipelineShaderStageCreateInfo.pSpecializationInfo = NULL;
+
+    if (!VULKAN_INTERNAL_InitializeComputePipelineResourceLayout(
+            renderer,
+            pipelineCreateInfo,
+            &vulkanComputePipeline->resourceLayout)) {
+        renderer->vkDestroyShaderModule(
+            renderer->logicalDevice,
+            vulkanComputePipeline->shaderModule,
+            NULL);
+        SDL_free(vulkanComputePipeline);
+        return NULL;
+    }
+
+    computePipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
+    computePipelineCreateInfo.pNext = NULL;
+    computePipelineCreateInfo.flags = 0;
+    computePipelineCreateInfo.stage = pipelineShaderStageCreateInfo;
+    computePipelineCreateInfo.layout =
+        vulkanComputePipeline->resourceLayout.pipelineLayout;
+    computePipelineCreateInfo.basePipelineHandle = (VkPipeline)VK_NULL_HANDLE;
+    computePipelineCreateInfo.basePipelineIndex = 0;
+
+    vulkanResult = renderer->vkCreateComputePipelines(
+        renderer->logicalDevice,
+        (VkPipelineCache)VK_NULL_HANDLE,
+        1,
+        &computePipelineCreateInfo,
+        NULL,
+        &vulkanComputePipeline->pipeline);
+
+    if (vulkanResult != VK_SUCCESS) {
+        renderer->vkDestroyPipelineLayout(
+            renderer->logicalDevice,
+            vulkanComputePipeline->resourceLayout.pipelineLayout,
+            NULL);
+
+        for (i = 0; i < 3; i += 1) {
+            VULKAN_INTERNAL_DestroyDescriptorSetPool(
+                renderer,
+                &vulkanComputePipeline->resourceLayout.descriptorSetPools[i]);
+        }
+
+        renderer->vkDestroyShaderModule(
+            renderer->logicalDevice,
+            vulkanComputePipeline->shaderModule,
+            NULL);
+
+        LogVulkanResultAsError("vkCreateComputePipeline", vulkanResult);
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create compute pipeline!");
+        return NULL;
+    }
+
+    SDL_AtomicSet(&vulkanComputePipeline->referenceCount, 0);
+
+    return (SDL_GpuComputePipeline *)vulkanComputePipeline;
+}
+
+static SDL_GpuSampler *VULKAN_CreateSampler(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuSamplerCreateInfo *samplerCreateInfo)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanSampler *vulkanSampler = SDL_malloc(sizeof(VulkanSampler));
+    VkResult vulkanResult;
+
+    VkSamplerCreateInfo vkSamplerCreateInfo;
+    vkSamplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+    vkSamplerCreateInfo.pNext = NULL;
+    vkSamplerCreateInfo.flags = 0;
+    vkSamplerCreateInfo.magFilter = SDLToVK_Filter[samplerCreateInfo->magFilter];
+    vkSamplerCreateInfo.minFilter = SDLToVK_Filter[samplerCreateInfo->minFilter];
+    vkSamplerCreateInfo.mipmapMode = SDLToVK_SamplerMipmapMode[samplerCreateInfo->mipmapMode];
+    vkSamplerCreateInfo.addressModeU = SDLToVK_SamplerAddressMode[samplerCreateInfo->addressModeU];
+    vkSamplerCreateInfo.addressModeV = SDLToVK_SamplerAddressMode[samplerCreateInfo->addressModeV];
+    vkSamplerCreateInfo.addressModeW = SDLToVK_SamplerAddressMode[samplerCreateInfo->addressModeW];
+    vkSamplerCreateInfo.mipLodBias = samplerCreateInfo->mipLodBias;
+    vkSamplerCreateInfo.anisotropyEnable = samplerCreateInfo->anisotropyEnable;
+    vkSamplerCreateInfo.maxAnisotropy = samplerCreateInfo->maxAnisotropy;
+    vkSamplerCreateInfo.compareEnable = samplerCreateInfo->compareEnable;
+    vkSamplerCreateInfo.compareOp = SDLToVK_CompareOp[samplerCreateInfo->compareOp];
+    vkSamplerCreateInfo.minLod = samplerCreateInfo->minLod;
+    vkSamplerCreateInfo.maxLod = samplerCreateInfo->maxLod;
+    vkSamplerCreateInfo.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; // arbitrary, unused
+    vkSamplerCreateInfo.unnormalizedCoordinates = VK_FALSE;
+
+    vulkanResult = renderer->vkCreateSampler(
+        renderer->logicalDevice,
+        &vkSamplerCreateInfo,
+        NULL,
+        &vulkanSampler->sampler);
+
+    if (vulkanResult != VK_SUCCESS) {
+        SDL_free(vulkanSampler);
+        LogVulkanResultAsError("vkCreateSampler", vulkanResult);
+        return NULL;
+    }
+
+    SDL_AtomicSet(&vulkanSampler->referenceCount, 0);
+
+    return (SDL_GpuSampler *)vulkanSampler;
+}
+
+static SDL_GpuShader *VULKAN_CreateShader(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuShaderCreateInfo *shaderCreateInfo)
+{
+    VulkanShader *vulkanShader;
+    VkResult vulkanResult;
+    VkShaderModuleCreateInfo vkShaderModuleCreateInfo;
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    size_t entryPointNameLength;
+
+    vulkanShader = SDL_malloc(sizeof(VulkanShader));
+    vkShaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+    vkShaderModuleCreateInfo.pNext = NULL;
+    vkShaderModuleCreateInfo.flags = 0;
+    vkShaderModuleCreateInfo.codeSize = shaderCreateInfo->codeSize;
+    vkShaderModuleCreateInfo.pCode = (Uint32 *)shaderCreateInfo->code;
+
+    vulkanResult = renderer->vkCreateShaderModule(
+        renderer->logicalDevice,
+        &vkShaderModuleCreateInfo,
+        NULL,
+        &vulkanShader->shaderModule);
+
+    if (vulkanResult != VK_SUCCESS) {
+        SDL_free(vulkanShader);
+        LogVulkanResultAsError("vkCreateShaderModule", vulkanResult);
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create shader module!");
+        return NULL;
+    }
+
+    entryPointNameLength = SDL_strlen(shaderCreateInfo->entryPointName) + 1;
+    vulkanShader->entryPointName = SDL_malloc(entryPointNameLength);
+    SDL_utf8strlcpy((char *)vulkanShader->entryPointName, shaderCreateInfo->entryPointName, entryPointNameLength);
+
+    vulkanShader->samplerCount = shaderCreateInfo->samplerCount;
+    vulkanShader->storageTextureCount = shaderCreateInfo->storageTextureCount;
+    vulkanShader->storageBufferCount = shaderCreateInfo->storageBufferCount;
+    vulkanShader->uniformBufferCount = shaderCreateInfo->uniformBufferCount;
+
+    SDL_AtomicSet(&vulkanShader->referenceCount, 0);
+
+    return (SDL_GpuShader *)vulkanShader;
+}
+
+static SDL_bool VULKAN_SupportsSampleCount(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureFormat format,
+    SDL_GpuSampleCount sampleCount)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VkSampleCountFlags bits = IsDepthFormat(format) ? renderer->physicalDeviceProperties.properties.limits.framebufferDepthSampleCounts : renderer->physicalDeviceProperties.properties.limits.framebufferColorSampleCounts;
+    VkSampleCountFlagBits vkSampleCount = SDLToVK_SampleCount[sampleCount];
+    return !!(bits & vkSampleCount);
+}
+
+static SDL_GpuTexture *VULKAN_CreateTexture(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureCreateInfo *textureCreateInfo)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VkImageAspectFlags imageAspectFlags;
+    Uint8 isDepthFormat = IsDepthFormat(textureCreateInfo->format);
+    VkFormat format;
+    VkComponentMapping swizzle;
+    VulkanTextureContainer *container;
+    VulkanTextureHandle *textureHandle;
+
+    format = SDLToVK_SurfaceFormat[textureCreateInfo->format];
+    swizzle = SDLToVK_SurfaceSwizzle[textureCreateInfo->format];
+
+    if (isDepthFormat) {
+        imageAspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT;
+
+        if (IsStencilFormat(textureCreateInfo->format)) {
+            imageAspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
+        }
+    } else {
+        imageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;
+    }
+
+    textureHandle = VULKAN_INTERNAL_CreateTextureHandle(
+        renderer,
+        textureCreateInfo->width,
+        textureCreateInfo->height,
+        textureCreateInfo->type == SDL_GPU_TEXTURETYPE_3D ? textureCreateInfo->layerCountOrDepth : 1,
+        textureCreateInfo->type,
+        textureCreateInfo->type == SDL_GPU_TEXTURETYPE_3D ? 1 : textureCreateInfo->layerCountOrDepth,
+        textureCreateInfo->levelCount,
+        SDLToVK_SampleCount[textureCreateInfo->sampleCount],
+        format,
+        swizzle,
+        imageAspectFlags,
+        textureCreateInfo->usageFlags,
+        SDL_FALSE);
+
+    if (textureHandle == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create texture container!");
+        return NULL;
+    }
+
+    container = SDL_malloc(sizeof(VulkanTextureContainer));
+    container->header.info = *textureCreateInfo;
+    container->canBeCycled = 1;
+    container->activeTextureHandle = textureHandle;
+    container->textureCapacity = 1;
+    container->textureCount = 1;
+    container->textureHandles = SDL_malloc(
+        container->textureCapacity * sizeof(VulkanTextureHandle *));
+    container->textureHandles[0] = container->activeTextureHandle;
+    container->debugName = NULL;
+
+    textureHandle->container = container;
+
+    return (SDL_GpuTexture *)container;
+}
+
+static SDL_GpuBuffer *VULKAN_CreateBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBufferUsageFlags usageFlags,
+    Uint32 sizeInBytes)
+{
+    return (SDL_GpuBuffer *)VULKAN_INTERNAL_CreateBufferContainer(
+        (VulkanRenderer *)driverData,
+        (VkDeviceSize)sizeInBytes,
+        usageFlags,
+        VULKAN_BUFFER_TYPE_GPU);
+}
+
+static VulkanUniformBuffer *VULKAN_INTERNAL_CreateUniformBuffer(
+    VulkanRenderer *renderer,
+    Uint32 sizeInBytes)
+{
+    VulkanUniformBuffer *uniformBuffer = SDL_malloc(sizeof(VulkanUniformBuffer));
+
+    uniformBuffer->bufferHandle = VULKAN_INTERNAL_CreateBufferHandle(
+        renderer,
+        (VkDeviceSize)sizeInBytes,
+        0,
+        VULKAN_BUFFER_TYPE_UNIFORM);
+
+    uniformBuffer->drawOffset = 0;
+    uniformBuffer->writeOffset = 0;
+
+    return uniformBuffer;
+}
+
+static SDL_GpuTransferBuffer *VULKAN_CreateTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBufferUsage usage, // ignored on Vulkan
+    Uint32 sizeInBytes)
+{
+    return (SDL_GpuTransferBuffer *)VULKAN_INTERNAL_CreateBufferContainer(
+        (VulkanRenderer *)driverData,
+        (VkDeviceSize)sizeInBytes,
+        0,
+        VULKAN_BUFFER_TYPE_TRANSFER);
+}
+
+static void VULKAN_INTERNAL_ReleaseTexture(
+    VulkanRenderer *renderer,
+    VulkanTexture *vulkanTexture)
+{
+    if (vulkanTexture->markedForDestroy) {
+        return;
+    }
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->texturesToDestroy,
+        VulkanTexture *,
+        renderer->texturesToDestroyCount + 1,
+        renderer->texturesToDestroyCapacity,
+        renderer->texturesToDestroyCapacity * 2)
+
+    renderer->texturesToDestroy[renderer->texturesToDestroyCount] = vulkanTexture;
+    renderer->texturesToDestroyCount += 1;
+
+    vulkanTexture->markedForDestroy = 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void VULKAN_ReleaseTexture(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTexture *texture)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer *)texture;
+    Uint32 i;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    for (i = 0; i < vulkanTextureContainer->textureCount; i += 1) {
+        VULKAN_INTERNAL_ReleaseTexture(renderer, vulkanTextureContainer->textureHandles[i]->vulkanTexture);
+        SDL_free(vulkanTextureContainer->textureHandles[i]);
+    }
+
+    // Containers are just client handles, so we can destroy immediately
+    if (vulkanTextureContainer->debugName != NULL) {
+        SDL_free(vulkanTextureContainer->debugName);
+    }
+    SDL_free(vulkanTextureContainer->textureHandles);
+    SDL_free(vulkanTextureContainer);
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void VULKAN_ReleaseSampler(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuSampler *sampler)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanSampler *vulkanSampler = (VulkanSampler *)sampler;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->samplersToDestroy,
+        VulkanSampler *,
+        renderer->samplersToDestroyCount + 1,
+        renderer->samplersToDestroyCapacity,
+        renderer->samplersToDestroyCapacity * 2)
+
+    renderer->samplersToDestroy[renderer->samplersToDestroyCount] = vulkanSampler;
+    renderer->samplersToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void VULKAN_INTERNAL_ReleaseBuffer(
+    VulkanRenderer *renderer,
+    VulkanBuffer *vulkanBuffer)
+{
+    if (vulkanBuffer->markedForDestroy) {
+        return;
+    }
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->buffersToDestroy,
+        VulkanBuffer *,
+        renderer->buffersToDestroyCount + 1,
+        renderer->buffersToDestroyCapacity,
+        renderer->buffersToDestroyCapacity * 2)
+
+    renderer->buffersToDestroy[renderer->buffersToDestroyCount] = vulkanBuffer;
+    renderer->buffersToDestroyCount += 1;
+
+    vulkanBuffer->markedForDestroy = 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void VULKAN_INTERNAL_ReleaseBufferContainer(
+    VulkanRenderer *renderer,
+    VulkanBufferContainer *bufferContainer)
+{
+    Uint32 i;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    for (i = 0; i < bufferContainer->bufferCount; i += 1) {
+        VULKAN_INTERNAL_ReleaseBuffer(renderer, bufferContainer->bufferHandles[i]->vulkanBuffer);
+        SDL_free(bufferContainer->bufferHandles[i]);
+    }
+
+    // Containers are just client handles, so we can free immediately
+    if (bufferContainer->debugName != NULL) {
+        SDL_free(bufferContainer->debugName);
+    }
+    SDL_free(bufferContainer->bufferHandles);
+    SDL_free(bufferContainer);
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void VULKAN_ReleaseBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuBuffer *buffer)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanBufferContainer *vulkanBufferContainer = (VulkanBufferContainer *)buffer;
+
+    VULKAN_INTERNAL_ReleaseBufferContainer(
+        renderer,
+        vulkanBufferContainer);
+}
+
+static void VULKAN_ReleaseTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)transferBuffer;
+
+    VULKAN_INTERNAL_ReleaseBufferContainer(
+        renderer,
+        transferBufferContainer);
+}
+
+static void VULKAN_ReleaseShader(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuShader *shader)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanShader *vulkanShader = (VulkanShader *)shader;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->shadersToDestroy,
+        VulkanShader *,
+        renderer->shadersToDestroyCount + 1,
+        renderer->shadersToDestroyCapacity,
+        renderer->shadersToDestroyCapacity * 2)
+
+    renderer->shadersToDestroy[renderer->shadersToDestroyCount] = vulkanShader;
+    renderer->shadersToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void VULKAN_ReleaseComputePipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuComputePipeline *computePipeline)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanComputePipeline *vulkanComputePipeline = (VulkanComputePipeline *)computePipeline;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->computePipelinesToDestroy,
+        VulkanComputePipeline *,
+        renderer->computePipelinesToDestroyCount + 1,
+        renderer->computePipelinesToDestroyCapacity,
+        renderer->computePipelinesToDestroyCapacity * 2)
+
+    renderer->computePipelinesToDestroy[renderer->computePipelinesToDestroyCount] = vulkanComputePipeline;
+    renderer->computePipelinesToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void VULKAN_ReleaseGraphicsPipeline(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuGraphicsPipeline *graphicsPipeline)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanGraphicsPipeline *vulkanGraphicsPipeline = (VulkanGraphicsPipeline *)graphicsPipeline;
+
+    SDL_LockMutex(renderer->disposeLock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->graphicsPipelinesToDestroy,
+        VulkanGraphicsPipeline *,
+        renderer->graphicsPipelinesToDestroyCount + 1,
+        renderer->graphicsPipelinesToDestroyCapacity,
+        renderer->graphicsPipelinesToDestroyCapacity * 2)
+
+    renderer->graphicsPipelinesToDestroy[renderer->graphicsPipelinesToDestroyCount] = vulkanGraphicsPipeline;
+    renderer->graphicsPipelinesToDestroyCount += 1;
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+// Command Buffer render state
+
+static VkRenderPass VULKAN_INTERNAL_FetchRenderPass(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer,
+    SDL_GpuColorAttachmentInfo *colorAttachmentInfos,
+    Uint32 colorAttachmentCount,
+    SDL_GpuDepthStencilAttachmentInfo *depthStencilAttachmentInfo)
+{
+    VulkanRenderPassHashTableValue *renderPassWrapper = NULL;
+    VkRenderPass renderPassHandle;
+    RenderPassHashTableKey key;
+    Uint32 i;
+
+    for (i = 0; i < colorAttachmentCount; i += 1) {
+        key.colorTargetDescriptions[i].format = ((VulkanTextureContainer *)colorAttachmentInfos[i].texture)->activeTextureHandle->vulkanTexture->format;
+        key.colorTargetDescriptions[i].loadOp = colorAttachmentInfos[i].loadOp;
+        key.colorTargetDescriptions[i].storeOp = colorAttachmentInfos[i].storeOp;
+    }
+
+    key.colorAttachmentSampleCount = VK_SAMPLE_COUNT_1_BIT;
+    if (colorAttachmentCount > 0) {
+        key.colorAttachmentSampleCount = ((VulkanTextureContainer *)colorAttachmentInfos[0].texture)->activeTextureHandle->vulkanTexture->sampleCount;
+    }
+
+    key.colorAttachmentCount = colorAttachmentCount;
+
+    if (depthStencilAttachmentInfo == NULL) {
+        key.depthStencilTargetDescription.format = 0;
+        key.depthStencilTargetDescription.loadOp = SDL_GPU_LOADOP_DONT_CARE;
+        key.depthStencilTargetDescription.storeOp = SDL_GPU_STOREOP_DONT_CARE;
+        key.depthStencilTargetDescription.stencilLoadOp = SDL_GPU_LOADOP_DONT_CARE;
+        key.depthStencilTargetDescription.stencilStoreOp = SDL_GPU_STOREOP_DONT_CARE;
+    } else {
+        key.depthStencilTargetDescription.format = ((VulkanTextureContainer *)depthStencilAttachmentInfo->texture)->activeTextureHandle->vulkanTexture->format;
+        key.depthStencilTargetDescription.loadOp = depthStencilAttachmentInfo->loadOp;
+        key.depthStencilTargetDescription.storeOp = depthStencilAttachmentInfo->storeOp;
+        key.depthStencilTargetDescription.stencilLoadOp = depthStencilAttachmentInfo->stencilLoadOp;
+        key.depthStencilTargetDescription.stencilStoreOp = depthStencilAttachmentInfo->stencilStoreOp;
+    }
+
+    SDL_LockMutex(renderer->renderPassFetchLock);
+
+    SDL_bool result = SDL_FindInHashTable(
+        renderer->renderPassHashTable,
+        (const void *)&key,
+        (const void **)&renderPassWrapper);
+
+    SDL_UnlockMutex(renderer->renderPassFetchLock);
+
+    if (result) {
+        return renderPassWrapper->handle;
+    }
+
+    renderPassHandle = VULKAN_INTERNAL_CreateRenderPass(
+        renderer,
+        commandBuffer,
+        colorAttachmentInfos,
+        colorAttachmentCount,
+        depthStencilAttachmentInfo);
+
+    if (renderPassHandle == VK_NULL_HANDLE) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create VkRenderPass!");
+        return VK_NULL_HANDLE;
+    }
+
+    // Have to malloc the key to store it in the hashtable
+    RenderPassHashTableKey *allocedKey = SDL_malloc(sizeof(RenderPassHashTableKey));
+    SDL_memcpy(allocedKey, &key, sizeof(RenderPassHashTableKey));
+
+    renderPassWrapper = SDL_malloc(sizeof(VulkanRenderPassHashTableValue));
+    renderPassWrapper->handle = renderPassHandle;
+
+    SDL_LockMutex(renderer->renderPassFetchLock);
+
+    SDL_InsertIntoHashTable(
+        renderer->renderPassHashTable,
+        (const void *)allocedKey,
+        (const void *)renderPassWrapper);
+
+    SDL_UnlockMutex(renderer->renderPassFetchLock);
+    return renderPassHandle;
+}
+
+static VulkanFramebuffer *VULKAN_INTERNAL_FetchFramebuffer(
+    VulkanRenderer *renderer,
+    VkRenderPass renderPass,
+    SDL_GpuColorAttachmentInfo *colorAttachmentInfos,
+    Uint32 colorAttachmentCount,
+    SDL_GpuDepthStencilAttachmentInfo *depthStencilAttachmentInfo,
+    Uint32 width,
+    Uint32 height)
+{
+    VulkanFramebuffer *vulkanFramebuffer = NULL;
+    VkFramebufferCreateInfo framebufferInfo;
+    VkResult result;
+    VkImageView imageViewAttachments[2 * MAX_COLOR_TARGET_BINDINGS + 1];
+    FramebufferHashTableKey key;
+    Uint32 attachmentCount = 0;
+    Uint32 i;
+
+    for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
+        key.colorAttachmentViews[i] = VK_NULL_HANDLE;
+        key.colorMultiSampleAttachmentViews[i] = VK_NULL_HANDLE;
+    }
+
+    key.colorAttachmentCount = colorAttachmentCount;
+
+    for (i = 0; i < colorAttachmentCount; i += 1) {
+        VulkanTextureContainer *container = (VulkanTextureContainer *)colorAttachmentInfos[i].texture;
+        VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
+            container,
+            container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorAttachmentInfos[i].layerOrDepthPlane,
+            colorAttachmentInfos[i].mipLevel);
+
+        Uint32 rtvIndex =
+            container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorAttachmentInfos[i].layerOrDepthPlane : 0;
+        key.colorAttachmentViews[i] = subresource->renderTargetViews[rtvIndex];
+
+        if (subresource->msaaTexHandle != NULL) {
+            key.colorMultiSampleAttachmentViews[i] = subresource->msaaTexHandle->vulkanTexture->subresources[0].renderTargetViews[0];
+        }
+    }
+
+    if (depthStencilAttachmentInfo == NULL) {
+        key.depthStencilAttachmentView = VK_NULL_HANDLE;
+    } else {
+        VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
+            (VulkanTextureContainer *)depthStencilAttachmentInfo->texture,
+            0,
+            0);
+        key.depthStencilAttachmentView = subresource->depthStencilView;
+    }
+
+    key.width = width;
+    key.height = height;
+
+    SDL_LockMutex(renderer->framebufferFetchLock);
+
+    SDL_bool findResult = SDL_FindInHashTable(
+        renderer->framebufferHashTable,
+        (const void *)&key,
+        (const void **)&vulkanFramebuffer);
+
+    SDL_UnlockMutex(renderer->framebufferFetchLock);
+
+    if (findResult) {
+        return vulkanFramebuffer;
+    }
+
+    vulkanFramebuffer = SDL_malloc(sizeof(VulkanFramebuffer));
+
+    SDL_AtomicSet(&vulkanFramebuffer->referenceCount, 0);
+
+    // Create a new framebuffer
+
+    for (i = 0; i < colorAttachmentCount; i += 1) {
+        VulkanTextureContainer *container = (VulkanTextureContainer *)colorAttachmentInfos[i].texture;
+        VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
+            container,
+            container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorAttachmentInfos[i].layerOrDepthPlane,
+            colorAttachmentInfos[i].mipLevel);
+
+        Uint32 rtvIndex =
+            container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorAttachmentInfos[i].layerOrDepthPlane : 0;
+
+        imageViewAttachments[attachmentCount] =
+            subresource->renderTargetViews[rtvIndex];
+
+        attachmentCount += 1;
+
+        if (subresource->msaaTexHandle != NULL) {
+            imageViewAttachments[attachmentCount] =
+                subresource->msaaTexHandle->vulkanTexture->subresources[0].renderTargetViews[0];
+
+            attachmentCount += 1;
+        }
+    }
+
+    if (depthStencilAttachmentInfo != NULL) {
+        VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
+            (VulkanTextureContainer *)depthStencilAttachmentInfo->texture,
+            0,
+            0);
+        imageViewAttachments[attachmentCount] = subresource->depthStencilView;
+
+        attachmentCount += 1;
+    }
+
+    framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+    framebufferInfo.pNext = NULL;
+    framebufferInfo.flags = 0;
+    framebufferInfo.renderPass = renderPass;
+    framebufferInfo.attachmentCount = attachmentCount;
+    framebufferInfo.pAttachments = imageViewAttachments;
+    framebufferInfo.width = key.width;
+    framebufferInfo.height = key.height;
+    framebufferInfo.layers = 1;
+
+    result = renderer->vkCreateFramebuffer(
+        renderer->logicalDevice,
+        &framebufferInfo,
+        NULL,
+        &vulkanFramebuffer->framebuffer);
+
+    if (result == VK_SUCCESS) {
+        // Have to malloc the key to store it in the hashtable
+        FramebufferHashTableKey *allocedKey = SDL_malloc(sizeof(FramebufferHashTableKey));
+        SDL_memcpy(allocedKey, &key, sizeof(FramebufferHashTableKey));
+
+        SDL_LockMutex(renderer->framebufferFetchLock);
+
+        SDL_InsertIntoHashTable(
+            renderer->framebufferHashTable,
+            (const void *)allocedKey,
+            (const void *)vulkanFramebuffer);
+
+        SDL_UnlockMutex(renderer->framebufferFetchLock);
+    } else {
+        LogVulkanResultAsError("vkCreateFramebuffer", result);
+        SDL_free(vulkanFramebuffer);
+        vulkanFramebuffer = NULL;
+    }
+
+    return vulkanFramebuffer;
+}
+
+static void VULKAN_INTERNAL_SetCurrentViewport(
+    VulkanCommandBuffer *commandBuffer,
+    SDL_GpuViewport *viewport)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+
+    vulkanCommandBuffer->currentViewport.x = viewport->x;
+    vulkanCommandBuffer->currentViewport.width = viewport->w;
+    vulkanCommandBuffer->currentViewport.minDepth = viewport->minDepth;
+    vulkanCommandBuffer->currentViewport.maxDepth = viewport->maxDepth;
+
+    // Viewport flip for consistency with other backends
+    // FIXME: need moltenVK hack
+    vulkanCommandBuffer->currentViewport.y = viewport->y + viewport->h;
+    vulkanCommandBuffer->currentViewport.height = -viewport->h;
+}
+
+static void VULKAN_SetViewport(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuViewport *viewport)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+
+    VULKAN_INTERNAL_SetCurrentViewport(
+        vulkanCommandBuffer,
+        viewport);
+
+    renderer->vkCmdSetViewport(
+        vulkanCommandBuffer->commandBuffer,
+        0,
+        1,
+        &vulkanCommandBuffer->currentViewport);
+}
+
+static void VULKAN_INTERNAL_SetCurrentScissor(
+    VulkanCommandBuffer *vulkanCommandBuffer,
+    SDL_Rect *scissor)
+{
+    vulkanCommandBuffer->currentScissor.offset.x = scissor->x;
+    vulkanCommandBuffer->currentScissor.offset.y = scissor->y;
+    vulkanCommandBuffer->currentScissor.extent.width = scissor->w;
+    vulkanCommandBuffer->currentScissor.extent.height = scissor->h;
+}
+
+static void VULKAN_SetScissor(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_Rect *scissor)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+
+    VULKAN_INTERNAL_SetCurrentScissor(
+        vulkanCommandBuffer,
+        scissor);
+
+    renderer->vkCmdSetScissor(
+        vulkanCommandBuffer->commandBuffer,
+        0,
+        1,
+        &vulkanCommandBuffer->currentScissor);
+}
+
+static void VULKAN_BindVertexSamplers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
+        vulkanCommandBuffer->vertexSamplerTextures[firstSlot + i] = textureContainer->activeTextureHandle->vulkanTexture;
+        vulkanCommandBuffer->vertexSamplers[firstSlot + i] = (VulkanSampler *)textureSamplerBindings[i].sampler;
+
+        VULKAN_INTERNAL_TrackSampler(
+            vulkanCommandBuffer,
+            (VulkanSampler *)textureSamplerBindings[i].sampler);
+
+        VULKAN_INTERNAL_TrackTexture(
+            vulkanCommandBuffer,
+            textureContainer->activeTextureHandle->vulkanTexture);
+    }
+
+    vulkanCommandBuffer->needNewVertexResourceDescriptorSet = SDL_TRUE;
+}
+
+static void VULKAN_BindVertexStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
+
+        vulkanCommandBuffer->vertexStorageTextures[firstSlot + i] = textureContainer->activeTextureHandle->vulkanTexture;
+
+        VULKAN_INTERNAL_TrackTexture(
+            vulkanCommandBuffer,
+            textureContainer->activeTextureHandle->vulkanTexture);
+    }
+
+    vulkanCommandBuffer->needNewVertexResourceDescriptorSet = SDL_TRUE;
+}
+
+static void VULKAN_BindVertexStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanBufferContainer *bufferContainer;
+    Uint32 i;
+
+    for (i = 0; i < bindingCount; i += 1) {
+        bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
+
+        vulkanCommandBuffer->vertexStorageBuffers[firstSlot + i] = bufferContainer->activeBufferHandle->vulkanBuffer;
+
+        VULKAN_INTERNAL_TrackBuffer(
+            vulkanCommandBuffer,
+            bufferContainer->activeBufferHandle->vulkanBuffer);
+    }
+
+    vulkanCommandBuffer->needNewVertexResourceDescriptorSet = SDL_TRUE;
+}
+
+static void VULKAN_BindFragmentSamplers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTextureSamplerBinding *textureSamplerBindings,
+    Uint32 bindingCount)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
+        vulkanCommandBuffer->fragmentSamplerTextures[firstSlot + i] = textureContainer->activeTextureHandle->vulkanTexture;
+        vulkanCommandBuffer->fragmentSamplers[firstSlot + i] = (VulkanSampler *)textureSamplerBindings[i].sampler;
+
+        VULKAN_INTERNAL_TrackSampler(
+            vulkanCommandBuffer,
+            (VulkanSampler *)textureSamplerBindings[i].sampler);
+
+        VULKAN_INTERNAL_TrackTexture(
+            vulkanCommandBuffer,
+            textureContainer->activeTextureHandle->vulkanTexture);
+    }
+
+    vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = SDL_TRUE;
+}
+
+static void VULKAN_BindFragmentStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
+
+        vulkanCommandBuffer->fragmentStorageTextures[firstSlot + i] =
+            textureContainer->activeTextureHandle->vulkanTexture;
+
+        VULKAN_INTERNAL_TrackTexture(
+            vulkanCommandBuffer,
+            textureContainer->activeTextureHandle->vulkanTexture);
+    }
+
+    vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = SDL_TRUE;
+}
+
+static void VULKAN_BindFragmentStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanBufferContainer *bufferContainer;
+    Uint32 i;
+
+    for (i = 0; i < bindingCount; i += 1) {
+        bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
+
+        vulkanCommandBuffer->fragmentStorageBuffers[firstSlot + i] = bufferContainer->activeBufferHandle->vulkanBuffer;
+
+        VULKAN_INTERNAL_TrackBuffer(
+            vulkanCommandBuffer,
+            bufferContainer->activeBufferHandle->vulkanBuffer);
+    }
+
+    vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = SDL_TRUE;
+}
+
+static VulkanUniformBuffer *VULKAN_INTERNAL_AcquireUniformBufferFromPool(
+    VulkanCommandBuffer *commandBuffer)
+{
+    VulkanRenderer *renderer = commandBuffer->renderer;
+    VulkanUniformBuffer *uniformBuffer;
+
+    SDL_LockMutex(renderer->acquireUniformBufferLock);
+
+    if (renderer->uniformBufferPoolCount > 0) {
+        uniformBuffer = renderer->uniformBufferPool[renderer->uniformBufferPoolCount - 1];
+        renderer->uniformBufferPoolCount -= 1;
+    } else {
+        uniformBuffer = VULKAN_INTERNAL_CreateUniformBuffer(
+            renderer,
+            UNIFORM_BUFFER_SIZE);
+    }
+
+    SDL_UnlockMutex(renderer->acquireUniformBufferLock);
+
+    VULKAN_INTERNAL_TrackUniformBuffer(commandBuffer, uniformBuffer);
+
+    return uniformBuffer;
+}
+
+static void VULKAN_INTERNAL_ReturnUniformBufferToPool(
+    VulkanRenderer *renderer,
+    VulkanUniformBuffer *uniformBuffer)
+{
+    if (renderer->uniformBufferPoolCount >= renderer->uniformBufferPoolCapacity) {
+        renderer->uniformBufferPoolCapacity *= 2;
+        renderer->uniformBufferPool = SDL_realloc(
+            renderer->uniformBufferPool,
+            renderer->uniformBufferPoolCapacity * sizeof(VulkanUniformBuffer *));
+    }
+
+    renderer->uniformBufferPool[renderer->uniformBufferPoolCount] = uniformBuffer;
+    renderer->uniformBufferPoolCount += 1;
+
+    uniformBuffer->writeOffset = 0;
+    uniformBuffer->drawOffset = 0;
+}
+
+static void VULKAN_INTERNAL_PushUniformData(
+    VulkanCommandBuffer *commandBuffer,
+    VulkanUniformBufferStage uniformBufferStage,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    Uint32 blockSize =
+        VULKAN_INTERNAL_NextHighestAlignment32(
+            dataLengthInBytes,
+            commandBuffer->renderer->minUBOAlignment);
+
+    VulkanUniformBuffer *uniformBuffer;
+
+    if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_VERTEX) {
+        if (commandBuffer->vertexUniformBuffers[slotIndex] == NULL) {
+            commandBuffer->vertexUniformBuffers[slotIndex] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
+                commandBuffer);
+        }
+        uniformBuffer = commandBuffer->vertexUniformBuffers[slotIndex];
+    } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT) {
+        if (commandBuffer->fragmentUniformBuffers[slotIndex] == NULL) {
+            commandBuffer->fragmentUniformBuffers[slotIndex] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
+                commandBuffer);
+        }
+        uniformBuffer = commandBuffer->fragmentUniformBuffers[slotIndex];
+    } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE) {
+        if (commandBuffer->computeUniformBuffers[slotIndex] == NULL) {
+            commandBuffer->computeUniformBuffers[slotIndex] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
+                commandBuffer);
+        }
+        uniformBuffer = commandBuffer->computeUniformBuffers[slotIndex];
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+        return;
+    }
+
+    // If there is no more room, acquire a new uniform buffer
+    if (uniformBuffer->writeOffset + blockSize + MAX_UBO_SECTION_SIZE >= uniformBuffer->bufferHandle->vulkanBuffer->size) {
+        uniformBuffer = VULKAN_INTERNAL_AcquireUniformBufferFromPool(commandBuffer);
+
+        uniformBuffer->drawOffset = 0;
+        uniformBuffer->writeOffset = 0;
+
+        if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_VERTEX) {
+            commandBuffer->vertexUniformBuffers[slotIndex] = uniformBuffer;
+            commandBuffer->needNewVertexUniformDescriptorSet = SDL_TRUE;
+        } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT) {
+            commandBuffer->fragmentUniformBuffers[slotIndex] = uniformBuffer;
+            commandBuffer->needNewFragmentUniformDescriptorSet = SDL_TRUE;
+        } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE) {
+            commandBuffer->computeUniformBuffers[slotIndex] = uniformBuffer;
+            commandBuffer->needNewComputeUniformDescriptorSet = SDL_TRUE;
+        } else {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+            return;
+        }
+    }
+
+    uniformBuffer->drawOffset = uniformBuffer->writeOffset;
+
+    Uint8 *dst =
+        uniformBuffer->bufferHandle->vulkanBuffer->usedRegion->allocation->mapPointer +
+        uniformBuffer->bufferHandle->vulkanBuffer->usedRegion->resourceOffset +
+        uniformBuffer->writeOffset;
+
+    SDL_memcpy(
+        dst,
+        data,
+        dataLengthInBytes);
+
+    uniformBuffer->writeOffset += blockSize;
+
+    if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_VERTEX) {
+        commandBuffer->needNewVertexUniformOffsets = SDL_TRUE;
+    } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT) {
+        commandBuffer->needNewFragmentUniformOffsets = SDL_TRUE;
+    } else if (uniformBufferStage == VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE) {
+        commandBuffer->needNewComputeUniformOffsets = SDL_TRUE;
+    } else {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!");
+        return;
+    }
+}
+
+static void VULKAN_BeginRenderPass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuColorAttachmentInfo *colorAttachmentInfos,
+    Uint32 colorAttachmentCount,
+    SDL_GpuDepthStencilAttachmentInfo *depthStencilAttachmentInfo)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VkRenderPass renderPass;
+    VulkanFramebuffer *framebuffer;
+
+    Uint32 w, h;
+    VkClearValue *clearValues;
+    Uint32 clearCount = colorAttachmentCount;
+    Uint32 multisampleAttachmentCount = 0;
+    Uint32 totalColorAttachmentCount = 0;
+    Uint32 i;
+    SDL_GpuViewport defaultViewport;
+    SDL_Rect defaultScissor;
+    Uint32 framebufferWidth = UINT32_MAX;
+    Uint32 framebufferHeight = UINT32_MAX;
+
+    for (i = 0; i < colorAttachmentCount; i += 1) {
+        VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)colorAttachmentInfos[i].texture;
+
+        w = textureContainer->activeTextureHandle->vulkanTexture->dimensions.width >> colorAttachmentInfos[i].mipLevel;
+        h = textureContainer->activeTextureHandle->vulkanTexture->dimensions.height >> colorAttachmentInfos[i].mipLevel;
+
+        // The framebuffer cannot be larger than the smallest attachment.
+
+        if (w < framebufferWidth) {
+            framebufferWidth = w;
+        }
+
+        if (h < framebufferHeight) {
+            framebufferHeight = h;
+        }
+
+        // FIXME: validate this in gpu.c
+        if (!(textureContainer->header.info.usageFlags & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT)) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Color attachment texture was not designated as a target!");
+            return;
+        }
+    }
+
+    if (depthStencilAttachmentInfo != NULL) {
+        VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)depthStencilAttachmentInfo->texture;
+
+        w = textureContainer->activeTextureHandle->vulkanTexture->dimensions.width;
+        h = textureContainer->activeTextureHandle->vulkanTexture->dimensions.height;
+
+        // The framebuffer cannot be larger than the smallest attachment.
+
+        if (w < framebufferWidth) {
+            framebufferWidth = w;
+        }
+
+        if (h < framebufferHeight) {
+            framebufferHeight = h;
+        }
+
+        // FIXME: validate this in gpu.c
+        if (!(textureContainer->header.info.usageFlags & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT)) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Depth stencil attachment texture was not designated as a target!");
+            return;
+        }
+    }
+
+    for (i = 0; i < colorAttachmentCount; i += 1) {
+        VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)colorAttachmentInfos[i].texture;
+        VulkanTextureSubresource *subresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
+            renderer,
+            vulkanCommandBuffer,
+            textureContainer,
+            textureContainer->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorAttachmentInfos[i].layerOrDepthPlane,
+            colorAttachmentInfos[i].mipLevel,
+            colorAttachmentInfos[i].cycle,
+            VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT);
+
+        if (subresource->msaaTexHandle != NULL) {
+            // Transition the multisample attachment
+            VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+                renderer,
+                vulkanCommandBuffer,
+                VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT,
+                &subresource->msaaTexHandle->vulkanTexture->subresources[0]);
+
+            clearCount += 1;
+            multisampleAttachmentCount += 1;
+        }
+
+        vulkanCommandBuffer->colorAttachmentSubresources[i] = subresource;
+
+        VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, subresource->parent);
+        // TODO: do we need to track the msaa texture? or is it implicitly only used when the regular texture is used?
+    }
+
+    vulkanCommandBuffer->colorAttachmentSubresourceCount = colorAttachmentCount;
+
+    if (depthStencilAttachmentInfo != NULL) {
+        VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)depthStencilAttachmentInfo->texture;
+        VulkanTextureSubresource *subresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
+            renderer,
+            vulkanCommandBuffer,
+            textureContainer,
+            0,
+            0,
+            depthStencilAttachmentInfo->cycle,
+            VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT);
+
+        clearCount += 1;
+
+        vulkanCommandBuffer->depthStencilAttachmentSubresource = subresource;
+
+        VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, subresource->parent);
+    }
+
+    // Fetch required render objects
+
+    renderPass = VULKAN_INTERNAL_FetchRenderPass(
+        renderer,
+        vulkanCommandBuffer,
+        colorAttachmentInfos,
+        colorAttachmentCount,
+        depthStencilAttachmentInfo);
+
+    framebuffer = VULKAN_INTERNAL_FetchFramebuffer(
+        renderer,
+        renderPass,
+        colorAttachmentInfos,
+        colorAttachmentCount,
+        depthStencilAttachmentInfo,
+        framebufferWidth,
+        framebufferHeight);
+
+    VULKAN_INTERNAL_TrackFramebuffer(renderer, vulkanCommandBuffer, framebuffer);
+
+    // Set clear values
+
+    clearValues = SDL_stack_alloc(VkClearValue, clearCount);
+
+    totalColorAttachmentCount = colorAttachmentCount + multisampleAttachmentCount;
+
+    for (i = 0; i < totalColorAttachmentCount; i += 1) {
+        clearValues[i].color.float32[0] = colorAttachmentInfos[i].clearColor.r;
+        clearValues[i].color.float32[1] = colorAttachmentInfos[i].clearColor.g;
+        clearValues[i].color.float32[2] = colorAttachmentInfos[i].clearColor.b;
+        clearValues[i].color.float32[3] = colorAttachmentInfos[i].clearColor.a;
+
+        VulkanTextureContainer *container = (VulkanTextureContainer *)colorAttachmentInfos[i].texture;
+        VulkanTextureSubresource *subresource = VULKAN_INTERNAL_FetchTextureSubresource(
+            container,
+            container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorAttachmentInfos[i].layerOrDepthPlane,
+            colorAttachmentInfos[i].mipLevel);
+
+        if (subresource->parent->sampleCount > VK_SAMPLE_COUNT_1_BIT) {
+            clearValues[i + 1].color.float32[0] = colorAttachmentInfos[i].clearColor.r;
+            clearValues[i + 1].color.float32[1] = colorAttachmentInfos[i].clearColor.g;
+            clearValues[i + 1].color.float32[2] = colorAttachmentInfos[i].clearColor.b;
+            clearValues[i + 1].color.float32[3] = colorAttachmentInfos[i].clearColor.a;
+            i += 1;
+        }
+    }
+
+    if (depthStencilAttachmentInfo != NULL) {
+        clearValues[totalColorAttachmentCount].depthStencil.depth =
+            depthStencilAttachmentInfo->depthStencilClearValue.depth;
+        clearValues[totalColorAttachmentCount].depthStencil.stencil =
+            depthStencilAttachmentInfo->depthStencilClearValue.stencil;
+    }
+
+    VkRenderPassBeginInfo renderPassBeginInfo;
+    renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+    renderPassBeginInfo.pNext = NULL;
+    renderPassBeginInfo.renderPass = renderPass;
+    renderPassBeginInfo.framebuffer = framebuffer->framebuffer;
+    renderPassBeginInfo.pClearValues = clearValues;
+    renderPassBeginInfo.clearValueCount = clearCount;
+    renderPassBeginInfo.renderArea.extent.width = framebufferWidth;
+    renderPassBeginInfo.renderArea.extent.height = framebufferHeight;
+    renderPassBeginInfo.renderArea.offset.x = 0;
+    renderPassBeginInfo.renderArea.offset.y = 0;
+
+    renderer->vkCmdBeginRenderPass(
+        vulkanCommandBuffer->commandBuffer,
+        &renderPassBeginInfo,
+        VK_SUBPASS_CONTENTS_INLINE);
+
+    SDL_stack_free(clearValues);
+
+    // Set sensible default viewport state
+
+    defaultViewport.x = 0;
+    defaultViewport.y = 0;
+    defaultViewport.w = (float)framebufferWidth;
+    defaultViewport.h = (float)framebufferHeight;
+    defaultViewport.minDepth = 0;
+    defaultViewport.maxDepth = 1;
+
+    VULKAN_INTERNAL_SetCurrentViewport(
+        vulkanCommandBuffer,
+        &defaultViewport);
+
+    defaultScissor.x = 0;
+    defaultScissor.y = 0;
+    defaultScissor.w = (Sint32)framebufferWidth;
+    defaultScissor.h = (Sint32)framebufferHeight;
+
+    VULKAN_INTERNAL_SetCurrentScissor(
+        vulkanCommandBuffer,
+        &defaultScissor);
+}
+
+static void VULKAN_BindGraphicsPipeline(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuGraphicsPipeline *graphicsPipeline)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanGraphicsPipeline *pipeline = (VulkanGraphicsPipeline *)graphicsPipeline;
+
+    renderer->vkCmdBindPipeline(
+        vulkanCommandBuffer->commandBuffer,
+        VK_PIPELINE_BIND_POINT_GRAPHICS,
+        pipeline->pipeline);
+
+    vulkanCommandBuffer->currentGraphicsPipeline = pipeline;
+
+    VULKAN_INTERNAL_TrackGraphicsPipeline(vulkanCommandBuffer, pipeline);
+
+    renderer->vkCmdSetViewport(
+        vulkanCommandBuffer->commandBuffer,
+        0,
+        1,
+        &vulkanCommandBuffer->currentViewport);
+
+    renderer->vkCmdSetScissor(
+        vulkanCommandBuffer->commandBuffer,
+        0,
+        1,
+        &vulkanCommandBuffer->currentScissor);
+
+    // Acquire uniform buffers if necessary
+    for (Uint32 i = 0; i < pipeline->resourceLayout.vertexUniformBufferCount; i += 1) {
+        if (vulkanCommandBuffer->vertexUniformBuffers[i] == NULL) {
+            vulkanCommandBuffer->vertexUniformBuffers[i] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
+                vulkanCommandBuffer);
+        }
+    }
+
+    for (Uint32 i = 0; i < pipeline->resourceLayout.fragmentUniformBufferCount; i += 1) {
+        if (vulkanCommandBuffer->fragmentUniformBuffers[i] == NULL) {
+            vulkanCommandBuffer->fragmentUniformBuffers[i] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
+                vulkanCommandBuffer);
+        }
+    }
+
+    // Mark bindings as needed
+    vulkanCommandBuffer->needNewVertexResourceDescriptorSet = SDL_TRUE;
+    vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = SDL_TRUE;
+    vulkanCommandBuffer->needNewVertexUniformDescriptorSet = SDL_TRUE;
+    vulkanCommandBuffer->needNewFragmentUniformDescriptorSet = SDL_TRUE;
+    vulkanCommandBuffer->needNewVertexUniformOffsets = SDL_TRUE;
+    vulkanCommandBuffer->needNewFragmentUniformOffsets = SDL_TRUE;
+}
+
+static void VULKAN_BindVertexBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstBinding,
+    SDL_GpuBufferBinding *pBindings,
+    Uint32 bindingCount)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanBuffer *currentVulkanBuffer;
+    VkBuffer *buffers = SDL_stack_alloc(VkBuffer, bindingCount);
+    VkDeviceSize *offsets = SDL_stack_alloc(VkDeviceSize, bindingCount);
+    Uint32 i;
+
+    for (i = 0; i < bindingCount; i += 1) {
+        currentVulkanBuffer = ((VulkanBufferContainer *)pBindings[i].buffer)->activeBufferHandle->vulkanBuffer;
+        buffers[i] = currentVulkanBuffer->buffer;
+        offsets[i] = (VkDeviceSize)pBindings[i].offset;
+        VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, currentVulkanBuffer);
+    }
+
+    renderer->vkCmdBindVertexBuffers(
+        vulkanCommandBuffer->commandBuffer,
+        firstBinding,
+        bindingCount,
+        buffers,
+        offsets);
+
+    SDL_stack_free(buffers);
+    SDL_stack_free(offsets);
+}
+
+static void VULKAN_BindIndexBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferBinding *pBinding,
+    SDL_GpuIndexElementSize indexElementSize)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)pBinding->buffer)->activeBufferHandle->vulkanBuffer;
+
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
+
+    renderer->vkCmdBindIndexBuffer(
+        vulkanCommandBuffer->commandBuffer,
+        vulkanBuffer->buffer,
+        (VkDeviceSize)pBinding->offset,
+        SDLToVK_IndexType[indexElementSize]);
+}
+
+static void VULKAN_PushVertexUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+
+    VULKAN_INTERNAL_PushUniformData(
+        vulkanCommandBuffer,
+        VULKAN_UNIFORM_BUFFER_STAGE_VERTEX,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+static void VULKAN_PushFragmentUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+
+    VULKAN_INTERNAL_PushUniformData(
+        vulkanCommandBuffer,
+        VULKAN_UNIFORM_BUFFER_STAGE_FRAGMENT,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+static void VULKAN_EndRenderPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    Uint32 i;
+
+    renderer->vkCmdEndRenderPass(
+        vulkanCommandBuffer->commandBuffer);
+
+    for (i = 0; i < vulkanCommandBuffer->colorAttachmentSubresourceCount; i += 1) {
+        VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+            renderer,
+            vulkanCommandBuffer,
+            VULKAN_TEXTURE_USAGE_MODE_COLOR_ATTACHMENT,
+            vulkanCommandBuffer->colorAttachmentSubresources[i]);
+    }
+    vulkanCommandBuffer->colorAttachmentSubresourceCount = 0;
+
+    if (vulkanCommandBuffer->depthStencilAttachmentSubresource != NULL) {
+        VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+            renderer,
+            vulkanCommandBuffer,
+            VULKAN_TEXTURE_USAGE_MODE_DEPTH_STENCIL_ATTACHMENT,
+            vulkanCommandBuffer->depthStencilAttachmentSubresource);
+        vulkanCommandBuffer->depthStencilAttachmentSubresource = NULL;
+    }
+
+    vulkanCommandBuffer->currentGraphicsPipeline = NULL;
+
+    vulkanCommandBuffer->vertexResourceDescriptorSet = VK_NULL_HANDLE;
+    vulkanCommandBuffer->vertexUniformDescriptorSet = VK_NULL_HANDLE;
+    vulkanCommandBuffer->fragmentResourceDescriptorSet = VK_NULL_HANDLE;
+    vulkanCommandBuffer->fragmentUniformDescriptorSet = VK_NULL_HANDLE;
+
+    // Reset bind state
+    SDL_zeroa(vulkanCommandBuffer->colorAttachmentSubresources);
+    vulkanCommandBuffer->depthStencilAttachmentSubresource = NULL;
+
+    SDL_zeroa(vulkanCommandBuffer->vertexSamplers);
+    SDL_zeroa(vulkanCommandBuffer->vertexSamplerTextures);
+    SDL_zeroa(vulkanCommandBuffer->vertexStorageTextures);
+    SDL_zeroa(vulkanCommandBuffer->vertexStorageBuffers);
+
+    SDL_zeroa(vulkanCommandBuffer->fragmentSamplers);
+    SDL_zeroa(vulkanCommandBuffer->fragmentSamplerTextures);
+    SDL_zeroa(vulkanCommandBuffer->fragmentStorageTextures);
+    SDL_zeroa(vulkanCommandBuffer->fragmentStorageBuffers);
+}
+
+static void VULKAN_BeginComputePass(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuStorageTextureWriteOnlyBinding *storageTextureBindings,
+    Uint32 storageTextureBindingCount,
+    SDL_GpuStorageBufferWriteOnlyBinding *storageBufferBindings,
+    Uint32 storageBufferBindingCount)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
+    VulkanBufferContainer *bufferContainer;
+    VulkanBuffer *buffer;
+    Uint32 i;
+
+    vulkanCommandBuffer->writeOnlyComputeStorageTextureSubresourceCount = storageTextureBindingCount;
+
+    for (i = 0; i < storageTextureBindingCount; i += 1) {
+        VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextureBindings[i].texture;
+        if (!(textureContainer->activeTextureHandle->vulkanTexture->usageFlags & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT)) {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Attempted to bind read-only texture as compute write texture");
+        }
+
+        VulkanTextureSubresource *subresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
+            renderer,
+            vulkanCommandBuffer,
+            textureContainer,
+            storageTextureBindings[i].layer,
+            storageTextureBindings[i].mipLevel,
+            storageTextureBindings[i].cycle,
+            VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE);
+
+        vulkanCommandBuffer->writeOnlyComputeStorageTextureSubresources[i] = subresource;
+
+        VULKAN_INTERNAL_TrackTexture(
+            vulkanCommandBuffer,
+            subresource->parent);
+    }
+
+    for (i = 0; i < storageBufferBindingCount; i += 1) {
+        bufferContainer = (VulkanBufferContainer *)storageBufferBindings[i].buffer;
+        buffer = VULKAN_INTERNAL_PrepareBufferForWrite(
+            renderer,
+            vulkanCommandBuffer,
+            bufferContainer,
+            storageBufferBindings[i].cycle,
+            VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ);
+
+        vulkanCommandBuffer->writeOnlyComputeStorageBuffers[i] = buffer;
+
+        VULKAN_INTERNAL_TrackBuffer(
+            vulkanCommandBuffer,
+            buffer);
+    }
+}
+
+static void VULKAN_BindComputePipeline(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuComputePipeline *computePipeline)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanComputePipeline *vulkanComputePipeline = (VulkanComputePipeline *)computePipeline;
+
+    renderer->vkCmdBindPipeline(
+        vulkanCommandBuffer->commandBuffer,
+        VK_PIPELINE_BIND_POINT_COMPUTE,
+        vulkanComputePipeline->pipeline);
+
+    vulkanCommandBuffer->currentComputePipeline = vulkanComputePipeline;
+
+    VULKAN_INTERNAL_TrackComputePipeline(vulkanCommandBuffer, vulkanComputePipeline);
+
+    // Acquire uniform buffers if necessary
+    for (Uint32 i = 0; i < vulkanComputePipeline->resourceLayout.uniformBufferCount; i += 1) {
+        if (vulkanCommandBuffer->computeUniformBuffers[i] == NULL) {
+            vulkanCommandBuffer->computeUniformBuffers[i] = VULKAN_INTERNAL_AcquireUniformBufferFromPool(
+                vulkanCommandBuffer);
+        }
+    }
+
+    // Mark binding as needed
+    vulkanCommandBuffer->needNewComputeWriteOnlyDescriptorSet = SDL_TRUE;
+    vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = SDL_TRUE;
+    vulkanCommandBuffer->needNewComputeUniformDescriptorSet = SDL_TRUE;
+    vulkanCommandBuffer->needNewComputeUniformOffsets = SDL_TRUE;
+}
+
+static void VULKAN_BindComputeStorageTextures(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuTexture **storageTextures,
+    Uint32 bindingCount)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
+
+    for (Uint32 i = 0; i < bindingCount; i += 1) {
+        if (vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i] != NULL) {
+            VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
+                renderer,
+                vulkanCommandBuffer,
+                VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
+                vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i]);
+        }
+
+        VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
+
+        vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i] =
+            textureContainer->activeTextureHandle->vulkanTexture;
+
+        VULKAN_INTERNAL_TextureTransitionFromDefaultUsage(
+            renderer,
+            vulkanCommandBuffer,
+            VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
+            textureContainer->activeTextureHandle->vulkanTexture);
+
+        VULKAN_INTERNAL_TrackTexture(
+            vulkanCommandBuffer,
+            textureContainer->activeTextureHandle->vulkanTexture);
+    }
+
+    vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = SDL_TRUE;
+}
+
+static void VULKAN_BindComputeStorageBuffers(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 firstSlot,
+    SDL_GpuBuffer **storageBuffers,
+    Uint32 bindingCount)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
+    VulkanBufferContainer *bufferContainer;
+    Uint32 i;
+
+    for (i = 0; i < bindingCount; i += 1) {
+        if (vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i] != NULL) {
+            VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
+                renderer,
+                vulkanCommandBuffer,
+                VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
+                vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i]);
+        }
+
+        bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
+
+        vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i] = bufferContainer->activeBufferHandle->vulkanBuffer;
+
+        VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
+            renderer,
+            vulkanCommandBuffer,
+            VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
+            bufferContainer->activeBufferHandle->vulkanBuffer);
+
+        VULKAN_INTERNAL_TrackBuffer(
+            vulkanCommandBuffer,
+            bufferContainer->activeBufferHandle->vulkanBuffer);
+    }
+
+    vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = SDL_TRUE;
+}
+
+static void VULKAN_PushComputeUniformData(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 slotIndex,
+    const void *data,
+    Uint32 dataLengthInBytes)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+
+    VULKAN_INTERNAL_PushUniformData(
+        vulkanCommandBuffer,
+        VULKAN_UNIFORM_BUFFER_STAGE_COMPUTE,
+        slotIndex,
+        data,
+        dataLengthInBytes);
+}
+
+static void VULKAN_INTERNAL_BindComputeDescriptorSets(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer)
+{
+    VulkanComputePipelineResourceLayout *resourceLayout;
+    VkWriteDescriptorSet *writeDescriptorSets;
+    VkWriteDescriptorSet *currentWriteDescriptorSet;
+    DescriptorSetPool *descriptorSetPool;
+    VkDescriptorBufferInfo bufferInfos[MAX_STORAGE_BUFFERS_PER_STAGE]; // 8 is max for both read and write
+    VkDescriptorImageInfo imageInfos[MAX_STORAGE_TEXTURES_PER_STAGE];  // 8 is max for both read and write
+    Uint32 dynamicOffsets[MAX_UNIFORM_BUFFERS_PER_STAGE];
+    Uint32 bufferInfoCount = 0;
+    Uint32 imageInfoCount = 0;
+    Uint32 i;
+
+    resourceLayout = &commandBuffer->currentComputePipeline->resourceLayout;
+
+    if (commandBuffer->needNewComputeReadOnlyDescriptorSet) {
+        descriptorSetPool = &resourceLayout->descriptorSetPools[0];
+
+        commandBuffer->computeReadOnlyDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
+            renderer,
+            commandBuffer,
+            descriptorSetPool);
+
+        writeDescriptorSets = SDL_stack_alloc(
+            VkWriteDescriptorSet,
+            resourceLayout->readOnlyStorageTextureCount +
+                resourceLayout->readOnlyStorageBufferCount);
+
+        for (i = 0; i < resourceLayout->readOnlyStorageTextureCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[i];
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->computeReadOnlyDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pBufferInfo = NULL;
+
+            imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
+            imageInfos[imageInfoCount].imageView = commandBuffer->readOnlyComputeStorageTextures[i]->fullView;
+            imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+
+            currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
+
+            imageInfoCount += 1;
+        }
+
+        for (i = 0; i < resourceLayout->readOnlyStorageBufferCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[resourceLayout->readOnlyStorageTextureCount + i];
+
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = resourceLayout->readOnlyStorageTextureCount + i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->computeReadOnlyDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pImageInfo = NULL;
+
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->readOnlyComputeStorageBuffers[i]->buffer;
+            bufferInfos[bufferInfoCount].offset = 0;
+            bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
+
+            currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
+
+            bufferInfoCount += 1;
+        }
+
+        renderer->vkUpdateDescriptorSets(
+            renderer->logicalDevice,
+            resourceLayout->readOnlyStorageTextureCount + resourceLayout->readOnlyStorageBufferCount,
+            writeDescriptorSets,
+            0,
+            NULL);
+
+        renderer->vkCmdBindDescriptorSets(
+            commandBuffer->commandBuffer,
+            VK_PIPELINE_BIND_POINT_COMPUTE,
+            resourceLayout->pipelineLayout,
+            0,
+            1,
+            &commandBuffer->computeReadOnlyDescriptorSet,
+            0,
+            NULL);
+
+        SDL_stack_free(writeDescriptorSets);
+        bufferInfoCount = 0;
+        imageInfoCount = 0;
+
+        commandBuffer->needNewComputeReadOnlyDescriptorSet = SDL_FALSE;
+    }
+
+    if (commandBuffer->needNewComputeWriteOnlyDescriptorSet) {
+        descriptorSetPool = &resourceLayout->descriptorSetPools[1];
+
+        commandBuffer->computeWriteOnlyDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
+            renderer,
+            commandBuffer,
+            descriptorSetPool);
+
+        writeDescriptorSets = SDL_stack_alloc(
+            VkWriteDescriptorSet,
+            resourceLayout->writeOnlyStorageTextureCount +
+                resourceLayout->writeOnlyStorageBufferCount);
+
+        for (i = 0; i < resourceLayout->writeOnlyStorageTextureCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[i];
+
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->computeWriteOnlyDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pBufferInfo = NULL;
+
+            imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
+            imageInfos[imageInfoCount].imageView = commandBuffer->writeOnlyComputeStorageTextureSubresources[i]->computeWriteView;
+            imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+
+            currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
+
+            imageInfoCount += 1;
+        }
+
+        for (i = 0; i < resourceLayout->writeOnlyStorageBufferCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[resourceLayout->writeOnlyStorageTextureCount + i];
+
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = resourceLayout->writeOnlyStorageTextureCount + i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->computeWriteOnlyDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pImageInfo = NULL;
+
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->writeOnlyComputeStorageBuffers[i]->buffer;
+            bufferInfos[bufferInfoCount].offset = 0;
+            bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
+
+            currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
+
+            bufferInfoCount += 1;
+        }
+
+        renderer->vkUpdateDescriptorSets(
+            renderer->logicalDevice,
+            resourceLayout->writeOnlyStorageTextureCount + resourceLayout->writeOnlyStorageBufferCount,
+            writeDescriptorSets,
+            0,
+            NULL);
+
+        renderer->vkCmdBindDescriptorSets(
+            commandBuffer->commandBuffer,
+            VK_PIPELINE_BIND_POINT_COMPUTE,
+            resourceLayout->pipelineLayout,
+            1,
+            1,
+            &commandBuffer->computeWriteOnlyDescriptorSet,
+            0,
+            NULL);
+
+        SDL_stack_free(writeDescriptorSets);
+        bufferInfoCount = 0;
+        imageInfoCount = 0;
+
+        commandBuffer->needNewComputeWriteOnlyDescriptorSet = SDL_FALSE;
+    }
+
+    if (commandBuffer->needNewComputeUniformDescriptorSet) {
+        descriptorSetPool = &resourceLayout->descriptorSetPools[2];
+
+        commandBuffer->computeUniformDescriptorSet = VULKAN_INTERNAL_FetchDescriptorSet(
+            renderer,
+            commandBuffer,
+            descriptorSetPool);
+
+        writeDescriptorSets = SDL_stack_alloc(
+            VkWriteDescriptorSet,
+            resourceLayout->uniformBufferCount);
+
+        for (i = 0; i < resourceLayout->uniformBufferCount; i += 1) {
+            currentWriteDescriptorSet = &writeDescriptorSets[i];
+
+            currentWriteDescriptorSet->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+            currentWriteDescriptorSet->pNext = NULL;
+            currentWriteDescriptorSet->descriptorCount = 1;
+            currentWriteDescriptorSet->descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+            currentWriteDescriptorSet->dstArrayElement = 0;
+            currentWriteDescriptorSet->dstBinding = i;
+            currentWriteDescriptorSet->dstSet = commandBuffer->computeUniformDescriptorSet;
+            currentWriteDescriptorSet->pTexelBufferView = NULL;
+            currentWriteDescriptorSet->pImageInfo = NULL;
+
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->computeUniformBuffers[i]->bufferHandle->vulkanBuffer->buffer;
+            bufferInfos[bufferInfoCount].offset = 0;
+            bufferInfos[bufferInfoCount].range = MAX_UBO_SECTION_SIZE;
+
+            currentWriteDescriptorSet->pBufferInfo = &bufferInfos[bufferInfoCount];
+
+            bufferInfoCount += 1;
+        }
+
+        renderer->vkUpdateDescriptorSets(
+            renderer->logicalDevice,
+            resourceLayout->uniformBufferCount,
+            writeDescriptorSets,
+            0,
+            NULL);
+
+        SDL_stack_free(writeDescriptorSets);
+        bufferInfoCount = 0;
+        imageInfoCount = 0;
+
+        commandBuffer->needNewComputeUniformDescriptorSet = SDL_FALSE;
+        commandBuffer->needNewComputeUniformOffsets = SDL_TRUE;
+    }
+
+    if (commandBuffer->needNewComputeUniformOffsets) {
+        for (i = 0; i < resourceLayout->uniformBufferCount; i += 1) {
+            dynamicOffsets[i] = commandBuffer->computeUniformBuffers[i]->drawOffset;
+        }
+
+        renderer->vkCmdBindDescriptorSets(
+            commandBuffer->commandBuffer,
+            VK_PIPELINE_BIND_POINT_COMPUTE,
+            resourceLayout->pipelineLayout,
+            2,
+            1,
+            &commandBuffer->computeUniformDescriptorSet,
+            resourceLayout->uniformBufferCount,
+            dynamicOffsets);
+
+        commandBuffer->needNewComputeUniformOffsets = SDL_FALSE;
+    }
+}
+
+static void VULKAN_DispatchCompute(
+    SDL_GpuCommandBuffer *commandBuffer,
+    Uint32 groupCountX,
+    Uint32 groupCountY,
+    Uint32 groupCountZ)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+
+    VULKAN_INTERNAL_BindComputeDescriptorSets(renderer, vulkanCommandBuffer);
+
+    renderer->vkCmdDispatch(
+        vulkanCommandBuffer->commandBuffer,
+        groupCountX,
+        groupCountY,
+        groupCountZ);
+}
+
+static void VULKAN_DispatchComputeIndirect(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBuffer *buffer,
+    Uint32 offsetInBytes)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanBuffer *vulkanBuffer = ((VulkanBufferContainer *)buffer)->activeBufferHandle->vulkanBuffer;
+
+    VULKAN_INTERNAL_BindComputeDescriptorSets(renderer, vulkanCommandBuffer);
+
+    renderer->vkCmdDispatchIndirect(
+        vulkanCommandBuffer->commandBuffer,
+        vulkanBuffer->buffer,
+        offsetInBytes);
+
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
+}
+
+static void VULKAN_EndComputePass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    Uint32 i;
+
+    for (i = 0; i < vulkanCommandBuffer->writeOnlyComputeStorageTextureSubresourceCount; i += 1) {
+        VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+            vulkanCommandBuffer->renderer,
+            vulkanCommandBuffer,
+            VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
+            vulkanCommandBuffer->writeOnlyComputeStorageTextureSubresources[i]);
+        vulkanCommandBuffer->writeOnlyComputeStorageTextureSubresources[i] = NULL;
+    }
+    vulkanCommandBuffer->writeOnlyComputeStorageTextureSubresourceCount = 0;
+
+    for (i = 0; i < MAX_COMPUTE_WRITE_BUFFERS; i += 1) {
+        if (vulkanCommandBuffer->writeOnlyComputeStorageBuffers[i] != NULL) {
+            VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
+                vulkanCommandBuffer->renderer,
+                vulkanCommandBuffer,
+                VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE,
+                vulkanCommandBuffer->writeOnlyComputeStorageBuffers[i]);
+
+            vulkanCommandBuffer->writeOnlyComputeStorageBuffers[i] = NULL;
+        }
+    }
+
+    for (i = 0; i < MAX_STORAGE_TEXTURES_PER_STAGE; i += 1) {
+        if (vulkanCommandBuffer->readOnlyComputeStorageTextures[i] != NULL) {
+            VULKAN_INTERNAL_TextureTransitionToDefaultUsage(
+                vulkanCommandBuffer->renderer,
+                vulkanCommandBuffer,
+                VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ,
+                vulkanCommandBuffer->readOnlyComputeStorageTextures[i]);
+
+            vulkanCommandBuffer->readOnlyComputeStorageTextures[i] = NULL;
+        }
+    }
+
+    for (i = 0; i < MAX_STORAGE_BUFFERS_PER_STAGE; i += 1) {
+        if (vulkanCommandBuffer->readOnlyComputeStorageBuffers[i] != NULL) {
+            VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
+                vulkanCommandBuffer->renderer,
+                vulkanCommandBuffer,
+                VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ,
+                vulkanCommandBuffer->readOnlyComputeStorageBuffers[i]);
+
+            vulkanCommandBuffer->readOnlyComputeStorageBuffers[i] = NULL;
+        }
+    }
+
+    vulkanCommandBuffer->currentComputePipeline = NULL;
+
+    vulkanCommandBuffer->computeReadOnlyDescriptorSet = VK_NULL_HANDLE;
+    vulkanCommandBuffer->computeWriteOnlyDescriptorSet = VK_NULL_HANDLE;
+    vulkanCommandBuffer->computeUniformDescriptorSet = VK_NULL_HANDLE;
+}
+
+static void *VULKAN_MapTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer,
+    SDL_bool cycle)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)transferBuffer;
+
+    if (
+        cycle &&
+        SDL_AtomicGet(&transferBufferContainer->activeBufferHandle->vulkanBuffer->referenceCount) > 0) {
+        VULKAN_INTERNAL_CycleActiveBuffer(
+            renderer,
+            transferBufferContainer);
+    }
+
+    Uint8 *bufferPointer =
+        transferBufferContainer->activeBufferHandle->vulkanBuffer->usedRegion->allocation->mapPointer +
+        transferBufferContainer->activeBufferHandle->vulkanBuffer->usedRegion->resourceOffset;
+
+    return bufferPointer;
+}
+
+static void VULKAN_UnmapTransferBuffer(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTransferBuffer *transferBuffer)
+{
+    // no-op because transfer buffers are persistently mapped
+    (void)driverData;
+    (void)transferBuffer;
+}
+
+static void VULKAN_BeginCopyPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    // no-op
+    (void)commandBuffer;
+}
+
+static void VULKAN_UploadToTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureTransferInfo *source,
+    SDL_GpuTextureRegion *destination,
+    SDL_bool cycle)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)source->transferBuffer;
+    VulkanTextureContainer *vulkanTextureContainer = (VulkanTextureContainer *)destination->texture;
+    VulkanTextureSubresource *vulkanTextureSubresource;
+    VkBufferImageCopy imageCopy;
+
+    // Note that the transfer buffer does not need a barrier, as it is synced by the client
+
+    vulkanTextureSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
+        renderer,
+        vulkanCommandBuffer,
+        vulkanTextureContainer,
+        destination->layer,
+        destination->mipLevel,
+        cycle,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION);
+
+    imageCopy.imageExtent.width = destination->w;
+    imageCopy.imageExtent.height = destination->h;
+    imageCopy.imageExtent.depth = destination->d;
+    imageCopy.imageOffset.x = destination->x;
+    imageCopy.imageOffset.y = destination->y;
+    imageCopy.imageOffset.z = destination->z;
+    imageCopy.imageSubresource.aspectMask = vulkanTextureSubresource->parent->aspectFlags;
+    imageCopy.imageSubresource.baseArrayLayer = destination->layer;
+    imageCopy.imageSubresource.layerCount = 1;
+    imageCopy.imageSubresource.mipLevel = destination->mipLevel;
+    imageCopy.bufferOffset = source->offset;
+    imageCopy.bufferRowLength = source->imagePitch;
+    imageCopy.bufferImageHeight = source->imageHeight;
+
+    renderer->vkCmdCopyBufferToImage(
+        vulkanCommandBuffer->commandBuffer,
+        transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer,
+        vulkanTextureSubresource->parent->image,
+        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+        1,
+        &imageCopy);
+
+    VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
+        vulkanTextureSubresource);
+
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer);
+    VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, vulkanTextureSubresource->parent);
+}
+
+static void VULKAN_UploadToBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTransferBufferLocation *source,
+    SDL_GpuBufferRegion *destination,
+    SDL_bool cycle)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)source->transferBuffer;
+    VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)destination->buffer;
+    VkBufferCopy bufferCopy;
+
+    // Note that the transfer buffer does not need a barrier, as it is synced by the client
+
+    VulkanBuffer *vulkanBuffer = VULKAN_INTERNAL_PrepareBufferForWrite(
+        renderer,
+        vulkanCommandBuffer,
+        bufferContainer,
+        cycle,
+        VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION);
+
+    bufferCopy.srcOffset = source->offset;
+    bufferCopy.dstOffset = destination->offset;
+    bufferCopy.size = destination->size;
+
+    renderer->vkCmdCopyBuffer(
+        vulkanCommandBuffer->commandBuffer,
+        transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer,
+        vulkanBuffer->buffer,
+        1,
+        &bufferCopy);
+
+    VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
+        vulkanBuffer);
+
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer);
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, vulkanBuffer);
+}
+
+// Readback
+
+static void VULKAN_DownloadFromTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureRegion *source,
+    SDL_GpuTextureTransferInfo *destination)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
+    VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)source->texture;
+    VulkanTextureSubresource *vulkanTextureSubresource;
+    VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)destination->transferBuffer;
+    VkBufferImageCopy imageCopy;
+    vulkanTextureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
+        textureContainer,
+        source->layer,
+        source->mipLevel);
+
+    // Note that the transfer buffer does not need a barrier, as it is synced by the client
+
+    VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
+        vulkanTextureSubresource);
+
+    imageCopy.imageExtent.width = source->w;
+    imageCopy.imageExtent.height = source->h;
+    imageCopy.imageExtent.depth = source->d;
+    imageCopy.imageOffset.x = source->x;
+    imageCopy.imageOffset.y = source->y;
+    imageCopy.imageOffset.z = source->z;
+    imageCopy.imageSubresource.aspectMask = vulkanTextureSubresource->parent->aspectFlags;
+    imageCopy.imageSubresource.baseArrayLayer = source->layer;
+    imageCopy.imageSubresource.layerCount = 1;
+    imageCopy.imageSubresource.mipLevel = source->mipLevel;
+    imageCopy.bufferOffset = destination->offset;
+    imageCopy.bufferRowLength = destination->imagePitch;
+    imageCopy.bufferImageHeight = destination->imageHeight;
+
+    renderer->vkCmdCopyImageToBuffer(
+        vulkanCommandBuffer->commandBuffer,
+        vulkanTextureSubresource->parent->image,
+        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+        transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer,
+        1,
+        &imageCopy);
+
+    VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
+        vulkanTextureSubresource);
+
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer);
+    VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, vulkanTextureSubresource->parent);
+}
+
+static void VULKAN_DownloadFromBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferRegion *source,
+    SDL_GpuTransferBufferLocation *destination)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = vulkanCommandBuffer->renderer;
+    VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)source->buffer;
+    VulkanBufferContainer *transferBufferContainer = (VulkanBufferContainer *)destination->transferBuffer;
+    VkBufferCopy bufferCopy;
+
+    // Note that transfer buffer does not need a barrier, as it is synced by the client
+
+    VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
+        bufferContainer->activeBufferHandle->vulkanBuffer);
+
+    bufferCopy.srcOffset = source->offset;
+    bufferCopy.dstOffset = destination->offset;
+    bufferCopy.size = source->size;
+
+    renderer->vkCmdCopyBuffer(
+        vulkanCommandBuffer->commandBuffer,
+        bufferContainer->activeBufferHandle->vulkanBuffer->buffer,
+        transferBufferContainer->activeBufferHandle->vulkanBuffer->buffer,
+        1,
+        &bufferCopy);
+
+    VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
+        bufferContainer->activeBufferHandle->vulkanBuffer);
+
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, transferBufferContainer->activeBufferHandle->vulkanBuffer);
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, bufferContainer->activeBufferHandle->vulkanBuffer);
+}
+
+static void VULKAN_CopyTextureToTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTextureLocation *source,
+    SDL_GpuTextureLocation *destination,
+    Uint32 w,
+    Uint32 h,
+    Uint32 d,
+    SDL_bool cycle)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanTextureSubresource *srcSubresource;
+    VulkanTextureSubresource *dstSubresource;
+    VkImageCopy imageCopy;
+
+    srcSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
+        (VulkanTextureContainer *)source->texture,
+        source->layer,
+        source->mipLevel);
+
+    dstSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
+        renderer,
+        vulkanCommandBuffer,
+        (VulkanTextureContainer *)destination->texture,
+        destination->layer,
+        destination->mipLevel,
+        cycle,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION);
+
+    VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
+        srcSubresource);
+
+    imageCopy.srcOffset.x = source->x;
+    imageCopy.srcOffset.y = source->y;
+    imageCopy.srcOffset.z = source->z;
+    imageCopy.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
+    imageCopy.srcSubresource.baseArrayLayer = source->layer;
+    imageCopy.srcSubresource.layerCount = 1;
+    imageCopy.srcSubresource.mipLevel = source->mipLevel;
+    imageCopy.dstOffset.x = destination->x;
+    imageCopy.dstOffset.y = destination->y;
+    imageCopy.dstOffset.z = destination->z;
+    imageCopy.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
+    imageCopy.dstSubresource.baseArrayLayer = destination->layer;
+    imageCopy.dstSubresource.layerCount = 1;
+    imageCopy.dstSubresource.mipLevel = destination->mipLevel;
+    imageCopy.extent.width = w;
+    imageCopy.extent.height = h;
+    imageCopy.extent.depth = d;
+
+    renderer->vkCmdCopyImage(
+        vulkanCommandBuffer->commandBuffer,
+        srcSubresource->parent->image,
+        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+        dstSubresource->parent->image,
+        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+        1,
+        &imageCopy);
+
+    VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
+        srcSubresource);
+
+    VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
+        dstSubresource);
+
+    VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcSubresource->parent);
+    VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstSubresource->parent);
+}
+
+static void VULKAN_CopyBufferToBuffer(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBufferLocation *source,
+    SDL_GpuBufferLocation *destination,
+    Uint32 size,
+    SDL_bool cycle)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanBufferContainer *srcContainer = (VulkanBufferContainer *)source->buffer;
+    VulkanBufferContainer *dstContainer = (VulkanBufferContainer *)destination->buffer;
+    VkBufferCopy bufferCopy;
+
+    VulkanBuffer *dstBuffer = VULKAN_INTERNAL_PrepareBufferForWrite(
+        renderer,
+        vulkanCommandBuffer,
+        dstContainer,
+        cycle,
+        VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION);
+
+    VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
+        srcContainer->activeBufferHandle->vulkanBuffer);
+
+    bufferCopy.srcOffset = source->offset;
+    bufferCopy.dstOffset = destination->offset;
+    bufferCopy.size = size;
+
+    renderer->vkCmdCopyBuffer(
+        vulkanCommandBuffer->commandBuffer,
+        srcContainer->activeBufferHandle->vulkanBuffer->buffer,
+        dstBuffer->buffer,
+        1,
+        &bufferCopy);
+
+    VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
+        srcContainer->activeBufferHandle->vulkanBuffer);
+
+    VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
+        dstBuffer);
+
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, srcContainer->activeBufferHandle->vulkanBuffer);
+    VULKAN_INTERNAL_TrackBuffer(vulkanCommandBuffer, dstBuffer);
+}
+
+static void VULKAN_GenerateMipmaps(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuTexture *texture)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VulkanTexture *vulkanTexture = ((VulkanTextureContainer *)texture)->activeTextureHandle->vulkanTexture;
+    VulkanTextureSubresource *srcTextureSubresource;
+    VulkanTextureSubresource *dstTextureSubresource;
+    VkImageBlit blit;
+
+    // Blit each slice sequentially. Barriers, barriers everywhere!
+    for (Uint32 layerOrDepthIndex = 0; layerOrDepthIndex < vulkanTexture->layerCount; layerOrDepthIndex += 1)
+        for (Uint32 level = 1; level < vulkanTexture->levelCount; level += 1) {
+            Uint32 layer = vulkanTexture->type == SDL_GPU_TEXTURETYPE_3D ? 0 : layerOrDepthIndex;
+            Uint32 depth = vulkanTexture->type == SDL_GPU_TEXTURETYPE_3D ? layerOrDepthIndex : 0;
+
+            Uint32 srcSubresourceIndex = VULKAN_INTERNAL_GetTextureSubresourceIndex(
+                level - 1,
+                layer,
+                vulkanTexture->levelCount);
+            Uint32 dstSubresourceIndex = VULKAN_INTERNAL_GetTextureSubresourceIndex(
+                level,
+                layer,
+                vulkanTexture->levelCount);
+
+            srcTextureSubresource = &vulkanTexture->subresources[srcSubresourceIndex];
+            dstTextureSubresource = &vulkanTexture->subresources[dstSubresourceIndex];
+
+            VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+                renderer,
+                vulkanCommandBuffer,
+                VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
+                srcTextureSubresource);
+
+            VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+                renderer,
+                vulkanCommandBuffer,
+                VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
+                dstTextureSubresource);
+
+            blit.srcOffsets[0].x = 0;
+            blit.srcOffsets[0].y = 0;
+            blit.srcOffsets[0].z = depth;
+
+            blit.srcOffsets[1].x = vulkanTexture->dimensions.width >> (level - 1);
+            blit.srcOffsets[1].y = vulkanTexture->dimensions.height >> (level - 1);
+            blit.srcOffsets[1].z = depth + 1;
+
+            blit.dstOffsets[0].x = 0;
+            blit.dstOffsets[0].y = 0;
+            blit.dstOffsets[0].z = depth;
+
+            blit.dstOffsets[1].x = vulkanTexture->dimensions.width >> level;
+            blit.dstOffsets[1].y = vulkanTexture->dimensions.height >> level;
+            blit.dstOffsets[1].z = depth + 1;
+
+            blit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+            blit.srcSubresource.baseArrayLayer = layer;
+            blit.srcSubresource.layerCount = 1;
+            blit.srcSubresource.mipLevel = level - 1;
+
+            blit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+            blit.dstSubresource.baseArrayLayer = layer;
+            blit.dstSubresource.layerCount = 1;
+            blit.dstSubresource.mipLevel = level;
+
+            renderer->vkCmdBlitImage(
+                vulkanCommandBuffer->commandBuffer,
+                vulkanTexture->image,
+                VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                vulkanTexture->image,
+                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                1,
+                &blit,
+                VK_FILTER_LINEAR);
+
+            VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+                renderer,
+                vulkanCommandBuffer,
+                VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
+                srcTextureSubresource);
+
+            VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+                renderer,
+                vulkanCommandBuffer,
+                VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
+                dstTextureSubresource);
+
+            VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcTextureSubresource->parent);
+            VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstTextureSubresource->parent);
+        }
+}
+
+static void VULKAN_EndCopyPass(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    // no-op
+    (void)commandBuffer;
+}
+
+static void VULKAN_Blit(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_GpuBlitRegion *source,
+    SDL_GpuBlitRegion *destination,
+    SDL_FlipMode flipMode,
+    SDL_GpuFilter filterMode,
+    SDL_bool cycle)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    TextureCommonHeader *srcHeader = (TextureCommonHeader *)source->texture;
+    TextureCommonHeader *dstHeader = (TextureCommonHeader *)destination->texture;
+    VkImageBlit region;
+    Uint32 srcLayer = srcHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : source->layerOrDepthPlane;
+    Uint32 srcDepth = srcHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? source->layerOrDepthPlane : 0;
+    Uint32 dstLayer = dstHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : destination->layerOrDepthPlane;
+    Uint32 dstDepth = dstHeader->info.type == SDL_GPU_TEXTURETYPE_3D ? destination->layerOrDepthPlane : 0;
+    int32_t swap;
+
+    VulkanTextureSubresource *srcSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
+        (VulkanTextureContainer *)source->texture,
+        srcLayer,
+        source->mipLevel);
+
+    VulkanTextureSubresource *dstSubresource = VULKAN_INTERNAL_PrepareTextureSubresourceForWrite(
+        renderer,
+        vulkanCommandBuffer,
+        (VulkanTextureContainer *)destination->texture,
+        dstLayer,
+        destination->mipLevel,
+        cycle,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION);
+
+    VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
+        srcSubresource);
+
+    region.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
+    region.srcSubresource.baseArrayLayer = srcSubresource->layer;
+    region.srcSubresource.layerCount = 1;
+    region.srcSubresource.mipLevel = srcSubresource->level;
+    region.srcOffsets[0].x = source->x;
+    region.srcOffsets[0].y = source->y;
+    region.srcOffsets[0].z = srcDepth;
+    region.srcOffsets[1].x = source->x + source->w;
+    region.srcOffsets[1].y = source->y + source->h;
+    region.srcOffsets[1].z = srcDepth + 1;
+
+    if (flipMode & SDL_FLIP_HORIZONTAL) {
+        // flip the x positions
+        swap = region.srcOffsets[0].x;
+        region.srcOffsets[0].x = region.srcOffsets[1].x;
+        region.srcOffsets[1].x = swap;
+    }
+
+    if (flipMode & SDL_FLIP_VERTICAL) {
+        // flip the y positions
+        swap = region.srcOffsets[0].y;
+        region.srcOffsets[0].y = region.srcOffsets[1].y;
+        region.srcOffsets[1].y = swap;
+    }
+
+    region.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
+    region.dstSubresource.baseArrayLayer = dstSubresource->layer;
+    region.dstSubresource.layerCount = 1;
+    region.dstSubresource.mipLevel = dstSubresource->level;
+    region.dstOffsets[0].x = destination->x;
+    region.dstOffsets[0].y = destination->y;
+    region.dstOffsets[0].z = dstDepth;
+    region.dstOffsets[1].x = destination->x + destination->w;
+    region.dstOffsets[1].y = destination->y + destination->h;
+    region.dstOffsets[1].z = dstDepth + 1;
+
+    renderer->vkCmdBlitImage(
+        vulkanCommandBuffer->commandBuffer,
+        srcSubresource->parent->image,
+        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+        dstSubresource->parent->image,
+        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+        1,
+        &region,
+        SDLToVK_Filter[filterMode]);
+
+    VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
+        srcSubresource);
+
+    VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+        renderer,
+        vulkanCommandBuffer,
+        VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
+        dstSubresource);
+
+    VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, srcSubresource->parent);
+    VULKAN_INTERNAL_TrackTexture(vulkanCommandBuffer, dstSubresource->parent);
+}
+
+static void VULKAN_INTERNAL_AllocateCommandBuffers(
+    VulkanRenderer *renderer,
+    VulkanCommandPool *vulkanCommandPool,
+    Uint32 allocateCount)
+{
+    VkCommandBufferAllocateInfo allocateInfo;
+    VkResult vulkanResult;
+    Uint32 i;
+    VkCommandBuffer *commandBuffers = SDL_stack_alloc(VkCommandBuffer, allocateCount);
+    VulkanCommandBuffer *commandBuffer;
+
+    vulkanCommandPool->inactiveCommandBufferCapacity += allocateCount;
+
+    vulkanCommandPool->inactiveCommandBuffers = SDL_realloc(
+        vulkanCommandPool->inactiveCommandBuffers,
+        sizeof(VulkanCommandBuffer *) *
+            vulkanCommandPool->inactiveCommandBufferCapacity);
+
+    allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+    allocateInfo.pNext = NULL;
+    allocateInfo.commandPool = vulkanCommandPool->commandPool;
+    allocateInfo.commandBufferCount = allocateCount;
+    allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+
+    vulkanResult = renderer->vkAllocateCommandBuffers(
+        renderer->logicalDevice,
+        &allocateInfo,
+        commandBuffers);
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkAllocateCommandBuffers", vulkanResult);
+        SDL_stack_free(commandBuffers);
+        return;
+    }
+
+    for (i = 0; i < allocateCount; i += 1) {
+        commandBuffer = SDL_malloc(sizeof(VulkanCommandBuffer));
+        commandBuffer->renderer = renderer;
+        commandBuffer->commandPool = vulkanCommandPool;
+        commandBuffer->commandBuffer = commandBuffers[i];
+
+        commandBuffer->inFlightFence = VK_NULL_HANDLE;
+
+        // Presentation tracking
+
+        commandBuffer->presentDataCapacity = 1;
+        commandBuffer->presentDataCount = 0;
+        commandBuffer->presentDatas = SDL_malloc(
+            commandBuffer->presentDataCapacity * sizeof(VulkanPresentData));
+
+        commandBuffer->waitSemaphoreCapacity = 1;
+        commandBuffer->waitSemaphoreCount = 0;
+        commandBuffer->waitSemaphores = SDL_malloc(
+            commandBuffer->waitSemaphoreCapacity * sizeof(VkSemaphore));
+
+        commandBuffer->signalSemaphoreCapacity = 1;
+        commandBuffer->signalSemaphoreCount = 0;
+        commandBuffer->signalSemaphores = SDL_malloc(
+            commandBuffer->signalSemaphoreCapacity * sizeof(VkSemaphore));
+
+        // Descriptor set tracking
+
+        commandBuffer->boundDescriptorSetDataCapacity = 16;
+        commandBuffer->boundDescriptorSetDataCount = 0;
+        commandBuffer->boundDescriptorSetDatas = SDL_malloc(
+            commandBuffer->boundDescriptorSetDataCapacity * sizeof(DescriptorSetData));
+
+        // Resource bind tracking
+
+        commandBuffer->needNewVertexResourceDescriptorSet = SDL_TRUE;
+        commandBuffer->needNewVertexUniformDescriptorSet = SDL_TRUE;
+        commandBuffer->needNewVertexUniformOffsets = SDL_TRUE;
+        commandBuffer->needNewFragmentResourceDescriptorSet = SDL_TRUE;
+        commandBuffer->needNewFragmentUniformDescriptorSet = SDL_TRUE;
+        commandBuffer->needNewFragmentUniformOffsets = SDL_TRUE;
+
+        commandBuffer->needNewComputeWriteOnlyDescriptorSet = SDL_TRUE;
+        commandBuffer->needNewComputeReadOnlyDescriptorSet = SDL_TRUE;
+        commandBuffer->needNewComputeUniformDescriptorSet = SDL_TRUE;
+        commandBuffer->needNewComputeUniformOffsets = SDL_TRUE;
+
+        commandBuffer->vertexResourceDescriptorSet = VK_NULL_HANDLE;
+        commandBuffer->vertexUniformDescriptorSet = VK_NULL_HANDLE;
+        commandBuffer->fragmentResourceDescriptorSet = VK_NULL_HANDLE;
+        commandBuffer->fragmentUniformDescriptorSet = VK_NULL_HANDLE;
+
+        commandBuffer->computeReadOnlyDescriptorSet = VK_NULL_HANDLE;
+        commandBuffer->computeWriteOnlyDescriptorSet = VK_NULL_HANDLE;
+        commandBuffer->computeUniformDescriptorSet = VK_NULL_HANDLE;
+
+        // Resource tracking
+
+        commandBuffer->usedBufferCapacity = 4;
+        commandBuffer->usedBufferCount = 0;
+        commandBuffer->usedBuffers = SDL_malloc(
+            commandBuffer->usedBufferCapacity * sizeof(VulkanBuffer *));
+
+        commandBuffer->usedTextureCapacity = 4;
+        commandBuffer->usedTextureCount = 0;
+        commandBuffer->usedTextures = SDL_malloc(
+            commandBuffer->usedTextureCapacity * sizeof(VulkanTexture *));
+
+        commandBuffer->usedSamplerCapacity = 4;
+        commandBuffer->usedSamplerCount = 0;
+        commandBuffer->usedSamplers = SDL_malloc(
+            commandBuffer->usedSamplerCapacity * sizeof(VulkanSampler *));
+
+        commandBuffer->usedGraphicsPipelineCapacity = 4;
+        commandBuffer->usedGraphicsPipelineCount = 0;
+        commandBuffer->usedGraphicsPipelines = SDL_malloc(
+            commandBuffer->usedGraphicsPipelineCapacity * sizeof(VulkanGraphicsPipeline *));
+
+        commandBuffer->usedComputePipelineCapacity = 4;
+        commandBuffer->usedComputePipelineCount = 0;
+        commandBuffer->usedComputePipelines = SDL_malloc(
+            commandBuffer->usedComputePipelineCapacity * sizeof(VulkanComputePipeline *));
+
+        commandBuffer->usedFramebufferCapacity = 4;
+        commandBuffer->usedFramebufferCount = 0;
+        commandBuffer->usedFramebuffers = SDL_malloc(
+            commandBuffer->usedFramebufferCapacity * sizeof(VulkanFramebuffer *));
+
+        commandBuffer->usedUniformBufferCapacity = 4;
+        commandBuffer->usedUniformBufferCount = 0;
+        commandBuffer->usedUniformBuffers = SDL_malloc(
+            commandBuffer->usedUniformBufferCapacity * sizeof(VulkanUniformBuffer *));
+
+        // Pool it!
+
+        vulkanCommandPool->inactiveCommandBuffers[vulkanCommandPool->inactiveCommandBufferCount] = commandBuffer;
+        vulkanCommandPool->inactiveCommandBufferCount += 1;
+    }
+
+    SDL_stack_free(commandBuffers);
+}
+
+static VulkanCommandPool *VULKAN_INTERNAL_FetchCommandPool(
+    VulkanRenderer *renderer,
+    SDL_ThreadID threadID)
+{
+    VulkanCommandPool *vulkanCommandPool = NULL;
+    VkCommandPoolCreateInfo commandPoolCreateInfo;
+    VkResult vulkanResult;
+    CommandPoolHashTableKey key;
+    key.threadID = threadID;
+
+    SDL_bool result = SDL_FindInHashTable(
+        renderer->commandPoolHashTable,
+        (const void *)&key,
+        (const void **)&vulkanCommandPool);
+
+    if (result) {
+        return vulkanCommandPool;
+    }
+
+    vulkanCommandPool = (VulkanCommandPool *)SDL_malloc(sizeof(VulkanCommandPool));
+
+    commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+    commandPoolCreateInfo.pNext = NULL;
+    commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+    commandPoolCreateInfo.queueFamilyIndex = renderer->queueFamilyIndex;
+
+    vulkanResult = renderer->vkCreateCommandPool(
+        renderer->logicalDevice,
+        &commandPoolCreateInfo,
+        NULL,
+        &vulkanCommandPool->commandPool);
+
+    if (vulkanResult != VK_SUCCESS) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create command pool!");
+        LogVulkanResultAsError("vkCreateCommandPool", vulkanResult);
+        return NULL;
+    }
+
+    vulkanCommandPool->threadID = threadID;
+
+    vulkanCommandPool->inactiveCommandBufferCapacity = 0;
+    vulkanCommandPool->inactiveCommandBufferCount = 0;
+    vulkanCommandPool->inactiveCommandBuffers = NULL;
+
+    VULKAN_INTERNAL_AllocateCommandBuffers(
+        renderer,
+        vulkanCommandPool,
+        2);
+
+    CommandPoolHashTableKey *allocedKey = SDL_malloc(sizeof(CommandPoolHashTableKey));
+    allocedKey->threadID = threadID;
+
+    SDL_InsertIntoHashTable(
+        renderer->commandPoolHashTable,
+        (const void *)allocedKey,
+        (const void *)vulkanCommandPool);
+
+    return vulkanCommandPool;
+}
+
+static VulkanCommandBuffer *VULKAN_INTERNAL_GetInactiveCommandBufferFromPool(
+    VulkanRenderer *renderer,
+    SDL_ThreadID threadID)
+{
+    VulkanCommandPool *commandPool =
+        VULKAN_INTERNAL_FetchCommandPool(renderer, threadID);
+    VulkanCommandBuffer *commandBuffer;
+
+    if (commandPool == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to fetch command pool!");
+        return NULL;
+    }
+
+    if (commandPool->inactiveCommandBufferCount == 0) {
+        VULKAN_INTERNAL_AllocateCommandBuffers(
+            renderer,
+            commandPool,
+            commandPool->inactiveCommandBufferCapacity);
+    }
+
+    commandBuffer = commandPool->inactiveCommandBuffers[commandPool->inactiveCommandBufferCount - 1];
+    commandPool->inactiveCommandBufferCount -= 1;
+
+    return commandBuffer;
+}
+
+static SDL_GpuCommandBuffer *VULKAN_AcquireCommandBuffer(
+    SDL_GpuRenderer *driverData)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VkResult result;
+    Uint32 i;
+
+    SDL_ThreadID threadID = SDL_GetCurrentThreadID();
+
+    SDL_LockMutex(renderer->acquireCommandBufferLock);
+
+    VulkanCommandBuffer *commandBuffer =
+        VULKAN_INTERNAL_GetInactiveCommandBufferFromPool(renderer, threadID);
+
+    SDL_UnlockMutex(renderer->acquireCommandBufferLock);
+
+    if (commandBuffer == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to acquire command buffer!");
+        return NULL;
+    }
+
+    // Reset state
+
+    commandBuffer->currentComputePipeline = NULL;
+    commandBuffer->currentGraphicsPipeline = NULL;
+
+    for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) {
+        commandBuffer->colorAttachmentSubresources[i] = NULL;
+    }
+
+    for (i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
+        commandBuffer->vertexUniformBuffers[i] = NULL;
+        commandBuffer->fragmentUniformBuffers[i] = NULL;
+        commandBuffer->computeUniformBuffers[i] = NULL;
+    }
+
+    commandBuffer->depthStencilAttachmentSubresource = NULL;
+
+    commandBuffer->needNewVertexResourceDescriptorSet = SDL_TRUE;
+    commandBuffer->needNewVertexUniformDescriptorSet = SDL_TRUE;
+    commandBuffer->needNewVertexUniformOffsets = SDL_TRUE;
+    commandBuffer->needNewFragmentResourceDescriptorSet = SDL_TRUE;
+    commandBuffer->needNewFragmentUniformDescriptorSet = SDL_TRUE;
+    commandBuffer->needNewFragmentUniformOffsets = SDL_TRUE;
+
+    commandBuffer->needNewComputeReadOnlyDescriptorSet = SDL_TRUE;
+    commandBuffer->needNewComputeUniformDescriptorSet = SDL_TRUE;
+    commandBuffer->needNewComputeUniformOffsets = SDL_TRUE;
+
+    commandBuffer->vertexResourceDescriptorSet = VK_NULL_HANDLE;
+    commandBuffer->vertexUniformDescriptorSet = VK_NULL_HANDLE;
+    commandBuffer->fragmentResourceDescriptorSet = VK_NULL_HANDLE;
+    commandBuffer->fragmentUniformDescriptorSet = VK_NULL_HANDLE;
+
+    commandBuffer->computeReadOnlyDescriptorSet = VK_NULL_HANDLE;
+    commandBuffer->computeWriteOnlyDescriptorSet = VK_NULL_HANDLE;
+    commandBuffer->computeUniformDescriptorSet = VK_NULL_HANDLE;
+
+    SDL_zeroa(commandBuffer->vertexSamplerTextures);
+    SDL_zeroa(commandBuffer->vertexSamplers);
+    SDL_zeroa(commandBuffer->vertexStorageTextures);
+    SDL_zeroa(commandBuffer->vertexStorageBuffers);
+
+    SDL_zeroa(commandBuffer->fragmentSamplerTextures);
+    SDL_zeroa(commandBuffer->fragmentSamplers);
+    SDL_zeroa(commandBuffer->fragmentStorageTextures);
+    SDL_zeroa(commandBuffer->fragmentStorageBuffers);
+
+    SDL_zeroa(commandBuffer->writeOnlyComputeStorageTextureSubresources);
+    commandBuffer->writeOnlyComputeStorageTextureSubresourceCount = 0;
+    SDL_zeroa(commandBuffer->writeOnlyComputeStorageBuffers);
+    SDL_zeroa(commandBuffer->readOnlyComputeStorageTextures);
+    SDL_zeroa(commandBuffer->readOnlyComputeStorageBuffers);
+
+    commandBuffer->autoReleaseFence = 1;
+
+    commandBuffer->isDefrag = 0;
+
+    /* Reset the command buffer here to avoid resets being called
+     * from a separate thread than where the command buffer was acquired
+     */
+    result = renderer->vkResetCommandBuffer(
+        commandBuffer->commandBuffer,
+        VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
+
+    if (result != VK_SUCCESS) {
+        LogVulkanResultAsError("vkResetCommandBuffer", result);
+    }
+
+    VULKAN_INTERNAL_BeginCommandBuffer(renderer, commandBuffer);
+
+    return (SDL_GpuCommandBuffer *)commandBuffer;
+}
+
+static SDL_bool VULKAN_QueryFence(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuFence *fence)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VkResult result;
+
+    result = renderer->vkGetFenceStatus(
+        renderer->logicalDevice,
+        ((VulkanFenceHandle *)fence)->fence);
+
+    if (result == VK_SUCCESS) {
+        return 1;
+    } else if (result == VK_NOT_READY) {
+        return 0;
+    } else {
+        LogVulkanResultAsError("vkGetFenceStatus", result);
+        return 0;
+    }
+}
+
+static void VULKAN_INTERNAL_ReturnFenceToPool(
+    VulkanRenderer *renderer,
+    VulkanFenceHandle *fenceHandle)
+{
+    SDL_LockMutex(renderer->fencePool.lock);
+
+    EXPAND_ARRAY_IF_NEEDED(
+        renderer->fencePool.availableFences,
+        VulkanFenceHandle *,
+        renderer->fencePool.availableFenceCount + 1,
+        renderer->fencePool.availableFenceCapacity,
+        renderer->fencePool.availableFenceCapacity * 2);
+
+    renderer->fencePool.availableFences[renderer->fencePool.availableFenceCount] = fenceHandle;
+    renderer->fencePool.availableFenceCount += 1;
+
+    SDL_UnlockMutex(renderer->fencePool.lock);
+}
+
+static void VULKAN_ReleaseFence(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuFence *fence)
+{
+    VulkanFenceHandle *handle = (VulkanFenceHandle *)fence;
+
+    if (SDL_AtomicDecRef(&handle->referenceCount)) {
+        VULKAN_INTERNAL_ReturnFenceToPool((VulkanRenderer *)driverData, handle);
+    }
+}
+
+static WindowData *VULKAN_INTERNAL_FetchWindowData(
+    SDL_Window *window)
+{
+    SDL_PropertiesID properties = SDL_GetWindowProperties(window);
+    return (WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
+}
+
+static SDL_bool VULKAN_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
+{
+    SDL_Window *w = (SDL_Window *)userdata;
+    WindowData *data;
+    if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
+        data = VULKAN_INTERNAL_FetchWindowData(w);
+        data->needsSwapchainRecreate = SDL_TRUE;
+    }
+
+    return SDL_FALSE;
+}
+
+static SDL_bool VULKAN_SupportsSwapchainComposition(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
+    VkSurfaceKHR surface;
+    SwapchainSupportDetails supportDetails;
+    SDL_bool result = SDL_FALSE;
+
+    if (windowData == NULL || windowData->swapchainData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Must claim window before querying swapchain composition support!");
+        return SDL_FALSE;
+    }
+
+    surface = windowData->swapchainData->surface;
+
+    if (VULKAN_INTERNAL_QuerySwapchainSupport(
+            renderer,
+            renderer->physicalDevice,
+            surface,
+            &supportDetails)) {
+
+        result = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
+            SwapchainCompositionToFormat[swapchainComposition],
+            SwapchainCompositionToColorSpace[swapchainComposition],
+            supportDetails.formats,
+            supportDetails.formatsLength);
+
+        if (!result) {
+            // Let's try again with the fallback format...
+            result = VULKAN_INTERNAL_VerifySwapSurfaceFormat(
+                SwapchainCompositionToFallbackFormat[swapchainComposition],
+                SwapchainCompositionToColorSpace[swapchainComposition],
+                supportDetails.formats,
+                supportDetails.formatsLength);
+        }
+
+        SDL_free(supportDetails.formats);
+        SDL_free(supportDetails.presentModes);
+    }
+
+    return result;
+}
+
+static SDL_bool VULKAN_SupportsPresentMode(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuPresentMode presentMode)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
+    VkSurfaceKHR surface;
+    SwapchainSupportDetails supportDetails;
+    SDL_bool result = SDL_FALSE;
+
+    if (windowData == NULL || windowData->swapchainData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Must claim window before querying present mode support!");
+        return SDL_FALSE;
+    }
+
+    surface = windowData->swapchainData->surface;
+
+    if (VULKAN_INTERNAL_QuerySwapchainSupport(
+            renderer,
+            renderer->physicalDevice,
+            surface,
+            &supportDetails)) {
+
+        result = VULKAN_INTERNAL_VerifySwapPresentMode(
+            SDLToVK_PresentMode[presentMode],
+            supportDetails.presentModes,
+            supportDetails.presentModesLength);
+
+        SDL_free(supportDetails.formats);
+        SDL_free(supportDetails.presentModes);
+    }
+
+    return result;
+}
+
+static SDL_bool VULKAN_ClaimWindow(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        windowData = SDL_malloc(sizeof(WindowData));
+        windowData->window = window;
+        windowData->presentMode = SDL_GPU_PRESENTMODE_VSYNC;
+        windowData->swapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR;
+
+        if (VULKAN_INTERNAL_CreateSwapchain(renderer, windowData)) {
+            SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
+
+            if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
+                renderer->claimedWindowCapacity *= 2;
+                renderer->claimedWindows = SDL_realloc(
+                    renderer->claimedWindows,
+                    renderer->claimedWindowCapacity * sizeof(WindowData *));
+            }
+
+            renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
+            renderer->claimedWindowCount += 1;
+
+            SDL_AddEventWatch(VULKAN_INTERNAL_OnWindowResize, window);
+
+            return 1;
+        } else {
+            SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not create swapchain, failed to claim window!");
+            SDL_free(windowData);
+            return 0;
+        }
+    } else {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Window already claimed!");
+        return 0;
+    }
+}
+
+static void VULKAN_UnclaimWindow(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
+    Uint32 i;
+
+    if (windowData == NULL) {
+        return;
+    }
+
+    if (windowData->swapchainData != NULL) {
+        VULKAN_Wait(driverData);
+
+        for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+            if (windowData->swapchainData->inFlightFences[i] != NULL) {
+                VULKAN_ReleaseFence(
+                    driverData,
+                    (SDL_GpuFence *)windowData->swapchainData->inFlightFences[i]);
+            }
+        }
+
+        VULKAN_INTERNAL_DestroySwapchain(
+            (VulkanRenderer *)driverData,
+            windowData);
+    }
+
+    for (i = 0; i < renderer->claimedWindowCount; i += 1) {
+        if (renderer->claimedWindows[i]->window == window) {
+            renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1];
+            renderer->claimedWindowCount -= 1;
+            break;
+        }
+    }
+
+    SDL_free(windowData);
+
+    SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
+    SDL_DelEventWatch(VULKAN_INTERNAL_OnWindowResize, window);
+}
+
+static SDL_bool VULKAN_INTERNAL_RecreateSwapchain(
+    VulkanRenderer *renderer,
+    WindowData *windowData)
+{
+    Uint32 i;
+
+    if (windowData->swapchainData != NULL) {
+        VULKAN_Wait((SDL_GpuRenderer *)renderer);
+
+        for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
+            if (windowData->swapchainData->inFlightFences[i] != NULL) {
+                VULKAN_ReleaseFence(
+                    (SDL_GpuRenderer *)renderer,
+                    (SDL_GpuFence *)windowData->swapchainData->inFlightFences[i]);
+            }
+        }
+    }
+
+    VULKAN_INTERNAL_DestroySwapchain(renderer, windowData);
+    return VULKAN_INTERNAL_CreateSwapchain(renderer, windowData);
+}
+
+static SDL_GpuTexture *VULKAN_AcquireSwapchainTexture(
+    SDL_GpuCommandBuffer *commandBuffer,
+    SDL_Window *window,
+    Uint32 *pWidth,
+    Uint32 *pHeight)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    Uint32 swapchainImageIndex;
+    WindowData *windowData;
+    VulkanSwapchainData *swapchainData;
+    VkResult acquireResult = VK_SUCCESS;
+    VulkanTextureContainer *swapchainTextureContainer = NULL;
+    VulkanPresentData *presentData;
+
+    windowData = VULKAN_INTERNAL_FetchWindowData(window);
+    if (windowData == NULL) {
+        return NULL;
+    }
+
+    swapchainData = windowData->swapchainData;
+
+    // Window is claimed but swapchain is invalid!
+    if (swapchainData == NULL) {
+        if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) {
+            // Window is minimized, don't bother
+            return NULL;
+        }
+
+        // Let's try to recreate
+        VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
+        swapchainData = windowData->swapchainData;
+
+        if (swapchainData == NULL) {
+            SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Failed to recreate swapchain!");
+            return NULL;
+        }
+    }
+
+    if (swapchainData->inFlightFences[swapchainData->frameCounter] != NULL) {
+        if (swapchainData->presentMode == VK_PRESENT_MODE_FIFO_KHR) {
+            // In VSYNC mode, block until the least recent presented frame is done
+            VULKAN_WaitForFences(
+                (SDL_GpuRenderer *)renderer,
+                SDL_TRUE,
+                (SDL_GpuFence **)&swapchainData->inFlightFences[swapchainData->frameCounter],
+                1);
+        } else {
+            if (!VULKAN_QueryFence(
+                    (SDL_GpuRenderer *)renderer,
+                    (SDL_GpuFence *)swapchainData->inFlightFences[swapchainData->frameCounter])) {
+                /*
+                 * In MAILBOX or IMMEDIATE mode, if the least recent fence is not signaled,
+                 * return NULL to indicate that rendering should be skipped
+                 */
+                return NULL;
+            }
+        }
+
+        VULKAN_ReleaseFence(
+            (SDL_GpuRenderer *)renderer,
+            (SDL_GpuFence *)swapchainData->inFlightFences[swapchainData->frameCounter]);
+
+        swapchainData->inFlightFences[swapchainData->frameCounter] = NULL;
+    }
+
+    // If window data marked as needing swapchain recreate, try to recreate
+    if (windowData->needsSwapchainRecreate) {
+        VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
+        swapchainData = windowData->swapchainData;
+
+        if (swapchainData == NULL) {
+            SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Failed to recreate swapchain!");
+            return NULL;
+        }
+    }
+
+    // Finally, try to acquire!
+    acquireResult = renderer->vkAcquireNextImageKHR(
+        renderer->logicalDevice,
+        swapchainData->swapchain,
+        UINT64_MAX,
+        swapchainData->imageAvailableSemaphore[swapchainData->frameCounter],
+        VK_NULL_HANDLE,
+        &swapchainImageIndex);
+
+    // Acquisition is invalid, let's try to recreate
+    if (acquireResult != VK_SUCCESS && acquireResult != VK_SUBOPTIMAL_KHR) {
+        VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
+        swapchainData = windowData->swapchainData;
+
+        if (swapchainData == NULL) {
+            SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Failed to recreate swapchain!");
+            return NULL;
+        }
+
+        acquireResult = renderer->vkAcquireNextImageKHR(
+            renderer->logicalDevice,
+            swapchainData->swapchain,
+            UINT64_MAX,
+            swapchainData->imageAvailableSemaphore[swapchainData->frameCounter],
+            VK_NULL_HANDLE,
+            &swapchainImageIndex);
+
+        if (acquireResult != VK_SUCCESS && acquireResult != VK_SUBOPTIMAL_KHR) {
+            SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Failed to acquire swapchain texture!");
+            return NULL;
+        }
+    }
+
+    swapchainTextureContainer = &swapchainData->textureContainers[swapchainImageIndex];
+
+    // We need a special execution dependency with pWaitDstStageMask or image transition can start before acquire finishes
+
+    VkImageMemoryBarrier imageBarrier;
+    imageBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+    imageBarrier.pNext = NULL;
+    imageBarrier.srcAccessMask = 0;
+    imageBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+    imageBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+    imageBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+    imageBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    imageBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+    imageBarrier.image = swapchainTextureContainer->activeTextureHandle->vulkanTexture->image;
+    imageBarrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+    imageBarrier.subresourceRange.baseMipLevel = 0;
+    imageBarrier.subresourceRange.levelCount = 1;
+    imageBarrier.subresourceRange.baseArrayLayer = 0;
+    imageBarrier.subresourceRange.layerCount = 1;
+
+    renderer->vkCmdPipelineBarrier(
+        vulkanCommandBuffer->commandBuffer,
+        VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+        VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+        0,
+        0,
+        NULL,
+        0,
+        NULL,
+        1,
+        &imageBarrier);
+
+    // Set up present struct
+
+    if (vulkanCommandBuffer->presentDataCount == vulkanCommandBuffer->presentDataCapacity) {
+        vulkanCommandBuffer->presentDataCapacity += 1;
+        vulkanCommandBuffer->presentDatas = SDL_realloc(
+            vulkanCommandBuffer->presentDatas,
+            vulkanCommandBuffer->presentDataCapacity * sizeof(VulkanPresentData));
+    }
+
+    presentData = &vulkanCommandBuffer->presentDatas[vulkanCommandBuffer->presentDataCount];
+    vulkanCommandBuffer->presentDataCount += 1;
+
+    presentData->windowData = windowData;
+    presentData->swapchainImageIndex = swapchainImageIndex;
+
+    // Set up present semaphores
+
+    if (vulkanCommandBuffer->waitSemaphoreCount == vulkanCommandBuffer->waitSemaphoreCapacity) {
+        vulkanCommandBuffer->waitSemaphoreCapacity += 1;
+        vulkanCommandBuffer->waitSemaphores = SDL_realloc(
+            vulkanCommandBuffer->waitSemaphores,
+            vulkanCommandBuffer->waitSemaphoreCapacity * sizeof(VkSemaphore));
+    }
+
+    vulkanCommandBuffer->waitSemaphores[vulkanCommandBuffer->waitSemaphoreCount] =
+        swapchainData->imageAvailableSemaphore[swapchainData->frameCounter];
+    vulkanCommandBuffer->waitSemaphoreCount += 1;
+
+    if (vulkanCommandBuffer->signalSemaphoreCount == vulkanCommandBuffer->signalSemaphoreCapacity) {
+        vulkanCommandBuffer->signalSemaphoreCapacity += 1;
+        vulkanCommandBuffer->signalSemaphores = SDL_realloc(
+            vulkanCommandBuffer->signalSemaphores,
+            vulkanCommandBuffer->signalSemaphoreCapacity * sizeof(VkSemaphore));
+    }
+
+    vulkanCommandBuffer->signalSemaphores[vulkanCommandBuffer->signalSemaphoreCount] =
+        swapchainData->renderFinishedSemaphore[swapchainData->frameCounter];
+    vulkanCommandBuffer->signalSemaphoreCount += 1;
+
+    *pWidth = swapchainData->textureContainers[swapchainData->frameCounter].header.info.width;
+    *pHeight = swapchainData->textureContainers[swapchainData->frameCounter].header.info.height;
+
+    return (SDL_GpuTexture *)swapchainTextureContainer;
+}
+
+static SDL_GpuTextureFormat VULKAN_GetSwapchainTextureFormat(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window)
+{
+    WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Cannot get swapchain format, window has not been claimed!");
+        return 0;
+    }
+
+    if (windowData->swapchainData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Cannot get swapchain format, swapchain is currently invalid!");
+        return 0;
+    }
+
+    return SwapchainCompositionToSDLFormat(
+        windowData->swapchainComposition,
+        windowData->swapchainData->usingFallbackFormat);
+}
+
+static SDL_bool VULKAN_SetSwapchainParameters(
+    SDL_GpuRenderer *driverData,
+    SDL_Window *window,
+    SDL_GpuSwapchainComposition swapchainComposition,
+    SDL_GpuPresentMode presentMode)
+{
+    WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
+
+    if (windowData == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Cannot set swapchain parameters on unclaimed window!");
+        return SDL_FALSE;
+    }
+
+    if (!VULKAN_SupportsSwapchainComposition(driverData, window, swapchainComposition)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Swapchain composition not supported!");
+        return SDL_FALSE;
+    }
+
+    if (!VULKAN_SupportsPresentMode(driverData, window, presentMode)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Present mode not supported!");
+        return SDL_FALSE;
+    }
+
+    windowData->presentMode = presentMode;
+    windowData->swapchainComposition = swapchainComposition;
+
+    return VULKAN_INTERNAL_RecreateSwapchain(
+        (VulkanRenderer *)driverData,
+        windowData);
+}
+
+// Submission structure
+
+static VulkanFenceHandle *VULKAN_INTERNAL_AcquireFenceFromPool(
+    VulkanRenderer *renderer)
+{
+    VulkanFenceHandle *handle;
+    VkFenceCreateInfo fenceCreateInfo;
+    VkFence fence;
+    VkResult vulkanResult;
+
+    if (renderer->fencePool.availableFenceCount == 0) {
+        // Create fence
+        fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+        fenceCreateInfo.pNext = NULL;
+        fenceCreateInfo.flags = 0;
+
+        vulkanResult = renderer->vkCreateFence(
+            renderer->logicalDevice,
+            &fenceCreateInfo,
+            NULL,
+            &fence);
+
+        if (vulkanResult != VK_SUCCESS) {
+            LogVulkanResultAsError("vkCreateFence", vulkanResult);
+            return NULL;
+        }
+
+        handle = SDL_malloc(sizeof(VulkanFenceHandle));
+        handle->fence = fence;
+        SDL_AtomicSet(&handle->referenceCount, 0);
+        return handle;
+    }
+
+    SDL_LockMutex(renderer->fencePool.lock);
+
+    handle = renderer->fencePool.availableFences[renderer->fencePool.availableFenceCount - 1];
+    renderer->fencePool.availableFenceCount -= 1;
+
+    vulkanResult = renderer->vkResetFences(
+        renderer->logicalDevice,
+        1,
+        &handle->fence);
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkResetFences", vulkanResult);
+    }
+
+    SDL_UnlockMutex(renderer->fencePool.lock);
+
+    return handle;
+}
+
+static void VULKAN_INTERNAL_PerformPendingDestroys(
+    VulkanRenderer *renderer)
+{
+    SDL_LockMutex(renderer->disposeLock);
+
+    for (Sint32 i = renderer->texturesToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->texturesToDestroy[i]->referenceCount) == 0) {
+            VULKAN_INTERNAL_DestroyTexture(
+                renderer,
+                renderer->texturesToDestroy[i]);
+
+            renderer->texturesToDestroy[i] = renderer->texturesToDestroy[renderer->texturesToDestroyCount - 1];
+            renderer->texturesToDestroyCount -= 1;
+        }
+    }
+
+    for (Sint32 i = renderer->buffersToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->buffersToDestroy[i]->referenceCount) == 0) {
+            VULKAN_INTERNAL_DestroyBuffer(
+                renderer,
+                renderer->buffersToDestroy[i]);
+
+            renderer->buffersToDestroy[i] = renderer->buffersToDestroy[renderer->buffersToDestroyCount - 1];
+            renderer->buffersToDestroyCount -= 1;
+        }
+    }
+
+    for (Sint32 i = renderer->graphicsPipelinesToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->graphicsPipelinesToDestroy[i]->referenceCount) == 0) {
+            VULKAN_INTERNAL_DestroyGraphicsPipeline(
+                renderer,
+                renderer->graphicsPipelinesToDestroy[i]);
+
+            renderer->graphicsPipelinesToDestroy[i] = renderer->graphicsPipelinesToDestroy[renderer->graphicsPipelinesToDestroyCount - 1];
+            renderer->graphicsPipelinesToDestroyCount -= 1;
+        }
+    }
+
+    for (Sint32 i = renderer->computePipelinesToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->computePipelinesToDestroy[i]->referenceCount) == 0) {
+            VULKAN_INTERNAL_DestroyComputePipeline(
+                renderer,
+                renderer->computePipelinesToDestroy[i]);
+
+            renderer->computePipelinesToDestroy[i] = renderer->computePipelinesToDestroy[renderer->computePipelinesToDestroyCount - 1];
+            renderer->computePipelinesToDestroyCount -= 1;
+        }
+    }
+
+    for (Sint32 i = renderer->shadersToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->shadersToDestroy[i]->referenceCount) == 0) {
+            VULKAN_INTERNAL_DestroyShader(
+                renderer,
+                renderer->shadersToDestroy[i]);
+
+            renderer->shadersToDestroy[i] = renderer->shadersToDestroy[renderer->shadersToDestroyCount - 1];
+            renderer->shadersToDestroyCount -= 1;
+        }
+    }
+
+    for (Sint32 i = renderer->samplersToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->samplersToDestroy[i]->referenceCount) == 0) {
+            VULKAN_INTERNAL_DestroySampler(
+                renderer,
+                renderer->samplersToDestroy[i]);
+
+            renderer->samplersToDestroy[i] = renderer->samplersToDestroy[renderer->samplersToDestroyCount - 1];
+            renderer->samplersToDestroyCount -= 1;
+        }
+    }
+
+    for (Sint32 i = renderer->framebuffersToDestroyCount - 1; i >= 0; i -= 1) {
+        if (SDL_AtomicGet(&renderer->framebuffersToDestroy[i]->referenceCount) == 0) {
+            VULKAN_INTERNAL_DestroyFramebuffer(
+                renderer,
+                renderer->framebuffersToDestroy[i]);
+
+            renderer->framebuffersToDestroy[i] = renderer->framebuffersToDestroy[renderer->framebuffersToDestroyCount - 1];
+            renderer->framebuffersToDestroyCount -= 1;
+        }
+    }
+
+    SDL_UnlockMutex(renderer->disposeLock);
+}
+
+static void VULKAN_INTERNAL_CleanCommandBuffer(
+    VulkanRenderer *renderer,
+    VulkanCommandBuffer *commandBuffer)
+{
+    Uint32 i;
+    DescriptorSetData *descriptorSetData;
+
+    if (commandBuffer->autoReleaseFence) {
+        VULKAN_ReleaseFence(
+            (SDL_GpuRenderer *)renderer,
+            (SDL_GpuFence *)commandBuffer->inFlightFence);
+
+        commandBuffer->inFlightFence = NULL;
+    }
+
+    // Bound descriptor sets are now available
+
+    for (i = 0; i < commandBuffer->boundDescriptorSetDataCount; i += 1) {
+        descriptorSetData = &commandBuffer->boundDescriptorSetDatas[i];
+
+        SDL_LockMutex(descriptorSetData->descriptorSetPool->lock);
+
+        if (descriptorSetData->descriptorSetPool->inactiveDescriptorSetCount == descriptorSetData->descriptorSetPool->inactiveDescriptorSetCapacity) {
+            descriptorSetData->descriptorSetPool->inactiveDescriptorSetCapacity *= 2;
+            descriptorSetData->descriptorSetPool->inactiveDescriptorSets = SDL_realloc(
+                descriptorSetData->descriptorSetPool->inactiveDescriptorSets,
+                descriptorSetData->descriptorSetPool->inactiveDescriptorSetCapacity * sizeof(VkDescriptorSet));
+        }
+
+        descriptorSetData->descriptorSetPool->inactiveDescriptorSets[descriptorSetData->descriptorSetPool->inactiveDescriptorSetCount] = descriptorSetData->descriptorSet;
+        descriptorSetData->descriptorSetPool->inactiveDescriptorSetCount += 1;
+
+        SDL_UnlockMutex(descriptorSetData->descriptorSetPool->lock);
+    }
+
+    commandBuffer->boundDescriptorSetDataCount = 0;
+
+    // Uniform buffers are now available
+
+    SDL_LockMutex(renderer->acquireUniformBufferLock);
+
+    for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) {
+        VULKAN_INTERNAL_ReturnUniformBufferToPool(
+            renderer,
+            commandBuffer->usedUniformBuffers[i]);
+    }
+    commandBuffer->usedUniformBufferCount = 0;
+
+    SDL_UnlockMutex(renderer->acquireUniformBufferLock);
+
+    // Decrement reference counts
+
+    for (i = 0; i < commandBuffer->usedBufferCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount);
+    }
+    commandBuffer->usedBufferCount = 0;
+
+    for (i = 0; i < commandBuffer->usedTextureCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount);
+    }
+    commandBuffer->usedTextureCount = 0;
+
+    for (i = 0; i < commandBuffer->usedSamplerCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedSamplers[i]->referenceCount);
+    }
+    commandBuffer->usedSamplerCount = 0;
+
+    for (i = 0; i < commandBuffer->usedGraphicsPipelineCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedGraphicsPipelines[i]->referenceCount);
+    }
+    commandBuffer->usedGraphicsPipelineCount = 0;
+
+    for (i = 0; i < commandBuffer->usedComputePipelineCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedComputePipelines[i]->referenceCount);
+    }
+    commandBuffer->usedComputePipelineCount = 0;
+
+    for (i = 0; i < commandBuffer->usedFramebufferCount; i += 1) {
+        (void)SDL_AtomicDecRef(&commandBuffer->usedFramebuffers[i]->referenceCount);
+    }
+    commandBuffer->usedFramebufferCount = 0;
+
+    // Reset presentation data
+
+    commandBuffer->presentDataCount = 0;
+    commandBuffer->waitSemaphoreCount = 0;
+    commandBuffer->signalSemaphoreCount = 0;
+
+    // Reset defrag state
+
+    if (commandBuffer->isDefrag) {
+        renderer->defragInProgress = 0;
+    }
+
+    // Return command buffer to pool
+
+    SDL_LockMutex(renderer->acquireCommandBufferLock);
+
+    if (commandBuffer->commandPool->inactiveCommandBufferCount == commandBuffer->commandPool->inactiveCommandBufferCapacity) {
+        commandBuffer->commandPool->inactiveCommandBufferCapacity += 1;
+        commandBuffer->commandPool->inactiveCommandBuffers = SDL_realloc(
+            commandBuffer->commandPool->inactiveCommandBuffers,
+            commandBuffer->commandPool->inactiveCommandBufferCapacity * sizeof(VulkanCommandBuffer *));
+    }
+
+    commandBuffer->commandPool->inactiveCommandBuffers[commandBuffer->commandPool->inactiveCommandBufferCount] = commandBuffer;
+    commandBuffer->commandPool->inactiveCommandBufferCount += 1;
+
+    SDL_UnlockMutex(renderer->acquireCommandBufferLock);
+
+    // Remove this command buffer from the submitted list
+    for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) {
+        if (renderer->submittedCommandBuffers[i] == commandBuffer) {
+            renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1];
+            renderer->submittedCommandBufferCount -= 1;
+        }
+    }
+}
+
+static void VULKAN_WaitForFences(
+    SDL_GpuRenderer *driverData,
+    SDL_bool waitAll,
+    SDL_GpuFence **pFences,
+    Uint32 fenceCount)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VkFence *fences = SDL_stack_alloc(VkFence, fenceCount);
+    VkResult result;
+
+    for (Uint32 i = 0; i < fenceCount; i += 1) {
+        fences[i] = ((VulkanFenceHandle *)pFences[i])->fence;
+    }
+
+    result = renderer->vkWaitForFences(
+        renderer->logicalDevice,
+        fenceCount,
+        fences,
+        waitAll,
+        UINT64_MAX);
+
+    if (result != VK_SUCCESS) {
+        LogVulkanResultAsError("vkWaitForFences", result);
+    }
+
+    SDL_stack_free(fences);
+
+    SDL_LockMutex(renderer->submitLock);
+
+    for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+        result = renderer->vkGetFenceStatus(
+            renderer->logicalDevice,
+            renderer->submittedCommandBuffers[i]->inFlightFence->fence);
+
+        if (result == VK_SUCCESS) {
+            VULKAN_INTERNAL_CleanCommandBuffer(
+                renderer,
+                renderer->submittedCommandBuffers[i]);
+        }
+    }
+
+    VULKAN_INTERNAL_PerformPendingDestroys(renderer);
+
+    SDL_UnlockMutex(renderer->submitLock);
+}
+
+static void VULKAN_Wait(
+    SDL_GpuRenderer *driverData)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VulkanCommandBuffer *commandBuffer;
+    VkResult result;
+    Sint32 i;
+
+    result = renderer->vkDeviceWaitIdle(renderer->logicalDevice);
+
+    if (result != VK_SUCCESS) {
+        LogVulkanResultAsError("vkDeviceWaitIdle", result);
+        return;
+    }
+
+    SDL_LockMutex(renderer->submitLock);
+
+    for (i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+        commandBuffer = renderer->submittedCommandBuffers[i];
+        VULKAN_INTERNAL_CleanCommandBuffer(renderer, commandBuffer);
+    }
+
+    VULKAN_INTERNAL_PerformPendingDestroys(renderer);
+
+    SDL_UnlockMutex(renderer->submitLock);
+}
+
+static SDL_GpuFence *VULKAN_SubmitAndAcquireFence(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer;
+
+    vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    vulkanCommandBuffer->autoReleaseFence = 0;
+
+    VULKAN_Submit(commandBuffer);
+
+    return (SDL_GpuFence *)vulkanCommandBuffer->inFlightFence;
+}
+
+static void VULKAN_Submit(
+    SDL_GpuCommandBuffer *commandBuffer)
+{
+    VulkanCommandBuffer *vulkanCommandBuffer = (VulkanCommandBuffer *)commandBuffer;
+    VulkanRenderer *renderer = (VulkanRenderer *)vulkanCommandBuffer->renderer;
+    VkSubmitInfo submitInfo;
+    VkPresentInfoKHR presentInfo;
+    VulkanPresentData *presentData;
+    VkResult vulkanResult, presentResult = VK_SUCCESS;
+    VkPipelineStageFlags waitStages[MAX_PRESENT_COUNT];
+    Uint32 swapchainImageIndex;
+    VulkanTextureSubresource *swapchainTextureSubresource;
+    Uint8 commandBufferCleaned = 0;
+    VulkanMemorySubAllocator *allocator;
+    SDL_bool presenting = SDL_FALSE;
+
+    SDL_LockMutex(renderer->submitLock);
+
+    // FIXME: Can this just be permanent?
+    for (Uint32 i = 0; i < MAX_PRESENT_COUNT; i += 1) {
+        waitStages[i] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+    }
+
+    for (Uint32 j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) {
+        swapchainImageIndex = vulkanCommandBuffer->presentDatas[j].swapchainImageIndex;
+        swapchainTextureSubresource = VULKAN_INTERNAL_FetchTextureSubresource(
+            &vulkanCommandBuffer->presentDatas[j].windowData->swapchainData->textureContainers[swapchainImageIndex],
+            0,
+            0);
+
+        VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+            renderer,
+            vulkanCommandBuffer,
+            VULKAN_TEXTURE_USAGE_MODE_PRESENT,
+            swapchainTextureSubresource);
+    }
+
+    VULKAN_INTERNAL_EndCommandBuffer(renderer, vulkanCommandBuffer);
+
+    vulkanCommandBuffer->inFlightFence = VULKAN_INTERNAL_AcquireFenceFromPool(renderer);
+
+    // Command buffer has a reference to the in-flight fence
+    (void)SDL_AtomicIncRef(&vulkanCommandBuffer->inFlightFence->referenceCount);
+
+    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+    submitInfo.pNext = NULL;
+    submitInfo.commandBufferCount = 1;
+    submitInfo.pCommandBuffers = &vulkanCommandBuffer->commandBuffer;
+
+    submitInfo.pWaitDstStageMask = waitStages;
+    submitInfo.pWaitSemaphores = vulkanCommandBuffer->waitSemaphores;
+    submitInfo.waitSemaphoreCount = vulkanCommandBuffer->waitSemaphoreCount;
+    submitInfo.pSignalSemaphores = vulkanCommandBuffer->signalSemaphores;
+    submitInfo.signalSemaphoreCount = vulkanCommandBuffer->signalSemaphoreCount;
+
+    vulkanResult = renderer->vkQueueSubmit(
+        renderer->unifiedQueue,
+        1,
+        &submitInfo,
+        vulkanCommandBuffer->inFlightFence->fence);
+
+    if (vulkanResult != VK_SUCCESS) {
+        LogVulkanResultAsError("vkQueueSubmit", vulkanResult);
+    }
+
+    // Mark command buffers as submitted
+
+    if (renderer->submittedCommandBufferCount + 1 >= renderer->submittedCommandBufferCapacity) {
+        renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1;
+
+        renderer->submittedCommandBuffers = SDL_realloc(
+            renderer->submittedCommandBuffers,
+            sizeof(VulkanCommandBuffer *) * renderer->submittedCommandBufferCapacity);
+    }
+
+    renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = vulkanCommandBuffer;
+    renderer->submittedCommandBufferCount += 1;
+
+    // Present, if applicable
+
+    for (Uint32 j = 0; j < vulkanCommandBuffer->presentDataCount; j += 1) {
+        presenting = SDL_TRUE;
+
+        presentData = &vulkanCommandBuffer->presentDatas[j];
+
+        presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+        presentInfo.pNext = NULL;
+        presentInfo.pWaitSemaphores =
+            &presentData->windowData->swapchainData->renderFinishedSemaphore[presentData->windowData->swapchainData->frameCounter];
+        presentInfo.waitSemaphoreCount = 1;
+        presentInfo.pSwapchains = &presentData->windowData->swapchainData->swapchain;
+        presentInfo.swapchainCount = 1;
+        presentInfo.pImageIndices = &presentData->swapchainImageIndex;
+        presentInfo.pResults = NULL;
+
+        presentResult = renderer->vkQueuePresentKHR(
+            renderer->unifiedQueue,
+            &presentInfo);
+
+        presentData->windowData->swapchainData->frameCounter =
+            (presentData->windowData->swapchainData->frameCounter + 1) % MAX_FRAMES_IN_FLIGHT;
+
+        if (presentResult != VK_SUCCESS) {
+            VULKAN_INTERNAL_RecreateSwapchain(
+                renderer,
+                presentData->windowData);
+        } else {
+            // If presenting, the swapchain is using the in-flight fence
+            presentData->windowData->swapchainData->inFlightFences[presentData->windowData->swapchainData->frameCounter] = vulkanCommandBuffer->inFlightFence;
+
+            (void)SDL_AtomicIncRef(&vulkanCommandBuffer->inFlightFence->referenceCount);
+        }
+    }
+
+    // Check if we can perform any cleanups
+
+    for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) {
+        vulkanResult = renderer->vkGetFenceStatus(
+            renderer->logicalDevice,
+            renderer->submittedCommandBuffers[i]->inFlightFence->fence);
+
+        if (vulkanResult == VK_SUCCESS) {
+            VULKAN_INTERNAL_CleanCommandBuffer(
+                renderer,
+                renderer->submittedCommandBuffers[i]);
+
+            commandBufferCleaned = 1;
+        }
+    }
+
+    if (commandBufferCleaned) {
+        SDL_LockMutex(renderer->allocatorLock);
+
+        for (Uint32 i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
+            allocator = &renderer->memoryAllocator->subAllocators[i];
+
+            for (Sint32 j = allocator->allocationCount - 1; j >= 0; j -= 1) {
+                if (allocator->allocations[j]->usedRegionCount == 0) {
+                    VULKAN_INTERNAL_DeallocateMemory(
+                        renderer,
+                        allocator,
+                        j);
+                }
+            }
+        }
+
+        SDL_UnlockMutex(renderer->allocatorLock);
+    }
+
+    // Check pending destroys
+    VULKAN_INTERNAL_PerformPendingDestroys(renderer);
+
+    // Defrag!
+    if (
+        presenting &&
+        renderer->allocationsToDefragCount > 0 &&
+        !renderer->defragInProgress) {
+        VULKAN_INTERNAL_DefragmentMemory(renderer);
+    }
+
+    SDL_UnlockMutex(renderer->submitLock);
+}
+
+static Uint8 VULKAN_INTERNAL_DefragmentMemory(
+    VulkanRenderer *renderer)
+{
+    VulkanMemoryAllocation *allocation;
+    VulkanMemoryUsedRegion *currentRegion;
+    VulkanBuffer *newBuffer;
+    VulkanTexture *newTexture;
+    VkBufferCopy bufferCopy;
+    VkImageCopy imageCopy;
+    VulkanCommandBuffer *commandBuffer;
+    VulkanTextureSubresource *srcSubresource;
+    VulkanTextureSubresource *dstSubresource;
+    Uint32 i, subresourceIndex;
+
+    SDL_LockMutex(renderer->allocatorLock);
+
+    renderer->defragInProgress = 1;
+
+    commandBuffer = (VulkanCommandBuffer *)VULKAN_AcquireCommandBuffer((SDL_GpuRenderer *)renderer);
+    if (commandBuffer == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create defrag command buffer!");
+        return 0;
+    }
+    commandBuffer->isDefrag = 1;
+
+    allocation = renderer->allocationsToDefrag[renderer->allocationsToDefragCount - 1];
+    renderer->allocationsToDefragCount -= 1;
+
+    /* For each used region in the allocation
+     * create a new resource, copy the data
+     * and re-point the resource containers
+     */
+    for (i = 0; i < allocation->usedRegionCount; i += 1) {
+        currentRegion = allocation->usedRegions[i];
+
+        if (currentRegion->isBuffer && !currentRegion->vulkanBuffer->markedForDestroy) {
+            currentRegion->vulkanBuffer->usageFlags |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+            newBuffer = VULKAN_INTERNAL_CreateBuffer(
+                renderer,
+                currentRegion->vulkanBuffer->size,
+                currentRegion->vulkanBuffer->usageFlags,
+                currentRegion->vulkanBuffer->type);
+
+            if (newBuffer == NULL) {
+                SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create defrag buffer!");
+                return 0;
+            }
+
+            if (
+                renderer->debugMode &&
+                renderer->supportsDebugUtils &&
+                currentRegion->vulkanBuffer->handle != NULL &&
+                currentRegion->vulkanBuffer->handle->container != NULL &&
+                currentRegion->vulkanBuffer->handle->container->debugName != NULL) {
+                VULKAN_INTERNAL_SetBufferName(
+                    renderer,
+                    newBuffer,
+                    currentRegion->vulkanBuffer->handle->container->debugName);
+            }
+
+            // Copy buffer contents if necessary
+            if (
+                currentRegion->vulkanBuffer->type == VULKAN_BUFFER_TYPE_GPU && currentRegion->vulkanBuffer->transitioned) {
+                VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
+                    renderer,
+                    commandBuffer,
+                    VULKAN_BUFFER_USAGE_MODE_COPY_SOURCE,
+                    currentRegion->vulkanBuffer);
+
+                VULKAN_INTERNAL_BufferTransitionFromDefaultUsage(
+                    renderer,
+                    commandBuffer,
+                    VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
+                    newBuffer);
+
+                bufferCopy.srcOffset = 0;
+                bufferCopy.dstOffset = 0;
+                bufferCopy.size = currentRegion->resourceSize;
+
+                renderer->vkCmdCopyBuffer(
+                    commandBuffer->commandBuffer,
+                    currentRegion->vulkanBuffer->buffer,
+                    newBuffer->buffer,
+                    1,
+                    &bufferCopy);
+
+                VULKAN_INTERNAL_BufferTransitionToDefaultUsage(
+                    renderer,
+                    commandBuffer,
+                    VULKAN_BUFFER_USAGE_MODE_COPY_DESTINATION,
+                    newBuffer);
+
+                VULKAN_INTERNAL_TrackBuffer(commandBuffer, currentRegion->vulkanBuffer);
+                VULKAN_INTERNAL_TrackBuffer(commandBuffer, newBuffer);
+            }
+
+            // re-point original container to new buffer
+            if (currentRegion->vulkanBuffer->handle != NULL) {
+                newBuffer->handle = currentRegion->vulkanBuffer->handle;
+                newBuffer->handle->vulkanBuffer = newBuffer;
+                currentRegion->vulkanBuffer->handle = NULL;
+            }
+
+            VULKAN_INTERNAL_ReleaseBuffer(renderer, currentRegion->vulkanBuffer);
+        } else if (!currentRegion->isBuffer && !currentRegion->vulkanTexture->markedForDestroy) {
+            newTexture = VULKAN_INTERNAL_CreateTexture(
+                renderer,
+                currentRegion->vulkanTexture->dimensions.width,
+                currentRegion->vulkanTexture->dimensions.height,
+                currentRegion->vulkanTexture->depth,
+                currentRegion->vulkanTexture->type,
+                currentRegion->vulkanTexture->layerCount,
+                currentRegion->vulkanTexture->levelCount,
+                currentRegion->vulkanTexture->sampleCount,
+                currentRegion->vulkanTexture->format,
+                currentRegion->vulkanTexture->swizzle,
+                currentRegion->vulkanTexture->aspectFlags,
+                currentRegion->vulkanTexture->usageFlags,
+                currentRegion->vulkanTexture->isMSAAColorTarget);
+
+            if (newTexture == NULL) {
+                SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create defrag texture!");
+                return 0;
+            }
+
+            for (subresourceIndex = 0; subresourceIndex < currentRegion->vulkanTexture->subresourceCount; subresourceIndex += 1) {
+                // copy subresource if necessary
+                srcSubresource = &currentRegion->vulkanTexture->subresources[subresourceIndex];
+                dstSubresource = &newTexture->subresources[subresourceIndex];
+
+                // Set debug name if it exists
+                if (
+                    renderer->debugMode &&
+                    renderer->supportsDebugUtils &&
+                    srcSubresource->parent->handle != NULL &&
+                    srcSubresource->parent->handle->container != NULL &&
+                    srcSubresource->parent->handle->container->debugName != NULL) {
+                    VULKAN_INTERNAL_SetTextureName(
+                        renderer,
+                        currentRegion->vulkanTexture,
+                        srcSubresource->parent->handle->container->debugName);
+                }
+
+                if (srcSubresource->transitioned) {
+                    VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+                        renderer,
+                        commandBuffer,
+                        VULKAN_TEXTURE_USAGE_MODE_COPY_SOURCE,
+                        srcSubresource);
+
+                    VULKAN_INTERNAL_TextureSubresourceTransitionFromDefaultUsage(
+                        renderer,
+                        commandBuffer,
+                        VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
+                        dstSubresource);
+
+                    imageCopy.srcOffset.x = 0;
+                    imageCopy.srcOffset.y = 0;
+                    imageCopy.srcOffset.z = 0;
+                    imageCopy.srcSubresource.aspectMask = srcSubresource->parent->aspectFlags;
+                    imageCopy.srcSubresource.baseArrayLayer = srcSubresource->layer;
+                    imageCopy.srcSubresource.layerCount = 1;
+                    imageCopy.srcSubresource.mipLevel = srcSubresource->level;
+                    imageCopy.extent.width = SDL_max(1, srcSubresource->parent->dimensions.width >> srcSubresource->level);
+                    imageCopy.extent.height = SDL_max(1, srcSubresource->parent->dimensions.height >> srcSubresource->level);
+                    imageCopy.extent.depth = srcSubresource->parent->depth;
+                    imageCopy.dstOffset.x = 0;
+                    imageCopy.dstOffset.y = 0;
+                    imageCopy.dstOffset.z = 0;
+                    imageCopy.dstSubresource.aspectMask = dstSubresource->parent->aspectFlags;
+                    imageCopy.dstSubresource.baseArrayLayer = dstSubresource->layer;
+                    imageCopy.dstSubresource.layerCount = 1;
+                    imageCopy.dstSubresource.mipLevel = dstSubresource->level;
+
+                    renderer->vkCmdCopyImage(
+                        commandBuffer->commandBuffer,
+                        currentRegion->vulkanTexture->image,
+                        VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                        newTexture->image,
+                        VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                        1,
+                        &imageCopy);
+
+                    VULKAN_INTERNAL_TextureSubresourceTransitionToDefaultUsage(
+                        renderer,
+                        commandBuffer,
+                        VULKAN_TEXTURE_USAGE_MODE_COPY_DESTINATION,
+                        dstSubresource);
+
+                    VULKAN_INTERNAL_TrackTexture(commandBuffer, srcSubresource->parent);
+                    VULKAN_INTERNAL_TrackTexture(commandBuffer, dstSubresource->parent);
+                }
+            }
+
+            // re-point original container to new texture
+            newTexture->handle = currentRegion->vulkanTexture->handle;
+            newTexture->handle->vulkanTexture = newTexture;
+            currentRegion->vulkanTexture->handle = NULL;
+
+            VULKAN_INTERNAL_ReleaseTexture(renderer, currentRegion->vulkanTexture);
+        }
+    }
+
+    SDL_UnlockMutex(renderer->allocatorLock);
+
+    VULKAN_Submit(
+        (SDL_GpuCommandBuffer *)commandBuffer);
+
+    return 1;
+}
+
+// Format Info
+
+static SDL_bool VULKAN_SupportsTextureFormat(
+    SDL_GpuRenderer *driverData,
+    SDL_GpuTextureFormat format,
+    SDL_GpuTextureType type,
+    SDL_GpuTextureUsageFlags usage)
+{
+    VulkanRenderer *renderer = (VulkanRenderer *)driverData;
+    VkFormat vulkanFormat = SDLToVK_SurfaceFormat[format];
+    VkImageUsageFlags vulkanUsage = 0;
+    VkImageCreateFlags createFlags = 0;
+    VkImageFormatProperties properties;
+    VkResult vulkanResult;
+
+    if (usage & SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT) {
+        vulkanUsage |= VK_IMAGE_USAGE_SAMPLED_BIT;
+    }
+    if (usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT) {
+        vulkanUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+    }
+    if (usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT) {
+        vulkanUsage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+    }
+    if (usage & (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ_BIT |
+                 SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ_BIT |
+                 SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE_BIT)) {
+        vulkanUsage |= VK_IMAGE_USAGE_STORAGE_BIT;
+    }
+
+    if (type == SDL_GPU_TEXTURETYPE_CUBE) {
+        createFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
+    }
+
+    vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties(
+        renderer->physicalDevice,
+        vulkanFormat,
+        (type == SDL_GPU_TEXTURETYPE_3D) ? VK_IMAGE_TYPE_3D : VK_IMAGE_TYPE_2D,
+        VK_IMAGE_TILING_OPTIMAL,
+        vulkanUsage,
+        createFlags,
+        &properties);
+
+    return vulkanResult == VK_SUCCESS;
+}
+
+// Device instantiation
+
+static inline Uint8 CheckDeviceExtensions(
+    VkExtensionProperties *extensions,
+    Uint32 numExtensions,
+    VulkanExtensions *supports)
+{
+    Uint32 i;
+
+    SDL_memset(supports, '\0', sizeof(VulkanExtensions));
+    for (i = 0; i < numExtensions; i += 1) {
+        const char *name = extensions[i].extensionName;
+#define CHECK(ext)                           \
+    if (SDL_strcmp(name, "VK_" #ext) == 0) { \
+        supports->ext = 1;                   \
+    }
+        CHECK(KHR_swapchain)
+        else CHECK(KHR_maintenance1) else CHECK(KHR_driver_properties) else CHECK(EXT_vertex_attribute_divisor) else CHECK(KHR_portability_subset)
+#undef CHECK
+    }
+
+    return (supports->KHR_swapchain &&
+            supports->KHR_maintenance1);
+}
+
+static inline Uint32 GetDeviceExtensionCount(VulkanExtensions *supports)
+{
+    return (
+        supports->KHR_swapchain +
+        supports->KHR_maintenance1 +
+        supports->KHR_driver_properties +
+        supports->EXT_vertex_attribute_divisor +
+        supports->KHR_portability_subset);
+}
+
+static inline void CreateDeviceExtensionArray(
+    VulkanExtensions *supports,
+    const char **extensions)
+{
+    Uint8 cur = 0;
+#define CHECK(ext)                      \
+    if (supports->ext) {                \
+        extensions[cur++] = "VK_" #ext; \
+    }
+    CHECK(KHR_swapchain)
+    CHECK(KHR_maintenance1)
+    CHECK(KHR_driver_properties)
+    CHECK(EXT_vertex_attribute_divisor)
+    CHECK(KHR_portability_subset)
+#undef CHECK
+}
+
+static inline Uint8 SupportsInstanceExtension(
+    const char *ext,
+    VkExtensionProperties *availableExtensions,
+    Uint32 numAvailableExtensions)
+{
+    Uint32 i;
+    for (i = 0; i < numAvailableExtensions; i += 1) {
+        if (SDL_strcmp(ext, availableExtensions[i].extensionName) == 0) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static Uint8 VULKAN_INTERNAL_CheckInstanceExtensions(
+    const char **requiredExtensions,
+    Uint32 requiredExtensionsLength,
+    SDL_bool *supportsDebugUtils,
+    SDL_bool *supportsColorspace)
+{
+    Uint32 extensionCount, i;
+    VkExtensionProperties *availableExtensions;
+    Uint8 allExtensionsSupported = 1;
+
+    vkEnumerateInstanceExtensionProperties(
+        NULL,
+        &extensionCount,
+        NULL);
+    availableExtensions = SDL_malloc(
+        extensionCount * sizeof(VkExtensionProperties));
+    vkEnumerateInstanceExtensionProperties(
+        NULL,
+        &extensionCount,
+        availableExtensions);
+
+    for (i = 0; i < requiredExtensionsLength; i += 1) {
+        if (!SupportsInstanceExtension(
+                requiredExtensions[i],
+                availableExtensions,
+                extensionCount)) {
+            allExtensionsSupported = 0;
+            break;
+        }
+    }
+
+    // This is optional, but nice to have!
+    *supportsDebugUtils = SupportsInstanceExtension(
+        VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
+        availableExtensions,
+        extensionCount);
+
+    // Also optional and nice to have!
+    *supportsColorspace = SupportsInstanceExtension(
+        VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME,
+        availableExtensions,
+        extensionCount);
+
+    SDL_free(availableExtensions);
+    return allExtensionsSupported;
+}
+
+static Uint8 VULKAN_INTERNAL_CheckDeviceExtensions(
+    VulkanRenderer *renderer,
+    VkPhysicalDevice physicalDevice,
+    VulkanExtensions *physicalDeviceExtensions)
+{
+    Uint32 extensionCount;
+    VkExtensionProperties *availableExtensions;
+    Uint8 allExtensionsSupported;
+
+    renderer->vkEnumerateDeviceExtensionProperties(
+        physicalDevice,
+        NULL,
+        &extensionCount,
+        NULL);
+    availableExtensions = (VkExtensionProperties *)SDL_malloc(
+        extensionCount * sizeof(VkExtensionProperties));
+    renderer->vkEnumerateDeviceExtensionProperties(
+        physicalDevice,
+        NULL,
+        &extensionCount,
+        availableExtensions);
+
+    allExtensionsSupported = CheckDeviceExtensions(
+        availableExtensions,
+        extensionCount,
+        physicalDeviceExtensions);
+
+    SDL_free(availableExtensions);
+    return allExtensionsSupported;
+}
+
+static Uint8 VULKAN_INTERNAL_CheckValidationLayers(
+    const char **validationLayers,
+    Uint32 validationLayersLength)
+{
+    Uint32 layerCount;
+    VkLayerProperties *availableLayers;
+    Uint32 i, j;
+    Uint8 layerFound = 0;
+
+    vkEnumerateInstanceLayerProperties(&layerCount, NULL);
+    availableLayers = (VkLayerProperties *)SDL_malloc(
+        layerCount * sizeof(VkLayerProperties));
+    vkEnumerateInstanceLayerProperties(&layerCount, availableLayers);
+
+    for (i = 0; i < validationLayersLength; i += 1) {
+        layerFound = 0;
+
+        for (j = 0; j < layerCount; j += 1) {
+            if (SDL_strcmp(validationLayers[i], availableLayers[j].layerName) == 0) {
+                layerFound = 1;
+                break;
+            }
+        }
+
+        if (!layerFound) {
+            break;
+        }
+    }
+
+    SDL_free(availableLayers);
+    return layerFound;
+}
+
+static Uint8 VULKAN_INTERNAL_CreateInstance(VulkanRenderer *renderer)
+{
+    VkResult vulkanResult;
+    VkApplicationInfo appInfo;
+    VkInstanceCreateFlags createFlags;
+    const char *const *originalInstanceExtensionNames;
+    const char **instanceExtensionNames;
+    Uint32 instanceExtensionCount;
+    VkInstanceCreateInfo createInfo;
+    static const char *layerNames[] = { "VK_LAYER_KHRONOS_validation" };
+
+    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+    appInfo.pNext = NULL;
+    appInfo.pApplicationName = NULL;
+    appInfo.applicationVersion = 0;
+    appInfo.pEngineName = "SDLGPU";
+    appInfo.engineVersion = SDL_VERSION;
+    appInfo.apiVersion = VK_MAKE_VERSION(1, 0, 0);
+
+    createFlags = 0;
+
+    originalInstanceExtensionNames = SDL_Vulkan_GetInstanceExtensions(&instanceExtensionCount);
+    if (!originalInstanceExtensionNames) {
+        SDL_LogError(
+            SDL_LOG_CATEGORY_GPU,
+            "SDL_Vulkan_GetInstanceExtensions(): getExtensionCount: %s",
+            SDL_GetError());
+
+        return 0;
+    }
+
+    /* Extra space for the following extensions:
+     * VK_KHR_get_physical_device_properties2
+     * VK_EXT_swapchain_colorspace
+     * VK_EXT_debug_utils
+     * VK_KHR_portability_enumeration
+     */
+    instanceExtensionNames = SDL_stack_alloc(
+        const char *,
+        instanceExtensionCount + 4);
+    SDL_memcpy(instanceExtensionNames, originalInstanceExtensionNames, instanceExtensionCount * sizeof(const char *));
+
+    // Core since 1.1
+    instanceExtensionNames[instanceExtensionCount++] =
+        VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME;
+
+#ifdef SDL_PLATFORM_APPLE
+    instanceExtensionNames[instanceExtensionCount++] =
+        VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME;
+    createFlags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
+#endif
+
+    if (!VULKAN_INTERNAL_CheckInstanceExtensions(
+            instanceExtensionNames,
+            instanceExtensionCount,
+            &renderer->supportsDebugUtils,
+            &renderer->supportsColorspace)) {
+        SDL_LogError(
+            SDL_LOG_CATEGORY_GPU,
+            "Required Vulkan instance extensions not supported");
+
+        SDL_stack_free((char *)instanceExtensionNames);
+        return 0;
+    }
+
+    if (renderer->supportsDebugUtils) {
+        // Append the debug extension
+        instanceExtensionNames[instanceExtensionCount++] =
+            VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
+    } else {
+        SDL_LogWarn(
+            SDL_LOG_CATEGORY_GPU,
+            "%s is not supported!",
+            VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+    }
+
+    if (renderer->supportsColorspace) {
+        // Append colorspace extension
+        instanceExtensionNames[instanceExtensionCount++] =
+            VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME;
+    }
+
+    createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+    createInfo.pNext = NULL;
+    createInfo.flags = createFlags;
+    createInfo.pApplicationInfo = &appInfo;
+    createInfo.ppEnabledLayerNames = layerNames;
+    createInfo.enabledExtensionCount = instanceExtensionCount;
+    createInfo.ppEnabledExtensionNames = instanceExtensionNames;
+    if (renderer->debugMode) {
+        createInfo.enabledLayerCount = SDL_arraysize(layerNames);
+        if (!VULKAN_INTERNAL_CheckValidationLayers(
+                layerNames,
+                createInfo.enabledLayerCount)) {
+            SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Validation layers not found, continuing without validation");
+            createInfo.enabledLayerCount = 0;
+        } else {
+            SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Validation layers enabled, expect debug level performance!");
+        }
+    } else {
+        createInfo.enabledLayerCount = 0;
+    }
+
+    vulkanResult = vkCreateInstance(&createInfo, NULL, &renderer->instance);
+    if (vulkanResult != VK_SUCCESS) {
+        SDL_LogError(
+            SDL_LOG_CATEGORY_GPU,
+            "vkCreateInstance failed: %s",
+            VkErrorMessages(vulkanResult));
+
+        SDL_stack_free((char *)instanceExtensionNames);
+        return 0;
+    }
+
+    SDL_stack_free((char *)instanceExtensionNames);
+    return 1;
+}
+
+static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
+    VulkanRenderer *renderer,
+    VkPhysicalDevice physicalDevice,
+    VulkanExtensions *physicalDeviceExtensions,
+    Uint32 *queueFamilyIndex,
+    Uint8 *deviceRank)
+{
+    Uint32 queueFamilyCount, queueFamilyRank, queueFamilyBest;
+    VkQueueFamilyProperties *queueProps;
+    SDL_bool supportsPresent;
+    VkPhysicalDeviceProperties deviceProperties;
+    Uint32 i;
+
+    const Uint8 *devicePriority = renderer->preferLowPower ? DEVICE_PRIORITY_LOWPOWER : DEVICE_PRIORITY_HIGHPERFORMANCE;
+
+    /* Get the device rank before doing any checks, in case one fails.
+     * Note: If no dedicated device exists, one that supports our features
+     * would be fine
+     */
+    renderer->vkGetPhysicalDeviceProperties(
+        physicalDevice,
+        &deviceProperties);
+    if (*deviceRank < devicePriority[deviceProperties.deviceType]) {
+        /* This device outranks the best device we've found so far!
+         * This includes a dedicated GPU that has less features than an
+         * integrated GPU, because this is a freak case that is almost
+         * never intentionally desired by the end user
+         */
+        *deviceRank = devicePriority[deviceProperties.deviceType];
+    } else if (*deviceRank > devicePriority[deviceProperties.deviceType]) {
+        /* Device is outranked by a previous device, don't even try to
+         * run a query and reset the rank to avoid overwrites
+         */
+        *deviceRank = 0;
+        return 0;
+    }
+
+    if (!VULKAN_INTERNAL_CheckDeviceExtensions(
+            renderer,
+            physicalDevice,
+            physicalDeviceExtensions)) {
+        return 0;
+    }
+
+    renderer->vkGetPhysicalDeviceQueueFamilyProperties(
+        physicalDevice,
+        &queueFamilyCount,
+        NULL);
+
+    queueProps = (VkQueueFamilyProperties *)SDL_stack_alloc(
+        VkQueueFamilyProperties,
+        queueFamilyCount);
+    renderer->vkGetPhysicalDeviceQueueFamilyProperties(
+        physicalDevice,
+        &queueFamilyCount,
+        queueProps);
+
+    queueFamilyBest = 0;
+    *queueFamilyIndex = UINT32_MAX;
+    for (i = 0; i < queueFamilyCount; i += 1) {
+        supportsPresent = SDL_Vulkan_GetPresentationSupport(
+            renderer->instance,
+            physicalDevice,
+            i);
+        if (!supportsPresent ||
+            !(queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) {
+            // Not a graphics family, ignore.
+            continue;
+        }
+
+        /* The queue family bitflags are kind of annoying.
+         *
+         * We of course need a graphics family, but we ideally want the
+         * _primary_ graphics family. The spec states that at least one
+         * graphics family must also be a compute family, so generally
+         * drivers make that the first one. But hey, maybe something
+         * genuinely can't do compute or something, and FNA doesn't
+         * need it, so we'll be open to a non-compute queue family.
+         *
+         * Additionally, it's common to see the primary queue family
+         * have the transfer bit set, which is great! But this is
+         * actually optional; it's impossible to NOT have transfers in
+         * graphics/compute but it _is_ possible for a graphics/compute
+         * family, even the primary one, to just decide not to set the
+         * bitflag. Admittedly, a driver may want to isolate transfer
+         * queues to a dedicated family so that queues made solely for
+         * transfers can have an optimized DMA queue.
+         *
+         * That, or the driver author got lazy and decided not to set
+         * the bit. Looking at you, Android.
+         *
+         * -flibit
+         */
+        if (queueProps[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
+            if (queueProps[i].queueFlags & VK_QUEUE_TRANSFER_BIT) {
+                // Has all attribs!
+                queueFamilyRank = 3;
+            } else {
+                // Probably has a DMA transfer queue family
+                queueFamilyRank = 2;
+            }
+        } else {
+            // Just a graphics family, probably has something better
+            queueFamilyRank = 1;
+        }
+        if (queueFamilyRank > queueFamilyBest) {
+            *queueFamilyIndex = i;
+            queueFamilyBest = queueFamilyRank;
+        }
+    }
+
+    SDL_stack_free(queueProps);
+
+    if (*queueFamilyIndex == UINT32_MAX) {
+        // Somehow no graphics queues existed. Compute-only device?
+        return 0;
+    }
+
+    // FIXME: Need better structure for checking vs storing swapchain support details
+    return 1;
+}
+
+static Uint8 VULKAN_INTERNAL_DeterminePhysicalDevice(VulkanRenderer *renderer)
+{
+    VkResult vulkanResult;
+    VkPhysicalDevice *physicalDevices;
+    VulkanExtensions *physicalDeviceExtensions;
+    Uint32 physicalDeviceCount, i, suitableIndex;
+    Uint32 queueFamilyIndex, suitableQueueFamilyIndex;
+    Uint8 deviceRank, highestRank;
+
+    vulkanResult = renderer->vkEnumeratePhysicalDevices(
+        renderer->instance,
+        &physicalDeviceCount,
+        NULL);
+    VULKAN_ERROR_CHECK(vulkanResult, vkEnumeratePhysicalDevices, 0)
+
+    if (physicalDeviceCount == 0) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Failed to find any GPUs with Vulkan support");
+        return 0;
+    }
+
+    physicalDevices = SDL_stack_alloc(VkPhysicalDevice, physicalDeviceCount);
+    physicalDeviceExtensions = SDL_stack_alloc(VulkanExtensions, physicalDeviceCount);
+
+    vulkanResult = renderer->vkEnumeratePhysicalDevices(
+        renderer->instance,
+        &physicalDeviceCount,
+        physicalDevices);
+
+    /* This should be impossible to hit, but from what I can tell this can
+     * be triggered not because the array is too small, but because there
+     * were drivers that turned out to be bogus, so this is the loader's way
+     * of telling us that the list is now smaller than expected :shrug:
+     */
+    if (vulkanResult == VK_INCOMPLETE) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "vkEnumeratePhysicalDevices returned VK_INCOMPLETE, will keep trying anyway...");
+        vulkanResult = VK_SUCCESS;
+    }
+
+    if (vulkanResult != VK_SUCCESS) {
+        SDL_LogWarn(
+            SDL_LOG_CATEGORY_GPU,
+            "vkEnumeratePhysicalDevices failed: %s",
+            VkErrorMessages(vulkanResult));
+        SDL_stack_free(physicalDevices);
+        SDL_stack_free(physicalDeviceExtensions);
+        return 0;
+    }
+
+    // Any suitable device will do, but we'd like the best
+    suitableIndex = -1;
+    suitableQueueFamilyIndex = 0;
+    highestRank = 0;
+    for (i = 0; i < physicalDeviceCount; i += 1) {
+        deviceRank = highestRank;
+        if (VULKAN_INTERNAL_IsDeviceSuitable(
+                renderer,
+                physicalDevices[i],
+                &physicalDeviceExtensions[i],
+                &queueFamilyIndex,
+                &deviceRank)) {
+            /* Use this for rendering.
+             * Note that this may override a previous device that
+             * supports rendering, but shares the same device rank.
+             */
+            suitableIndex = i;
+            suitableQueueFamilyIndex = queueFamilyIndex;
+            highestRank = deviceRank;
+        } else if (deviceRank > highestRank) {
+            /* In this case, we found a... "realer?" GPU,
+             * but it doesn't actually support our Vulkan.
+             * We should disqualify all devices below as a
+             * result, because if we don't we end up
+             * ignoring real hardware and risk using
+             * something like LLVMpipe instead!
+             * -flibit
+             */
+            suitableIndex = -1;
+            highestRank = deviceRank;
+        }
+    }
+
+    if (suitableIndex != -1) {
+        renderer->supports = physicalDeviceExtensions[suitableIndex];
+        renderer->physicalDevice = physicalDevices[suitableIndex];
+        renderer->queueFamilyIndex = suitableQueueFamilyIndex;
+    } else {
+        SDL_stack_free(physicalDevices);
+        SDL_stack_free(physicalDeviceExtensions);
+        return 0;
+    }
+
+    renderer->physicalDeviceProperties.sType =
+        VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+    if (renderer->supports.KHR_driver_properties) {
+        renderer->physicalDeviceDriverProperties.sType =
+            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR;
+        renderer->physicalDeviceDriverProperties.pNext = NULL;
+
+        renderer->physicalDeviceProperties.pNext =
+            &renderer->physicalDeviceDriverProperties;
+
+        renderer->vkGetPhysicalDeviceProperties2KHR(
+            renderer->physicalDevice,
+            &renderer->physicalDeviceProperties);
+    } else {
+        renderer->physicalDeviceProperties.pNext = NULL;
+
+        renderer->vkGetPhysicalDeviceProperties(
+            renderer->physicalDevice,
+            &renderer->physicalDeviceProperties.properties);
+    }
+
+    renderer->vkGetPhysicalDeviceMemoryProperties(
+        renderer->physicalDevice,
+        &renderer->memoryProperties);
+
+    SDL_stack_free(physicalDevices);
+    SDL_stack_free(physicalDeviceExtensions);
+    return 1;
+}
+
+static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
+    VulkanRenderer *renderer)
+{
+    VkResult vulkanResult;
+    VkDeviceCreateInfo deviceCreateInfo;
+    VkPhysicalDeviceFeatures desiredDeviceFeatures;
+    VkPhysicalDeviceFeatures haveDeviceFeatures;
+    VkPhysicalDevicePortabilitySubsetFeaturesKHR portabilityFeatures;
+    const char **deviceExtensions;
+
+    VkDeviceQueueCreateInfo queueCreateInfo;
+    float queuePriority = 1.0f;
+
+    queueCreateInfo.sType =
+        VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+    queueCreateInfo.pNext = NULL;
+    queueCreateInfo.flags = 0;
+    queueCreateInfo.queueFamilyIndex = renderer->queueFamilyIndex;
+    queueCreateInfo.queueCount = 1;
+    queueCreateInfo.pQueuePriorities = &queuePriority;
+
+    // check feature support
+
+    renderer->vkGetPhysicalDeviceFeatures(
+        renderer->physicalDevice,
+        &haveDeviceFeatures);
+
+    // specifying used device features
+
+    SDL_zero(desiredDeviceFeatures);
+    desiredDeviceFeatures.independentBlend = VK_TRUE;
+    desiredDeviceFeatures.samplerAnisotropy = VK_TRUE;
+
+    if (haveDeviceFeatures.fillModeNonSolid) {
+        desiredDeviceFeatures.fillModeNonSolid = VK_TRUE;
+        renderer->supportsFillModeNonSolid = SDL_TRUE;
+    }
+
+    if (haveDeviceFeatures.multiDrawIndirect) {
+        desiredDeviceFeatures.multiDrawIndirect = VK_TRUE;
+        renderer->supportsMultiDrawIndirect = SDL_TRUE;
+    }
+
+    // creating the logical device
+
+    deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+    if (renderer->supports.KHR_portability_subset) {
+        portabilityFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR;
+        portabilityFeatures.pNext = NULL;
+        portabilityFeatures.constantAlphaColorBlendFactors = VK_FALSE;
+        portabilityFeatures.events = VK_FALSE;
+        portabilityFeatures.imageViewFormatReinterpretation = VK_FALSE;
+        portabilityFeatures.imageViewFormatSwizzle = VK_TRUE;
+        portabilityFeatures.imageView2DOn3DImage = VK_FALSE;
+        portabilityFeatures.multisampleArrayImage = VK_FALSE;
+        portabilityFeatures.mutableComparisonSamplers = VK_FALSE;
+        portabilityFeatures.pointPolygons = VK_FALSE;
+        portabilityFeatures.samplerMipLodBias = VK_FALSE; // Technically should be true, but eh
+        portabilityFeatures.separateStencilMaskRef = VK_FALSE;
+        portabilityFeatures.shaderSampleRateInterpolationFunctions = VK_FALSE;
+        portabilityFeatures.tessellationIsolines = VK_FALSE;
+        portabilityFeatures.tessellationPointMode = VK_FALSE;
+        portabilityFeatures.triangleFans = VK_FALSE;
+        portabilityFeatures.vertexAttributeAccessBeyondStride = VK_FALSE;
+        deviceCreateInfo.pNext = &portabilityFeatures;
+    } else {
+        deviceCreateInfo.pNext = NULL;
+    }
+    deviceCreateInfo.flags = 0;
+    deviceCreateInfo.queueCreateInfoCount = 1;
+    deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
+    deviceCreateInfo.enabledLayerCount = 0;
+    deviceCreateInfo.ppEnabledLayerNames = NULL;
+    deviceCreateInfo.enabledExtensionCount = GetDeviceExtensionCount(
+        &renderer->supports);
+    deviceExtensions = SDL_stack_alloc(
+        const char *,
+        deviceCreateInfo.enabledExtensionCount);
+    CreateDeviceExtensionArray(&renderer->supports, deviceExtensions);
+    deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions;
+    deviceCreateInfo.pEnabledFeatures = &desiredDeviceFeatures;
+
+    vulkanResult = renderer->vkCreateDevice(
+        renderer->physicalDevice,
+        &deviceCreateInfo,
+        NULL,
+        &renderer->logicalDevice);
+    SDL_stack_free(deviceExtensions);
+    VULKAN_ERROR_CHECK(vulkanResult, vkCreateDevice, 0)
+
+    // Load vkDevice entry points
+
+#define VULKAN_DEVICE_FUNCTION(func)                    \
+    renderer->func = (PFN_##func)                       \
+                         renderer->vkGetDeviceProcAddr( \
+                             renderer->logicalDevice,   \
+                             #func);
+#include "SDL_gpu_vulkan_vkfuncs.h"
+
+    renderer->vkGetDeviceQueue(
+        renderer->logicalDevice,
+        renderer->queueFamilyIndex,
+        0,
+        &renderer->unifiedQueue);
+
+    return 1;
+}
+
+static void VULKAN_INTERNAL_LoadEntryPoints(void)
+{
+    // Required for MoltenVK support
+    SDL_setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
+
+    // Load Vulkan entry points
+    if (!SDL_Vulkan_LoadLibrary(NULL)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Vulkan: SDL_Vulkan_LoadLibrary failed!");
+        return;
+    }
+
+#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpedantic"
+#endif
+    vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr();
+#ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA
+#pragma GCC diagnostic pop
+#endif
+    if (vkGetInstanceProcAddr == NULL) {
+        SDL_LogWarn(
+            SDL_LOG_CATEGORY_GPU,
+            "SDL_Vulkan_GetVkGetInstanceProcAddr(): %s",
+            SDL_GetError());
+        return;
+    }
+
+#define VULKAN_GLOBAL_FUNCTION(name)                                                                      \
+    name = (PFN_##name)vkGetInstanceProcAddr(VK_NULL_HANDLE, #name);                                      \
+    if (name == NULL) {                                                                                   \
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "vkGetInstanceProcAddr(VK_NULL_HANDLE, \"" #name "\") failed"); \
+        return;                                                                                           \
+    }
+#include "SDL_gpu_vulkan_vkfuncs.h"
+}
+
+static SDL_bool VULKAN_INTERNAL_PrepareVulkan(
+    VulkanRenderer *renderer)
+{
+    VULKAN_INTERNAL_LoadEntryPoints();
+
+    if (!VULKAN_INTERNAL_CreateInstance(renderer)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Vulkan: Could not create Vulkan instance");
+        return SDL_FALSE;
+    }
+
+#define VULKAN_INSTANCE_FUNCTION(func) \
+    renderer->func = (PFN_##func)vkGetInstanceProcAddr(renderer->instance, #func);
+#include "SDL_gpu_vulkan_vkfuncs.h"
+
+    if (!VULKAN_INTERNAL_DeterminePhysicalDevice(renderer)) {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Vulkan: Failed to determine a suitable physical device");
+        return SDL_FALSE;
+    }
+    return SDL_TRUE;
+}
+
+static SDL_bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
+{
+    // Set up dummy VulkanRenderer
+    VulkanRenderer *renderer;
+    Uint8 result;
+
+    if (_this->Vulkan_CreateSurface == NULL) {
+        return SDL_FALSE;
+    }
+
+    if (!SDL_Vulkan_LoadLibrary(NULL)) {
+        return SDL_FALSE;
+    }
+
+    renderer = (VulkanRenderer *)SDL_malloc(sizeof(VulkanRenderer));
+    SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
+
+    result = VULKAN_INTERNAL_PrepareVulkan(renderer);
+
+    if (result) {
+        renderer->vkDestroyInstance(renderer->instance, NULL);
+    }
+    SDL_free(renderer);
+    SDL_Vulkan_UnloadLibrary();
+    return result;
+}
+
+static SDL_GpuDevice *VULKAN_CreateDevice(SDL_bool debugMode, SDL_bool preferLowPower, SDL_PropertiesID props)
+{
+    VulkanRenderer *renderer;
+
+    SDL_GpuDevice *result;
+    VkResult vulkanResult;
+    Uint32 i;
+
+    // Variables: Image Format Detection
+    VkImageFormatProperties imageFormatProperties;
+
+    if (!SDL_Vulkan_LoadLibrary(NULL)) {
+        SDL_assert(!"This should have failed in PrepareDevice first!");
+        return NULL;
+    }
+
+    renderer = (VulkanRenderer *)SDL_malloc(sizeof(VulkanRenderer));
+    SDL_memset(renderer, '\0', sizeof(VulkanRenderer));
+    renderer->debugMode = debugMode;
+    renderer->preferLowPower = preferLowPower;
+
+    if (!VULKAN_INTERNAL_PrepareVulkan(renderer)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to initialize Vulkan!");
+        SDL_free(renderer);
+        SDL_Vulkan_UnloadLibrary();
+        return NULL;
+    }
+
+    SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL_Gpu Driver: Vulkan");
+    SDL_LogInfo(
+        SDL_LOG_CATEGORY_GPU,
+        "Vulkan Device: %s",
+        renderer->physicalDeviceProperties.properties.deviceName);
+    if (renderer->supports.KHR_driver_properties) {
+        SDL_LogInfo(
+            SDL_LOG_CATEGORY_GPU,
+            "Vulkan Driver: %s %s",
+            renderer->physicalDeviceDriverProperties.driverName,
+            renderer->physicalDeviceDriverProperties.driverInfo);
+        SDL_LogInfo(
+            SDL_LOG_CATEGORY_GPU,
+            "Vulkan Conformance: %u.%u.%u",
+            renderer->physicalDeviceDriverProperties.conformanceVersion.major,
+            renderer->physicalDeviceDriverProperties.conformanceVersion.minor,
+            renderer->physicalDeviceDriverProperties.conformanceVersion.patch);
+    } else {
+        SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "KHR_driver_properties unsupported! Bother your vendor about this!");
+    }
+
+    if (!VULKAN_INTERNAL_CreateLogicalDevice(
+            renderer)) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create logical device");
+        SDL_free(renderer);
+        SDL_Vulkan_UnloadLibrary();
+        return NULL;
+    }
+
+    // FIXME: just move this into this function
+    result = (SDL_GpuDevice *)SDL_malloc(sizeof(SDL_GpuDevice));
+    ASSIGN_DRIVER(VULKAN)
+
+    result->driverData = (SDL_GpuRenderer *)renderer;
+
+    /*
+     * Create initial swapchain array
+     */
+
+    renderer->claimedWindowCapacity = 1;
+    renderer->claimedWindowCount = 0;
+    renderer->claimedWindows = SDL_malloc(
+        renderer->claimedWindowCapacity * sizeof(WindowData *));
+
+    // Threading
+
+    renderer->allocatorLock = SDL_CreateMutex();
+    renderer->disposeLock = SDL_CreateMutex();
+    renderer->submitLock = SDL_CreateMutex();
+    renderer->acquireCommandBufferLock = SDL_CreateMutex();
+    renderer->acquireUniformBufferLock = SDL_CreateMutex();
+    renderer->renderPassFetchLock = SDL_CreateMutex();
+    renderer->framebufferFetchLock = SDL_CreateMutex();
+
+    /*
+     * Create submitted command buffer list
+     */
+
+    renderer->submittedCommandBufferCapacity = 16;
+    renderer->submittedCommandBufferCount = 0;
+    renderer->submittedCommandBuffers = SDL_malloc(sizeof(VulkanCommandBuffer *) * renderer->submittedCommandBufferCapacity);
+
+    // Memory Allocator
+
+    renderer->memoryAllocator = (VulkanMemoryAllocator *)SDL_malloc(
+        sizeof(VulkanMemoryAllocator));
+
+    for (i = 0; i < VK_MAX_MEMORY_TYPES; i += 1) {
+        renderer->memoryAllocator->subAllocators[i].memoryTypeIndex = i;
+        renderer->memoryAllocator->subAllocators[i].allocations = NULL;
+        renderer->memoryAllocator->subAllocators[i].allocationCount = 0;
+        renderer->memoryAllocator->subAllocators[i].sortedFreeRegions = SDL_malloc(
+            sizeof(VulkanMemoryFreeRegion *) * 4);
+        renderer->memoryAllocator->subAllocators[i].sortedFreeRegionCount = 0;
+        renderer->memoryAllocator->subAllocators[i].sortedFreeRegionCapacity = 4;
+    }
+
+    // Create uniform buffer pool
+
+    renderer->uniformBufferPoolCount = 32;
+    renderer->uniformBufferPoolCapacity = 32;
+    renderer->uniformBufferPool = SDL_malloc(
+        renderer->uniformBufferPoolCapacity * sizeof(VulkanUniformBuffer *));
+
+    for (i = 0; i < renderer->uniformBufferPoolCount; i += 1) {
+        renderer->uniformBufferPool[i] = VULKAN_INTERNAL_CreateUniformBuffer(
+            renderer,
+            UNIFORM_BUFFER_SIZE);
+    }
+
+    // Device limits
+
+    renderer->minUBOAlignment = (Uint32)renderer->physicalDeviceProperties.properties.limits.minUniformBufferOffsetAlignment;
+
+    // Initialize caches
+
+    renderer->commandPoolHashTable = SDL_CreateHashTable(
+        (void *)renderer,
+        64,
+        VULKAN_INTERNAL_CommandPoolHashFunction,
+        VULKAN_INTERNAL_CommandPoolHashKeyMatch,
+        VULKAN_INTERNAL_CommandPoolHashNuke,
+        SDL_FALSE);
+
+    renderer->renderPassHashTable = SDL_CreateHashTable(
+        (void *)renderer,
+        64,
+        VULKAN_INTERNAL_RenderPassHashFunction,
+        VULKAN_INTERNAL_RenderPassHashKeyMatch,
+        VULKAN_INTERNAL_RenderPassHashNuke,
+        SDL_FALSE);
+
+    renderer->framebufferHashTable = SDL_CreateHashTable(
+        (void *)renderer,
+        64,
+        VULKAN_INTERNAL_FramebufferHashFunction,
+        VULKAN_INTERNAL_FramebufferHashKeyMatch,
+        VULKAN_INTERNAL_FramebufferHashNuke,
+        SDL_FALSE);
+
+    // Initialize fence pool
+
+    renderer->fencePool.lock = SDL_CreateMutex();
+
+    renderer->fencePool.availableFenceCapacity = 4;
+    renderer->fencePool.availableFenceCount = 0;
+    renderer->fencePool.availableFences = SDL_malloc(
+        renderer->fencePool.availableFenceCapacity * sizeof(VulkanFenceHandle *));
+
+    // Some drivers don't support D16, so we have to fall back to D32.
+
+    vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties(
+        renderer->physicalDevice,
+        VK_FORMAT_D16_UNORM,
+        VK_IMAGE_TYPE_2D,
+        VK_IMAGE_TILING_OPTIMAL,
+        VK_IMAGE_ASPECT_DEPTH_BIT,
+        0,
+        &imageFormatProperties);
+
+    if (vulkanResult == VK_ERROR_FORMAT_NOT_SUPPORTED) {
+        renderer->D16Format = VK_FORMAT_D32_SFLOAT;
+    } else {
+        renderer->D16Format = VK_FORMAT_D16_UNORM;
+    }
+
+    vulkanResult = renderer->vkGetPhysicalDeviceImageFormatProperties(
+        renderer->physicalDevice,
+        VK_FORMAT_D16_UNORM_S8_UINT,
+        VK_IMAGE_TYPE_2D,
+        VK_IMAGE_TILING_OPTIMAL,
+        VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
+        0,
+        &imageFormatProperties);
+
+    if (vulkanResult == VK_ERROR_FORMAT_NOT_SUPPORTED) {
+        renderer->D16S8Format = VK_FORMAT_D32_SFLOAT_S8_UINT;
+    } else {
+        renderer->D16S8Format = VK_FORMAT_D16_UNORM_S8_UINT;
+    }
+
+    // Deferred destroy storage
+
+    renderer->texturesToDestroyCapacity = 16;
+    renderer->texturesToDestroyCount = 0;
+
+    renderer->texturesToDestroy = (VulkanTexture **)SDL_malloc(
+        sizeof(VulkanTexture *) *
+        renderer->texturesToDestroyCapacity);
+
+    renderer->buffersToDestroyCapacity = 16;
+    renderer->buffersToDestroyCount = 0;
+
+    renderer->buffersToDestroy = SDL_malloc(
+        sizeof(VulkanBuffer *) *
+        renderer->buffersToDestroyCapacity);
+
+    renderer->samplersToDestroyCapacity = 16;
+    renderer->samplersToDestroyCount = 0;
+
+    renderer->samplersToDestroy = SDL_malloc(
+        sizeof(VulkanSampler *) *
+        renderer->samplersToDestroyCapacity);
+
+    renderer->graphicsPipelinesToDestroyCapacity = 16;
+    renderer->graphicsPipelinesToDestroyCount = 0;
+
+    renderer->graphicsPipelinesToDestroy = SDL_malloc(
+        sizeof(VulkanGraphicsPipeline *) *
+        renderer->graphicsPipelinesToDestroyCapacity);
+
+    renderer->computePipelinesToDestroyCapacity = 16;
+    renderer->computePipelinesToDestroyCount = 0;
+
+    renderer->computePipelinesToDestroy = SDL_malloc(
+        sizeof(VulkanComputePipeline *) *
+        renderer->computePipelinesToDestroyCapacity);
+
+    renderer->shadersToDestroyCapacity = 16;
+    renderer->shadersToDestroyCount = 0;
+
+    renderer->shadersToDestroy = SDL_malloc(
+        sizeof(VulkanShader *) *
+        renderer->shadersToDestroyCapacity);
+
+    renderer->framebuffersToDestroyCapacity = 16;
+    renderer->framebuffersToDestroyCount = 0;
+    renderer->framebuffersToDestroy = SDL_malloc(
+        sizeof(VulkanFramebuffer *) *
+        renderer->framebuffersToDestroyCapacity);
+
+    // Defrag state
+
+    renderer->defragInProgress = 0;
+
+    renderer->allocationsToDefragCount = 0;
+    renderer->allocationsToDefragCapacity = 4;
+    renderer->allocationsToDefrag = SDL_malloc(
+        renderer->allocationsToDefragCapacity * sizeof(VulkanMemoryAllocation *));
+
+    return result;
+}
+
+SDL_GpuBootstrap VulkanDriver = {
+    "Vulkan",
+    SDL_GPU_DRIVER_VULKAN,
+    SDL_GPU_SHADERFORMAT_SPIRV,
+    VULKAN_PrepareDriver,
+    VULKAN_CreateDevice
+};
+
+#endif // SDL_GPU_VULKAN

+ 176 - 0
src/gpu/vulkan/SDL_gpu_vulkan_vkfuncs.h

@@ -0,0 +1,176 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+ * Global functions from the Vulkan Loader
+ */
+
+#ifndef VULKAN_GLOBAL_FUNCTION
+#define VULKAN_GLOBAL_FUNCTION(name)
+#endif
+VULKAN_GLOBAL_FUNCTION(vkCreateInstance)
+VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties)
+VULKAN_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties)
+
+/*
+ * vkInstance, created by global vkCreateInstance function
+ */
+
+#ifndef VULKAN_INSTANCE_FUNCTION
+#define VULKAN_INSTANCE_FUNCTION(name)
+#endif
+
+// Vulkan 1.0
+VULKAN_INSTANCE_FUNCTION(vkGetDeviceProcAddr)
+VULKAN_INSTANCE_FUNCTION(vkCreateDevice)
+VULKAN_INSTANCE_FUNCTION(vkDestroyInstance)
+VULKAN_INSTANCE_FUNCTION(vkEnumerateDeviceExtensionProperties)
+VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices)
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures)
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties)
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceFormatProperties)
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties)
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties)
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties)
+
+// VK_KHR_get_physical_device_properties2, needed for KHR_driver_properties
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2KHR)
+
+// VK_KHR_surface
+VULKAN_INSTANCE_FUNCTION(vkDestroySurfaceKHR)
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceCapabilitiesKHR)
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR)
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR)
+VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR)
+
+// VK_EXT_debug_utils
+VULKAN_INSTANCE_FUNCTION(vkCmdBeginDebugUtilsLabelEXT)
+VULKAN_INSTANCE_FUNCTION(vkSetDebugUtilsObjectNameEXT)
+VULKAN_INSTANCE_FUNCTION(vkCmdEndDebugUtilsLabelEXT)
+VULKAN_INSTANCE_FUNCTION(vkCmdInsertDebugUtilsLabelEXT)
+
+/*
+ * vkDevice, created by a vkInstance
+ */
+
+#ifndef VULKAN_DEVICE_FUNCTION
+#define VULKAN_DEVICE_FUNCTION(name)
+#endif
+
+// Vulkan 1.0
+VULKAN_DEVICE_FUNCTION(vkAllocateCommandBuffers)
+VULKAN_DEVICE_FUNCTION(vkAllocateDescriptorSets)
+VULKAN_DEVICE_FUNCTION(vkAllocateMemory)
+VULKAN_DEVICE_FUNCTION(vkBeginCommandBuffer)
+VULKAN_DEVICE_FUNCTION(vkBindBufferMemory)
+VULKAN_DEVICE_FUNCTION(vkBindImageMemory)
+VULKAN_DEVICE_FUNCTION(vkCmdBeginRenderPass)
+VULKAN_DEVICE_FUNCTION(vkCmdBindDescriptorSets)
+VULKAN_DEVICE_FUNCTION(vkCmdBindIndexBuffer)
+VULKAN_DEVICE_FUNCTION(vkCmdBindPipeline)
+VULKAN_DEVICE_FUNCTION(vkCmdBindVertexBuffers)
+VULKAN_DEVICE_FUNCTION(vkCmdBlitImage)
+VULKAN_DEVICE_FUNCTION(vkCmdClearAttachments)
+VULKAN_DEVICE_FUNCTION(vkCmdClearColorImage)
+VULKAN_DEVICE_FUNCTION(vkCmdClearDepthStencilImage)
+VULKAN_DEVICE_FUNCTION(vkCmdCopyBuffer)
+VULKAN_DEVICE_FUNCTION(vkCmdCopyImage)
+VULKAN_DEVICE_FUNCTION(vkCmdCopyBufferToImage)
+VULKAN_DEVICE_FUNCTION(vkCmdCopyImageToBuffer)
+VULKAN_DEVICE_FUNCTION(vkCmdDispatch)
+VULKAN_DEVICE_FUNCTION(vkCmdDispatchIndirect)
+VULKAN_DEVICE_FUNCTION(vkCmdDraw)
+VULKAN_DEVICE_FUNCTION(vkCmdDrawIndexed)
+VULKAN_DEVICE_FUNCTION(vkCmdDrawIndexedIndirect)
+VULKAN_DEVICE_FUNCTION(vkCmdDrawIndirect)
+VULKAN_DEVICE_FUNCTION(vkCmdEndRenderPass)
+VULKAN_DEVICE_FUNCTION(vkCmdPipelineBarrier)
+VULKAN_DEVICE_FUNCTION(vkCmdResolveImage)
+VULKAN_DEVICE_FUNCTION(vkCmdSetBlendConstants)
+VULKAN_DEVICE_FUNCTION(vkCmdSetDepthBias)
+VULKAN_DEVICE_FUNCTION(vkCmdSetScissor)
+VULKAN_DEVICE_FUNCTION(vkCmdSetStencilReference)
+VULKAN_DEVICE_FUNCTION(vkCmdSetViewport)
+VULKAN_DEVICE_FUNCTION(vkCreateBuffer)
+VULKAN_DEVICE_FUNCTION(vkCreateCommandPool)
+VULKAN_DEVICE_FUNCTION(vkCreateDescriptorPool)
+VULKAN_DEVICE_FUNCTION(vkCreateDescriptorSetLayout)
+VULKAN_DEVICE_FUNCTION(vkCreateFence)
+VULKAN_DEVICE_FUNCTION(vkCreateFramebuffer)
+VULKAN_DEVICE_FUNCTION(vkCreateComputePipelines)
+VULKAN_DEVICE_FUNCTION(vkCreateGraphicsPipelines)
+VULKAN_DEVICE_FUNCTION(vkCreateImage)
+VULKAN_DEVICE_FUNCTION(vkCreateImageView)
+VULKAN_DEVICE_FUNCTION(vkCreatePipelineCache)
+VULKAN_DEVICE_FUNCTION(vkCreatePipelineLayout)
+VULKAN_DEVICE_FUNCTION(vkCreateRenderPass)
+VULKAN_DEVICE_FUNCTION(vkCreateSampler)
+VULKAN_DEVICE_FUNCTION(vkCreateSemaphore)
+VULKAN_DEVICE_FUNCTION(vkCreateShaderModule)
+VULKAN_DEVICE_FUNCTION(vkDestroyBuffer)
+VULKAN_DEVICE_FUNCTION(vkDestroyCommandPool)
+VULKAN_DEVICE_FUNCTION(vkDestroyDescriptorPool)
+VULKAN_DEVICE_FUNCTION(vkDestroyDescriptorSetLayout)
+VULKAN_DEVICE_FUNCTION(vkDestroyDevice)
+VULKAN_DEVICE_FUNCTION(vkDestroyFence)
+VULKAN_DEVICE_FUNCTION(vkDestroyFramebuffer)
+VULKAN_DEVICE_FUNCTION(vkDestroyImage)
+VULKAN_DEVICE_FUNCTION(vkDestroyImageView)
+VULKAN_DEVICE_FUNCTION(vkDestroyPipeline)
+VULKAN_DEVICE_FUNCTION(vkDestroyPipelineCache)
+VULKAN_DEVICE_FUNCTION(vkDestroyPipelineLayout)
+VULKAN_DEVICE_FUNCTION(vkDestroyRenderPass)
+VULKAN_DEVICE_FUNCTION(vkDestroySampler)
+VULKAN_DEVICE_FUNCTION(vkDestroySemaphore)
+VULKAN_DEVICE_FUNCTION(vkDestroyShaderModule)
+VULKAN_DEVICE_FUNCTION(vkDeviceWaitIdle)
+VULKAN_DEVICE_FUNCTION(vkEndCommandBuffer)
+VULKAN_DEVICE_FUNCTION(vkFreeCommandBuffers)
+VULKAN_DEVICE_FUNCTION(vkFreeMemory)
+VULKAN_DEVICE_FUNCTION(vkGetDeviceQueue)
+VULKAN_DEVICE_FUNCTION(vkGetPipelineCacheData)
+VULKAN_DEVICE_FUNCTION(vkGetFenceStatus)
+VULKAN_DEVICE_FUNCTION(vkGetBufferMemoryRequirements)
+VULKAN_DEVICE_FUNCTION(vkGetImageMemoryRequirements)
+VULKAN_DEVICE_FUNCTION(vkMapMemory)
+VULKAN_DEVICE_FUNCTION(vkQueueSubmit)
+VULKAN_DEVICE_FUNCTION(vkQueueWaitIdle)
+VULKAN_DEVICE_FUNCTION(vkResetCommandBuffer)
+VULKAN_DEVICE_FUNCTION(vkResetCommandPool)
+VULKAN_DEVICE_FUNCTION(vkResetDescriptorPool)
+VULKAN_DEVICE_FUNCTION(vkResetFences)
+VULKAN_DEVICE_FUNCTION(vkUnmapMemory)
+VULKAN_DEVICE_FUNCTION(vkUpdateDescriptorSets)
+VULKAN_DEVICE_FUNCTION(vkWaitForFences)
+
+// VK_KHR_swapchain
+VULKAN_DEVICE_FUNCTION(vkAcquireNextImageKHR)
+VULKAN_DEVICE_FUNCTION(vkCreateSwapchainKHR)
+VULKAN_DEVICE_FUNCTION(vkDestroySwapchainKHR)
+VULKAN_DEVICE_FUNCTION(vkQueuePresentKHR)
+VULKAN_DEVICE_FUNCTION(vkGetSwapchainImagesKHR)
+
+/*
+ * Redefine these every time you include this header!
+ */
+#undef VULKAN_GLOBAL_FUNCTION
+#undef VULKAN_INSTANCE_FUNCTION
+#undef VULKAN_DEVICE_FUNCTION

+ 1 - 1
src/render/SDL_d3dmath.h

@@ -20,7 +20,7 @@
 */
 #include "SDL_internal.h"
 
-#if (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12 || SDL_VIDEO_RENDER_VULKAN)
+#if (SDL_VIDEO_RENDER_D3D || SDL_VIDEO_RENDER_D3D11 || SDL_VIDEO_RENDER_D3D12 || SDL_VIDEO_RENDER_VULKAN || SDL_VIDEO_RENDER_GPU)
 
 // Set up for C function definitions, even when using C++
 #ifdef __cplusplus

+ 4 - 1
src/render/SDL_render.c

@@ -137,7 +137,10 @@ static const SDL_RenderDriver *render_drivers[] = {
     &VULKAN_RenderDriver,
 #endif
 #if SDL_VIDEO_RENDER_SW
-    &SW_RenderDriver
+    &SW_RenderDriver,
+#endif
+#if SDL_VIDEO_RENDER_GPU
+    &GPU_RenderDriver,
 #endif
 };
 #endif // !SDL_RENDER_DISABLED

+ 1 - 0
src/render/SDL_sysrender.h

@@ -324,6 +324,7 @@ extern SDL_RenderDriver PS2_RenderDriver;
 extern SDL_RenderDriver PSP_RenderDriver;
 extern SDL_RenderDriver SW_RenderDriver;
 extern SDL_RenderDriver VITA_GXM_RenderDriver;
+extern SDL_RenderDriver GPU_RenderDriver;
 
 // Clean up any renderers at shutdown
 extern void SDL_QuitRender(void);

+ 74 - 0
src/render/sdlgpu/SDL_gpu_util.h

@@ -0,0 +1,74 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_gpu_util_h_
+#define SDL_gpu_util_h_
+
+#define SDL_GPU_BLENDOP_INVALID     ((SDL_GpuBlendOp)0x7fffffff)
+#define SDL_GPU_BLENDFACTOR_INVALID ((SDL_GpuBlendFactor)0x7fffffff)
+
+static SDL_INLINE SDL_GpuBlendFactor GPU_ConvertBlendFactor(SDL_BlendFactor factor)
+{
+    switch (factor) {
+    case SDL_BLENDFACTOR_ZERO:
+        return SDL_GPU_BLENDFACTOR_ZERO;
+    case SDL_BLENDFACTOR_ONE:
+        return SDL_GPU_BLENDFACTOR_ONE;
+    case SDL_BLENDFACTOR_SRC_COLOR:
+        return SDL_GPU_BLENDFACTOR_SRC_COLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
+        return SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_COLOR;
+    case SDL_BLENDFACTOR_SRC_ALPHA:
+        return SDL_GPU_BLENDFACTOR_SRC_ALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
+        return SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
+    case SDL_BLENDFACTOR_DST_COLOR:
+        return SDL_GPU_BLENDFACTOR_DST_COLOR;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
+        return SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_COLOR;
+    case SDL_BLENDFACTOR_DST_ALPHA:
+        return SDL_GPU_BLENDFACTOR_DST_ALPHA;
+    case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
+        return SDL_GPU_BLENDFACTOR_ONE_MINUS_DST_ALPHA;
+    default:
+        return SDL_GPU_BLENDFACTOR_INVALID;
+    }
+}
+
+static SDL_INLINE SDL_GpuBlendOp GPU_ConvertBlendOperation(SDL_BlendOperation operation)
+{
+    switch (operation) {
+    case SDL_BLENDOPERATION_ADD:
+        return SDL_GPU_BLENDOP_ADD;
+    case SDL_BLENDOPERATION_SUBTRACT:
+        return SDL_GPU_BLENDOP_SUBTRACT;
+    case SDL_BLENDOPERATION_REV_SUBTRACT:
+        return SDL_GPU_BLENDOP_REVERSE_SUBTRACT;
+    case SDL_BLENDOPERATION_MINIMUM:
+        return SDL_GPU_BLENDOP_MIN;
+    case SDL_BLENDOPERATION_MAXIMUM:
+        return SDL_GPU_BLENDOP_MAX;
+    default:
+        return SDL_GPU_BLENDOP_INVALID;
+    }
+}
+
+#endif // SDL_gpu_util_h

+ 223 - 0
src/render/sdlgpu/SDL_pipeline_gpu.c

@@ -0,0 +1,223 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_internal.h"
+
+#if SDL_VIDEO_RENDER_GPU
+
+#include "SDL_gpu_util.h"
+#include "SDL_pipeline_gpu.h"
+
+#include "../SDL_sysrender.h"
+
+struct GPU_PipelineCacheKeyStruct
+{
+    Uint64 blend_mode : 28;
+    Uint64 frag_shader : 4;
+    Uint64 vert_shader : 4;
+    Uint64 attachment_format : 6;
+    Uint64 primitive_type : 3;
+};
+
+typedef union GPU_PipelineCacheKey
+{
+    struct GPU_PipelineCacheKeyStruct as_struct;
+    Uint64 as_uint64;
+} GPU_PipelineCacheKey;
+
+SDL_COMPILE_TIME_ASSERT(GPU_PipelineCacheKey_Size, sizeof(GPU_PipelineCacheKey) <= sizeof(Uint64));
+
+typedef struct GPU_PipelineCacheEntry
+{
+    GPU_PipelineCacheKey key;
+    SDL_GpuGraphicsPipeline *pipeline;
+} GPU_PipelineCacheEntry;
+
+static Uint32 HashPipelineCacheKey(const GPU_PipelineCacheKey *key)
+{
+    Uint64 x = key->as_uint64;
+    // 64-bit uint hash function stolen from taisei (which stole it from somewhere else)
+    x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
+    x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb);
+    x = x ^ (x >> 31);
+    return (Uint32)(x & 0xffffffff);
+}
+
+static Uint32 HashPassthrough(const void *key, void *data)
+{
+    // double-cast to silence a clang warning
+    return (Uint32)(uintptr_t)key;
+}
+
+static bool MatchPipelineCacheKey(const void *a, const void *b, void *data)
+{
+    return a == b;
+}
+
+static void NukePipelineCacheEntry(const void *key, const void *value, void *data)
+{
+    GPU_PipelineCacheEntry *entry = (GPU_PipelineCacheEntry *)value;
+    SDL_GpuDevice *device = data;
+
+    SDL_ReleaseGpuGraphicsPipeline(device, entry->pipeline);
+    SDL_free(entry);
+}
+
+bool GPU_InitPipelineCache(GPU_PipelineCache *cache, SDL_GpuDevice *device)
+{
+    // FIXME how many buckets do we need?
+    cache->table = SDL_CreateHashTable(device, 32, HashPassthrough, MatchPipelineCacheKey, NukePipelineCacheEntry, true);
+
+    return (bool)cache->table;
+}
+
+void GPU_DestroyPipelineCache(GPU_PipelineCache *cache)
+{
+    SDL_DestroyHashTable(cache->table);
+}
+
+static SDL_GpuGraphicsPipeline *MakePipeline(SDL_GpuDevice *device, GPU_Shaders *shaders, const GPU_PipelineParameters *params)
+{
+    SDL_GpuColorAttachmentDescription ad;
+    SDL_zero(ad);
+    ad.format = params->attachment_format;
+
+    SDL_BlendMode blend = params->blend_mode;
+    ad.blendState.blendEnable = blend != 0;
+    ad.blendState.colorWriteMask = 0xF;
+    ad.blendState.alphaBlendOp = GPU_ConvertBlendOperation(SDL_GetBlendModeAlphaOperation(blend));
+    ad.blendState.dstAlphaBlendFactor = GPU_ConvertBlendFactor(SDL_GetBlendModeDstAlphaFactor(blend));
+    ad.blendState.srcAlphaBlendFactor = GPU_ConvertBlendFactor(SDL_GetBlendModeSrcAlphaFactor(blend));
+    ad.blendState.colorBlendOp = GPU_ConvertBlendOperation(SDL_GetBlendModeColorOperation(blend));
+    ad.blendState.dstColorBlendFactor = GPU_ConvertBlendFactor(SDL_GetBlendModeDstColorFactor(blend));
+    ad.blendState.srcColorBlendFactor = GPU_ConvertBlendFactor(SDL_GetBlendModeSrcColorFactor(blend));
+
+    SDL_GpuGraphicsPipelineCreateInfo pci;
+    SDL_zero(pci);
+    pci.attachmentInfo.hasDepthStencilAttachment = false;
+    pci.attachmentInfo.colorAttachmentCount = 1;
+    pci.attachmentInfo.colorAttachmentDescriptions = &ad;
+    pci.vertexShader = GPU_GetVertexShader(shaders, params->vert_shader);
+    pci.fragmentShader = GPU_GetFragmentShader(shaders, params->frag_shader);
+    pci.multisampleState.sampleCount = SDL_GPU_SAMPLECOUNT_1;
+    pci.multisampleState.sampleMask = 0xFFFF;
+    pci.primitiveType = params->primitive_type;
+
+    pci.rasterizerState.cullMode = SDL_GPU_CULLMODE_NONE;
+    pci.rasterizerState.fillMode = SDL_GPU_FILLMODE_FILL;
+    pci.rasterizerState.frontFace = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE;
+
+    SDL_GpuVertexBinding bind;
+    SDL_zero(bind);
+
+    Uint32 num_attribs = 0;
+    SDL_GpuVertexAttribute attribs[4];
+    SDL_zero(attribs);
+
+    bool have_attr_color = false;
+    bool have_attr_uv = false;
+
+    switch (params->vert_shader) {
+    case VERT_SHADER_TRI_TEXTURE:
+        have_attr_uv = true;
+        SDL_FALLTHROUGH;
+    case VERT_SHADER_TRI_COLOR:
+        have_attr_color = true;
+        SDL_FALLTHROUGH;
+    default:
+        break;
+    }
+
+    // Position
+    attribs[num_attribs].location = num_attribs;
+    attribs[num_attribs].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
+    attribs[num_attribs].offset = bind.stride;
+    bind.stride += 2 * sizeof(float);
+    num_attribs++;
+
+    if (have_attr_color) {
+        // Color
+        attribs[num_attribs].location = num_attribs;
+        attribs[num_attribs].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4;
+        attribs[num_attribs].offset = bind.stride;
+        bind.stride += 4 * sizeof(float);
+        num_attribs++;
+    }
+
+    if (have_attr_uv) {
+        // UVs
+        attribs[num_attribs].location = num_attribs;
+        attribs[num_attribs].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
+        attribs[num_attribs].offset = bind.stride;
+        bind.stride += 2 * sizeof(float);
+        num_attribs++;
+    }
+
+    pci.vertexInputState.vertexAttributeCount = num_attribs;
+    pci.vertexInputState.vertexAttributes = attribs;
+    pci.vertexInputState.vertexBindingCount = 1;
+    pci.vertexInputState.vertexBindings = &bind;
+
+    return SDL_CreateGpuGraphicsPipeline(device, &pci);
+}
+
+static GPU_PipelineCacheKey MakePipelineCacheKey(const GPU_PipelineParameters *params)
+{
+    GPU_PipelineCacheKey key;
+    SDL_zero(key);
+    key.as_struct.blend_mode = params->blend_mode;
+    key.as_struct.frag_shader = params->frag_shader;
+    key.as_struct.vert_shader = params->vert_shader;
+    key.as_struct.attachment_format = params->attachment_format;
+    key.as_struct.primitive_type = params->primitive_type;
+    return key;
+}
+
+SDL_GpuGraphicsPipeline *GPU_GetPipeline(GPU_PipelineCache *cache, GPU_Shaders *shaders, SDL_GpuDevice *device, const GPU_PipelineParameters *params)
+{
+    GPU_PipelineCacheKey key = MakePipelineCacheKey(params);
+    void *keyval = (void *)(uintptr_t)HashPipelineCacheKey(&key);
+    SDL_GpuGraphicsPipeline *pipeline = NULL;
+
+    void *iter = NULL;
+    GPU_PipelineCacheEntry *entry = NULL;
+
+    while (SDL_IterateHashTableKey(cache->table, keyval, (const void **)&entry, &iter)) {
+        if (entry->key.as_uint64 == key.as_uint64) {
+            return entry->pipeline;
+        }
+    }
+
+    pipeline = MakePipeline(device, shaders, params);
+
+    if (pipeline == NULL) {
+        return NULL;
+    }
+
+    entry = SDL_malloc(sizeof(*entry));
+    entry->key = key;
+    entry->pipeline = pipeline;
+
+    SDL_InsertIntoHashTable(cache->table, keyval, entry);
+
+    return pipeline;
+}
+
+#endif

+ 49 - 0
src/render/sdlgpu/SDL_pipeline_gpu.h

@@ -0,0 +1,49 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_pipeline_gpu_h_
+#define SDL_pipeline_gpu_h_
+
+#include "SDL_internal.h"
+
+#include "SDL_shaders_gpu.h"
+
+#include "SDL_hashtable.h"
+
+typedef struct GPU_PipelineParameters
+{
+    SDL_BlendMode blend_mode;
+    GPU_FragmentShaderID frag_shader;
+    GPU_VertexShaderID vert_shader;
+    SDL_GpuTextureFormat attachment_format;
+    SDL_GpuPrimitiveType primitive_type;
+} GPU_PipelineParameters;
+
+typedef struct GPU_PipelineCache
+{
+    SDL_HashTable *table;
+} GPU_PipelineCache;
+
+extern bool GPU_InitPipelineCache(GPU_PipelineCache *cache, SDL_GpuDevice *device);
+extern void GPU_DestroyPipelineCache(GPU_PipelineCache *cache);
+extern SDL_GpuGraphicsPipeline *GPU_GetPipeline(GPU_PipelineCache *cache, GPU_Shaders *shaders, SDL_GpuDevice *device, const GPU_PipelineParameters *params);
+
+#endif // SDL_pipeline_gpu_h_

+ 1303 - 0
src/render/sdlgpu/SDL_render_gpu.c

@@ -0,0 +1,1303 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_internal.h"
+
+#if SDL_VIDEO_RENDER_GPU
+#include "../../video/SDL_pixels_c.h"
+#include "../SDL_d3dmath.h"
+#include "../SDL_sysrender.h"
+#include "SDL_gpu_util.h"
+#include "SDL_pipeline_gpu.h"
+#include "SDL_shaders_gpu.h"
+
+typedef struct GPU_ShaderUniformData
+{
+    Float4X4 mvp;
+    SDL_FColor color;
+    float texture_size[2];
+} GPU_ShaderUniformData;
+
+typedef struct GPU_RenderData
+{
+    SDL_GpuDevice *device;
+    GPU_Shaders shaders;
+    GPU_PipelineCache pipeline_cache;
+    SDL_GpuFence *present_fence;
+
+    struct
+    {
+        SDL_GpuTexture *texture;
+        SDL_GpuTextureFormat format;
+        Uint32 width;
+        Uint32 height;
+    } backbuffer;
+
+    struct
+    {
+        SDL_GpuSwapchainComposition composition;
+        SDL_GpuPresentMode present_mode;
+    } swapchain;
+
+    struct
+    {
+        SDL_GpuTransferBuffer *transfer_buf;
+        SDL_GpuBuffer *buffer;
+        Uint32 buffer_size;
+    } vertices;
+
+    struct
+    {
+        SDL_GpuRenderPass *render_pass;
+        SDL_Texture *render_target;
+        SDL_GpuCommandBuffer *command_buffer;
+        SDL_GpuColorAttachmentInfo color_attachment;
+        SDL_GpuViewport viewport;
+        SDL_Rect scissor;
+        SDL_FColor draw_color;
+        bool scissor_enabled;
+        bool scissor_was_enabled;
+        GPU_ShaderUniformData shader_data;
+    } state;
+
+    SDL_GpuSampler *samplers[3][2];
+} GPU_RenderData;
+
+typedef struct GPU_TextureData
+{
+    SDL_GpuTexture *texture;
+    SDL_GpuTextureFormat format;
+    GPU_FragmentShaderID shader;
+    void *pixels;
+    int pitch;
+    SDL_Rect locked_rect;
+} GPU_TextureData;
+
+static bool GPU_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode)
+{
+    SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
+    SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
+    SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
+    SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
+    SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
+    SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
+
+    if (GPU_ConvertBlendFactor(srcColorFactor) == SDL_GPU_BLENDFACTOR_INVALID ||
+        GPU_ConvertBlendFactor(srcAlphaFactor) == SDL_GPU_BLENDFACTOR_INVALID ||
+        GPU_ConvertBlendOperation(colorOperation) == SDL_GPU_BLENDOP_INVALID ||
+        GPU_ConvertBlendFactor(dstColorFactor) == SDL_GPU_BLENDFACTOR_INVALID ||
+        GPU_ConvertBlendFactor(dstAlphaFactor) == SDL_GPU_BLENDFACTOR_INVALID ||
+        GPU_ConvertBlendOperation(alphaOperation) == SDL_GPU_BLENDOP_INVALID) {
+        return false;
+    }
+
+    return true;
+}
+
+static SDL_GpuTextureFormat PixFormatToTexFormat(SDL_PixelFormat pixel_format)
+{
+    switch (pixel_format) {
+    case SDL_PIXELFORMAT_BGRA32:
+    case SDL_PIXELFORMAT_BGRX32:
+        return SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM;
+    case SDL_PIXELFORMAT_RGBA32:
+    case SDL_PIXELFORMAT_RGBX32:
+        return SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
+
+    // YUV TODO
+    case SDL_PIXELFORMAT_YV12:
+    case SDL_PIXELFORMAT_IYUV:
+    case SDL_PIXELFORMAT_NV12:
+    case SDL_PIXELFORMAT_NV21:
+    case SDL_PIXELFORMAT_UYVY:
+    default:
+        return SDL_GPU_TEXTUREFORMAT_INVALID;
+    }
+}
+
+static SDL_PixelFormat TexFormatToPixFormat(SDL_GpuTextureFormat tex_format)
+{
+    switch (tex_format) {
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM:
+        return SDL_PIXELFORMAT_RGBA32;
+    case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM:
+        return SDL_PIXELFORMAT_BGRA32;
+    case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM:
+        return SDL_PIXELFORMAT_BGR565;
+    case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM:
+        return SDL_PIXELFORMAT_BGRA5551;
+    case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM:
+        return SDL_PIXELFORMAT_BGRA4444;
+    case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM:
+        return SDL_PIXELFORMAT_ABGR2101010;
+    case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM:
+        return SDL_PIXELFORMAT_RGBA64;
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM:
+        return SDL_PIXELFORMAT_RGBA32;
+    case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT:
+        return SDL_PIXELFORMAT_RGBA64_FLOAT;
+    case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT:
+        return SDL_PIXELFORMAT_RGBA128_FLOAT;
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT:
+        return SDL_PIXELFORMAT_RGBA32;
+    case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT:
+        return SDL_PIXELFORMAT_RGBA64;
+    case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB:
+        return SDL_PIXELFORMAT_RGBA32;
+    case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB:
+        return SDL_PIXELFORMAT_BGRA32;
+    default:
+        return SDL_PIXELFORMAT_UNKNOWN;
+    }
+}
+
+static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
+{
+    GPU_RenderData *renderdata = (GPU_RenderData *)renderer->internal;
+    GPU_TextureData *data;
+    SDL_GpuTextureFormat format;
+    SDL_GpuTextureUsageFlags usage = SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT;
+
+    format = PixFormatToTexFormat(texture->format);
+
+    if (format == SDL_GPU_TEXTUREFORMAT_INVALID) {
+        return SDL_SetError("Texture format %s not supported by SDL_Gpu",
+                            SDL_GetPixelFormatName(texture->format));
+    }
+
+    data = (GPU_TextureData *)SDL_calloc(1, sizeof(*data));
+    if (!data) {
+        return false;
+    }
+
+    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
+        size_t size;
+        data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
+        size = (size_t)texture->h * data->pitch;
+        if (texture->format == SDL_PIXELFORMAT_YV12 ||
+            texture->format == SDL_PIXELFORMAT_IYUV) {
+            // Need to add size for the U and V planes
+            size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
+        }
+        if (texture->format == SDL_PIXELFORMAT_NV12 ||
+            texture->format == SDL_PIXELFORMAT_NV21) {
+            // Need to add size for the U/V plane
+            size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
+        }
+        data->pixels = SDL_calloc(1, size);
+        if (!data->pixels) {
+            SDL_free(data);
+            return false;
+        }
+
+        // TODO allocate a persistent transfer buffer
+    }
+
+    if (texture->access == SDL_TEXTUREACCESS_TARGET) {
+        usage |= SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT;
+    }
+
+    texture->internal = data;
+    SDL_GpuTextureCreateInfo tci;
+    SDL_zero(tci);
+    tci.format = format;
+    tci.layerCountOrDepth = 1;
+    tci.levelCount = 1;
+    tci.usageFlags = usage;
+    tci.width = texture->w;
+    tci.height = texture->h;
+    tci.sampleCount = SDL_GPU_SAMPLECOUNT_1;
+
+    data->format = format;
+    data->texture = SDL_CreateGpuTexture(renderdata->device, &tci);
+
+    if (!data->texture) {
+        return false;
+    }
+
+    if (texture->format == SDL_PIXELFORMAT_RGBA32 || texture->format == SDL_PIXELFORMAT_BGRA32) {
+        data->shader = FRAG_SHADER_TEXTURE_RGBA;
+    } else {
+        data->shader = FRAG_SHADER_TEXTURE_RGB;
+    }
+
+    return true;
+}
+
+static bool GPU_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture,
+                              const SDL_Rect *rect, const void *pixels, int pitch)
+{
+    GPU_RenderData *renderdata = (GPU_RenderData *)renderer->internal;
+    GPU_TextureData *data = (GPU_TextureData *)texture->internal;
+    const Uint32 texturebpp = SDL_BYTESPERPIXEL(texture->format);
+
+    Uint32 row_size = texturebpp * rect->w;
+    Uint32 data_size = row_size * rect->h;
+
+    SDL_GpuTransferBufferCreateInfo tbci;
+    SDL_zero(tbci);
+    tbci.sizeInBytes = data_size;
+    tbci.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
+
+    SDL_GpuTransferBuffer *tbuf = SDL_CreateGpuTransferBuffer(renderdata->device, &tbci);
+
+    if (tbuf == NULL) {
+        return false;
+    }
+
+    Uint8 *output = SDL_MapGpuTransferBuffer(renderdata->device, tbuf, false);
+
+    if (pitch == row_size) {
+        memcpy(output, pixels, data_size);
+    } else {
+        // FIXME is negative pitch supposed to work?
+        // If not, maybe use SDL_GpuTextureTransferInfo::imagePitch instead of this
+        const Uint8 *input = pixels;
+
+        for (int i = 0; i < rect->h; ++i) {
+            memcpy(output, input, row_size);
+            output += row_size;
+            input += pitch;
+        }
+    }
+
+    SDL_UnmapGpuTransferBuffer(renderdata->device, tbuf);
+
+    SDL_GpuCommandBuffer *cbuf = renderdata->state.command_buffer;
+    SDL_GpuCopyPass *cpass = SDL_BeginGpuCopyPass(cbuf);
+
+    SDL_GpuTextureTransferInfo tex_src;
+    SDL_zero(tex_src);
+    tex_src.transferBuffer = tbuf;
+    tex_src.imageHeight = rect->h;
+    tex_src.imagePitch = rect->w;
+
+    SDL_GpuTextureRegion tex_dst;
+    SDL_zero(tex_dst);
+    tex_dst.texture = data->texture;
+    tex_dst.x = rect->x;
+    tex_dst.y = rect->y;
+    tex_dst.w = rect->w;
+    tex_dst.h = rect->h;
+    tex_dst.d = 1;
+
+    SDL_UploadToGpuTexture(cpass, &tex_src, &tex_dst, true);
+    SDL_EndGpuCopyPass(cpass);
+    SDL_ReleaseGpuTransferBuffer(renderdata->device, tbuf);
+
+    return true;
+}
+
+static bool GPU_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
+                            const SDL_Rect *rect, void **pixels, int *pitch)
+{
+    GPU_TextureData *data = (GPU_TextureData *)texture->internal;
+
+    data->locked_rect = *rect;
+    *pixels =
+        (void *)((Uint8 *)data->pixels + rect->y * data->pitch +
+                 rect->x * SDL_BYTESPERPIXEL(texture->format));
+    *pitch = data->pitch;
+    return true;
+}
+
+static void GPU_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
+{
+    GPU_TextureData *data = (GPU_TextureData *)texture->internal;
+    const SDL_Rect *rect;
+    void *pixels;
+
+    rect = &data->locked_rect;
+    pixels =
+        (void *)((Uint8 *)data->pixels + rect->y * data->pitch +
+                 rect->x * SDL_BYTESPERPIXEL(texture->format));
+    GPU_UpdateTexture(renderer, texture, rect, pixels, data->pitch);
+}
+
+static void GPU_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scale_mode)
+{
+    // nothing to do in this backend.
+}
+
+static bool GPU_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
+{
+    GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
+
+    data->state.render_target = texture;
+
+    return true;
+}
+
+static bool GPU_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
+{
+    return true; // nothing to do in this backend.
+}
+
+static SDL_FColor GetDrawCmdColor(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
+{
+    SDL_FColor color = cmd->data.color.color;
+
+    if (SDL_RenderingLinearSpace(renderer)) {
+        SDL_ConvertToLinear(&color);
+    }
+
+    color.r *= cmd->data.color.color_scale;
+    color.g *= cmd->data.color.color_scale;
+    color.b *= cmd->data.color.color_scale;
+
+    return color;
+}
+
+static bool GPU_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
+{
+    float *verts = (float *)SDL_AllocateRenderVertices(renderer, count * 2 * sizeof(float), 0, &cmd->data.draw.first);
+
+    if (!verts) {
+        return false;
+    }
+
+    cmd->data.draw.count = count;
+    for (int i = 0; i < count; i++) {
+        *(verts++) = 0.5f + points[i].x;
+        *(verts++) = 0.5f + points[i].y;
+    }
+
+    return true;
+}
+
+static bool GPU_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
+                              const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride,
+                              int num_vertices, const void *indices, int num_indices, int size_indices,
+                              float scale_x, float scale_y)
+{
+    int i;
+    int count = indices ? num_indices : num_vertices;
+    float *verts;
+    size_t sz = 2 * sizeof(float) + 4 * sizeof(float) + (texture ? 2 : 0) * sizeof(float);
+    const float color_scale = cmd->data.draw.color_scale;
+    bool convert_color = SDL_RenderingLinearSpace(renderer);
+
+    verts = (float *)SDL_AllocateRenderVertices(renderer, count * sz, 0, &cmd->data.draw.first);
+    if (!verts) {
+        return false;
+    }
+
+    cmd->data.draw.count = count;
+    size_indices = indices ? size_indices : 0;
+
+    for (i = 0; i < count; i++) {
+        int j;
+        float *xy_;
+        SDL_FColor col_;
+        if (size_indices == 4) {
+            j = ((const Uint32 *)indices)[i];
+        } else if (size_indices == 2) {
+            j = ((const Uint16 *)indices)[i];
+        } else if (size_indices == 1) {
+            j = ((const Uint8 *)indices)[i];
+        } else {
+            j = i;
+        }
+
+        xy_ = (float *)((char *)xy + j * xy_stride);
+
+        *(verts++) = xy_[0] * scale_x;
+        *(verts++) = xy_[1] * scale_y;
+
+        col_ = *(SDL_FColor *)((char *)color + j * color_stride);
+        if (convert_color) {
+            SDL_ConvertToLinear(&col_);
+        }
+
+        // FIXME: The Vulkan backend doesn't multiply by color_scale. GL does. I'm not sure which one is wrong.
+        *(verts++) = col_.r * color_scale;
+        *(verts++) = col_.g * color_scale;
+        *(verts++) = col_.b * color_scale;
+        *(verts++) = col_.a;
+
+        if (texture) {
+            float *uv_ = (float *)((char *)uv + j * uv_stride);
+            *(verts++) = uv_[0] * texture->w;
+            *(verts++) = uv_[1] * texture->h;
+        }
+    }
+    return true;
+}
+
+static void GPU_InvalidateCachedState(SDL_Renderer *renderer)
+{
+    GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
+
+    data->state.render_target = NULL;
+    data->state.scissor_enabled = false;
+}
+
+static SDL_GpuRenderPass *RestartRenderPass(GPU_RenderData *data)
+{
+    if (data->state.render_pass) {
+        SDL_EndGpuRenderPass(data->state.render_pass);
+    }
+
+    data->state.render_pass = SDL_BeginGpuRenderPass(
+        data->state.command_buffer, &data->state.color_attachment, 1, NULL);
+
+    // *** FIXME ***
+    // This is busted. We should be able to know which load op to use.
+    // LOAD is incorrect behavior most of the time, unless we had to break a render pass.
+    // -cosmonaut
+    data->state.color_attachment.loadOp = SDL_GPU_LOADOP_LOAD;
+    data->state.scissor_was_enabled = false;
+
+    return data->state.render_pass;
+}
+
+static void PushUniforms(GPU_RenderData *data, SDL_RenderCommand *cmd)
+{
+    GPU_ShaderUniformData uniforms;
+    SDL_zero(uniforms);
+    uniforms.mvp.m[0][0] = 2.0f / data->state.viewport.w;
+    uniforms.mvp.m[1][1] = -2.0f / data->state.viewport.h;
+    uniforms.mvp.m[2][2] = 1.0f;
+    uniforms.mvp.m[3][0] = -1.0f;
+    uniforms.mvp.m[3][1] = 1.0f;
+    uniforms.mvp.m[3][3] = 1.0f;
+
+    uniforms.color = data->state.draw_color;
+
+    if (cmd->data.draw.texture) {
+        uniforms.texture_size[0] = cmd->data.draw.texture->w;
+        uniforms.texture_size[1] = cmd->data.draw.texture->h;
+    }
+
+    SDL_PushGpuVertexUniformData(data->state.command_buffer, 0, &uniforms, sizeof(uniforms));
+}
+
+static SDL_GpuSampler **SamplerPointer(
+    GPU_RenderData *data, SDL_TextureAddressMode address_mode, SDL_ScaleMode scale_mode)
+{
+    return &data->samplers[scale_mode][address_mode - 1];
+}
+
+static void SetViewportAndScissor(GPU_RenderData *data)
+{
+    SDL_SetGpuViewport(data->state.render_pass, &data->state.viewport);
+
+    if (data->state.scissor_enabled) {
+        SDL_SetGpuScissor(data->state.render_pass, &data->state.scissor);
+        data->state.scissor_was_enabled = true;
+    } else if (data->state.scissor_was_enabled) {
+        SDL_Rect r;
+        r.x = (int)data->state.viewport.x;
+        r.y = (int)data->state.viewport.y;
+        r.w = (int)data->state.viewport.w;
+        r.h = (int)data->state.viewport.h;
+        SDL_SetGpuScissor(data->state.render_pass, &r);
+        data->state.scissor_was_enabled = false;
+    }
+}
+
+static void Draw(
+    GPU_RenderData *data, SDL_RenderCommand *cmd,
+    Uint32 num_verts,
+    Uint32 offset,
+    SDL_GpuPrimitiveType prim)
+{
+    if (!data->state.render_pass || data->state.color_attachment.loadOp == SDL_GPU_LOADOP_CLEAR) {
+        RestartRenderPass(data);
+    }
+
+    GPU_VertexShaderID v_shader;
+    GPU_FragmentShaderID f_shader;
+    SDL_GpuRenderPass *pass = data->state.render_pass;
+    GPU_TextureData *tdata = NULL;
+
+    if (cmd->data.draw.texture) {
+        tdata = (GPU_TextureData *)cmd->data.draw.texture->internal;
+    }
+
+    if (prim == SDL_GPU_PRIMITIVETYPE_TRIANGLELIST) {
+        if (cmd->data.draw.texture) {
+            v_shader = VERT_SHADER_TRI_TEXTURE;
+            f_shader = tdata->shader;
+        } else {
+            v_shader = VERT_SHADER_TRI_COLOR;
+            f_shader = FRAG_SHADER_COLOR;
+        }
+    } else {
+        v_shader = VERT_SHADER_LINEPOINT;
+        f_shader = FRAG_SHADER_COLOR;
+    }
+
+    GPU_PipelineParameters pipe_params;
+    SDL_zero(pipe_params);
+    pipe_params.blend_mode = cmd->data.draw.blend;
+    pipe_params.vert_shader = v_shader;
+    pipe_params.frag_shader = f_shader;
+    pipe_params.primitive_type = prim;
+
+    if (data->state.render_target) {
+        pipe_params.attachment_format = ((GPU_TextureData *)data->state.render_target->internal)->format;
+    } else {
+        pipe_params.attachment_format = data->backbuffer.format;
+    }
+
+    SDL_GpuGraphicsPipeline *pipe = GPU_GetPipeline(&data->pipeline_cache, &data->shaders, data->device, &pipe_params);
+
+    if (!pipe) {
+        return;
+    }
+
+    SetViewportAndScissor(data);
+    SDL_BindGpuGraphicsPipeline(data->state.render_pass, pipe);
+
+    if (tdata) {
+        SDL_GpuTextureSamplerBinding sampler_bind;
+        SDL_zero(sampler_bind);
+        sampler_bind.sampler = *SamplerPointer(data, cmd->data.draw.texture_address_mode, cmd->data.draw.texture->scaleMode);
+        sampler_bind.texture = tdata->texture;
+        SDL_BindGpuFragmentSamplers(pass, 0, &sampler_bind, 1);
+    }
+
+    SDL_GpuBufferBinding buffer_bind;
+    SDL_zero(buffer_bind);
+    buffer_bind.buffer = data->vertices.buffer;
+    buffer_bind.offset = offset;
+
+    SDL_BindGpuVertexBuffers(pass, 0, &buffer_bind, 1);
+    PushUniforms(data, cmd);
+    SDL_DrawGpuPrimitives(data->state.render_pass, num_verts, 1, 0, 0);
+}
+
+static void ReleaseVertexBuffer(GPU_RenderData *data)
+{
+    if (data->vertices.buffer) {
+        SDL_ReleaseGpuBuffer(data->device, data->vertices.buffer);
+    }
+
+    if (data->vertices.transfer_buf) {
+        SDL_ReleaseGpuTransferBuffer(data->device, data->vertices.transfer_buf);
+    }
+
+    data->vertices.buffer_size = 0;
+}
+
+static bool InitVertexBuffer(GPU_RenderData *data, Uint32 size)
+{
+    SDL_GpuBufferCreateInfo bci;
+    SDL_zero(bci);
+    bci.sizeInBytes = size;
+    bci.usageFlags = SDL_GPU_BUFFERUSAGE_VERTEX_BIT;
+
+    data->vertices.buffer = SDL_CreateGpuBuffer(data->device, &bci);
+
+    if (!data->vertices.buffer) {
+        return -1;
+    }
+
+    SDL_GpuTransferBufferCreateInfo tbci;
+    SDL_zero(tbci);
+    tbci.sizeInBytes = size;
+    tbci.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
+
+    data->vertices.transfer_buf = SDL_CreateGpuTransferBuffer(data->device, &tbci);
+    return (bool)data->vertices.transfer_buf;
+}
+
+static bool UploadVertices(GPU_RenderData *data, void *vertices, size_t vertsize)
+{
+    if (vertsize == 0) {
+        return true;
+    }
+
+    if (vertsize > data->vertices.buffer_size) {
+        ReleaseVertexBuffer(data);
+        if (!InitVertexBuffer(data, (Uint32)vertsize)) {
+            return false;
+        }
+    }
+
+    void *staging_buf = SDL_MapGpuTransferBuffer(data->device, data->vertices.transfer_buf, true);
+    memcpy(staging_buf, vertices, vertsize);
+    SDL_UnmapGpuTransferBuffer(data->device, data->vertices.transfer_buf);
+
+    SDL_GpuCopyPass *pass = SDL_BeginGpuCopyPass(data->state.command_buffer);
+
+    if (!pass) {
+        return false;
+    }
+
+    SDL_GpuTransferBufferLocation src;
+    SDL_zero(src);
+    src.transferBuffer = data->vertices.transfer_buf;
+
+    SDL_GpuBufferRegion dst;
+    SDL_zero(dst);
+    dst.buffer = data->vertices.buffer;
+    dst.size = (Uint32)vertsize;
+
+    SDL_UploadToGpuBuffer(pass, &src, &dst, true);
+    SDL_EndGpuCopyPass(pass);
+
+    return true;
+}
+
+// *** FIXME ***
+// We might be able to run these data uploads on a separate command buffer
+// which would allow us to avoid breaking render passes.
+// Honestly I'm a little skeptical of this entire approach,
+// we already have a command buffer structure
+// so it feels weird to be deferring the operations manually.
+// We could also fairly easily run the geometry transformations
+// on compute shaders instead of the CPU, which would be a HUGE performance win.
+// -cosmonaut
+static bool GPU_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
+{
+    GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
+
+    if (!UploadVertices(data, vertices, vertsize)) {
+        return false;
+    }
+
+    data->state.color_attachment.loadOp = SDL_GPU_LOADOP_LOAD;
+
+    if (renderer->target) {
+        GPU_TextureData *tdata = renderer->target->internal;
+        data->state.color_attachment.texture = tdata->texture;
+    } else {
+        data->state.color_attachment.texture = data->backbuffer.texture;
+    }
+
+    if (!data->state.color_attachment.texture) {
+        return SDL_SetError("Render target texture is NULL");
+    }
+
+    while (cmd) {
+        switch (cmd->command) {
+        case SDL_RENDERCMD_SETDRAWCOLOR:
+        {
+            data->state.draw_color = GetDrawCmdColor(renderer, cmd);
+            break;
+        }
+
+        case SDL_RENDERCMD_SETVIEWPORT:
+        {
+            SDL_Rect *viewport = &cmd->data.viewport.rect;
+            data->state.viewport.x = viewport->x;
+            data->state.viewport.y = viewport->y;
+            data->state.viewport.w = viewport->w;
+            data->state.viewport.h = viewport->h;
+            break;
+        }
+
+        case SDL_RENDERCMD_SETCLIPRECT:
+        {
+            const SDL_Rect *rect = &cmd->data.cliprect.rect;
+            data->state.scissor.x = (int)data->state.viewport.x + rect->x;
+            data->state.scissor.y = (int)data->state.viewport.y + rect->y;
+            data->state.scissor.w = rect->w;
+            data->state.scissor.h = rect->h;
+            data->state.scissor_enabled = cmd->data.cliprect.enabled;
+            break;
+        }
+
+        case SDL_RENDERCMD_CLEAR:
+        {
+            data->state.color_attachment.clearColor = GetDrawCmdColor(renderer, cmd);
+            data->state.color_attachment.loadOp = SDL_GPU_LOADOP_CLEAR;
+            break;
+        }
+
+        case SDL_RENDERCMD_FILL_RECTS: // unused
+            break;
+
+        case SDL_RENDERCMD_COPY: // unused
+            break;
+
+        case SDL_RENDERCMD_COPY_EX: // unused
+            break;
+
+        case SDL_RENDERCMD_DRAW_LINES:
+        {
+            Uint32 count = (Uint32)cmd->data.draw.count;
+            Uint32 offset = (Uint32)cmd->data.draw.first;
+
+            if (count > 2) {
+                // joined lines cannot be grouped
+                Draw(data, cmd, count, offset, SDL_GPU_PRIMITIVETYPE_LINESTRIP);
+            } else {
+                // let's group non joined lines
+                SDL_RenderCommand *finalcmd = cmd;
+                SDL_RenderCommand *nextcmd = cmd->next;
+                SDL_BlendMode thisblend = cmd->data.draw.blend;
+
+                while (nextcmd) {
+                    const SDL_RenderCommandType nextcmdtype = nextcmd->command;
+                    if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
+                        break; // can't go any further on this draw call, different render command up next.
+                    } else if (nextcmd->data.draw.count != 2) {
+                        break; // can't go any further on this draw call, those are joined lines
+                    } else if (nextcmd->data.draw.blend != thisblend) {
+                        break; // can't go any further on this draw call, different blendmode copy up next.
+                    } else {
+                        finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
+                        count += (Uint32)nextcmd->data.draw.count;
+                    }
+                    nextcmd = nextcmd->next;
+                }
+
+                Draw(data, cmd, count, offset, SDL_GPU_PRIMITIVETYPE_LINELIST);
+                cmd = finalcmd; // skip any copy commands we just combined in here.
+            }
+            break;
+        }
+
+        case SDL_RENDERCMD_DRAW_POINTS:
+        case SDL_RENDERCMD_GEOMETRY:
+        {
+            /* as long as we have the same copy command in a row, with the
+               same texture, we can combine them all into a single draw call. */
+            SDL_Texture *thistexture = cmd->data.draw.texture;
+            SDL_BlendMode thisblend = cmd->data.draw.blend;
+            const SDL_RenderCommandType thiscmdtype = cmd->command;
+            SDL_RenderCommand *finalcmd = cmd;
+            SDL_RenderCommand *nextcmd = cmd->next;
+            Uint32 count = (Uint32)cmd->data.draw.count;
+            Uint32 offset = (Uint32)cmd->data.draw.first;
+
+            while (nextcmd) {
+                const SDL_RenderCommandType nextcmdtype = nextcmd->command;
+                if (nextcmdtype != thiscmdtype) {
+                    break; // can't go any further on this draw call, different render command up next.
+                } else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
+                    // FIXME should we check address mode too?
+                    break; // can't go any further on this draw call, different texture/blendmode copy up next.
+                } else {
+                    finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
+                    count += (Uint32)nextcmd->data.draw.count;
+                }
+                nextcmd = nextcmd->next;
+            }
+
+            SDL_GpuPrimitiveType prim = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST; // SDL_RENDERCMD_GEOMETRY
+            if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) {
+                prim = SDL_GPU_PRIMITIVETYPE_POINTLIST;
+            }
+
+            Draw(data, cmd, count, offset, prim);
+
+            cmd = finalcmd; // skip any copy commands we just combined in here.
+            break;
+        }
+
+        case SDL_RENDERCMD_NO_OP:
+            break;
+        }
+
+        cmd = cmd->next;
+    }
+
+    if (data->state.color_attachment.loadOp == SDL_GPU_LOADOP_CLEAR) {
+        RestartRenderPass(data);
+    }
+
+    if (data->state.render_pass) {
+        SDL_EndGpuRenderPass(data->state.render_pass);
+        data->state.render_pass = NULL;
+    }
+
+    return true;
+}
+
+static SDL_Surface *GPU_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
+{
+    GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
+    SDL_GpuTexture *gpu_tex;
+    SDL_PixelFormat pixfmt;
+
+    if (data->state.render_target) {
+        SDL_Texture *texture = data->state.render_target;
+        GPU_TextureData *texdata = texture->internal;
+        gpu_tex = texdata->texture;
+        pixfmt = texture->format;
+    } else {
+        gpu_tex = data->backbuffer.texture;
+        pixfmt = TexFormatToPixFormat(data->backbuffer.format);
+
+        if (pixfmt == SDL_PIXELFORMAT_UNKNOWN) {
+            SDL_SetError("Unsupported backbuffer format");
+            return NULL;
+        }
+    }
+
+    Uint32 bpp = SDL_BYTESPERPIXEL(pixfmt);
+    Uint32 row_size = rect->w * bpp;
+    Uint32 image_size = row_size * rect->h;
+
+    SDL_Surface *surface = SDL_CreateSurface(rect->w, rect->h, pixfmt);
+
+    if (!surface) {
+        return NULL;
+    }
+
+    SDL_GpuTransferBufferCreateInfo tbci;
+    SDL_zero(tbci);
+    tbci.sizeInBytes = image_size;
+    tbci.usage = SDL_GPU_TRANSFERBUFFERUSAGE_DOWNLOAD;
+
+    SDL_GpuTransferBuffer *tbuf = SDL_CreateGpuTransferBuffer(data->device, &tbci);
+
+    if (!tbuf) {
+        return NULL;
+    }
+
+    SDL_GpuCopyPass *pass = SDL_BeginGpuCopyPass(data->state.command_buffer);
+
+    SDL_GpuTextureRegion src;
+    SDL_zero(src);
+    src.texture = gpu_tex;
+    src.x = rect->x;
+    src.y = rect->y;
+    src.w = rect->w;
+    src.h = rect->h;
+    src.d = 1;
+
+    SDL_GpuTextureTransferInfo dst;
+    SDL_zero(dst);
+    dst.transferBuffer = tbuf;
+    dst.imageHeight = rect->h;
+    dst.imagePitch = rect->w;
+
+    SDL_DownloadFromGpuTexture(pass, &src, &dst);
+    SDL_EndGpuCopyPass(pass);
+
+    SDL_GpuFence *fence = SDL_SubmitGpuAndAcquireFence(data->state.command_buffer);
+    SDL_WaitGpuForFences(data->device, true, &fence, 1);
+    SDL_ReleaseGpuFence(data->device, fence);
+    data->state.command_buffer = SDL_AcquireGpuCommandBuffer(data->device);
+
+    void *mapped_tbuf = SDL_MapGpuTransferBuffer(data->device, tbuf, false);
+
+    if (surface->pitch == row_size) {
+        memcpy(surface->pixels, mapped_tbuf, image_size);
+    } else {
+        Uint8 *input = mapped_tbuf;
+        Uint8 *output = surface->pixels;
+
+        for (int row = 0; row < rect->h; ++row) {
+            memcpy(output, input, row_size);
+            output += surface->pitch;
+            input += row_size;
+        }
+    }
+
+    SDL_UnmapGpuTransferBuffer(data->device, tbuf);
+    SDL_ReleaseGpuTransferBuffer(data->device, tbuf);
+
+    return surface;
+}
+
+static bool CreateBackbuffer(GPU_RenderData *data, Uint32 w, Uint32 h, SDL_GpuTextureFormat fmt)
+{
+    SDL_GpuTextureCreateInfo tci;
+    SDL_zero(tci);
+    tci.width = w;
+    tci.height = h;
+    tci.format = fmt;
+    tci.layerCountOrDepth = 1;
+    tci.levelCount = 1;
+    tci.sampleCount = SDL_GPU_SAMPLECOUNT_1;
+    tci.usageFlags = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT | SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT;
+
+    data->backbuffer.texture = SDL_CreateGpuTexture(data->device, &tci);
+    data->backbuffer.width = w;
+    data->backbuffer.height = h;
+    data->backbuffer.format = fmt;
+
+    return (bool)data->backbuffer.texture;
+}
+
+static bool GPU_RenderPresent(SDL_Renderer *renderer)
+{
+    GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
+
+    Uint32 swapchain_w, swapchain_h;
+
+    SDL_GpuTexture *swapchain = SDL_AcquireGpuSwapchainTexture(data->state.command_buffer, renderer->window, &swapchain_w, &swapchain_h);
+
+    if (swapchain == NULL) {
+        goto submit;
+    }
+
+    SDL_GpuTextureFormat swapchain_fmt = SDL_GetGpuSwapchainTextureFormat(data->device, renderer->window);
+
+    if (swapchain_w != data->backbuffer.width || swapchain_h != data->backbuffer.height || swapchain_fmt != data->backbuffer.format) {
+        SDL_GpuBlitRegion src;
+        SDL_zero(src);
+        src.texture = data->backbuffer.texture;
+        src.w = data->backbuffer.width;
+        src.h = data->backbuffer.height;
+
+        SDL_GpuBlitRegion dst;
+        SDL_zero(dst);
+        dst.texture = swapchain;
+        dst.w = swapchain_w;
+        dst.h = swapchain_h;
+
+        SDL_BlitGpu(data->state.command_buffer, &src, &dst, SDL_FLIP_NONE, SDL_GPU_FILTER_LINEAR, true);
+        SDL_ReleaseGpuTexture(data->device, data->backbuffer.texture);
+        CreateBackbuffer(data, swapchain_w, swapchain_h, swapchain_fmt);
+    } else {
+        SDL_GpuTextureLocation src;
+        SDL_zero(src);
+        src.texture = data->backbuffer.texture;
+
+        SDL_GpuTextureLocation dst;
+        SDL_zero(dst);
+        dst.texture = swapchain;
+
+        SDL_GpuCopyPass *pass = SDL_BeginGpuCopyPass(data->state.command_buffer);
+        SDL_CopyGpuTextureToTexture(pass, &src, &dst, swapchain_w, swapchain_h, 1, true);
+        SDL_EndGpuCopyPass(pass);
+    }
+
+// *** FIXME ***
+// This is going to block if there is ever a frame in flight.
+// We should do something similar to FNA3D
+// where we keep track of MAX_FRAMES_IN_FLIGHT number of fences
+// and only block if we have maxed out the backpressure.
+// -cosmonaut
+submit:
+#if 1
+    if (data->present_fence) {
+        SDL_WaitGpuForFences(data->device, true, &data->present_fence, 1);
+        SDL_ReleaseGpuFence(data->device, data->present_fence);
+    }
+
+    data->present_fence = SDL_SubmitGpuAndAcquireFence(data->state.command_buffer);
+#else
+    SDL_SubmitGpu(data->state.command_buffer);
+#endif
+
+    data->state.command_buffer = SDL_AcquireGpuCommandBuffer(data->device);
+
+    return true;
+}
+
+static void GPU_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
+{
+    GPU_RenderData *renderdata = (GPU_RenderData *)renderer->internal;
+    GPU_TextureData *data = (GPU_TextureData *)texture->internal;
+
+    if (renderdata->state.render_target == texture) {
+        renderdata->state.render_target = NULL;
+    }
+
+    if (!data) {
+        return;
+    }
+
+    SDL_ReleaseGpuTexture(renderdata->device, data->texture);
+    SDL_free(data->pixels);
+    SDL_free(data);
+    texture->internal = NULL;
+}
+
+static void GPU_DestroyRenderer(SDL_Renderer *renderer)
+{
+    GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
+
+    if (!data) {
+        return;
+    }
+
+    if (data->present_fence) {
+        SDL_WaitGpuForFences(data->device, true, &data->present_fence, 1);
+        SDL_ReleaseGpuFence(data->device, data->present_fence);
+    }
+
+    if (data->state.command_buffer) {
+        SDL_SubmitGpu(data->state.command_buffer);
+        data->state.command_buffer = NULL;
+    }
+
+    for (Uint32 i = 0; i < sizeof(data->samplers) / sizeof(SDL_GpuSampler *); ++i) {
+        SDL_ReleaseGpuSampler(data->device, ((SDL_GpuSampler **)data->samplers)[i]);
+    }
+
+    if (data->backbuffer.texture) {
+        SDL_ReleaseGpuTexture(data->device, data->backbuffer.texture);
+    }
+
+    if (renderer->window) {
+        SDL_UnclaimGpuWindow(data->device, renderer->window);
+    }
+
+    ReleaseVertexBuffer(data);
+    GPU_DestroyPipelineCache(&data->pipeline_cache);
+    GPU_ReleaseShaders(&data->shaders, data->device);
+    SDL_DestroyGpuDevice(data->device);
+
+    SDL_free(data);
+}
+
+static bool ChoosePresentMode(SDL_GpuDevice *device, SDL_Window *window, const int vsync, SDL_GpuPresentMode *out_mode)
+{
+    SDL_GpuPresentMode mode;
+
+    switch (vsync) {
+    case 0:
+        mode = SDL_GPU_PRESENTMODE_MAILBOX;
+
+        if (!SDL_SupportsGpuPresentMode(device, window, mode)) {
+            mode = SDL_GPU_PRESENTMODE_IMMEDIATE;
+
+            if (!SDL_SupportsGpuPresentMode(device, window, mode)) {
+                mode = SDL_GPU_PRESENTMODE_VSYNC;
+            }
+        }
+
+        // FIXME should we return an error if both mailbox and immediate fail?
+        break;
+
+    case 1:
+        mode = SDL_GPU_PRESENTMODE_VSYNC;
+        break;
+
+    default:
+        return SDL_Unsupported();
+    }
+
+    *out_mode = mode;
+    return true;
+}
+
+static bool GPU_SetVSync(SDL_Renderer *renderer, const int vsync)
+{
+    GPU_RenderData *data = (GPU_RenderData *)renderer->internal;
+    SDL_GpuPresentMode mode = SDL_GPU_PRESENTMODE_VSYNC;
+
+    if (!ChoosePresentMode(data->device, renderer->window, vsync, &mode)) {
+        return false;
+    }
+
+    if (mode != data->swapchain.present_mode) {
+        // XXX returns bool instead of SDL-style error code
+        if (SDL_SetGpuSwapchainParameters(data->device, renderer->window, data->swapchain.composition, mode)) {
+            data->swapchain.present_mode = mode;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+static bool InitSamplers(GPU_RenderData *data)
+{
+    struct
+    {
+        struct
+        {
+            SDL_TextureAddressMode address_mode;
+            SDL_ScaleMode scale_mode;
+        } sdl;
+        struct
+        {
+            SDL_GpuSamplerAddressMode address_mode;
+            SDL_GpuFilter filter;
+            SDL_GpuSamplerMipmapMode mipmap_mode;
+            Uint32 anisotropy;
+        } gpu;
+    } configs[] = {
+        {
+            { SDL_TEXTURE_ADDRESS_CLAMP, SDL_SCALEMODE_NEAREST },
+            { SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_NEAREST, SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, 0 },
+        },
+        {
+            { SDL_TEXTURE_ADDRESS_CLAMP, SDL_SCALEMODE_LINEAR },
+            { SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_LINEAR, SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, 0 },
+        },
+        {
+            { SDL_TEXTURE_ADDRESS_CLAMP, SDL_SCALEMODE_BEST },
+            { SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_LINEAR, SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, 16 },
+        },
+        {
+            { SDL_TEXTURE_ADDRESS_WRAP, SDL_SCALEMODE_NEAREST },
+            { SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_NEAREST, SDL_GPU_SAMPLERMIPMAPMODE_NEAREST, 0 },
+        },
+        {
+            { SDL_TEXTURE_ADDRESS_WRAP, SDL_SCALEMODE_LINEAR },
+            { SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_LINEAR, SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, 0 },
+        },
+        {
+            { SDL_TEXTURE_ADDRESS_WRAP, SDL_SCALEMODE_BEST },
+            { SDL_GPU_SAMPLERADDRESSMODE_REPEAT, SDL_GPU_FILTER_LINEAR, SDL_GPU_SAMPLERMIPMAPMODE_LINEAR, 16 },
+        },
+    };
+
+    for (Uint32 i = 0; i < SDL_arraysize(configs); ++i) {
+        SDL_GpuSamplerCreateInfo sci;
+        SDL_zero(sci);
+        sci.maxAnisotropy = configs[i].gpu.anisotropy;
+        sci.anisotropyEnable = configs[i].gpu.anisotropy > 0;
+        sci.addressModeU = sci.addressModeV = sci.addressModeW = configs[i].gpu.address_mode;
+        sci.minFilter = sci.magFilter = configs[i].gpu.filter;
+        sci.mipmapMode = configs[i].gpu.mipmap_mode;
+
+        SDL_GpuSampler *sampler = SDL_CreateGpuSampler(data->device, &sci);
+
+        if (sampler == NULL) {
+            return false;
+        }
+
+        *SamplerPointer(data, configs[i].sdl.address_mode, configs[i].sdl.scale_mode) = sampler;
+    }
+
+    return true;
+}
+
+static bool GPU_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
+{
+    GPU_RenderData *data = NULL;
+
+    data = (GPU_RenderData *)SDL_calloc(1, sizeof(*data));
+    if (!data) {
+        return false;
+    }
+
+    renderer->internal = data;
+
+    SDL_SetupRendererColorspace(renderer, create_props);
+
+    if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
+        // TODO
+        SDL_SetError("Unsupported output colorspace");
+        goto error;
+    }
+
+    bool debug = SDL_GetBooleanProperty(create_props, SDL_PROP_GPU_CREATEDEVICE_DEBUGMODE_BOOL, false);
+    bool lowpower = SDL_GetBooleanProperty(create_props, SDL_PROP_GPU_CREATEDEVICE_PREFERLOWPOWER_BOOL, false);
+
+    // Prefer environment variables/hints if they exist, otherwise defer to properties
+    debug = SDL_GetHintBoolean(SDL_HINT_RENDER_GPU_DEBUG, debug);
+    lowpower = SDL_GetHintBoolean(SDL_HINT_RENDER_GPU_LOW_POWER, lowpower);
+
+    SDL_SetBooleanProperty(create_props, SDL_PROP_GPU_CREATEDEVICE_DEBUGMODE_BOOL, debug);
+    SDL_SetBooleanProperty(create_props, SDL_PROP_GPU_CREATEDEVICE_PREFERLOWPOWER_BOOL, lowpower);
+
+    GPU_FillSupportedShaderFormats(create_props);
+    data->device = SDL_CreateGpuDeviceWithProperties(create_props);
+
+    if (!data->device) {
+        goto error;
+    }
+
+    if (!GPU_InitShaders(&data->shaders, data->device)) {
+        goto error;
+    }
+
+    if (!GPU_InitPipelineCache(&data->pipeline_cache, data->device)) {
+        goto error;
+    }
+
+    // XXX what's a good initial size?
+    if (!InitVertexBuffer(data, 1 << 16)) {
+        goto error;
+    }
+
+    if (!InitSamplers(data)) {
+        goto error;
+    }
+
+    renderer->SupportsBlendMode = GPU_SupportsBlendMode;
+    renderer->CreateTexture = GPU_CreateTexture;
+    renderer->UpdateTexture = GPU_UpdateTexture;
+    renderer->LockTexture = GPU_LockTexture;
+    renderer->UnlockTexture = GPU_UnlockTexture;
+    renderer->SetTextureScaleMode = GPU_SetTextureScaleMode;
+    renderer->SetRenderTarget = GPU_SetRenderTarget;
+    renderer->QueueSetViewport = GPU_QueueNoOp;
+    renderer->QueueSetDrawColor = GPU_QueueNoOp;
+    renderer->QueueDrawPoints = GPU_QueueDrawPoints;
+    renderer->QueueDrawLines = GPU_QueueDrawPoints; // lines and points queue vertices the same way.
+    renderer->QueueGeometry = GPU_QueueGeometry;
+    renderer->InvalidateCachedState = GPU_InvalidateCachedState;
+    renderer->RunCommandQueue = GPU_RunCommandQueue;
+    renderer->RenderReadPixels = GPU_RenderReadPixels;
+    renderer->RenderPresent = GPU_RenderPresent;
+    renderer->DestroyTexture = GPU_DestroyTexture;
+    renderer->DestroyRenderer = GPU_DestroyRenderer;
+    renderer->SetVSync = GPU_SetVSync;
+    GPU_InvalidateCachedState(renderer);
+    renderer->window = window;
+    renderer->name = GPU_RenderDriver.name;
+
+    if (!SDL_ClaimGpuWindow(data->device, window)) {
+        goto error;
+    }
+
+    data->swapchain.composition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR;
+    data->swapchain.present_mode = SDL_GPU_PRESENTMODE_VSYNC;
+
+    int vsync = (int)SDL_GetNumberProperty(create_props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER, 0);
+    ChoosePresentMode(data->device, window, vsync, &data->swapchain.present_mode);
+
+    SDL_SetGpuSwapchainParameters(data->device, window, data->swapchain.composition, data->swapchain.present_mode);
+
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA32);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA32);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX32);
+    SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX32);
+
+    renderer->rect_index_order[0] = 0;
+    renderer->rect_index_order[1] = 1;
+    renderer->rect_index_order[2] = 3;
+    renderer->rect_index_order[3] = 1;
+    renderer->rect_index_order[4] = 3;
+    renderer->rect_index_order[5] = 2;
+
+    data->state.draw_color.r = 1.0f;
+    data->state.draw_color.g = 1.0f;
+    data->state.draw_color.b = 1.0f;
+    data->state.draw_color.a = 1.0f;
+    data->state.viewport.minDepth = 0;
+    data->state.viewport.maxDepth = 1;
+    data->state.command_buffer = SDL_AcquireGpuCommandBuffer(data->device);
+
+    int w, h;
+    SDL_GetWindowSizeInPixels(window, &w, &h);
+
+    if (!CreateBackbuffer(data, w, h, SDL_GetGpuSwapchainTextureFormat(data->device, window))) {
+        goto error;
+    }
+
+    return true;
+
+error:
+    GPU_DestroyRenderer(renderer);
+    return false;
+}
+
+SDL_RenderDriver GPU_RenderDriver = {
+    GPU_CreateRenderer, "gpu"
+};
+
+#endif // SDL_VIDEO_RENDER_GPU

+ 241 - 0
src/render/sdlgpu/SDL_shaders_gpu.c

@@ -0,0 +1,241 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+#include "SDL_internal.h"
+
+#if SDL_VIDEO_RENDER_GPU
+
+#include "SDL_shaders_gpu.h"
+
+// SDL_Gpu shader implementation
+
+typedef struct GPU_ShaderModuleSource
+{
+    const unsigned char *code;
+    unsigned int code_len;
+    SDL_GpuShaderFormat format;
+} GPU_ShaderModuleSource;
+
+#ifdef SDL_GPU_VULKAN
+#define IF_VULKAN(...)     __VA_ARGS__
+#define HAVE_SPIRV_SHADERS 1
+#include "shaders/spir-v.h"
+#else
+#define IF_VULKAN(...)
+#define HAVE_SPIRV_SHADERS 0
+#endif
+
+#ifdef SDL_GPU_D3D11
+#define IF_D3D11(...)       __VA_ARGS__
+#define HAVE_DXBC50_SHADERS 1
+#include "shaders/dxbc50.h"
+#else
+#define IF_D3D11(...)
+#define HAVE_DXBC50_SHADERS 0
+#endif
+
+#ifdef SDL_GPU_D3D12
+#define IF_D3D12(...)       __VA_ARGS__
+#define HAVE_DXIL60_SHADERS 1
+#include "shaders/dxil60.h"
+#else
+#define IF_D3D12(...)
+#define HAVE_DXIL60_SHADERS 0
+#endif
+
+#ifdef SDL_GPU_METAL
+#define IF_METAL(...)      __VA_ARGS__
+#define HAVE_METAL_SHADERS 1
+#include "shaders/metal.h"
+#else
+#define IF_METAL(...)
+#define HAVE_METAL_SHADERS 0
+#endif
+
+typedef struct GPU_ShaderSources
+{
+    IF_VULKAN(GPU_ShaderModuleSource spirv;)
+    IF_D3D11(GPU_ShaderModuleSource dxbc50;)
+    IF_D3D12(GPU_ShaderModuleSource dxil60;)
+    IF_METAL(GPU_ShaderModuleSource msl;)
+    unsigned int num_samplers;
+    unsigned int num_uniform_buffers;
+} GPU_ShaderSources;
+
+#define SHADER_SPIRV(code) \
+    IF_VULKAN(.spirv = { code, sizeof(code), SDL_GPU_SHADERFORMAT_SPIRV }, )
+
+#define SHADER_DXBC50(code) \
+    IF_D3D11(.dxbc50 = { code, sizeof(code), SDL_GPU_SHADERFORMAT_DXBC }, )
+
+#define SHADER_DXIL60(code) \
+    IF_D3D12(.dxil60 = { code, sizeof(code), SDL_GPU_SHADERFORMAT_DXIL }, )
+
+#define SHADER_METAL(code) \
+    IF_METAL(.msl = { code, sizeof(code), SDL_GPU_SHADERFORMAT_MSL }, )
+
+// clang-format off
+static const GPU_ShaderSources vert_shader_sources[NUM_VERT_SHADERS] = {
+    [VERT_SHADER_LINEPOINT] = {
+        .num_samplers = 0,
+        .num_uniform_buffers = 1,
+        SHADER_SPIRV(linepoint_vert_spv)
+        SHADER_DXBC50(linepoint_vert_sm50_dxbc)
+        SHADER_DXIL60(linepoint_vert_sm60_dxil)
+        SHADER_METAL(linepoint_vert_metal)
+    },
+    [VERT_SHADER_TRI_COLOR] = {
+        .num_samplers = 0,
+        .num_uniform_buffers = 1,
+        SHADER_SPIRV(tri_color_vert_spv)
+        SHADER_DXBC50(tri_color_vert_sm50_dxbc)
+        SHADER_DXIL60(tri_color_vert_sm60_dxil)
+        SHADER_METAL(tri_color_vert_metal)
+    },
+    [VERT_SHADER_TRI_TEXTURE] = {
+        .num_samplers = 0,
+        .num_uniform_buffers = 1,
+        SHADER_SPIRV(tri_texture_vert_spv)
+        SHADER_DXBC50(tri_texture_vert_sm50_dxbc)
+        SHADER_DXIL60(tri_texture_vert_sm60_dxil)
+        SHADER_METAL(tri_texture_vert_metal)
+    },
+};
+
+static const GPU_ShaderSources frag_shader_sources[NUM_FRAG_SHADERS] = {
+    [FRAG_SHADER_COLOR] = {
+        .num_samplers = 0,
+        .num_uniform_buffers = 0,
+        SHADER_SPIRV(color_frag_spv)
+        SHADER_DXBC50(color_frag_sm50_dxbc)
+        SHADER_DXIL60(color_frag_sm60_dxil)
+        SHADER_METAL(color_frag_metal)
+    },
+    [FRAG_SHADER_TEXTURE_RGB] = {
+        .num_samplers = 1,
+        .num_uniform_buffers = 0,
+        SHADER_SPIRV(texture_rgb_frag_spv)
+        SHADER_DXBC50(texture_rgb_frag_sm50_dxbc)
+        SHADER_DXIL60(texture_rgb_frag_sm60_dxil)
+        SHADER_METAL(texture_rgb_frag_metal)
+    },
+    [FRAG_SHADER_TEXTURE_RGBA] = {
+        .num_samplers = 1,
+        .num_uniform_buffers = 0,
+        SHADER_SPIRV(texture_rgba_frag_spv)
+        SHADER_DXBC50(texture_rgba_frag_sm50_dxbc)
+        SHADER_DXIL60(texture_rgba_frag_sm60_dxil)
+        SHADER_METAL(texture_rgb_frag_metal)
+    },
+};
+// clang-format on
+
+static SDL_GpuShader *CompileShader(const GPU_ShaderSources *sources, SDL_GpuDevice *device, SDL_GpuShaderStage stage)
+{
+    const GPU_ShaderModuleSource *sms = NULL;
+    SDL_GpuDriver driver = SDL_GetGpuDriver(device);
+
+    switch (driver) {
+        // clang-format off
+        IF_VULKAN(  case SDL_GPU_DRIVER_VULKAN: sms = &sources->spirv;  break;)
+        IF_D3D11(   case SDL_GPU_DRIVER_D3D11:  sms = &sources->dxbc50; break;)
+        IF_D3D12(   case SDL_GPU_DRIVER_D3D12:  sms = &sources->dxil60; break;)
+        IF_METAL(   case SDL_GPU_DRIVER_METAL:  sms = &sources->msl;    break;)
+        // clang-format on
+
+    default:
+        SDL_SetError("Unsupported GPU backend");
+        return NULL;
+    }
+
+    SDL_GpuShaderCreateInfo sci = { 0 };
+    sci.code = sms->code;
+    sci.codeSize = sms->code_len;
+    sci.format = sms->format;
+    // FIXME not sure if this is correct
+    sci.entryPointName = driver == SDL_GPU_DRIVER_METAL ? "main0" : "main";
+    sci.samplerCount = sources->num_samplers;
+    sci.uniformBufferCount = sources->num_uniform_buffers;
+    sci.stage = stage;
+
+    return SDL_CreateGpuShader(device, &sci);
+}
+
+bool GPU_InitShaders(GPU_Shaders *shaders, SDL_GpuDevice *device)
+{
+    for (int i = 0; i < SDL_arraysize(vert_shader_sources); ++i) {
+        shaders->vert_shaders[i] = CompileShader(
+            &vert_shader_sources[i], device, SDL_GPU_SHADERSTAGE_VERTEX);
+        if (shaders->vert_shaders[i] == NULL) {
+            GPU_ReleaseShaders(shaders, device);
+            return false;
+        }
+    }
+
+    for (int i = 0; i < SDL_arraysize(frag_shader_sources); ++i) {
+        shaders->frag_shaders[i] = CompileShader(
+            &frag_shader_sources[i], device, SDL_GPU_SHADERSTAGE_FRAGMENT);
+        if (shaders->frag_shaders[i] == NULL) {
+            GPU_ReleaseShaders(shaders, device);
+            return false;
+        }
+    }
+
+    return true;
+}
+
+void GPU_ReleaseShaders(GPU_Shaders *shaders, SDL_GpuDevice *device)
+{
+    for (int i = 0; i < SDL_arraysize(shaders->vert_shaders); ++i) {
+        SDL_ReleaseGpuShader(device, shaders->vert_shaders[i]);
+        shaders->vert_shaders[i] = NULL;
+    }
+
+    for (int i = 0; i < SDL_arraysize(shaders->frag_shaders); ++i) {
+        SDL_ReleaseGpuShader(device, shaders->frag_shaders[i]);
+        shaders->frag_shaders[i] = NULL;
+    }
+}
+
+SDL_GpuShader *GPU_GetVertexShader(GPU_Shaders *shaders, GPU_VertexShaderID id)
+{
+    SDL_assert((unsigned int)id < SDL_arraysize(shaders->vert_shaders));
+    SDL_GpuShader *shader = shaders->vert_shaders[id];
+    SDL_assert(shader != NULL);
+    return shader;
+}
+
+SDL_GpuShader *GPU_GetFragmentShader(GPU_Shaders *shaders, GPU_FragmentShaderID id)
+{
+    SDL_assert((unsigned int)id < SDL_arraysize(shaders->frag_shaders));
+    SDL_GpuShader *shader = shaders->frag_shaders[id];
+    SDL_assert(shader != NULL);
+    return shader;
+}
+
+void GPU_FillSupportedShaderFormats(SDL_PropertiesID props)
+{
+    SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_SPIRV_BOOL, HAVE_SPIRV_SHADERS);
+    SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_DXBC_BOOL, HAVE_DXBC50_SHADERS);
+    SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_DXIL_BOOL, HAVE_DXIL60_SHADERS);
+    SDL_SetBooleanProperty(props, SDL_PROP_GPU_CREATEDEVICE_SHADERS_MSL_BOOL, HAVE_METAL_SHADERS);
+}
+
+#endif // SDL_VIDEO_RENDER_GPU

+ 63 - 0
src/render/sdlgpu/SDL_shaders_gpu.h

@@ -0,0 +1,63 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_shaders_gpu_h_
+#define SDL_shaders_gpu_h_
+
+#include "SDL_internal.h"
+
+// SDL_Gpu shader implementation
+
+typedef enum
+{
+    VERT_SHADER_INVALID = -1,
+    VERT_SHADER_LINEPOINT,
+    VERT_SHADER_TRI_COLOR,
+    VERT_SHADER_TRI_TEXTURE,
+
+    NUM_VERT_SHADERS,
+} GPU_VertexShaderID;
+
+typedef enum
+{
+    FRAG_SHADER_INVALID = -1,
+    FRAG_SHADER_COLOR,
+    FRAG_SHADER_TEXTURE_RGB,
+    FRAG_SHADER_TEXTURE_RGBA,
+
+    NUM_FRAG_SHADERS,
+} GPU_FragmentShaderID;
+
+struct GPU_Shaders
+{
+    SDL_GpuShader *vert_shaders[NUM_VERT_SHADERS];
+    SDL_GpuShader *frag_shaders[NUM_FRAG_SHADERS];
+};
+
+typedef struct GPU_Shaders GPU_Shaders;
+
+void GPU_FillSupportedShaderFormats(SDL_PropertiesID props);
+extern bool GPU_InitShaders(GPU_Shaders *shaders, SDL_GpuDevice *device);
+extern void GPU_ReleaseShaders(GPU_Shaders *shaders, SDL_GpuDevice *device);
+extern SDL_GpuShader *GPU_GetVertexShader(GPU_Shaders *shaders, GPU_VertexShaderID id);
+extern SDL_GpuShader *GPU_GetFragmentShader(GPU_Shaders *shaders, GPU_FragmentShaderID id);
+
+#endif // SDL_shaders_gpu_h_

+ 1 - 0
src/render/sdlgpu/shaders/.gitattributes

@@ -0,0 +1 @@
+*.h linguist-generated

+ 3 - 0
src/render/sdlgpu/shaders/.gitignore

@@ -0,0 +1,3 @@
+*.hlsl
+*.metal
+*.spv

+ 85 - 0
src/render/sdlgpu/shaders/build-shaders.sh

@@ -0,0 +1,85 @@
+#!/usr/bin/env bash
+
+set -e
+
+# NOTE: fxc is tested on Linux with https://github.com/mozilla/fxc2
+
+which fxc &>/dev/null && HAVE_FXC=1 || HAVE_FXC=0
+which dxc &>/dev/null && HAVE_DXC=1 || HAVE_DXC=0
+
+[ "$HAVE_FXC" != 0 ] || echo "fxc not in PATH; D3D11 shaders will not be rebuilt"
+[ "$HAVE_DXC" != 0 ] || echo "dxc not in PATH; D3D12 shaders will not be rebuilt"
+
+USE_FXC=${USE_FXC:-HAVE_FXC}
+USE_DXC=${USE_DXC:-HAVE_DXC}
+
+spirv_bundle="spir-v.h"
+dxbc50_bundle="dxbc50.h"
+dxil60_bundle="dxil60.h"
+metal_bundle="metal.h"
+
+rm -f "$spirv_bundle"
+rm -f "$metal_bundle"
+[ "$USE_FXC" != 0 ] && rm -f "$dxbc50_bundle"
+[ "$USE_DXC" != 0 ] && rm -f "$dxil60_bundle"
+
+make-header() {
+    xxd -i "$1" | sed -e 's/^unsigned /const unsigned /g' > "$1.h"
+}
+
+compile-hlsl-dxbc() {
+    local src="$1"
+    local profile="$2"
+    local output_basename="$3"
+    local var_name="$(echo "$output_basename" | sed -e 's/\./_/g')"
+
+    fxc "$src" /E main /T $2 /Fh "$output_basename.h" || exit $?
+    sed -i "s/g_main/$var_name/;s/\r//g" "$output_basename.h"
+}
+
+compile-hlsl-dxil() {
+    local src="$1"
+    local profile="$2"
+    local output_basename="$3"
+    local var_name="$(echo "$output_basename" | sed -e 's/\./_/g')"
+
+    dxc "$src" -E main -T $2 -Fh "$output_basename.h" -O3 || exit $?
+    sed -i "s/g_main/$var_name/;s/\r//g" "$output_basename.h"
+}
+
+for i in *.vert *.frag; do
+    spv="$i.spv"
+    metal="$i.metal"
+    hlsl50="$i.sm50.hlsl"
+    dxbc50="$i.sm50.dxbc"
+    hlsl60="$i.sm60.hlsl"
+    dxil60="$i.sm60.dxil"
+
+    glslangValidator -g0 -Os "$i" -V -o "$spv" --quiet
+
+    make-header "$spv"
+    echo "#include \"$spv.h\"" >> "$spirv_bundle"
+
+    spirv-cross "$spv" --hlsl --shader-model 50 --hlsl-enable-compat --output "$hlsl50"
+    spirv-cross "$spv" --hlsl --shader-model 60 --hlsl-enable-compat --output "$hlsl60"
+
+    if [ "${i##*.}" == "frag" ]; then
+        hlsl_stage="ps"
+    else
+        hlsl_stage="vs"
+    fi
+
+    if [ "$USE_FXC" != "0" ]; then
+        compile-hlsl-dxbc "$hlsl50" ${hlsl_stage}_5_0 "$dxbc50"
+        echo "#include \"$dxbc50.h\"" >> "$dxbc50_bundle"
+    fi
+
+    if [ "$USE_DXC" != "0" ]; then
+        compile-hlsl-dxil "$hlsl60" ${hlsl_stage}_6_0 "$dxil60"
+        echo "#include \"$dxil60.h\"" >> "$dxil60_bundle"
+    fi
+
+    spirv-cross "$spv" --msl --output "$metal"
+    make-header "$metal"
+    echo "#include \"$metal.h\"" >> "$metal_bundle"
+done

+ 9 - 0
src/render/sdlgpu/shaders/color.frag

@@ -0,0 +1,9 @@
+#version 450
+
+layout(location = 0) in vec4 v_color;
+
+layout(location = 0) out vec4 o_color;
+
+void main() {
+    o_color = v_color;
+}

+ 28 - 0
src/render/sdlgpu/shaders/color.frag.metal.h

@@ -0,0 +1,28 @@
+const unsigned char color_frag_metal[] = {
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65,
+  0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a,
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 0x69,
+  0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a,
+  0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+  0x61, 0x63, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a,
+  0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30,
+  0x5f, 0x6f, 0x75, 0x74, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6d, 0x5f, 0x39, 0x20, 0x5b, 0x5b,
+  0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a,
+  0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6d,
+  0x61, 0x69, 0x6e, 0x30, 0x5f, 0x69, 0x6e, 0x0a, 0x7b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6d, 0x5f, 0x31,
+  0x31, 0x20, 0x5b, 0x5b, 0x75, 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63,
+  0x6e, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x66,
+  0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e,
+  0x30, 0x5f, 0x6f, 0x75, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x28,
+  0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x20,
+  0x5b, 0x5b, 0x73, 0x74, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x5d, 0x5d,
+  0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x69, 0x6e,
+  0x30, 0x5f, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20,
+  0x7b, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e,
+  0x6d, 0x5f, 0x39, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x2e, 0x6d, 0x5f, 0x31,
+  0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
+  0x6e, 0x20, 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a
+};
+const unsigned int color_frag_metal_len = 298;

+ 85 - 0
src/render/sdlgpu/shaders/color.frag.sm50.dxbc.h

@@ -0,0 +1,85 @@
+const unsigned char color_frag_sm50_dxbc[] =
+{
+  68,  88,  66,  67, 114,-117,
+-124,  82, -97,  76, -66, -74,
+  70, 116,  14, -14,  95,-122,
+  65,  73,   1,   0,   0,   0,
+ -24,   1,   0,   0,   5,   0,
+   0,   0,  52,   0,   0,   0,
+ -96,   0,   0,   0, -44,   0,
+   0,   0,   8,   1,   0,   0,
+  76,   1,   0,   0,  82,  68,
+  69,  70, 100,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+  60,   0,   0,   0,   0,   5,
+  -1,  -1,   0,   1,   0,   0,
+  60,   0,   0,   0,  82,  68,
+  49,  49,  60,   0,   0,   0,
+  24,   0,   0,   0,  32,   0,
+   0,   0,  40,   0,   0,   0,
+  36,   0,   0,   0,  12,   0,
+   0,   0,   0,   0,   0,   0,
+  77, 105,  99, 114, 111, 115,
+ 111, 102, 116,  32,  40,  82,
+  41,  32,  72,  76,  83,  76,
+  32,  83, 104,  97, 100, 101,
+ 114,  32,  67, 111, 109, 112,
+ 105, 108, 101, 114,  32,  49,
+  48,  46,  49,   0,  73,  83,
+  71,  78,  44,   0,   0,   0,
+   1,   0,   0,   0,   8,   0,
+   0,   0,  32,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   3,   0,   0,   0,
+   0,   0,   0,   0,  15,  15,
+   0,   0,  84,  69,  88,  67,
+  79,  79,  82,  68,   0, -85,
+ -85, -85,  79,  83,  71,  78,
+  44,   0,   0,   0,   1,   0,
+   0,   0,   8,   0,   0,   0,
+  32,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,   0,   0,
+   0,   0,  15,   0,   0,   0,
+  83,  86,  95,  84,  97, 114,
+ 103, 101, 116,   0, -85, -85,
+  83,  72,  69,  88,  60,   0,
+   0,   0,  80,   0,   0,   0,
+  15,   0,   0,   0, 106,   8,
+   0,   1,  98,  16,   0,   3,
+ -14,  16,  16,   0,   0,   0,
+   0,   0, 101,   0,   0,   3,
+ -14,  32,  16,   0,   0,   0,
+   0,   0,  54,   0,   0,   5,
+ -14,  32,  16,   0,   0,   0,
+   0,   0,  70,  30,  16,   0,
+   0,   0,   0,   0,  62,   0,
+   0,   1,  83,  84,  65,  84,
+-108,   0,   0,   0,   2,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   2,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   1,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   1,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0
+};

+ 340 - 0
src/render/sdlgpu/shaders/color.frag.sm60.dxil.h

@@ -0,0 +1,340 @@
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xyzw        0     NONE   float   xyzw
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_Target                0   xyzw        0   TARGET   float   xyzw
+;
+; shader hash: 79268435b7929fdbc9f529459f44b878
+;
+; Pipeline Runtime Information: 
+;
+; Pixel Shader
+; DepthOutput=0
+; SampleFrequency=0
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_Target                0                              
+;
+; Buffer Definitions:
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+;
+;
+; ViewId state:
+;
+; Number of inputs: 4, outputs: 4
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 0 }
+;   output 1 depends on inputs: { 1 }
+;   output 2 depends on inputs: { 2 }
+;   output 3 depends on inputs: { 3 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+define void @main() {
+  %1 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %2 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %3 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 2, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 3, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %1)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %2)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %3)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %4)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.viewIdState = !{!4}
+!dx.entryPoints = !{!5}
+
+!0 = !{!"dxc(private) 1.8.0.4662 (416fab6b5)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 8}
+!3 = !{!"ps", i32 6, i32 0}
+!4 = !{[6 x i32] [i32 4, i32 4, i32 1, i32 2, i32 4, i32 8]}
+!5 = !{void ()* @main, !"main", !6, null, null}
+!6 = !{!7, !11, null}
+!7 = !{!8}
+!8 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !9, i8 2, i32 1, i8 4, i32 0, i8 0, !10}
+!9 = !{i32 0}
+!10 = !{i32 3, i32 15}
+!11 = !{!12}
+!12 = !{i32 0, !"SV_Target", i8 9, i8 16, !9, i8 0, i32 1, i8 4, i32 0, i8 0, !10}
+
+#endif
+
+const unsigned char color_frag_sm60_dxil[] = {
+  0x44, 0x58, 0x42, 0x43, 0x33, 0x91, 0x9f, 0xec, 0x78, 0x7d, 0xbb, 0xfa,
+  0xeb, 0x8d, 0xfb, 0x1b, 0x79, 0x47, 0x1d, 0xb2, 0x01, 0x00, 0x00, 0x00,
+  0x0c, 0x0b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00,
+  0x58, 0x01, 0x00, 0x00, 0x10, 0x06, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44,
+  0x00, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65,
+  0x74, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30, 0x8c, 0x00, 0x00, 0x00,
+  0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52,
+  0x44, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x00, 0x03, 0x02, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x10,
+  0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54,
+  0xb0, 0x04, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00,
+  0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x98, 0x04, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00,
+  0x23, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42, 0x88,
+  0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42,
+  0xe4, 0x48, 0x0e, 0x90, 0x11, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c,
+  0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07,
+  0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20,
+  0x01, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x82, 0x60, 0x42, 0x20, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04,
+  0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14,
+  0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x30, 0x23, 0x00,
+  0x25, 0x00, 0x8a, 0x19, 0x80, 0x39, 0x02, 0x30, 0x98, 0x23, 0x40, 0x8a,
+  0x31, 0x44, 0x54, 0x44, 0x56, 0x0c, 0x20, 0xa2, 0x1a, 0xc2, 0x81, 0x80,
+  0x34, 0x20, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87,
+  0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50,
+  0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10,
+  0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e,
+  0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86,
+  0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xc8, 0x02, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0xa2,
+  0x12, 0x18, 0x01, 0x28, 0x86, 0x32, 0x28, 0x8f, 0x92, 0x28, 0x04, 0xaa,
+  0x92, 0x18, 0x01, 0x28, 0x82, 0x42, 0x28, 0x10, 0xda, 0xb1, 0x0c, 0x82,
+  0x08, 0x04, 0x02, 0x01, 0x79, 0x18, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00,
+  0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b,
+  0x43, 0x81, 0x93, 0x4b, 0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71,
+  0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb1, 0xb1, 0x91, 0x01, 0x41, 0xa1, 0x89,
+  0xb1, 0x31, 0x0b, 0x13, 0xb3, 0x11, 0xab, 0x49, 0xd9, 0x10, 0x04, 0x13,
+  0x04, 0x62, 0x98, 0x20, 0x10, 0xc4, 0x06, 0x61, 0x20, 0x36, 0x08, 0x04,
+  0x41, 0x01, 0x6e, 0x6e, 0x82, 0x40, 0x14, 0x1b, 0x86, 0x03, 0x21, 0x26,
+  0x08, 0x02, 0xb0, 0x01, 0xd8, 0x30, 0x10, 0xcb, 0xb2, 0x21, 0x60, 0x36,
+  0x0c, 0x83, 0xd2, 0x4c, 0x10, 0x96, 0x67, 0x43, 0xf0, 0x90, 0x68, 0x0b,
+  0x4b, 0x73, 0x23, 0x42, 0x55, 0x84, 0x35, 0xf4, 0xf4, 0x24, 0x45, 0x34,
+  0x41, 0x28, 0x94, 0x09, 0x42, 0xb1, 0x6c, 0x08, 0x88, 0x09, 0x42, 0xc1,
+  0x4c, 0x10, 0x8a, 0x66, 0x82, 0x40, 0x18, 0x13, 0x04, 0xe2, 0xd8, 0x20,
+  0x60, 0xd9, 0x86, 0x85, 0x90, 0x26, 0xaa, 0xb2, 0x86, 0x8b, 0xa0, 0xb4,
+  0x0d, 0xc1, 0xc6, 0x64, 0xca, 0xea, 0x8b, 0x2a, 0x4c, 0xee, 0xac, 0x8c,
+  0x6e, 0x82, 0x50, 0x38, 0x1b, 0x16, 0xa2, 0x9b, 0xbc, 0x8a, 0x1a, 0x2e,
+  0x82, 0xd2, 0x36, 0x04, 0xdf, 0x86, 0x81, 0x03, 0x03, 0x60, 0x43, 0xa1,
+  0x44, 0x61, 0x00, 0x00, 0x2c, 0xd2, 0xdc, 0xe6, 0xe8, 0xe6, 0x26, 0x08,
+  0x04, 0x42, 0x63, 0x2e, 0xed, 0xec, 0x8b, 0x8d, 0x6c, 0x82, 0x40, 0x24,
+  0x34, 0xe6, 0xd2, 0xce, 0xbe, 0xe6, 0xe8, 0x36, 0x18, 0x63, 0x40, 0x06,
+  0x65, 0x60, 0x06, 0x67, 0x60, 0x06, 0x55, 0xd8, 0xd8, 0xec, 0xda, 0x5c,
+  0xd2, 0xc8, 0xca, 0xdc, 0xe8, 0xa6, 0x04, 0x41, 0x15, 0x32, 0x3c, 0x17,
+  0xbb, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x29, 0x01, 0xd1, 0x84, 0x0c,
+  0xcf, 0xc5, 0x2e, 0x8c, 0xcd, 0xae, 0x4c, 0x6e, 0x4a, 0x50, 0xd4, 0x21,
+  0xc3, 0x73, 0x99, 0x43, 0x0b, 0x23, 0x2b, 0x93, 0x6b, 0x7a, 0x23, 0x2b,
+  0x63, 0x9b, 0x12, 0x20, 0x95, 0xc8, 0xf0, 0x5c, 0xe8, 0xf2, 0xe0, 0xca,
+  0x82, 0xdc, 0xdc, 0xde, 0xe8, 0xc2, 0xe8, 0xd2, 0xde, 0xdc, 0xe6, 0xa6,
+  0x04, 0x4d, 0x1d, 0x32, 0x3c, 0x17, 0xbb, 0xb4, 0xb2, 0xbb, 0x24, 0xb2,
+  0x29, 0xba, 0x30, 0xba, 0xb2, 0x29, 0xc1, 0x53, 0x87, 0x0c, 0xcf, 0xa5,
+  0xcc, 0x8d, 0x4e, 0x2e, 0x0f, 0xea, 0x2d, 0xcd, 0x8d, 0x6e, 0x6e, 0x4a,
+  0x10, 0x06, 0x5d, 0xc8, 0xf0, 0x5c, 0xc6, 0xde, 0xea, 0xdc, 0xe8, 0xca,
+  0xe4, 0xe6, 0xa6, 0x04, 0x67, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66,
+  0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10,
+  0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce,
+  0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b,
+  0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c,
+  0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07,
+  0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11,
+  0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0,
+  0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8,
+  0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b,
+  0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b,
+  0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87,
+  0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07,
+  0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87,
+  0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81,
+  0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30,
+  0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca,
+  0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b,
+  0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b,
+  0xb0, 0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x72, 0x10, 0x87,
+  0x73, 0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60, 0x87, 0x70, 0xc8, 0x87,
+  0x77, 0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4, 0x80, 0x0f, 0x6e, 0x40,
+  0x0f, 0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x16, 0x30, 0x0d, 0x97, 0xef, 0x3c, 0xfe, 0xe2,
+  0x00, 0x83, 0xd8, 0x3c, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x02, 0xd5, 0x70,
+  0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4,
+  0x17, 0xb7, 0x6d, 0x00, 0x04, 0x03, 0x20, 0x0d, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x79, 0x26, 0x84, 0x35, 0xb7, 0x92, 0x9f, 0xdb,
+  0xc9, 0xf5, 0x29, 0x45, 0x9f, 0x44, 0xb8, 0x78, 0x44, 0x58, 0x49, 0x4c,
+  0xd8, 0x04, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
+  0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0xc0, 0x04, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00,
+  0x2d, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42, 0x88,
+  0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42,
+  0xe4, 0x48, 0x0e, 0x90, 0x11, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c,
+  0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07,
+  0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20,
+  0x01, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x82, 0x60, 0x42, 0x20, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04,
+  0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14,
+  0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x30, 0x23, 0x00,
+  0x25, 0x00, 0x8a, 0x19, 0x80, 0x39, 0x02, 0x30, 0x98, 0x23, 0x40, 0x8a,
+  0x31, 0x44, 0x54, 0x44, 0x56, 0x0c, 0x20, 0xa2, 0x1a, 0xc2, 0x81, 0x80,
+  0x34, 0x20, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87,
+  0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50,
+  0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10,
+  0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86,
+  0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xc8, 0x02, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x10,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0xa2,
+  0x12, 0x18, 0x01, 0x28, 0x88, 0x62, 0x28, 0x83, 0xf2, 0xa0, 0x2a, 0x89,
+  0x11, 0x80, 0x22, 0x28, 0x84, 0x02, 0xa1, 0x1d, 0xcb, 0x20, 0x88, 0x40,
+  0x20, 0x10, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
+  0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b,
+  0x43, 0x81, 0x93, 0x4b, 0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71,
+  0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb1, 0xb1, 0x91, 0x01, 0x41, 0xa1, 0x89,
+  0xb1, 0x31, 0x0b, 0x13, 0xb3, 0x11, 0xab, 0x49, 0xd9, 0x10, 0x04, 0x13,
+  0x04, 0x62, 0x98, 0x20, 0x10, 0xc4, 0x06, 0x61, 0x20, 0x26, 0x08, 0x44,
+  0xb1, 0x41, 0x18, 0x0c, 0x0a, 0x70, 0x73, 0x13, 0x04, 0xc2, 0xd8, 0x30,
+  0x20, 0x09, 0x31, 0x41, 0x58, 0x9c, 0x0d, 0xc1, 0x32, 0x41, 0x10, 0x00,
+  0x12, 0x6d, 0x61, 0x69, 0x6e, 0x44, 0xa8, 0x8a, 0xb0, 0x86, 0x9e, 0x9e,
+  0xa4, 0x88, 0x26, 0x08, 0x45, 0x32, 0x41, 0x28, 0x94, 0x0d, 0x01, 0x31,
+  0x41, 0x28, 0x96, 0x09, 0x42, 0xc1, 0x4c, 0x10, 0x88, 0x63, 0x82, 0x40,
+  0x20, 0x1b, 0x84, 0xca, 0xda, 0xb0, 0x10, 0x0f, 0x14, 0x49, 0xd3, 0x40,
+  0x11, 0xd1, 0xb5, 0x21, 0xc0, 0x98, 0x4c, 0x59, 0x7d, 0x51, 0x85, 0xc9,
+  0x9d, 0x95, 0xd1, 0x4d, 0x10, 0x8a, 0x66, 0xc3, 0x42, 0x68, 0xd0, 0x26,
+  0x45, 0x03, 0x45, 0x44, 0xd7, 0x86, 0x80, 0xdb, 0x30, 0x64, 0x1d, 0xb0,
+  0xa1, 0x68, 0x1c, 0x0f, 0x00, 0xaa, 0xb0, 0xb1, 0xd9, 0xb5, 0xb9, 0xa4,
+  0x91, 0x95, 0xb9, 0xd1, 0x4d, 0x09, 0x82, 0x2a, 0x64, 0x78, 0x2e, 0x76,
+  0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x02, 0xa2, 0x09, 0x19, 0x9e,
+  0x8b, 0x5d, 0x18, 0x9b, 0x5d, 0x99, 0xdc, 0x94, 0xc0, 0xa8, 0x43, 0x86,
+  0xe7, 0x32, 0x87, 0x16, 0x46, 0x56, 0x26, 0xd7, 0xf4, 0x46, 0x56, 0xc6,
+  0x36, 0x25, 0x48, 0xea, 0x90, 0xe1, 0xb9, 0xd8, 0xa5, 0x95, 0xdd, 0x25,
+  0x91, 0x4d, 0xd1, 0x85, 0xd1, 0x95, 0x4d, 0x09, 0x96, 0x3a, 0x64, 0x78,
+  0x2e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73,
+  0x53, 0x02, 0x0f, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88,
+  0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73,
+  0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e,
+  0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30,
+  0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8,
+  0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b,
+  0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76,
+  0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e,
+  0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e,
+  0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61,
+  0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4,
+  0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37,
+  0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76,
+  0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71,
+  0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e,
+  0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61,
+  0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8,
+  0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc,
+  0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x8c, 0xc8,
+  0x21, 0x07, 0x7c, 0x70, 0x03, 0x72, 0x10, 0x87, 0x73, 0x70, 0x03, 0x7b,
+  0x08, 0x07, 0x79, 0x60, 0x87, 0x70, 0xc8, 0x87, 0x77, 0xa8, 0x07, 0x7a,
+  0x98, 0x81, 0x3c, 0xe4, 0x80, 0x0f, 0x6e, 0x40, 0x0f, 0xe5, 0xd0, 0x0e,
+  0xf0, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x16, 0x30, 0x0d, 0x97, 0xef, 0x3c, 0xfe, 0xe2, 0x00, 0x83, 0xd8, 0x3c,
+  0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x02, 0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b,
+  0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x00,
+  0x04, 0x03, 0x20, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x44, 0x85, 0x30, 0x03, 0x50, 0x0a, 0x54, 0x25,
+  0x50, 0x06, 0x00, 0x00, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x60, 0x4c,
+  0x05, 0x04, 0x29, 0xc4, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x94,
+  0x11, 0x45, 0x43, 0x31, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x46, 0x75,
+  0x48, 0xd2, 0x62, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x81, 0x61, 0x21,
+  0xd3, 0x44, 0x1c, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x80, 0x58, 0x07,
+  0x45, 0x39, 0xc4, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xd6, 0x41,
+  0x51, 0xc6, 0x30, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x88, 0x75, 0x50,
+  0x54, 0x23, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x62, 0x1d, 0x14,
+  0x55, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
+};

+ 29 - 0
src/render/sdlgpu/shaders/color.frag.spv.h

@@ -0,0 +1,29 @@
+const unsigned char color_frag_spv[] = {
+  0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+};
+const unsigned int color_frag_spv_len = 312;

+ 6 - 0
src/render/sdlgpu/shaders/dxbc50.h

@@ -0,0 +1,6 @@
+#include "linepoint.vert.sm50.dxbc.h"
+#include "tri_color.vert.sm50.dxbc.h"
+#include "tri_texture.vert.sm50.dxbc.h"
+#include "color.frag.sm50.dxbc.h"
+#include "texture_rgba.frag.sm50.dxbc.h"
+#include "texture_rgb.frag.sm50.dxbc.h"

+ 6 - 0
src/render/sdlgpu/shaders/dxil60.h

@@ -0,0 +1,6 @@
+#include "linepoint.vert.sm60.dxil.h"
+#include "tri_color.vert.sm60.dxil.h"
+#include "tri_texture.vert.sm60.dxil.h"
+#include "color.frag.sm60.dxil.h"
+#include "texture_rgba.frag.sm60.dxil.h"
+#include "texture_rgb.frag.sm60.dxil.h"

+ 17 - 0
src/render/sdlgpu/shaders/linepoint.vert

@@ -0,0 +1,17 @@
+#version 450
+
+layout(location = 0) in vec2 a_position;
+
+layout(location = 0) out vec4 v_color;
+
+layout(set = 1, binding = 0) uniform Context {
+    mat4 mvp;
+    vec4 color;
+    vec2 texture_size;  /* XXX unused */
+} u_context;
+
+void main() {
+    gl_PointSize = 1.0;  /* FIXME: D3D11 pls */
+    gl_Position = u_context.mvp * vec4(a_position, 0, 1);
+    v_color = u_context.color;
+}

+ 51 - 0
src/render/sdlgpu/shaders/linepoint.vert.metal.h

@@ -0,0 +1,51 @@
+const unsigned char linepoint_vert_metal[] = {
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65,
+  0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a,
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 0x69,
+  0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a,
+  0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+  0x61, 0x63, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a,
+  0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x32, 0x32, 0x0a, 0x7b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78,
+  0x34, 0x20, 0x5f, 0x6d, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x5f, 0x6d, 0x31, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x5f, 0x6d,
+  0x32, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63,
+  0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x6f, 0x75, 0x74, 0x0a,
+  0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
+  0x20, 0x6d, 0x5f, 0x33, 0x38, 0x20, 0x5b, 0x5b, 0x75, 0x73, 0x65, 0x72,
+  0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x67, 0x6c,
+  0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5b, 0x5b,
+  0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5d, 0x5d, 0x3b, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x67, 0x6c,
+  0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x5b,
+  0x5b, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x5d,
+  0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63,
+  0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x69, 0x6e, 0x0a, 0x7b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20,
+  0x6d, 0x5f, 0x32, 0x39, 0x20, 0x5b, 0x5b, 0x61, 0x74, 0x74, 0x72, 0x69,
+  0x62, 0x75, 0x74, 0x65, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x7d,
+  0x3b, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20, 0x6d, 0x61,
+  0x69, 0x6e, 0x30, 0x5f, 0x6f, 0x75, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e,
+  0x30, 0x28, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x69, 0x6e, 0x20, 0x69,
+  0x6e, 0x20, 0x5b, 0x5b, 0x73, 0x74, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x6e,
+  0x5d, 0x5d, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74,
+  0x20, 0x5f, 0x32, 0x32, 0x26, 0x20, 0x5f, 0x32, 0x34, 0x20, 0x5b, 0x5b,
+  0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x29,
+  0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30,
+  0x5f, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x7b,
+  0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x67,
+  0x6c, 0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x20,
+  0x3d, 0x20, 0x31, 0x2e, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f,
+  0x75, 0x74, 0x2e, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69,
+  0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x34, 0x2e, 0x5f, 0x6d, 0x30,
+  0x20, 0x2a, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x69, 0x6e,
+  0x2e, 0x6d, 0x5f, 0x32, 0x39, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20,
+  0x31, 0x2e, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75,
+  0x74, 0x2e, 0x6d, 0x5f, 0x33, 0x38, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x34,
+  0x2e, 0x5f, 0x6d, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
+  0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a,
+  0x0a
+};
+const unsigned int linepoint_vert_metal_len = 565;

+ 172 - 0
src/render/sdlgpu/shaders/linepoint.vert.sm50.dxbc.h

@@ -0,0 +1,172 @@
+const unsigned char linepoint_vert_sm50_dxbc[] =
+{
+  68,  88,  66,  67,   0, 119,
+ 101, -18, 103, 113,  34,  52,
+ -82,  96,  17,   4, -92,  11,
+ -67,  71,   1,   0,   0,   0,
+ -12,   3,   0,   0,   5,   0,
+   0,   0,  52,   0,   0,   0,
+ -12,   1,   0,   0,  40,   2,
+   0,   0,-128,   2,   0,   0,
+  88,   3,   0,   0,  82,  68,
+  69,  70, -72,   1,   0,   0,
+   1,   0,   0,   0, 100,   0,
+   0,   0,   1,   0,   0,   0,
+  60,   0,   0,   0,   0,   5,
+  -2,  -1,   0,   1,   0,   0,
+-112,   1,   0,   0,  82,  68,
+  49,  49,  60,   0,   0,   0,
+  24,   0,   0,   0,  32,   0,
+   0,   0,  40,   0,   0,   0,
+  36,   0,   0,   0,  12,   0,
+   0,   0,   0,   0,   0,   0,
+  92,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   1,   0,
+   0,   0,  95,  50,  50,  95,
+  50,  52,   0, -85,  92,   0,
+   0,   0,   3,   0,   0,   0,
+ 124,   0,   0,   0,  96,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0, -12,   0,
+   0,   0,   0,   0,   0,   0,
+  64,   0,   0,   0,   2,   0,
+   0,   0,   4,   1,   0,   0,
+   0,   0,   0,   0,  -1,  -1,
+  -1,  -1,   0,   0,   0,   0,
+  -1,  -1,  -1,  -1,   0,   0,
+   0,   0,  40,   1,   0,   0,
+  64,   0,   0,   0,  16,   0,
+   0,   0,   2,   0,   0,   0,
+  56,   1,   0,   0,   0,   0,
+   0,   0,  -1,  -1,  -1,  -1,
+   0,   0,   0,   0,  -1,  -1,
+  -1,  -1,   0,   0,   0,   0,
+  92,   1,   0,   0,  80,   0,
+   0,   0,   8,   0,   0,   0,
+   0,   0,   0,   0, 108,   1,
+   0,   0,   0,   0,   0,   0,
+  -1,  -1,  -1,  -1,   0,   0,
+   0,   0,  -1,  -1,  -1,  -1,
+   0,   0,   0,   0,  95,  50,
+  52,  95, 109,  48,   0, 102,
+ 108, 111,  97, 116,  52, 120,
+  52,   0,   2,   0,   3,   0,
+   4,   0,   4,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,  -5,   0,
+   0,   0,  95,  50,  52,  95,
+ 109,  49,   0, 102, 108, 111,
+  97, 116,  52,   0, -85, -85,
+   1,   0,   3,   0,   1,   0,
+   4,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,  47,   1,   0,   0,
+  95,  50,  52,  95, 109,  50,
+   0, 102, 108, 111,  97, 116,
+  50,   0, -85, -85,   1,   0,
+   3,   0,   1,   0,   2,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+  99,   1,   0,   0,  77, 105,
+  99, 114, 111, 115, 111, 102,
+ 116,  32,  40,  82,  41,  32,
+  72,  76,  83,  76,  32,  83,
+ 104,  97, 100, 101, 114,  32,
+  67, 111, 109, 112, 105, 108,
+ 101, 114,  32,  49,  48,  46,
+  49,   0,  73,  83,  71,  78,
+  44,   0,   0,   0,   1,   0,
+   0,   0,   8,   0,   0,   0,
+  32,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,   0,   0,
+   0,   0,   3,   3,   0,   0,
+  84,  69,  88,  67,  79,  79,
+  82,  68,   0, -85, -85, -85,
+  79,  83,  71,  78,  80,   0,
+   0,   0,   2,   0,   0,   0,
+   8,   0,   0,   0,  56,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   3,   0,
+   0,   0,   0,   0,   0,   0,
+  15,   0,   0,   0,  65,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   3,   0,
+   0,   0,   1,   0,   0,   0,
+  15,   0,   0,   0,  84,  69,
+  88,  67,  79,  79,  82,  68,
+   0,  83,  86,  95,  80, 111,
+ 115, 105, 116, 105, 111, 110,
+   0, -85, -85, -85,  83,  72,
+  69,  88, -48,   0,   0,   0,
+  80,   0,   1,   0,  52,   0,
+   0,   0, 106,   8,   0,   1,
+  89,   0,   0,   4,  70,-114,
+  32,   0,   0,   0,   0,   0,
+   5,   0,   0,   0,  95,   0,
+   0,   3,  50,  16,  16,   0,
+   0,   0,   0,   0, 101,   0,
+   0,   3, -14,  32,  16,   0,
+   0,   0,   0,   0, 103,   0,
+   0,   4, -14,  32,  16,   0,
+   1,   0,   0,   0,   1,   0,
+   0,   0, 104,   0,   0,   2,
+   1,   0,   0,   0,  54,   0,
+   0,   6, -14,  32,  16,   0,
+   0,   0,   0,   0,  70,-114,
+  32,   0,   0,   0,   0,   0,
+   4,   0,   0,   0,  56,   0,
+   0,   8, -14,   0,  16,   0,
+   0,   0,   0,   0,  86,  21,
+  16,   0,   0,   0,   0,   0,
+  70,-114,  32,   0,   0,   0,
+   0,   0,   1,   0,   0,   0,
+  50,   0,   0,  10, -14,   0,
+  16,   0,   0,   0,   0,   0,
+   6,  16,  16,   0,   0,   0,
+   0,   0,  70,-114,  32,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,  70,  14,  16,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   8, -14,  32,  16,   0,
+   1,   0,   0,   0,  70,  14,
+  16,   0,   0,   0,   0,   0,
+  70,-114,  32,   0,   0,   0,
+   0,   0,   3,   0,   0,   0,
+  62,   0,   0,   1,  83,  84,
+  65,  84,-108,   0,   0,   0,
+   5,   0,   0,   0,   1,   0,
+   0,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,   3,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   1,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   1,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0
+};

+ 496 - 0
src/render/sdlgpu/shaders/linepoint.vert.sm60.dxil.h

@@ -0,0 +1,496 @@
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xy          0     NONE   float   xy  
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xyzw        0     NONE   float   xyzw
+; SV_Position              0   xyzw        1      POS   float   xyzw
+;
+; shader hash: 28e70f2da15e5a0c84402943a6b12723
+;
+; Pipeline Runtime Information: 
+;
+; Vertex Shader
+; OutputPositionPresent=1
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                              
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; SV_Position              0          noperspective       
+;
+; Buffer Definitions:
+;
+; cbuffer _22_24
+; {
+;
+;   struct hostlayout._22_24
+;   {
+;
+;       row_major float4x4 _24_m0;                    ; Offset:    0
+;       float4 _24_m1;                                ; Offset:   64
+;       float2 _24_m2;                                ; Offset:   80
+;   
+;   } _22_24;                                         ; Offset:    0 Size:    88
+;
+; }
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; _22_24                            cbuffer      NA          NA     CB0     cb0,space1     1
+;
+;
+; ViewId state:
+;
+; Number of inputs: 2, outputs: 8
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 4 depends on inputs: { 0, 1 }
+;   output 5 depends on inputs: { 0, 1 }
+;   output 6 depends on inputs: { 0, 1 }
+;   output 7 depends on inputs: { 0, 1 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+%dx.types.Handle = type { i8* }
+%dx.types.CBufRet.f32 = type { float, float, float, float }
+%hostlayout._22_24 = type { [4 x <4 x float>], <4 x float>, <2 x float> }
+
+define void @main() {
+  %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %2 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %3 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %4 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 0)  ; CBufferLoadLegacy(handle,regIndex)
+  %5 = extractvalue %dx.types.CBufRet.f32 %4, 0
+  %6 = extractvalue %dx.types.CBufRet.f32 %4, 1
+  %7 = extractvalue %dx.types.CBufRet.f32 %4, 2
+  %8 = extractvalue %dx.types.CBufRet.f32 %4, 3
+  %9 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %10 = extractvalue %dx.types.CBufRet.f32 %9, 0
+  %11 = extractvalue %dx.types.CBufRet.f32 %9, 1
+  %12 = extractvalue %dx.types.CBufRet.f32 %9, 2
+  %13 = extractvalue %dx.types.CBufRet.f32 %9, 3
+  %14 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 3)  ; CBufferLoadLegacy(handle,regIndex)
+  %15 = extractvalue %dx.types.CBufRet.f32 %14, 0
+  %16 = extractvalue %dx.types.CBufRet.f32 %14, 1
+  %17 = extractvalue %dx.types.CBufRet.f32 %14, 2
+  %18 = extractvalue %dx.types.CBufRet.f32 %14, 3
+  %19 = fmul fast float %5, %2
+  %20 = call float @dx.op.tertiary.f32(i32 46, float %3, float %10, float %19)  ; FMad(a,b,c)
+  %21 = fadd fast float %15, %20
+  %22 = fmul fast float %6, %2
+  %23 = call float @dx.op.tertiary.f32(i32 46, float %3, float %11, float %22)  ; FMad(a,b,c)
+  %24 = fadd fast float %23, %16
+  %25 = fmul fast float %7, %2
+  %26 = call float @dx.op.tertiary.f32(i32 46, float %3, float %12, float %25)  ; FMad(a,b,c)
+  %27 = fadd fast float %26, %17
+  %28 = fmul fast float %8, %2
+  %29 = call float @dx.op.tertiary.f32(i32 46, float %3, float %13, float %28)  ; FMad(a,b,c)
+  %30 = fadd fast float %29, %18
+  %31 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 4)  ; CBufferLoadLegacy(handle,regIndex)
+  %32 = extractvalue %dx.types.CBufRet.f32 %31, 0
+  %33 = extractvalue %dx.types.CBufRet.f32 %31, 1
+  %34 = extractvalue %dx.types.CBufRet.f32 %31, 2
+  %35 = extractvalue %dx.types.CBufRet.f32 %31, 3
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %32)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %33)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %34)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %35)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 0, float %21)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 1, float %24)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 2, float %27)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 3, float %30)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.tertiary.f32(i32, float, float, float) #0
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.resources = !{!4}
+!dx.viewIdState = !{!7}
+!dx.entryPoints = !{!8}
+
+!0 = !{!"dxc(private) 1.8.0.4662 (416fab6b5)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 8}
+!3 = !{!"vs", i32 6, i32 0}
+!4 = !{null, null, !5, null}
+!5 = !{!6}
+!6 = !{i32 0, %hostlayout._22_24* undef, !"", i32 1, i32 0, i32 1, i32 88, null}
+!7 = !{[4 x i32] [i32 2, i32 8, i32 240, i32 240]}
+!8 = !{void ()* @main, !"main", !9, !4, null}
+!9 = !{!10, !14, null}
+!10 = !{!11}
+!11 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !12, i8 0, i32 1, i8 2, i32 0, i8 0, !13}
+!12 = !{i32 0}
+!13 = !{i32 3, i32 3}
+!14 = !{!15, !17}
+!15 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !12, i8 2, i32 1, i8 4, i32 0, i8 0, !16}
+!16 = !{i32 3, i32 15}
+!17 = !{i32 1, !"SV_Position", i8 9, i8 3, !12, i8 4, i32 1, i8 4, i32 1, i8 0, !16}
+
+#endif
+
+const unsigned char linepoint_vert_sm60_dxil[] = {
+  0x44, 0x58, 0x42, 0x43, 0x07, 0x97, 0x68, 0xde, 0x5f, 0x50, 0x0b, 0x5d,
+  0x22, 0x1b, 0xe5, 0xb4, 0xe8, 0xdb, 0x02, 0xea, 0x01, 0x00, 0x00, 0x00,
+  0x04, 0x0f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+  0xb8, 0x01, 0x00, 0x00, 0x0c, 0x08, 0x00, 0x00, 0x28, 0x08, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44,
+  0x00, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x60, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5f,
+  0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x50, 0x53, 0x56, 0x30, 0xc0, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52,
+  0x44, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x6d,
+  0x61, 0x69, 0x6e, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x42, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x00, 0x03, 0x02, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x44, 0x03,
+  0x03, 0x04, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54,
+  0x4c, 0x06, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x93, 0x01, 0x00, 0x00,
+  0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x34, 0x06, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00,
+  0x8a, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88,
+  0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42,
+  0xe4, 0x48, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c,
+  0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07,
+  0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20,
+  0x6d, 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42,
+  0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04,
+  0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14,
+  0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x6c, 0x23, 0x00,
+  0x25, 0x00, 0x14, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29,
+  0xc6, 0x20, 0x84, 0x14, 0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1,
+  0xa3, 0x86, 0xcb, 0x9f, 0xb0, 0x87, 0x90, 0x7c, 0x6e, 0xa3, 0x8a, 0x95,
+  0x98, 0xfc, 0xe2, 0xb6, 0x11, 0x31, 0xc6, 0x18, 0x54, 0xee, 0x19, 0x2e,
+  0x7f, 0xc2, 0x1e, 0x42, 0xf2, 0x43, 0xa0, 0x19, 0x16, 0x02, 0x05, 0xab,
+  0x10, 0x8a, 0x30, 0x42, 0xad, 0x14, 0x83, 0x8c, 0x31, 0xe8, 0xcd, 0x11,
+  0x04, 0xc5, 0x60, 0xa4, 0x10, 0x12, 0x49, 0x0e, 0x04, 0x0c, 0x23, 0x10,
+  0x43, 0x12, 0xd4, 0x61, 0x04, 0x61, 0xb8, 0xe8, 0x70, 0xa4, 0x69, 0x01,
+  0x30, 0x87, 0x9a, 0xfc, 0xdf, 0xb6, 0x7f, 0x1b, 0x47, 0x83, 0xad, 0x97,
+  0x70, 0x12, 0x10, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87,
+  0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50,
+  0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10,
+  0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e,
+  0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86,
+  0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x30, 0xe4, 0x79, 0x80, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x60, 0xc8, 0x23, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x40, 0x16, 0x08, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47,
+  0xc6, 0x04, 0x43, 0x22, 0x25, 0x30, 0x02, 0x50, 0x0c, 0x05, 0x1b, 0x50,
+  0x04, 0x85, 0x50, 0x06, 0xe5, 0x50, 0x12, 0x05, 0x18, 0x50, 0x1a, 0x05,
+  0x1a, 0x50, 0x1e, 0x05, 0x51, 0x58, 0x54, 0x4a, 0x62, 0x04, 0xa0, 0x08,
+  0x0a, 0xa1, 0x0c, 0x28, 0xd6, 0x00, 0xe1, 0x19, 0x00, 0xca, 0x33, 0x00,
+  0xa4, 0xc7, 0x22, 0x04, 0x04, 0x3e, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90,
+  0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b,
+  0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71,
+  0xa1, 0xb1, 0xb1, 0x91, 0x01, 0x41, 0xa1, 0x89, 0xb1, 0x31, 0x0b, 0x13,
+  0xb3, 0x11, 0xab, 0x49, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xc2, 0x98, 0x20,
+  0x10, 0xc7, 0x06, 0x61, 0x20, 0x36, 0x08, 0x04, 0x41, 0xc1, 0x6e, 0x6e,
+  0x82, 0x40, 0x20, 0x1b, 0x86, 0x03, 0x21, 0x26, 0x08, 0x19, 0x47, 0xe3,
+  0x4b, 0x46, 0xe6, 0x4b, 0x86, 0x66, 0x82, 0x40, 0x24, 0x1b, 0x10, 0x42,
+  0x59, 0x06, 0x62, 0x60, 0x80, 0x0d, 0x41, 0xb3, 0x81, 0x00, 0x00, 0x07,
+  0x98, 0x20, 0x60, 0x1b, 0x8d, 0x2f, 0x19, 0x9a, 0xaf, 0x36, 0x98, 0x09,
+  0x02, 0xa1, 0x4c, 0x10, 0x88, 0x65, 0xc3, 0x30, 0x4d, 0xc3, 0x04, 0x81,
+  0x60, 0x26, 0x08, 0x44, 0x33, 0x41, 0x20, 0x9c, 0x09, 0x42, 0xa4, 0x6d,
+  0x50, 0x90, 0x48, 0xa2, 0x2a, 0xc2, 0xba, 0x2e, 0x8c, 0xc6, 0x97, 0x0c,
+  0xcd, 0x57, 0x5b, 0xcc, 0x04, 0x81, 0x78, 0x26, 0x08, 0x04, 0xb4, 0x41,
+  0x41, 0xb4, 0x6a, 0xb3, 0xae, 0x0b, 0xe3, 0x26, 0x1a, 0x5f, 0x32, 0x34,
+  0x5f, 0x6d, 0x32, 0x13, 0x04, 0x22, 0xda, 0x80, 0x20, 0x5e, 0xf5, 0x59,
+  0x17, 0x27, 0x6d, 0x20, 0x98, 0xac, 0x03, 0x83, 0x0d, 0x03, 0x01, 0x85,
+  0xc1, 0x04, 0x41, 0x00, 0x36, 0x00, 0x1b, 0x06, 0x82, 0x0c, 0xc8, 0x60,
+  0x43, 0x50, 0x06, 0x1b, 0x86, 0x61, 0x0c, 0xcc, 0x60, 0x82, 0xa0, 0x75,
+  0x1b, 0x02, 0x34, 0x20, 0xd1, 0x16, 0x96, 0xe6, 0x46, 0x84, 0xaa, 0x08,
+  0x6b, 0xe8, 0xe9, 0x49, 0x8a, 0x68, 0x82, 0x50, 0x54, 0x13, 0x84, 0xc2,
+  0xda, 0x10, 0x10, 0x13, 0x84, 0xe2, 0xda, 0x20, 0x54, 0xd5, 0x86, 0x85,
+  0x58, 0x03, 0x36, 0x68, 0x03, 0x37, 0x68, 0x83, 0xe1, 0x0d, 0x88, 0x36,
+  0x80, 0x83, 0x0d, 0x41, 0x1c, 0x4c, 0x10, 0x0a, 0x6c, 0x82, 0x40, 0x48,
+  0x1b, 0x84, 0x8a, 0x0e, 0x36, 0x2c, 0xc4, 0x1a, 0xb0, 0x41, 0x1b, 0xb8,
+  0xc1, 0x1b, 0x0c, 0x73, 0x40, 0xb4, 0x41, 0x1d, 0x70, 0x99, 0xb2, 0xfa,
+  0x82, 0x7a, 0x9b, 0x4b, 0xa3, 0x4b, 0x7b, 0x73, 0x9b, 0x20, 0x14, 0xd9,
+  0x86, 0x65, 0xb8, 0x03, 0x36, 0xc0, 0x03, 0x37, 0x98, 0x83, 0x61, 0x0e,
+  0x86, 0x36, 0xa8, 0x83, 0x0d, 0x82, 0x1d, 0xe4, 0xc1, 0x86, 0x41, 0x0e,
+  0xf4, 0x00, 0xd8, 0x50, 0x8c, 0x81, 0x1a, 0xec, 0xc1, 0x03, 0xd0, 0x30,
+  0x63, 0x7b, 0x0b, 0xa3, 0x9b, 0x9b, 0x20, 0x10, 0x13, 0x8b, 0x34, 0xb7,
+  0x39, 0xba, 0xb9, 0x09, 0x02, 0x41, 0xd1, 0x98, 0x4b, 0x3b, 0xfb, 0x62,
+  0x23, 0xa3, 0x31, 0x97, 0x76, 0xf6, 0x35, 0x47, 0xb7, 0x01, 0xe9, 0x03,
+  0x3f, 0xf8, 0x03, 0x50, 0x08, 0x05, 0x49, 0x14, 0xfc, 0xa0, 0x0a, 0x1b,
+  0x9b, 0x5d, 0x9b, 0x4b, 0x1a, 0x59, 0x99, 0x1b, 0xdd, 0x94, 0x20, 0xa8,
+  0x42, 0x86, 0xe7, 0x62, 0x57, 0x26, 0x37, 0x97, 0xf6, 0xe6, 0x36, 0x25,
+  0x20, 0x9a, 0x90, 0xe1, 0xb9, 0xd8, 0x85, 0xb1, 0xd9, 0x95, 0xc9, 0x4d,
+  0x09, 0x8a, 0x3a, 0x64, 0x78, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72,
+  0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x53, 0x02, 0xa4, 0x0c, 0x19, 0x9e, 0x8b,
+  0x5c, 0xd9, 0xdc, 0x5b, 0x9d, 0xdc, 0x58, 0xd9, 0xdc, 0x94, 0xc0, 0xa9,
+  0x44, 0x86, 0xe7, 0x42, 0x97, 0x07, 0x57, 0x16, 0xe4, 0xe6, 0xf6, 0x46,
+  0x17, 0x46, 0x97, 0xf6, 0xe6, 0x36, 0x37, 0x45, 0x08, 0x03, 0x33, 0xa8,
+  0x43, 0x86, 0xe7, 0x62, 0x97, 0x56, 0x76, 0x97, 0x44, 0x36, 0x45, 0x17,
+  0x46, 0x57, 0x36, 0x25, 0x40, 0x83, 0x3a, 0x64, 0x78, 0x2e, 0x65, 0x6e,
+  0x74, 0x72, 0x79, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x53, 0x82, 0x3d,
+  0xe8, 0x42, 0x86, 0xe7, 0x32, 0xf6, 0x56, 0xe7, 0x46, 0x57, 0x26, 0x37,
+  0x37, 0x25, 0x10, 0x05, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66,
+  0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10,
+  0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce,
+  0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b,
+  0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c,
+  0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07,
+  0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11,
+  0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0,
+  0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8,
+  0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b,
+  0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b,
+  0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87,
+  0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07,
+  0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87,
+  0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81,
+  0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30,
+  0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca,
+  0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b,
+  0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b,
+  0xb0, 0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x72, 0x10, 0x87,
+  0x73, 0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60, 0x87, 0x70, 0xc8, 0x87,
+  0x77, 0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4, 0x80, 0x0f, 0x6e, 0x40,
+  0x0f, 0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x36, 0xb0, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x10,
+  0x50, 0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25, 0x61, 0x00, 0x02, 0xe6,
+  0x17, 0xb7, 0x6d, 0x05, 0xd2, 0x70, 0xf9, 0xce, 0xe3, 0x0b, 0x11, 0x01,
+  0x4c, 0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0xc0, 0x34, 0x5c, 0xbe, 0xf3,
+  0xf8, 0x8b, 0x03, 0x0c, 0x62, 0xf3, 0x50, 0x93, 0x5f, 0xdc, 0xb6, 0x09,
+  0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x4d, 0x4e, 0x44, 0xa0, 0xd4, 0xf4,
+  0x50, 0x93, 0x5f, 0xdc, 0xb6, 0x11, 0x48, 0xc3, 0xe5, 0x3b, 0x8f, 0x3f,
+  0x11, 0xd1, 0x84, 0x00, 0x11, 0xe6, 0x17, 0xb7, 0x6d, 0x00, 0x04, 0x03,
+  0x20, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48,
+  0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xe7, 0x0f, 0x2d,
+  0xa1, 0x5e, 0x5a, 0x0c, 0x84, 0x40, 0x29, 0x43, 0xa6, 0xb1, 0x27, 0x23,
+  0x44, 0x58, 0x49, 0x4c, 0xd4, 0x06, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00,
+  0xb5, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0xbc, 0x06, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde,
+  0x21, 0x0c, 0x00, 0x00, 0xac, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91,
+  0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c,
+  0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02,
+  0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b,
+  0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5,
+  0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50,
+  0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06,
+  0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff,
+  0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f,
+  0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00,
+  0x89, 0x20, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09,
+  0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3,
+  0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c,
+  0x10, 0x6c, 0x23, 0x00, 0x25, 0x00, 0x14, 0x66, 0x00, 0xe6, 0x08, 0xc0,
+  0x60, 0x8e, 0x00, 0x29, 0xc6, 0x20, 0x84, 0x14, 0x42, 0xa6, 0x18, 0x80,
+  0x10, 0x52, 0x06, 0xa1, 0xa3, 0x86, 0xcb, 0x9f, 0xb0, 0x87, 0x90, 0x7c,
+  0x6e, 0xa3, 0x8a, 0x95, 0x98, 0xfc, 0xe2, 0xb6, 0x11, 0x31, 0xc6, 0x18,
+  0x54, 0xee, 0x19, 0x2e, 0x7f, 0xc2, 0x1e, 0x42, 0xf2, 0x43, 0xa0, 0x19,
+  0x16, 0x02, 0x05, 0xab, 0x10, 0x8a, 0x30, 0x42, 0xad, 0x14, 0x83, 0x8c,
+  0x31, 0xe8, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0xa4, 0x10, 0x12, 0x49, 0x0e,
+  0x04, 0x0c, 0x23, 0x10, 0x43, 0x12, 0xd4, 0x61, 0x04, 0x61, 0xb8, 0xe8,
+  0x70, 0xa4, 0x69, 0x01, 0x30, 0x87, 0x9a, 0xfc, 0xdf, 0xb6, 0x7f, 0x1b,
+  0x47, 0x83, 0xad, 0x97, 0x70, 0x12, 0x10, 0x00, 0x13, 0x14, 0x72, 0xc0,
+  0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0,
+  0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d,
+  0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78,
+  0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x79, 0x80, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, 0x23, 0x01, 0x01,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x16, 0x08, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90,
+  0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x25, 0x30, 0x02, 0x50,
+  0x10, 0xc5, 0x50, 0xb0, 0x01, 0x65, 0x50, 0x1e, 0x54, 0x4a, 0x62, 0x04,
+  0xa0, 0x08, 0x0a, 0xa1, 0x0c, 0x28, 0xcf, 0x00, 0x90, 0x1e, 0x8b, 0x10,
+  0x10, 0xf8, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00,
+  0x53, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4,
+  0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b, 0xb3, 0x0b, 0xa3, 0x2b,
+  0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb1, 0xb1, 0x91,
+  0x01, 0x41, 0xa1, 0x89, 0xb1, 0x31, 0x0b, 0x13, 0xb3, 0x11, 0xab, 0x49,
+  0xd9, 0x10, 0x04, 0x13, 0x04, 0xc2, 0x98, 0x20, 0x10, 0xc7, 0x06, 0x61,
+  0x20, 0x26, 0x08, 0x04, 0xb2, 0x41, 0x18, 0x0c, 0x0a, 0x76, 0x73, 0x13,
+  0x04, 0x22, 0xd9, 0x30, 0x20, 0x09, 0x31, 0x41, 0xc8, 0x24, 0x02, 0x13,
+  0x04, 0x42, 0xd9, 0x80, 0x10, 0x0b, 0x33, 0x10, 0x43, 0x03, 0x6c, 0x08,
+  0x9c, 0x0d, 0x04, 0x00, 0x3c, 0xc0, 0x04, 0x41, 0x9b, 0x36, 0x04, 0xd1,
+  0x04, 0x41, 0x00, 0x48, 0xb4, 0x85, 0xa5, 0xb9, 0x11, 0xa1, 0x2a, 0xc2,
+  0x1a, 0x7a, 0x7a, 0x92, 0x22, 0x9a, 0x20, 0x14, 0xcd, 0x04, 0xa1, 0x70,
+  0x36, 0x04, 0xc4, 0x04, 0xa1, 0x78, 0x26, 0x08, 0xc4, 0xb2, 0x41, 0xd0,
+  0xb4, 0x0d, 0x0b, 0x51, 0x59, 0x17, 0x76, 0x0d, 0x19, 0x71, 0x6d, 0x1b,
+  0x02, 0x6e, 0x82, 0x50, 0x40, 0x13, 0x04, 0x82, 0xd9, 0x20, 0x68, 0xdf,
+  0x86, 0x85, 0xa8, 0xac, 0x0b, 0xcb, 0x06, 0x8f, 0xb8, 0xc0, 0x80, 0xcb,
+  0x94, 0xd5, 0x17, 0xd4, 0xdb, 0x5c, 0x1a, 0x5d, 0xda, 0x9b, 0xdb, 0x04,
+  0xa1, 0x88, 0x36, 0x2c, 0x83, 0x18, 0x58, 0x63, 0x80, 0x79, 0x83, 0x37,
+  0x5c, 0x60, 0xb0, 0x41, 0x08, 0x03, 0x32, 0xd8, 0x30, 0x74, 0x65, 0x00,
+  0x6c, 0x28, 0x26, 0xca, 0x0c, 0x20, 0xa0, 0x0a, 0x1b, 0x9b, 0x5d, 0x9b,
+  0x4b, 0x1a, 0x59, 0x99, 0x1b, 0xdd, 0x94, 0x20, 0xa8, 0x42, 0x86, 0xe7,
+  0x62, 0x57, 0x26, 0x37, 0x97, 0xf6, 0xe6, 0x36, 0x25, 0x20, 0x9a, 0x90,
+  0xe1, 0xb9, 0xd8, 0x85, 0xb1, 0xd9, 0x95, 0xc9, 0x4d, 0x09, 0x8c, 0x3a,
+  0x64, 0x78, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64,
+  0x65, 0x6c, 0x53, 0x82, 0xa4, 0x0c, 0x19, 0x9e, 0x8b, 0x5c, 0xd9, 0xdc,
+  0x5b, 0x9d, 0xdc, 0x58, 0xd9, 0xdc, 0x94, 0xe0, 0xa9, 0x43, 0x86, 0xe7,
+  0x62, 0x97, 0x56, 0x76, 0x97, 0x44, 0x36, 0x45, 0x17, 0x46, 0x57, 0x36,
+  0x25, 0x88, 0xea, 0x90, 0xe1, 0xb9, 0x94, 0xb9, 0xd1, 0xc9, 0xe5, 0x41,
+  0xbd, 0xa5, 0xb9, 0xd1, 0xcd, 0x4d, 0x09, 0xcc, 0x00, 0x00, 0x00, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c,
+  0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3,
+  0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6,
+  0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03,
+  0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48,
+  0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20,
+  0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e,
+  0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d,
+  0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89,
+  0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83,
+  0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78,
+  0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98,
+  0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5,
+  0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c,
+  0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43,
+  0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82,
+  0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70,
+  0x03, 0x72, 0x10, 0x87, 0x73, 0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60,
+  0x87, 0x70, 0xc8, 0x87, 0x77, 0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4,
+  0x80, 0x0f, 0x6e, 0x40, 0x0f, 0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00,
+  0x71, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x36, 0xb0, 0x0d, 0x97,
+  0xef, 0x3c, 0xbe, 0x10, 0x50, 0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25,
+  0x61, 0x00, 0x02, 0xe6, 0x17, 0xb7, 0x6d, 0x05, 0xd2, 0x70, 0xf9, 0xce,
+  0xe3, 0x0b, 0x11, 0x01, 0x4c, 0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0xc0,
+  0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x8b, 0x03, 0x0c, 0x62, 0xf3, 0x50, 0x93,
+  0x5f, 0xdc, 0xb6, 0x09, 0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x4d, 0x4e,
+  0x44, 0xa0, 0xd4, 0xf4, 0x50, 0x93, 0x5f, 0xdc, 0xb6, 0x11, 0x48, 0xc3,
+  0xe5, 0x3b, 0x8f, 0x3f, 0x11, 0xd1, 0x84, 0x00, 0x11, 0xe6, 0x17, 0xb7,
+  0x6d, 0x00, 0x04, 0x03, 0x20, 0x0d, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00,
+  0x5c, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x44, 0x4a, 0xa1, 0xec, 0x8a, 0xab, 0x10, 0x66,
+  0x00, 0x4a, 0x8e, 0x4a, 0x09, 0x50, 0x1c, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x20, 0x5d, 0x43, 0x53, 0x55, 0xc1,
+  0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x9c, 0x61, 0x59, 0x4f, 0x31,
+  0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x46, 0x77, 0x5c, 0x17, 0x61, 0x8c,
+  0x18, 0x1c, 0x00, 0x08, 0x82, 0x41, 0xc3, 0x29, 0x03, 0x36, 0x9a, 0x10,
+  0x00, 0xa3, 0x09, 0x42, 0x30, 0x9a, 0x30, 0x08, 0xa3, 0x09, 0xc4, 0x30,
+  0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x4d, 0x18, 0x3c, 0x88, 0x37, 0x9a,
+  0x10, 0x00, 0xa3, 0x09, 0x42, 0x30, 0x9a, 0x30, 0x08, 0xa3, 0x09, 0xc4,
+  0x30, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x8d, 0x19, 0x50, 0x8d, 0x37,
+  0x9a, 0x10, 0x00, 0xa3, 0x09, 0x42, 0x30, 0x9a, 0x30, 0x08, 0xa3, 0x09,
+  0xc4, 0x60, 0x4e, 0x24, 0x9f, 0x11, 0x03, 0x04, 0x00, 0x41, 0x30, 0x78,
+  0xd6, 0x20, 0x8b, 0x94, 0xc0, 0x8c, 0x00, 0x3a, 0x06, 0x51, 0xf2, 0x19,
+  0x31, 0x40, 0x00, 0x10, 0x04, 0x83, 0xc7, 0x0d, 0x38, 0x8a, 0x09, 0x2c,
+  0x40, 0xa0, 0x63, 0xd2, 0x25, 0x9f, 0x11, 0x03, 0x04, 0x00, 0x41, 0x30,
+  0x78, 0xe2, 0xe0, 0xbb, 0x9c, 0xc0, 0x02, 0x05, 0x3a, 0x46, 0x69, 0xf2,
+  0x19, 0x31, 0x40, 0x00, 0x10, 0x04, 0x83, 0x87, 0x0e, 0xc4, 0x40, 0x83,
+  0x02, 0x0b, 0x18, 0xe8, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0x41, 0x73,
+  0x07, 0x65, 0xe0, 0x8d, 0xc1, 0x68, 0x42, 0x00, 0x8c, 0x26, 0x08, 0xc1,
+  0x68, 0xc2, 0x20, 0x8c, 0x26, 0x10, 0xc3, 0x88, 0x41, 0x02, 0x80, 0x20,
+  0x18, 0x20, 0x7d, 0xb0, 0x06, 0x78, 0x80, 0x07, 0x71, 0x40, 0x8c, 0x18,
+  0x24, 0x00, 0x08, 0x82, 0x01, 0xd2, 0x07, 0x6b, 0x80, 0x07, 0x78, 0x50,
+  0x06, 0xc3, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x7d, 0xb0, 0x06,
+  0x78, 0x80, 0x07, 0x70, 0x20, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01,
+  0xd2, 0x07, 0x6b, 0x80, 0x07, 0x78, 0xe0, 0x06, 0xc1, 0x88, 0x41, 0x02,
+  0x80, 0x20, 0x18, 0x20, 0x7d, 0xb0, 0x06, 0x79, 0x80, 0x07, 0x71, 0xf0,
+  0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0xd2, 0x07, 0x6b, 0x90, 0x07,
+  0x78, 0x50, 0x06, 0xcc, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x7d,
+  0xb0, 0x06, 0x79, 0x80, 0x07, 0x70, 0x90, 0x8c, 0x18, 0x24, 0x00, 0x08,
+  0x82, 0x01, 0xd2, 0x07, 0x6b, 0x90, 0x07, 0x78, 0xe0, 0x06, 0x06, 0x02,
+  0x00, 0x00, 0x00, 0x00
+};

+ 93 - 0
src/render/sdlgpu/shaders/linepoint.vert.spv.h

@@ -0,0 +1,93 @@
+const unsigned char linepoint_vert_spv[] = {
+  0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00,
+  0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x26, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x20, 0x00, 0x04, 0x00,
+  0x11, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
+  0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00,
+  0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x1b, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x15, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
+  0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+  0x1f, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x91, 0x00, 0x05, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x25, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x26, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+  0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+};
+const unsigned int linepoint_vert_spv_len = 1076;

+ 6 - 0
src/render/sdlgpu/shaders/metal.h

@@ -0,0 +1,6 @@
+#include "linepoint.vert.metal.h"
+#include "tri_color.vert.metal.h"
+#include "tri_texture.vert.metal.h"
+#include "color.frag.metal.h"
+#include "texture_rgba.frag.metal.h"
+#include "texture_rgb.frag.metal.h"

+ 6 - 0
src/render/sdlgpu/shaders/spir-v.h

@@ -0,0 +1,6 @@
+#include "linepoint.vert.spv.h"
+#include "tri_color.vert.spv.h"
+#include "tri_texture.vert.spv.h"
+#include "color.frag.spv.h"
+#include "texture_rgba.frag.spv.h"
+#include "texture_rgb.frag.spv.h"

+ 12 - 0
src/render/sdlgpu/shaders/texture_rgb.frag

@@ -0,0 +1,12 @@
+#version 450
+
+layout(location = 0) in vec4 v_color;
+layout(location = 1) in vec2 v_uv;
+
+layout(set = 2, binding = 0) uniform sampler2D u_texture;
+
+layout(location = 0) out vec4 o_color;
+
+void main() {
+    o_color = vec4(texture(u_texture, v_uv).rgb, 1) * v_color;
+}

+ 41 - 0
src/render/sdlgpu/shaders/texture_rgb.frag.metal.h

@@ -0,0 +1,41 @@
+const unsigned char texture_rgb_frag_metal[] = {
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65,
+  0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a,
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 0x69,
+  0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a,
+  0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+  0x61, 0x63, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a,
+  0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30,
+  0x5f, 0x6f, 0x75, 0x74, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6d, 0x5f, 0x39, 0x20, 0x5b, 0x5b,
+  0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a,
+  0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6d,
+  0x61, 0x69, 0x6e, 0x30, 0x5f, 0x69, 0x6e, 0x0a, 0x7b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6d, 0x5f, 0x32,
+  0x38, 0x20, 0x5b, 0x5b, 0x75, 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63,
+  0x6e, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6d, 0x5f, 0x31, 0x37, 0x20, 0x5b,
+  0x5b, 0x75, 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x31, 0x29,
+  0x5d, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x66, 0x72, 0x61, 0x67,
+  0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x6f,
+  0x75, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x28, 0x6d, 0x61, 0x69,
+  0x6e, 0x30, 0x5f, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x5b, 0x73,
+  0x74, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x5d, 0x5d, 0x2c, 0x20, 0x74,
+  0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x64, 0x3c, 0x66, 0x6c, 0x6f,
+  0x61, 0x74, 0x3e, 0x20, 0x5f, 0x31, 0x33, 0x20, 0x5b, 0x5b, 0x74, 0x65,
+  0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x2c, 0x20,
+  0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x20, 0x5f, 0x31, 0x33, 0x53,
+  0x6d, 0x70, 0x6c, 0x72, 0x20, 0x5b, 0x5b, 0x73, 0x61, 0x6d, 0x70, 0x6c,
+  0x65, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x29, 0x0a, 0x7b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x6f, 0x75, 0x74,
+  0x20, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x6d, 0x5f, 0x39, 0x20, 0x3d,
+  0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x5f, 0x31, 0x33, 0x2e,
+  0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x28, 0x5f, 0x31, 0x33, 0x53, 0x6d,
+  0x70, 0x6c, 0x72, 0x2c, 0x20, 0x69, 0x6e, 0x2e, 0x6d, 0x5f, 0x31, 0x37,
+  0x29, 0x2e, 0x78, 0x79, 0x7a, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x20,
+  0x2a, 0x20, 0x69, 0x6e, 0x2e, 0x6d, 0x5f, 0x32, 0x38, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75,
+  0x74, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a
+};
+const unsigned int texture_rgb_frag_metal_len = 450;

+ 123 - 0
src/render/sdlgpu/shaders/texture_rgb.frag.sm50.dxbc.h

@@ -0,0 +1,123 @@
+const unsigned char texture_rgb_frag_sm50_dxbc[] =
+{
+  68,  88,  66,  67, -22, -54,
+ -48,  73, -47, -40, -92, -21,
+ -43, -46,  13,-120, -20, 126,
+ 110,  46,   1,   0,   0,   0,
+ -52,   2,   0,   0,   5,   0,
+   0,   0,  52,   0,   0,   0,
+ -12,   0,   0,   0,  64,   1,
+   0,   0, 116,   1,   0,   0,
+  48,   2,   0,   0,  82,  68,
+  69,  70, -72,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   2,   0,   0,   0,
+  60,   0,   0,   0,   0,   5,
+  -1,  -1,   0,   1,   0,   0,
+-115,   0,   0,   0,  82,  68,
+  49,  49,  60,   0,   0,   0,
+  24,   0,   0,   0,  32,   0,
+   0,   0,  40,   0,   0,   0,
+  36,   0,   0,   0,  12,   0,
+   0,   0,   0,   0,   0,   0,
+ 124,   0,   0,   0,   3,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   1,   0,
+   0,   0,-119,   0,   0,   0,
+   2,   0,   0,   0,   5,   0,
+   0,   0,   4,   0,   0,   0,
+  -1,  -1,  -1,  -1,   0,   0,
+   0,   0,   1,   0,   0,   0,
+  13,   0,   0,   0,  95,  95,
+  49,  51,  95, 115,  97, 109,
+ 112, 108, 101, 114,   0,  95,
+  49,  51,   0,  77, 105,  99,
+ 114, 111, 115, 111, 102, 116,
+  32,  40,  82,  41,  32,  72,
+  76,  83,  76,  32,  83, 104,
+  97, 100, 101, 114,  32,  67,
+ 111, 109, 112, 105, 108, 101,
+ 114,  32,  49,  48,  46,  49,
+   0, -85, -85, -85,  73,  83,
+  71,  78,  68,   0,   0,   0,
+   2,   0,   0,   0,   8,   0,
+   0,   0,  56,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   3,   0,   0,   0,
+   0,   0,   0,   0,  15,  15,
+   0,   0,  56,   0,   0,   0,
+   1,   0,   0,   0,   0,   0,
+   0,   0,   3,   0,   0,   0,
+   1,   0,   0,   0,   3,   3,
+   0,   0,  84,  69,  88,  67,
+  79,  79,  82,  68,   0, -85,
+ -85, -85,  79,  83,  71,  78,
+  44,   0,   0,   0,   1,   0,
+   0,   0,   8,   0,   0,   0,
+  32,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,   0,   0,
+   0,   0,  15,   0,   0,   0,
+  83,  86,  95,  84,  97, 114,
+ 103, 101, 116,   0, -85, -85,
+  83,  72,  69,  88, -76,   0,
+   0,   0,  80,   0,   0,   0,
+  45,   0,   0,   0, 106,   8,
+   0,   1,  90,   0,   0,   3,
+   0,  96,  16,   0,   0,   0,
+   0,   0,  88,  24,   0,   4,
+   0, 112,  16,   0,   0,   0,
+   0,   0,  85,  85,   0,   0,
+  98,  16,   0,   3, -14,  16,
+  16,   0,   0,   0,   0,   0,
+  98,  16,   0,   3,  50,  16,
+  16,   0,   1,   0,   0,   0,
+ 101,   0,   0,   3, -14,  32,
+  16,   0,   0,   0,   0,   0,
+ 104,   0,   0,   2,   1,   0,
+   0,   0,  69,   0,   0,-117,
+ -62,   0,   0,-128,  67,  85,
+  21,   0, 114,   0,  16,   0,
+   0,   0,   0,   0,  70,  16,
+  16,   0,   1,   0,   0,   0,
+  70, 126,  16,   0,   0,   0,
+   0,   0,   0,  96,  16,   0,
+   0,   0,   0,   0,  54,   0,
+   0,   5,-126,   0,  16,   0,
+   0,   0,   0,   0,   1,  64,
+   0,   0,   0,   0,-128,  63,
+  56,   0,   0,   7, -14,  32,
+  16,   0,   0,   0,   0,   0,
+  70,  14,  16,   0,   0,   0,
+   0,   0,  70,  30,  16,   0,
+   0,   0,   0,   0,  62,   0,
+   0,   1,  83,  84,  65,  84,
+-108,   0,   0,   0,   4,   0,
+   0,   0,   1,   0,   0,   0,
+   0,   0,   0,   0,   3,   0,
+   0,   0,   1,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   1,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   1,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0
+};

+ 465 - 0
src/render/sdlgpu/shaders/texture_rgb.frag.sm60.dxil.h

@@ -0,0 +1,465 @@
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xyzw        0     NONE   float   xyzw
+; TEXCOORD                 1   xy          1     NONE   float   xy  
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_Target                0   xyzw        0   TARGET   float   xyzw
+;
+; shader hash: 6899b843a76b999aab785570052af6a1
+;
+; Pipeline Runtime Information: 
+;
+; Pixel Shader
+; DepthOutput=0
+; SampleFrequency=0
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; TEXCOORD                 1                 linear       
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_Target                0                              
+;
+; Buffer Definitions:
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; __13_sampler                      sampler      NA          NA      S0      s0,space2     1
+; _13                               texture     f32          2d      T0      t0,space2     1
+;
+;
+; ViewId state:
+;
+; Number of inputs: 6, outputs: 4
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 0, 4, 5 }
+;   output 1 depends on inputs: { 1, 4, 5 }
+;   output 2 depends on inputs: { 2, 4, 5 }
+;   output 3 depends on inputs: { 3 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+%dx.types.Handle = type { i8* }
+%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
+%"class.Texture2D<vector<float, 4> >" = type { <4 x float>, %"class.Texture2D<vector<float, 4> >::mips_type" }
+%"class.Texture2D<vector<float, 4> >::mips_type" = type { i32 }
+%struct.SamplerState = type { i32 }
+
+define void @main() {
+  %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %3 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %6 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %7 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 2, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %8 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 3, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %9 = call %dx.types.ResRet.f32 @dx.op.sample.f32(i32 60, %dx.types.Handle %1, %dx.types.Handle %2, float %3, float %4, float undef, float undef, i32 0, i32 0, i32 undef, float undef)  ; Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp)
+  %10 = extractvalue %dx.types.ResRet.f32 %9, 0
+  %11 = extractvalue %dx.types.ResRet.f32 %9, 1
+  %12 = extractvalue %dx.types.ResRet.f32 %9, 2
+  %13 = fmul fast float %10, %5
+  %14 = fmul fast float %11, %6
+  %15 = fmul fast float %12, %7
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %13)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %14)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %15)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %8)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+; Function Attrs: nounwind readonly
+declare %dx.types.ResRet.f32 @dx.op.sample.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.resources = !{!4}
+!dx.viewIdState = !{!10}
+!dx.entryPoints = !{!11}
+
+!0 = !{!"dxc(private) 1.8.0.4662 (416fab6b5)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 8}
+!3 = !{!"ps", i32 6, i32 0}
+!4 = !{!5, null, null, !8}
+!5 = !{!6}
+!6 = !{i32 0, %"class.Texture2D<vector<float, 4> >"* undef, !"", i32 2, i32 0, i32 1, i32 2, i32 0, !7}
+!7 = !{i32 0, i32 9}
+!8 = !{!9}
+!9 = !{i32 0, %struct.SamplerState* undef, !"", i32 2, i32 0, i32 1, i32 0, null}
+!10 = !{[8 x i32] [i32 6, i32 4, i32 1, i32 2, i32 4, i32 8, i32 7, i32 7]}
+!11 = !{void ()* @main, !"main", !12, !4, null}
+!12 = !{!13, !20, null}
+!13 = !{!14, !17}
+!14 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !15, i8 2, i32 1, i8 4, i32 0, i8 0, !16}
+!15 = !{i32 0}
+!16 = !{i32 3, i32 15}
+!17 = !{i32 1, !"TEXCOORD", i8 9, i8 0, !18, i8 2, i32 1, i8 2, i32 1, i8 0, !19}
+!18 = !{i32 1}
+!19 = !{i32 3, i32 3}
+!20 = !{!21}
+!21 = !{i32 0, !"SV_Target", i8 9, i8 16, !15, i8 0, i32 1, i8 4, i32 0, i8 0, !16}
+
+#endif
+
+const unsigned char texture_rgb_frag_sm60_dxil[] = {
+  0x44, 0x58, 0x42, 0x43, 0x80, 0x0c, 0x49, 0xdc, 0x1e, 0x21, 0x6f, 0xab,
+  0x8e, 0x0c, 0x74, 0xde, 0x47, 0xb3, 0x50, 0xf3, 0x01, 0x00, 0x00, 0x00,
+  0x1c, 0x0f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00,
+  0xd8, 0x01, 0x00, 0x00, 0x38, 0x08, 0x00, 0x00, 0x54, 0x08, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x54, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x00,
+  0x4f, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x00, 0x00,
+  0x50, 0x53, 0x56, 0x30, 0xec, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52,
+  0x44, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x6d,
+  0x61, 0x69, 0x6e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x00, 0x03, 0x02, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x42, 0x00,
+  0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x44, 0x10, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0x58, 0x06, 0x00, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x96, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c,
+  0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00,
+  0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x00,
+  0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39,
+  0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
+  0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14,
+  0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20,
+  0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90,
+  0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a,
+  0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d,
+  0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06,
+  0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x68, 0x23, 0x00, 0x25, 0x00, 0x14, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x20, 0x84, 0x14,
+  0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1, 0x9b, 0x86, 0xcb, 0x9f,
+  0xb0, 0x87, 0x90, 0xfc, 0x95, 0x90, 0x56, 0x62, 0xf2, 0x8b, 0xdb, 0x46,
+  0xc5, 0x18, 0x63, 0x10, 0x2a, 0xf7, 0x0c, 0x97, 0x3f, 0x61, 0x0f, 0x21,
+  0xf9, 0x21, 0xd0, 0x0c, 0x0b, 0x81, 0x82, 0x55, 0x18, 0x45, 0x18, 0x1b,
+  0x63, 0x0c, 0x42, 0xc8, 0xa0, 0x36, 0x47, 0x10, 0x14, 0x83, 0x91, 0x42,
+  0xc8, 0x23, 0x38, 0x10, 0x30, 0x8c, 0x40, 0x0c, 0x33, 0xb5, 0xc1, 0x38,
+  0xb0, 0x43, 0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, 0x94, 0x03, 0x3e,
+  0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39, 0xc8, 0x01, 0x29, 0xf0, 0x81, 0x3d,
+  0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, 0x03, 0x3b,
+  0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, 0x01, 0x18,
+  0xf8, 0x81, 0x1e, 0xe8, 0x41, 0x3b, 0xa4, 0x03, 0x3c, 0xcc, 0xc3, 0x2f,
+  0xd0, 0x43, 0x3e, 0xc0, 0x43, 0x39, 0xa0, 0x80, 0xcc, 0x24, 0x06, 0xe3,
+  0xc0, 0x0e, 0xe1, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xb4, 0x50, 0x0e, 0xf8,
+  0x40, 0x0f, 0xf5, 0x20, 0x0f, 0xe5, 0x20, 0x07, 0xa4, 0xc0, 0x07, 0xf6,
+  0x50, 0x0e, 0xe3, 0x40, 0x0f, 0xef, 0x20, 0x0f, 0x7c, 0x60, 0x0e, 0xec,
+  0xf0, 0x0e, 0xe1, 0x40, 0x0f, 0x6c, 0x00, 0x06, 0x74, 0xe0, 0x07, 0x60,
+  0xe0, 0x07, 0x48, 0x98, 0x94, 0xea, 0x4d, 0xd2, 0x14, 0x51, 0xc2, 0xe4,
+  0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, 0x80, 0xd0,
+  0x4d, 0x04, 0x02, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87,
+  0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50,
+  0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10,
+  0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e,
+  0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86,
+  0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x20, 0x0b, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47,
+  0xc6, 0x04, 0x43, 0x22, 0x25, 0x30, 0x02, 0x50, 0x0c, 0x45, 0x50, 0x12,
+  0x65, 0x50, 0x1e, 0x85, 0x52, 0x08, 0x54, 0x4a, 0x62, 0x04, 0xa0, 0x08,
+  0x0a, 0xa1, 0x40, 0xc8, 0xce, 0x00, 0x10, 0x9e, 0x01, 0xa0, 0x3c, 0x16,
+  0x62, 0x10, 0x81, 0x40, 0x20, 0xc7, 0x01, 0x00, 0x79, 0x18, 0x00, 0x00,
+  0x7b, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4,
+  0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b, 0xb3, 0x0b, 0xa3, 0x2b,
+  0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb1, 0xb1, 0x91,
+  0x01, 0x41, 0xa1, 0x89, 0xb1, 0x31, 0x0b, 0x13, 0xb3, 0x11, 0xab, 0x49,
+  0xd9, 0x10, 0x04, 0x13, 0x04, 0xa2, 0x98, 0x20, 0x10, 0xc6, 0x06, 0x61,
+  0x20, 0x36, 0x08, 0x04, 0x41, 0x01, 0x6e, 0x6e, 0x82, 0x40, 0x1c, 0x1b,
+  0x86, 0x03, 0x21, 0x26, 0x08, 0xd6, 0xc4, 0xe1, 0x2b, 0x66, 0x66, 0x82,
+  0x40, 0x20, 0x13, 0x04, 0x22, 0xd9, 0x20, 0x10, 0xcd, 0x86, 0x84, 0x50,
+  0x16, 0x86, 0x18, 0x18, 0xc2, 0xd9, 0x10, 0x3c, 0x13, 0x04, 0x8c, 0x22,
+  0xf3, 0xf5, 0x15, 0x33, 0xf3, 0x35, 0x17, 0xd6, 0x06, 0xc7, 0x56, 0x26,
+  0xb7, 0x01, 0x21, 0x22, 0x89, 0x21, 0x06, 0x02, 0xd8, 0x10, 0x4c, 0x1b,
+  0x08, 0x08, 0x00, 0xa8, 0x09, 0x82, 0x00, 0x6c, 0x00, 0x36, 0x0c, 0xc4,
+  0x75, 0x6d, 0x08, 0xb0, 0x0d, 0xc3, 0x60, 0x65, 0x13, 0x84, 0xac, 0xda,
+  0x10, 0x6c, 0x24, 0xda, 0xc2, 0xd2, 0xdc, 0x88, 0x50, 0x15, 0x61, 0x0d,
+  0x3d, 0x3d, 0x49, 0x11, 0x4d, 0x10, 0x0a, 0x67, 0x82, 0x50, 0x3c, 0x1b,
+  0x02, 0x62, 0x82, 0x50, 0x40, 0x13, 0x84, 0x22, 0x9a, 0x20, 0x10, 0xca,
+  0x04, 0x81, 0x58, 0x36, 0x08, 0x64, 0x50, 0x06, 0x1b, 0x16, 0xc2, 0xfb,
+  0xc0, 0x20, 0x0c, 0xc4, 0x60, 0x18, 0x03, 0x02, 0x0c, 0xcc, 0x60, 0x43,
+  0x30, 0x6c, 0x10, 0xc8, 0x80, 0x0c, 0x36, 0x2c, 0x83, 0xf7, 0x81, 0x01,
+  0x1a, 0x88, 0xc1, 0x20, 0x06, 0x03, 0x18, 0xa4, 0xc1, 0x06, 0xe1, 0x0c,
+  0xd4, 0x80, 0xc9, 0x94, 0xd5, 0x17, 0x55, 0x98, 0xdc, 0x59, 0x19, 0xdd,
+  0x04, 0xa1, 0x90, 0x36, 0x2c, 0x04, 0x1b, 0x7c, 0x6d, 0x10, 0x06, 0x60,
+  0x30, 0x8c, 0x01, 0x01, 0x06, 0x66, 0xb0, 0x21, 0x70, 0x83, 0x0d, 0xc3,
+  0x1a, 0xbc, 0x01, 0xb0, 0xa1, 0xb0, 0x3a, 0x38, 0xa8, 0x00, 0x1a, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x73, 0x2c, 0xd2, 0xdc, 0xe6, 0xe8, 0xe6, 0x26,
+  0x08, 0x04, 0x43, 0x63, 0x2e, 0xed, 0xec, 0x8b, 0x8d, 0x8c, 0xc6, 0x5c,
+  0xda, 0xd9, 0xd7, 0x1c, 0xdd, 0x04, 0x81, 0x68, 0x88, 0xd0, 0x95, 0xe1,
+  0x7d, 0xb9, 0xbd, 0xc9, 0xb5, 0x6d, 0x50, 0xe4, 0x80, 0x0c, 0xe6, 0x80,
+  0x0e, 0xea, 0x00, 0xb1, 0x83, 0x3b, 0xc0, 0x83, 0xa1, 0x0a, 0x1b, 0x9b,
+  0x5d, 0x9b, 0x4b, 0x1a, 0x59, 0x99, 0x1b, 0xdd, 0x94, 0x20, 0xa8, 0x42,
+  0x86, 0xe7, 0x62, 0x57, 0x26, 0x37, 0x97, 0xf6, 0xe6, 0x36, 0x25, 0x20,
+  0x9a, 0x90, 0xe1, 0xb9, 0xd8, 0x85, 0xb1, 0xd9, 0x95, 0xc9, 0x4d, 0x09,
+  0x8a, 0x3a, 0x64, 0x78, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x4d,
+  0x6f, 0x64, 0x65, 0x6c, 0x53, 0x02, 0xa4, 0x0c, 0x19, 0x9e, 0x8b, 0x5c,
+  0xd9, 0xdc, 0x5b, 0x9d, 0xdc, 0x58, 0xd9, 0xdc, 0x94, 0x80, 0xaa, 0x44,
+  0x86, 0xe7, 0x42, 0x97, 0x07, 0x57, 0x16, 0xe4, 0xe6, 0xf6, 0x46, 0x17,
+  0x46, 0x97, 0xf6, 0xe6, 0x36, 0x37, 0x25, 0xc8, 0xea, 0x90, 0xe1, 0xb9,
+  0xd8, 0xa5, 0x95, 0xdd, 0x25, 0x91, 0x4d, 0xd1, 0x85, 0xd1, 0x95, 0x4d,
+  0x09, 0xb6, 0x3a, 0x64, 0x78, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50,
+  0x6f, 0x69, 0x6e, 0x74, 0x73, 0x53, 0x02, 0x38, 0xe8, 0x42, 0x86, 0xe7,
+  0x32, 0xf6, 0x56, 0xe7, 0x46, 0x57, 0x26, 0x37, 0x37, 0x25, 0xc0, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88,
+  0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73,
+  0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e,
+  0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30,
+  0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8,
+  0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b,
+  0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76,
+  0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e,
+  0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e,
+  0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61,
+  0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4,
+  0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37,
+  0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76,
+  0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71,
+  0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e,
+  0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61,
+  0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8,
+  0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc,
+  0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x8c, 0xc8,
+  0x21, 0x07, 0x7c, 0x70, 0x03, 0x72, 0x10, 0x87, 0x73, 0x70, 0x03, 0x7b,
+  0x08, 0x07, 0x79, 0x60, 0x87, 0x70, 0xc8, 0x87, 0x77, 0xa8, 0x07, 0x7a,
+  0x98, 0x81, 0x3c, 0xe4, 0x80, 0x0f, 0x6e, 0x40, 0x0f, 0xe5, 0xd0, 0x0e,
+  0xf0, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x46, 0x20, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x10, 0x11, 0xc0, 0x44, 0x84,
+  0x40, 0x33, 0x2c, 0x84, 0x05, 0x4c, 0xc3, 0xe5, 0x3b, 0x8f, 0xbf, 0x38,
+  0xc0, 0x20, 0x36, 0x0f, 0x35, 0xf9, 0xc5, 0x6d, 0xdb, 0x00, 0x34, 0x5c,
+  0xbe, 0xf3, 0xf8, 0x12, 0xc0, 0x3c, 0x0b, 0xe1, 0x17, 0xb7, 0x6d, 0x02,
+  0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d,
+  0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x00, 0x04, 0x03, 0x20, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x68, 0x99, 0xb8, 0x43, 0xa7, 0x6b, 0x99, 0x9a,
+  0xab, 0x78, 0x55, 0x70, 0x05, 0x2a, 0xf6, 0xa1, 0x44, 0x58, 0x49, 0x4c,
+  0xc0, 0x06, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
+  0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0xa8, 0x06, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00,
+  0xa7, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88,
+  0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42,
+  0xe4, 0x48, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c,
+  0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07,
+  0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20,
+  0x6d, 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42,
+  0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00,
+  0x43, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04,
+  0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14,
+  0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x68, 0x23, 0x00,
+  0x25, 0x00, 0x14, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29,
+  0xc6, 0x20, 0x84, 0x14, 0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1,
+  0x9b, 0x86, 0xcb, 0x9f, 0xb0, 0x87, 0x90, 0xfc, 0x95, 0x90, 0x56, 0x62,
+  0xf2, 0x8b, 0xdb, 0x46, 0xc5, 0x18, 0x63, 0x10, 0x2a, 0xf7, 0x0c, 0x97,
+  0x3f, 0x61, 0x0f, 0x21, 0xf9, 0x21, 0xd0, 0x0c, 0x0b, 0x81, 0x82, 0x55,
+  0x18, 0x45, 0x18, 0x1b, 0x63, 0x0c, 0x42, 0xc8, 0xa0, 0x36, 0x47, 0x10,
+  0x14, 0x83, 0x91, 0x42, 0xc8, 0x23, 0x38, 0x10, 0x30, 0x8c, 0x40, 0x0c,
+  0x33, 0xb5, 0xc1, 0x38, 0xb0, 0x43, 0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01,
+  0x2d, 0x94, 0x03, 0x3e, 0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39, 0xc8, 0x01,
+  0x29, 0xf0, 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03,
+  0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01,
+  0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x81, 0x1e, 0xe8, 0x41, 0x3b, 0xa4, 0x03,
+  0x3c, 0xcc, 0xc3, 0x2f, 0xd0, 0x43, 0x3e, 0xc0, 0x43, 0x39, 0xa0, 0x80,
+  0xcc, 0x24, 0x06, 0xe3, 0xc0, 0x0e, 0xe1, 0x30, 0x0f, 0xf3, 0xe0, 0x06,
+  0xb4, 0x50, 0x0e, 0xf8, 0x40, 0x0f, 0xf5, 0x20, 0x0f, 0xe5, 0x20, 0x07,
+  0xa4, 0xc0, 0x07, 0xf6, 0x50, 0x0e, 0xe3, 0x40, 0x0f, 0xef, 0x20, 0x0f,
+  0x7c, 0x60, 0x0e, 0xec, 0xf0, 0x0e, 0xe1, 0x40, 0x0f, 0x6c, 0x00, 0x06,
+  0x74, 0xe0, 0x07, 0x60, 0xe0, 0x07, 0x48, 0x98, 0x94, 0xea, 0x4d, 0xd2,
+  0x14, 0x51, 0xc2, 0xe4, 0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0,
+  0x44, 0xa0, 0x80, 0xd0, 0x4d, 0x04, 0x02, 0x00, 0x13, 0x14, 0x72, 0xc0,
+  0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0,
+  0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d,
+  0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78,
+  0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0b, 0x04, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90,
+  0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x25, 0x30, 0x02, 0x50,
+  0x10, 0xc5, 0x50, 0x04, 0x25, 0x51, 0x06, 0xe5, 0x41, 0xa5, 0x24, 0x46,
+  0x00, 0x8a, 0xa0, 0x10, 0x0a, 0x84, 0xec, 0x0c, 0x00, 0xe1, 0x19, 0x00,
+  0xca, 0x63, 0x21, 0x06, 0x11, 0x08, 0x04, 0x72, 0x1c, 0x00, 0x00, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90,
+  0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b,
+  0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71,
+  0xa1, 0xb1, 0xb1, 0x91, 0x01, 0x41, 0xa1, 0x89, 0xb1, 0x31, 0x0b, 0x13,
+  0xb3, 0x11, 0xab, 0x49, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xa2, 0x98, 0x20,
+  0x10, 0xc6, 0x06, 0x61, 0x20, 0x26, 0x08, 0xc4, 0xb1, 0x41, 0x18, 0x0c,
+  0x0a, 0x70, 0x73, 0x13, 0x04, 0x02, 0xd9, 0x30, 0x20, 0x09, 0x31, 0x41,
+  0xb0, 0x24, 0x02, 0x13, 0x04, 0x22, 0x99, 0x20, 0x10, 0xca, 0x06, 0x81,
+  0x70, 0x36, 0x24, 0xc4, 0xc2, 0x34, 0xc4, 0xd0, 0x10, 0xcf, 0x86, 0x00,
+  0x9a, 0x20, 0x60, 0xd3, 0x06, 0x84, 0x90, 0x98, 0x86, 0x18, 0x08, 0x60,
+  0x43, 0x30, 0x6d, 0x20, 0x22, 0x00, 0xa0, 0x26, 0x08, 0x19, 0xb5, 0x21,
+  0xb0, 0x26, 0x08, 0x02, 0x40, 0xa2, 0x2d, 0x2c, 0xcd, 0x8d, 0x08, 0x55,
+  0x11, 0xd6, 0xd0, 0xd3, 0x93, 0x14, 0xd1, 0x04, 0xa1, 0x68, 0x26, 0x08,
+  0x85, 0xb3, 0x21, 0x20, 0x26, 0x08, 0xc5, 0x33, 0x41, 0x28, 0xa0, 0x09,
+  0x02, 0xb1, 0x4c, 0x10, 0x08, 0x66, 0x83, 0x00, 0x06, 0x61, 0xb0, 0x61,
+  0x21, 0xb4, 0x8d, 0xeb, 0xbc, 0xe1, 0x23, 0x38, 0x31, 0xd8, 0x10, 0x0c,
+  0x1b, 0x04, 0x30, 0x00, 0x83, 0x0d, 0xcb, 0xa0, 0x6d, 0x1c, 0x19, 0x78,
+  0x83, 0x37, 0x70, 0x65, 0xb0, 0x41, 0x18, 0x03, 0x33, 0x60, 0x32, 0x65,
+  0xf5, 0x45, 0x15, 0x26, 0x77, 0x56, 0x46, 0x37, 0x41, 0x28, 0xa2, 0x0d,
+  0x0b, 0x81, 0x06, 0x5b, 0x1a, 0x74, 0xdc, 0xf0, 0x11, 0x9c, 0x18, 0x6c,
+  0x08, 0xd4, 0x60, 0xc3, 0x70, 0x06, 0x6b, 0x00, 0x6c, 0x28, 0xb0, 0x8c,
+  0x0d, 0x2a, 0xa0, 0x0a, 0x1b, 0x9b, 0x5d, 0x9b, 0x4b, 0x1a, 0x59, 0x99,
+  0x1b, 0xdd, 0x94, 0x20, 0xa8, 0x42, 0x86, 0xe7, 0x62, 0x57, 0x26, 0x37,
+  0x97, 0xf6, 0xe6, 0x36, 0x25, 0x20, 0x9a, 0x90, 0xe1, 0xb9, 0xd8, 0x85,
+  0xb1, 0xd9, 0x95, 0xc9, 0x4d, 0x09, 0x8c, 0x3a, 0x64, 0x78, 0x2e, 0x73,
+  0x68, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x53, 0x82,
+  0xa4, 0x0c, 0x19, 0x9e, 0x8b, 0x5c, 0xd9, 0xdc, 0x5b, 0x9d, 0xdc, 0x58,
+  0xd9, 0xdc, 0x94, 0x80, 0xaa, 0x43, 0x86, 0xe7, 0x62, 0x97, 0x56, 0x76,
+  0x97, 0x44, 0x36, 0x45, 0x17, 0x46, 0x57, 0x36, 0x25, 0xb0, 0xea, 0x90,
+  0xe1, 0xb9, 0x94, 0xb9, 0xd1, 0xc9, 0xe5, 0x41, 0xbd, 0xa5, 0xb9, 0xd1,
+  0xcd, 0x4d, 0x09, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66,
+  0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10,
+  0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce,
+  0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b,
+  0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c,
+  0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07,
+  0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11,
+  0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0,
+  0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8,
+  0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b,
+  0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b,
+  0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87,
+  0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07,
+  0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87,
+  0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81,
+  0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30,
+  0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca,
+  0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b,
+  0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b,
+  0xb0, 0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x72, 0x10, 0x87,
+  0x73, 0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60, 0x87, 0x70, 0xc8, 0x87,
+  0x77, 0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4, 0x80, 0x0f, 0x6e, 0x40,
+  0x0f, 0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x46, 0x20, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x10,
+  0x11, 0xc0, 0x44, 0x84, 0x40, 0x33, 0x2c, 0x84, 0x05, 0x4c, 0xc3, 0xe5,
+  0x3b, 0x8f, 0xbf, 0x38, 0xc0, 0x20, 0x36, 0x0f, 0x35, 0xf9, 0xc5, 0x6d,
+  0xdb, 0x00, 0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x12, 0xc0, 0x3c, 0x0b, 0xe1,
+  0x17, 0xb7, 0x6d, 0x02, 0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13,
+  0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x00, 0x04, 0x03,
+  0x20, 0x0d, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00,
+  0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0xf4, 0x46, 0x00, 0x88, 0xcc, 0x00, 0x14, 0x42, 0x29, 0x94, 0x5c, 0xe1,
+  0x51, 0x29, 0x83, 0x12, 0xa0, 0x31, 0x03, 0x00, 0x23, 0x06, 0x09, 0x00,
+  0x82, 0x60, 0x00, 0x69, 0x05, 0x84, 0x61, 0xc9, 0x88, 0x41, 0x02, 0x80,
+  0x20, 0x18, 0x40, 0x9b, 0x41, 0x64, 0x99, 0x32, 0x62, 0x90, 0x00, 0x20,
+  0x08, 0x06, 0xc6, 0x97, 0x6c, 0x9a, 0xa4, 0x8c, 0x18, 0x24, 0x00, 0x08,
+  0x82, 0x81, 0x01, 0x06, 0x0a, 0xb7, 0x15, 0xcb, 0x88, 0x41, 0x02, 0x80,
+  0x20, 0x18, 0x18, 0x61, 0xb0, 0x70, 0x1c, 0xc5, 0x8c, 0x18, 0x24, 0x00,
+  0x08, 0x82, 0x81, 0x21, 0x06, 0x4c, 0xd7, 0x1d, 0xcd, 0x88, 0x41, 0x02,
+  0x80, 0x20, 0x18, 0x18, 0x63, 0xd0, 0x78, 0x5e, 0xe5, 0x8c, 0x18, 0x24,
+  0x00, 0x08, 0x82, 0x81, 0x41, 0x06, 0xce, 0xf7, 0x29, 0xcf, 0x88, 0xc1,
+  0x03, 0x80, 0x20, 0x18, 0x34, 0x63, 0xc0, 0x20, 0x87, 0x51, 0x24, 0x09,
+  0x18, 0x80, 0x01, 0x94, 0x8c, 0x26, 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c,
+  0x26, 0x0c, 0x82, 0x0d, 0x88, 0x7c, 0x6c, 0x40, 0xe4, 0x63, 0x03, 0x22,
+  0x9f, 0x11, 0x83, 0x04, 0x00, 0x41, 0x30, 0x40, 0xd6, 0xa0, 0x3a, 0x83,
+  0x33, 0xf8, 0x86, 0x11, 0x83, 0x04, 0x00, 0x41, 0x30, 0x40, 0xd6, 0xa0,
+  0x3a, 0x83, 0x33, 0x88, 0x84, 0x11, 0x83, 0x04, 0x00, 0x41, 0x30, 0x40,
+  0xd6, 0xa0, 0x3a, 0x83, 0x33, 0xf0, 0x82, 0x11, 0x83, 0x04, 0x00, 0x41,
+  0x30, 0x40, 0xd6, 0xa0, 0x3a, 0x83, 0x33, 0x90, 0x10, 0x04, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00
+};

+ 59 - 0
src/render/sdlgpu/shaders/texture_rgb.frag.spv.h

@@ -0,0 +1,59 @@
+const unsigned char texture_rgb_frag_spv[] = {
+  0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00,
+  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x3f, 0x20, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x1b, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x57, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+};
+const unsigned int texture_rgb_frag_spv_len = 668;

+ 12 - 0
src/render/sdlgpu/shaders/texture_rgba.frag

@@ -0,0 +1,12 @@
+#version 450
+
+layout(location = 0) in vec4 v_color;
+layout(location = 1) in vec2 v_uv;
+
+layout(set = 2, binding = 0) uniform sampler2D u_texture;
+
+layout(location = 0) out vec4 o_color;
+
+void main() {
+    o_color = texture(u_texture, v_uv) * v_color;
+}

+ 40 - 0
src/render/sdlgpu/shaders/texture_rgba.frag.metal.h

@@ -0,0 +1,40 @@
+const unsigned char texture_rgba_frag_metal[] = {
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65,
+  0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a,
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 0x69,
+  0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a,
+  0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+  0x61, 0x63, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a,
+  0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30,
+  0x5f, 0x6f, 0x75, 0x74, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6d, 0x5f, 0x39, 0x20, 0x5b, 0x5b,
+  0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a,
+  0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6d,
+  0x61, 0x69, 0x6e, 0x30, 0x5f, 0x69, 0x6e, 0x0a, 0x7b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6d, 0x5f, 0x32,
+  0x31, 0x20, 0x5b, 0x5b, 0x75, 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63,
+  0x6e, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6d, 0x5f, 0x31, 0x37, 0x20, 0x5b,
+  0x5b, 0x75, 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x31, 0x29,
+  0x5d, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x66, 0x72, 0x61, 0x67,
+  0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x6f,
+  0x75, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x28, 0x6d, 0x61, 0x69,
+  0x6e, 0x30, 0x5f, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x5b, 0x73,
+  0x74, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x5d, 0x5d, 0x2c, 0x20, 0x74,
+  0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x64, 0x3c, 0x66, 0x6c, 0x6f,
+  0x61, 0x74, 0x3e, 0x20, 0x5f, 0x31, 0x33, 0x20, 0x5b, 0x5b, 0x74, 0x65,
+  0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x2c, 0x20,
+  0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x20, 0x5f, 0x31, 0x33, 0x53,
+  0x6d, 0x70, 0x6c, 0x72, 0x20, 0x5b, 0x5b, 0x73, 0x61, 0x6d, 0x70, 0x6c,
+  0x65, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x29, 0x0a, 0x7b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x6f, 0x75, 0x74,
+  0x20, 0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x6d, 0x5f, 0x39, 0x20, 0x3d,
+  0x20, 0x5f, 0x31, 0x33, 0x2e, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x28,
+  0x5f, 0x31, 0x33, 0x53, 0x6d, 0x70, 0x6c, 0x72, 0x2c, 0x20, 0x69, 0x6e,
+  0x2e, 0x6d, 0x5f, 0x31, 0x37, 0x29, 0x20, 0x2a, 0x20, 0x69, 0x6e, 0x2e,
+  0x6d, 0x5f, 0x32, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
+  0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a,
+  0x0a
+};
+const unsigned int texture_rgba_frag_metal_len = 433;

+ 120 - 0
src/render/sdlgpu/shaders/texture_rgba.frag.sm50.dxbc.h

@@ -0,0 +1,120 @@
+const unsigned char texture_rgba_frag_sm50_dxbc[] =
+{
+  68,  88,  66,  67, -83, 124,
+  -3, -84,-102, 126,  29, -62,
+-107,  79, -74,  72,  -7,  33,
+ 124,-103,   1,   0,   0,   0,
+ -72,   2,   0,   0,   5,   0,
+   0,   0,  52,   0,   0,   0,
+ -12,   0,   0,   0,  64,   1,
+   0,   0, 116,   1,   0,   0,
+  28,   2,   0,   0,  82,  68,
+  69,  70, -72,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   2,   0,   0,   0,
+  60,   0,   0,   0,   0,   5,
+  -1,  -1,   0,   1,   0,   0,
+-115,   0,   0,   0,  82,  68,
+  49,  49,  60,   0,   0,   0,
+  24,   0,   0,   0,  32,   0,
+   0,   0,  40,   0,   0,   0,
+  36,   0,   0,   0,  12,   0,
+   0,   0,   0,   0,   0,   0,
+ 124,   0,   0,   0,   3,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   1,   0,
+   0,   0,-119,   0,   0,   0,
+   2,   0,   0,   0,   5,   0,
+   0,   0,   4,   0,   0,   0,
+  -1,  -1,  -1,  -1,   0,   0,
+   0,   0,   1,   0,   0,   0,
+  13,   0,   0,   0,  95,  95,
+  49,  51,  95, 115,  97, 109,
+ 112, 108, 101, 114,   0,  95,
+  49,  51,   0,  77, 105,  99,
+ 114, 111, 115, 111, 102, 116,
+  32,  40,  82,  41,  32,  72,
+  76,  83,  76,  32,  83, 104,
+  97, 100, 101, 114,  32,  67,
+ 111, 109, 112, 105, 108, 101,
+ 114,  32,  49,  48,  46,  49,
+   0, -85, -85, -85,  73,  83,
+  71,  78,  68,   0,   0,   0,
+   2,   0,   0,   0,   8,   0,
+   0,   0,  56,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   3,   0,   0,   0,
+   0,   0,   0,   0,  15,  15,
+   0,   0,  56,   0,   0,   0,
+   1,   0,   0,   0,   0,   0,
+   0,   0,   3,   0,   0,   0,
+   1,   0,   0,   0,   3,   3,
+   0,   0,  84,  69,  88,  67,
+  79,  79,  82,  68,   0, -85,
+ -85, -85,  79,  83,  71,  78,
+  44,   0,   0,   0,   1,   0,
+   0,   0,   8,   0,   0,   0,
+  32,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,   0,   0,
+   0,   0,  15,   0,   0,   0,
+  83,  86,  95,  84,  97, 114,
+ 103, 101, 116,   0, -85, -85,
+  83,  72,  69,  88, -96,   0,
+   0,   0,  80,   0,   0,   0,
+  40,   0,   0,   0, 106,   8,
+   0,   1,  90,   0,   0,   3,
+   0,  96,  16,   0,   0,   0,
+   0,   0,  88,  24,   0,   4,
+   0, 112,  16,   0,   0,   0,
+   0,   0,  85,  85,   0,   0,
+  98,  16,   0,   3, -14,  16,
+  16,   0,   0,   0,   0,   0,
+  98,  16,   0,   3,  50,  16,
+  16,   0,   1,   0,   0,   0,
+ 101,   0,   0,   3, -14,  32,
+  16,   0,   0,   0,   0,   0,
+ 104,   0,   0,   2,   1,   0,
+   0,   0,  69,   0,   0,-117,
+ -62,   0,   0,-128,  67,  85,
+  21,   0, -14,   0,  16,   0,
+   0,   0,   0,   0,  70,  16,
+  16,   0,   1,   0,   0,   0,
+  70, 126,  16,   0,   0,   0,
+   0,   0,   0,  96,  16,   0,
+   0,   0,   0,   0,  56,   0,
+   0,   7, -14,  32,  16,   0,
+   0,   0,   0,   0,  70,  14,
+  16,   0,   0,   0,   0,   0,
+  70,  30,  16,   0,   0,   0,
+   0,   0,  62,   0,   0,   1,
+  83,  84,  65,  84,-108,   0,
+   0,   0,   3,   0,   0,   0,
+   1,   0,   0,   0,   0,   0,
+   0,   0,   3,   0,   0,   0,
+   1,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   1,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0
+
+};

+ 467 - 0
src/render/sdlgpu/shaders/texture_rgba.frag.sm60.dxil.h

@@ -0,0 +1,467 @@
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xyzw        0     NONE   float   xyzw
+; TEXCOORD                 1   xy          1     NONE   float   xy  
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_Target                0   xyzw        0   TARGET   float   xyzw
+;
+; shader hash: ab99026f3068b3314341ba15eaf626a8
+;
+; Pipeline Runtime Information: 
+;
+; Pixel Shader
+; DepthOutput=0
+; SampleFrequency=0
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; TEXCOORD                 1                 linear       
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_Target                0                              
+;
+; Buffer Definitions:
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; __13_sampler                      sampler      NA          NA      S0      s0,space2     1
+; _13                               texture     f32          2d      T0      t0,space2     1
+;
+;
+; ViewId state:
+;
+; Number of inputs: 6, outputs: 4
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 0, 4, 5 }
+;   output 1 depends on inputs: { 1, 4, 5 }
+;   output 2 depends on inputs: { 2, 4, 5 }
+;   output 3 depends on inputs: { 3, 4, 5 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+%dx.types.Handle = type { i8* }
+%dx.types.ResRet.f32 = type { float, float, float, float, i32 }
+%"class.Texture2D<vector<float, 4> >" = type { <4 x float>, %"class.Texture2D<vector<float, 4> >::mips_type" }
+%"class.Texture2D<vector<float, 4> >::mips_type" = type { i32 }
+%struct.SamplerState = type { i32 }
+
+define void @main() {
+  %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %3 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %6 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %7 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 2, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %8 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 3, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %9 = call %dx.types.ResRet.f32 @dx.op.sample.f32(i32 60, %dx.types.Handle %1, %dx.types.Handle %2, float %3, float %4, float undef, float undef, i32 0, i32 0, i32 undef, float undef)  ; Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp)
+  %10 = extractvalue %dx.types.ResRet.f32 %9, 0
+  %11 = extractvalue %dx.types.ResRet.f32 %9, 1
+  %12 = extractvalue %dx.types.ResRet.f32 %9, 2
+  %13 = extractvalue %dx.types.ResRet.f32 %9, 3
+  %14 = fmul fast float %10, %5
+  %15 = fmul fast float %11, %6
+  %16 = fmul fast float %12, %7
+  %17 = fmul fast float %13, %8
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %14)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %15)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %16)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %17)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+; Function Attrs: nounwind readonly
+declare %dx.types.ResRet.f32 @dx.op.sample.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.resources = !{!4}
+!dx.viewIdState = !{!10}
+!dx.entryPoints = !{!11}
+
+!0 = !{!"dxc(private) 1.8.0.4662 (416fab6b5)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 8}
+!3 = !{!"ps", i32 6, i32 0}
+!4 = !{!5, null, null, !8}
+!5 = !{!6}
+!6 = !{i32 0, %"class.Texture2D<vector<float, 4> >"* undef, !"", i32 2, i32 0, i32 1, i32 2, i32 0, !7}
+!7 = !{i32 0, i32 9}
+!8 = !{!9}
+!9 = !{i32 0, %struct.SamplerState* undef, !"", i32 2, i32 0, i32 1, i32 0, null}
+!10 = !{[8 x i32] [i32 6, i32 4, i32 1, i32 2, i32 4, i32 8, i32 15, i32 15]}
+!11 = !{void ()* @main, !"main", !12, !4, null}
+!12 = !{!13, !20, null}
+!13 = !{!14, !17}
+!14 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !15, i8 2, i32 1, i8 4, i32 0, i8 0, !16}
+!15 = !{i32 0}
+!16 = !{i32 3, i32 15}
+!17 = !{i32 1, !"TEXCOORD", i8 9, i8 0, !18, i8 2, i32 1, i8 2, i32 1, i8 0, !19}
+!18 = !{i32 1}
+!19 = !{i32 3, i32 3}
+!20 = !{!21}
+!21 = !{i32 0, !"SV_Target", i8 9, i8 16, !15, i8 0, i32 1, i8 4, i32 0, i8 0, !16}
+
+#endif
+
+const unsigned char texture_rgba_frag_sm60_dxil[] = {
+  0x44, 0x58, 0x42, 0x43, 0x5c, 0x82, 0x6d, 0x45, 0x43, 0x35, 0xdf, 0xf5,
+  0xad, 0xf7, 0x1b, 0x5e, 0xc0, 0x65, 0x38, 0x3f, 0x01, 0x00, 0x00, 0x00,
+  0x24, 0x0f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00,
+  0xd8, 0x01, 0x00, 0x00, 0x38, 0x08, 0x00, 0x00, 0x54, 0x08, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x54, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x00,
+  0x4f, 0x53, 0x47, 0x31, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x00, 0x00,
+  0x50, 0x53, 0x56, 0x30, 0xec, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52,
+  0x44, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x6d,
+  0x61, 0x69, 0x6e, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x00, 0x03, 0x02, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x42, 0x00,
+  0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x44, 0x10, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0x58, 0x06, 0x00, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x96, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c,
+  0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00,
+  0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x8d, 0x01, 0x00, 0x00,
+  0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39,
+  0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
+  0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14,
+  0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20,
+  0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90,
+  0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a,
+  0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d,
+  0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06,
+  0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x68, 0x23, 0x00, 0x25, 0x00, 0x14, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x20, 0x84, 0x14,
+  0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1, 0x9b, 0x86, 0xcb, 0x9f,
+  0xb0, 0x87, 0x90, 0xfc, 0x95, 0x90, 0x56, 0x62, 0xf2, 0x8b, 0xdb, 0x46,
+  0xc5, 0x18, 0x63, 0x10, 0x2a, 0xf7, 0x0c, 0x97, 0x3f, 0x61, 0x0f, 0x21,
+  0xf9, 0x21, 0xd0, 0x0c, 0x0b, 0x81, 0x82, 0x55, 0x18, 0x45, 0x18, 0x1b,
+  0x63, 0x0c, 0x42, 0xc8, 0xa0, 0x36, 0x47, 0x10, 0x14, 0x83, 0x91, 0x42,
+  0xc8, 0x23, 0x38, 0x10, 0x30, 0x8c, 0x40, 0x0c, 0x33, 0xb5, 0xc1, 0x38,
+  0xb0, 0x43, 0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, 0x94, 0x03, 0x3e,
+  0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39, 0xc8, 0x01, 0x29, 0xf0, 0x81, 0x3d,
+  0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, 0x03, 0x3b,
+  0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, 0x01, 0x18,
+  0xf8, 0x81, 0x1e, 0xe8, 0x41, 0x3b, 0xa4, 0x03, 0x3c, 0xcc, 0xc3, 0x2f,
+  0xd0, 0x43, 0x3e, 0xc0, 0x43, 0x39, 0xa0, 0x80, 0xcc, 0x24, 0x06, 0xe3,
+  0xc0, 0x0e, 0xe1, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xb4, 0x50, 0x0e, 0xf8,
+  0x40, 0x0f, 0xf5, 0x20, 0x0f, 0xe5, 0x20, 0x07, 0xa4, 0xc0, 0x07, 0xf6,
+  0x50, 0x0e, 0xe3, 0x40, 0x0f, 0xef, 0x20, 0x0f, 0x7c, 0x60, 0x0e, 0xec,
+  0xf0, 0x0e, 0xe1, 0x40, 0x0f, 0x6c, 0x00, 0x06, 0x74, 0xe0, 0x07, 0x60,
+  0xe0, 0x07, 0x48, 0x98, 0x94, 0xea, 0x4d, 0xd2, 0x14, 0x51, 0xc2, 0xe4,
+  0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, 0x80, 0xd0,
+  0x4d, 0x04, 0x02, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87,
+  0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50,
+  0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0,
+  0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10,
+  0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e,
+  0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86,
+  0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x20, 0x0b, 0x04, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47,
+  0xc6, 0x04, 0x43, 0x22, 0x25, 0x30, 0x02, 0x50, 0x0c, 0x45, 0x50, 0x12,
+  0x65, 0x50, 0x1e, 0x85, 0x50, 0x2c, 0x54, 0x4a, 0x62, 0x04, 0xa0, 0x08,
+  0x0a, 0xa1, 0x40, 0xc8, 0xce, 0x00, 0x10, 0x9e, 0x01, 0xa0, 0x3c, 0x16,
+  0x62, 0x10, 0x81, 0x40, 0x20, 0xcf, 0x03, 0x00, 0x79, 0x18, 0x00, 0x00,
+  0x7b, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4,
+  0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b, 0xb3, 0x0b, 0xa3, 0x2b,
+  0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb1, 0xb1, 0x91,
+  0x01, 0x41, 0xa1, 0x89, 0xb1, 0x31, 0x0b, 0x13, 0xb3, 0x11, 0xab, 0x49,
+  0xd9, 0x10, 0x04, 0x13, 0x04, 0xa2, 0x98, 0x20, 0x10, 0xc6, 0x06, 0x61,
+  0x20, 0x36, 0x08, 0x04, 0x41, 0x01, 0x6e, 0x6e, 0x82, 0x40, 0x1c, 0x1b,
+  0x86, 0x03, 0x21, 0x26, 0x08, 0xd6, 0xc4, 0xe1, 0x2b, 0x66, 0x66, 0x82,
+  0x40, 0x20, 0x13, 0x04, 0x22, 0xd9, 0x20, 0x10, 0xcd, 0x86, 0x84, 0x50,
+  0x16, 0x86, 0x18, 0x18, 0xc2, 0xd9, 0x10, 0x3c, 0x13, 0x04, 0x8c, 0x22,
+  0xf3, 0xf5, 0x15, 0x33, 0xf3, 0x35, 0x17, 0xd6, 0x06, 0xc7, 0x56, 0x26,
+  0xb7, 0x01, 0x21, 0x22, 0x89, 0x21, 0x06, 0x02, 0xd8, 0x10, 0x4c, 0x1b,
+  0x08, 0x08, 0x00, 0xa8, 0x09, 0x82, 0x00, 0x6c, 0x00, 0x36, 0x0c, 0xc4,
+  0x75, 0x6d, 0x08, 0xb0, 0x0d, 0xc3, 0x60, 0x65, 0x13, 0x84, 0xac, 0xda,
+  0x10, 0x6c, 0x24, 0xda, 0xc2, 0xd2, 0xdc, 0x88, 0x50, 0x15, 0x61, 0x0d,
+  0x3d, 0x3d, 0x49, 0x11, 0x4d, 0x10, 0x0a, 0x67, 0x82, 0x50, 0x3c, 0x1b,
+  0x02, 0x62, 0x82, 0x50, 0x40, 0x13, 0x84, 0x22, 0x9a, 0x20, 0x10, 0xca,
+  0x04, 0x81, 0x58, 0x36, 0x08, 0x64, 0x50, 0x06, 0x1b, 0x16, 0xc2, 0xfb,
+  0xc0, 0x20, 0x0c, 0xc4, 0x60, 0x18, 0x03, 0x02, 0x0c, 0xcc, 0x60, 0x43,
+  0x30, 0x6c, 0x10, 0xc8, 0x80, 0x0c, 0x36, 0x2c, 0x83, 0xf7, 0x81, 0x01,
+  0x1a, 0x88, 0xc1, 0x20, 0x06, 0x03, 0x18, 0xa4, 0xc1, 0x06, 0xe1, 0x0c,
+  0xd4, 0x80, 0xc9, 0x94, 0xd5, 0x17, 0x55, 0x98, 0xdc, 0x59, 0x19, 0xdd,
+  0x04, 0xa1, 0x90, 0x36, 0x2c, 0x04, 0x1b, 0x7c, 0x6d, 0x10, 0x06, 0x60,
+  0x30, 0x8c, 0x01, 0x01, 0x06, 0x66, 0xb0, 0x21, 0x70, 0x83, 0x0d, 0xc3,
+  0x1a, 0xbc, 0x01, 0xb0, 0xa1, 0xb0, 0x3a, 0x38, 0xa8, 0x00, 0x1a, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x73, 0x13, 0x04, 0x82, 0x61, 0x91, 0xe6, 0x36,
+  0x47, 0x37, 0x37, 0x41, 0x20, 0x1a, 0x1a, 0x73, 0x69, 0x67, 0x5f, 0x6c,
+  0x64, 0x34, 0xe6, 0xd2, 0xce, 0xbe, 0xe6, 0xe8, 0x88, 0xd0, 0x95, 0xe1,
+  0x7d, 0xb9, 0xbd, 0xc9, 0xb5, 0x6d, 0x50, 0xe4, 0x60, 0x0e, 0xe8, 0xa0,
+  0x0e, 0xec, 0x00, 0xb9, 0x83, 0x39, 0xc0, 0x83, 0xa1, 0x0a, 0x1b, 0x9b,
+  0x5d, 0x9b, 0x4b, 0x1a, 0x59, 0x99, 0x1b, 0xdd, 0x94, 0x20, 0xa8, 0x42,
+  0x86, 0xe7, 0x62, 0x57, 0x26, 0x37, 0x97, 0xf6, 0xe6, 0x36, 0x25, 0x20,
+  0x9a, 0x90, 0xe1, 0xb9, 0xd8, 0x85, 0xb1, 0xd9, 0x95, 0xc9, 0x4d, 0x09,
+  0x8a, 0x3a, 0x64, 0x78, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x65, 0x72, 0x4d,
+  0x6f, 0x64, 0x65, 0x6c, 0x53, 0x02, 0xa4, 0x0c, 0x19, 0x9e, 0x8b, 0x5c,
+  0xd9, 0xdc, 0x5b, 0x9d, 0xdc, 0x58, 0xd9, 0xdc, 0x94, 0x80, 0xaa, 0x44,
+  0x86, 0xe7, 0x42, 0x97, 0x07, 0x57, 0x16, 0xe4, 0xe6, 0xf6, 0x46, 0x17,
+  0x46, 0x97, 0xf6, 0xe6, 0x36, 0x37, 0x25, 0xc8, 0xea, 0x90, 0xe1, 0xb9,
+  0xd8, 0xa5, 0x95, 0xdd, 0x25, 0x91, 0x4d, 0xd1, 0x85, 0xd1, 0x95, 0x4d,
+  0x09, 0xb6, 0x3a, 0x64, 0x78, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50,
+  0x6f, 0x69, 0x6e, 0x74, 0x73, 0x53, 0x02, 0x38, 0xe8, 0x42, 0x86, 0xe7,
+  0x32, 0xf6, 0x56, 0xe7, 0x46, 0x57, 0x26, 0x37, 0x37, 0x25, 0xc0, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88,
+  0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73,
+  0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e,
+  0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30,
+  0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8,
+  0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b,
+  0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76,
+  0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e,
+  0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e,
+  0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61,
+  0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4,
+  0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37,
+  0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76,
+  0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71,
+  0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e,
+  0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61,
+  0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8,
+  0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc,
+  0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x8c, 0xc8,
+  0x21, 0x07, 0x7c, 0x70, 0x03, 0x72, 0x10, 0x87, 0x73, 0x70, 0x03, 0x7b,
+  0x08, 0x07, 0x79, 0x60, 0x87, 0x70, 0xc8, 0x87, 0x77, 0xa8, 0x07, 0x7a,
+  0x98, 0x81, 0x3c, 0xe4, 0x80, 0x0f, 0x6e, 0x40, 0x0f, 0xe5, 0xd0, 0x0e,
+  0xf0, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x46, 0x20, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x10, 0x11, 0xc0, 0x44, 0x84,
+  0x40, 0x33, 0x2c, 0x84, 0x05, 0x4c, 0xc3, 0xe5, 0x3b, 0x8f, 0xbf, 0x38,
+  0xc0, 0x20, 0x36, 0x0f, 0x35, 0xf9, 0xc5, 0x6d, 0xdb, 0x00, 0x34, 0x5c,
+  0xbe, 0xf3, 0xf8, 0x12, 0xc0, 0x3c, 0x0b, 0xe1, 0x17, 0xb7, 0x6d, 0x02,
+  0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d,
+  0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x00, 0x04, 0x03, 0x20, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xab, 0x99, 0x02, 0x6f, 0x30, 0x68, 0xb3, 0x31,
+  0x43, 0x41, 0xba, 0x15, 0xea, 0xf6, 0x26, 0xa8, 0x44, 0x58, 0x49, 0x4c,
+  0xc8, 0x06, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xb2, 0x01, 0x00, 0x00,
+  0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0xb0, 0x06, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00,
+  0xa9, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49,
+  0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19,
+  0x1e, 0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42,
+  0xa4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88,
+  0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42,
+  0xe4, 0x48, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c,
+  0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07,
+  0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20,
+  0x6d, 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42,
+  0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00,
+  0x43, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04,
+  0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14,
+  0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x68, 0x23, 0x00,
+  0x25, 0x00, 0x14, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29,
+  0xc6, 0x20, 0x84, 0x14, 0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1,
+  0x9b, 0x86, 0xcb, 0x9f, 0xb0, 0x87, 0x90, 0xfc, 0x95, 0x90, 0x56, 0x62,
+  0xf2, 0x8b, 0xdb, 0x46, 0xc5, 0x18, 0x63, 0x10, 0x2a, 0xf7, 0x0c, 0x97,
+  0x3f, 0x61, 0x0f, 0x21, 0xf9, 0x21, 0xd0, 0x0c, 0x0b, 0x81, 0x82, 0x55,
+  0x18, 0x45, 0x18, 0x1b, 0x63, 0x0c, 0x42, 0xc8, 0xa0, 0x36, 0x47, 0x10,
+  0x14, 0x83, 0x91, 0x42, 0xc8, 0x23, 0x38, 0x10, 0x30, 0x8c, 0x40, 0x0c,
+  0x33, 0xb5, 0xc1, 0x38, 0xb0, 0x43, 0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01,
+  0x2d, 0x94, 0x03, 0x3e, 0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39, 0xc8, 0x01,
+  0x29, 0xf0, 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03,
+  0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01,
+  0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x81, 0x1e, 0xe8, 0x41, 0x3b, 0xa4, 0x03,
+  0x3c, 0xcc, 0xc3, 0x2f, 0xd0, 0x43, 0x3e, 0xc0, 0x43, 0x39, 0xa0, 0x80,
+  0xcc, 0x24, 0x06, 0xe3, 0xc0, 0x0e, 0xe1, 0x30, 0x0f, 0xf3, 0xe0, 0x06,
+  0xb4, 0x50, 0x0e, 0xf8, 0x40, 0x0f, 0xf5, 0x20, 0x0f, 0xe5, 0x20, 0x07,
+  0xa4, 0xc0, 0x07, 0xf6, 0x50, 0x0e, 0xe3, 0x40, 0x0f, 0xef, 0x20, 0x0f,
+  0x7c, 0x60, 0x0e, 0xec, 0xf0, 0x0e, 0xe1, 0x40, 0x0f, 0x6c, 0x00, 0x06,
+  0x74, 0xe0, 0x07, 0x60, 0xe0, 0x07, 0x48, 0x98, 0x94, 0xea, 0x4d, 0xd2,
+  0x14, 0x51, 0xc2, 0xe4, 0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0,
+  0x44, 0xa0, 0x80, 0xd0, 0x4d, 0x04, 0x02, 0x00, 0x13, 0x14, 0x72, 0xc0,
+  0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0,
+  0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d,
+  0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78,
+  0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0b, 0x04, 0x00, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90,
+  0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x25, 0x30, 0x02, 0x50,
+  0x10, 0xc5, 0x50, 0x04, 0x25, 0x51, 0x06, 0xe5, 0x41, 0xa5, 0x24, 0x46,
+  0x00, 0x8a, 0xa0, 0x10, 0x0a, 0x84, 0xec, 0x0c, 0x00, 0xe1, 0x19, 0x00,
+  0xca, 0x63, 0x21, 0x06, 0x11, 0x08, 0x04, 0xf2, 0x3c, 0x00, 0x00, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90,
+  0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b,
+  0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71,
+  0xa1, 0xb1, 0xb1, 0x91, 0x01, 0x41, 0xa1, 0x89, 0xb1, 0x31, 0x0b, 0x13,
+  0xb3, 0x11, 0xab, 0x49, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xa2, 0x98, 0x20,
+  0x10, 0xc6, 0x06, 0x61, 0x20, 0x26, 0x08, 0xc4, 0xb1, 0x41, 0x18, 0x0c,
+  0x0a, 0x70, 0x73, 0x13, 0x04, 0x02, 0xd9, 0x30, 0x20, 0x09, 0x31, 0x41,
+  0xb0, 0x24, 0x02, 0x13, 0x04, 0x22, 0x99, 0x20, 0x10, 0xca, 0x06, 0x81,
+  0x70, 0x36, 0x24, 0xc4, 0xc2, 0x34, 0xc4, 0xd0, 0x10, 0xcf, 0x86, 0x00,
+  0x9a, 0x20, 0x60, 0xd3, 0x06, 0x84, 0x90, 0x98, 0x86, 0x18, 0x08, 0x60,
+  0x43, 0x30, 0x6d, 0x20, 0x22, 0x00, 0xa0, 0x26, 0x08, 0x19, 0xb5, 0x21,
+  0xb0, 0x26, 0x08, 0x02, 0x40, 0xa2, 0x2d, 0x2c, 0xcd, 0x8d, 0x08, 0x55,
+  0x11, 0xd6, 0xd0, 0xd3, 0x93, 0x14, 0xd1, 0x04, 0xa1, 0x68, 0x26, 0x08,
+  0x85, 0xb3, 0x21, 0x20, 0x26, 0x08, 0xc5, 0x33, 0x41, 0x28, 0xa0, 0x09,
+  0x02, 0xb1, 0x4c, 0x10, 0x08, 0x66, 0x83, 0x00, 0x06, 0x61, 0xb0, 0x61,
+  0x21, 0xb4, 0x8d, 0xeb, 0xbc, 0xe1, 0x23, 0x38, 0x31, 0xd8, 0x10, 0x0c,
+  0x1b, 0x04, 0x30, 0x00, 0x83, 0x0d, 0xcb, 0xa0, 0x6d, 0x1c, 0x19, 0x78,
+  0x83, 0x37, 0x70, 0x65, 0xb0, 0x41, 0x18, 0x03, 0x33, 0x60, 0x32, 0x65,
+  0xf5, 0x45, 0x15, 0x26, 0x77, 0x56, 0x46, 0x37, 0x41, 0x28, 0xa2, 0x0d,
+  0x0b, 0x81, 0x06, 0x5b, 0x1a, 0x74, 0xdc, 0xf0, 0x11, 0x9c, 0x18, 0x6c,
+  0x08, 0xd4, 0x60, 0xc3, 0x70, 0x06, 0x6b, 0x00, 0x6c, 0x28, 0xb0, 0x8c,
+  0x0d, 0x2a, 0xa0, 0x0a, 0x1b, 0x9b, 0x5d, 0x9b, 0x4b, 0x1a, 0x59, 0x99,
+  0x1b, 0xdd, 0x94, 0x20, 0xa8, 0x42, 0x86, 0xe7, 0x62, 0x57, 0x26, 0x37,
+  0x97, 0xf6, 0xe6, 0x36, 0x25, 0x20, 0x9a, 0x90, 0xe1, 0xb9, 0xd8, 0x85,
+  0xb1, 0xd9, 0x95, 0xc9, 0x4d, 0x09, 0x8c, 0x3a, 0x64, 0x78, 0x2e, 0x73,
+  0x68, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x53, 0x82,
+  0xa4, 0x0c, 0x19, 0x9e, 0x8b, 0x5c, 0xd9, 0xdc, 0x5b, 0x9d, 0xdc, 0x58,
+  0xd9, 0xdc, 0x94, 0x80, 0xaa, 0x43, 0x86, 0xe7, 0x62, 0x97, 0x56, 0x76,
+  0x97, 0x44, 0x36, 0x45, 0x17, 0x46, 0x57, 0x36, 0x25, 0xb0, 0xea, 0x90,
+  0xe1, 0xb9, 0x94, 0xb9, 0xd1, 0xc9, 0xe5, 0x41, 0xbd, 0xa5, 0xb9, 0xd1,
+  0xcd, 0x4d, 0x09, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66,
+  0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10,
+  0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce,
+  0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b,
+  0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c,
+  0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07,
+  0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11,
+  0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0,
+  0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8,
+  0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b,
+  0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b,
+  0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87,
+  0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07,
+  0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87,
+  0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81,
+  0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30,
+  0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca,
+  0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b,
+  0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b,
+  0xb0, 0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x72, 0x10, 0x87,
+  0x73, 0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60, 0x87, 0x70, 0xc8, 0x87,
+  0x77, 0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4, 0x80, 0x0f, 0x6e, 0x40,
+  0x0f, 0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x46, 0x20, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x10,
+  0x11, 0xc0, 0x44, 0x84, 0x40, 0x33, 0x2c, 0x84, 0x05, 0x4c, 0xc3, 0xe5,
+  0x3b, 0x8f, 0xbf, 0x38, 0xc0, 0x20, 0x36, 0x0f, 0x35, 0xf9, 0xc5, 0x6d,
+  0xdb, 0x00, 0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x12, 0xc0, 0x3c, 0x0b, 0xe1,
+  0x17, 0xb7, 0x6d, 0x02, 0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13,
+  0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x00, 0x04, 0x03,
+  0x20, 0x0d, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00,
+  0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0xf4, 0x46, 0x00, 0x88, 0xcc, 0x00, 0x14, 0x42, 0x29, 0x94, 0x5c, 0xe1,
+  0x51, 0x29, 0x83, 0x12, 0xa0, 0x31, 0x03, 0x00, 0x23, 0x06, 0x09, 0x00,
+  0x82, 0x60, 0x00, 0x69, 0x05, 0x84, 0x61, 0xc9, 0x88, 0x41, 0x02, 0x80,
+  0x20, 0x18, 0x40, 0x9b, 0x41, 0x64, 0x99, 0x32, 0x62, 0x90, 0x00, 0x20,
+  0x08, 0x06, 0xc6, 0x97, 0x6c, 0x9a, 0xa4, 0x8c, 0x18, 0x24, 0x00, 0x08,
+  0x82, 0x81, 0x01, 0x06, 0x0a, 0xb7, 0x15, 0xcb, 0x88, 0x41, 0x02, 0x80,
+  0x20, 0x18, 0x18, 0x61, 0xb0, 0x70, 0x1c, 0xc5, 0x8c, 0x18, 0x24, 0x00,
+  0x08, 0x82, 0x81, 0x21, 0x06, 0x4c, 0xd7, 0x1d, 0xcd, 0x88, 0x41, 0x02,
+  0x80, 0x20, 0x18, 0x18, 0x63, 0xd0, 0x78, 0x5e, 0xe5, 0x8c, 0x18, 0x24,
+  0x00, 0x08, 0x82, 0x81, 0x41, 0x06, 0xce, 0xf7, 0x29, 0xcf, 0x88, 0xc1,
+  0x03, 0x80, 0x20, 0x18, 0x34, 0x63, 0xc0, 0x20, 0x87, 0x51, 0x24, 0x09,
+  0x18, 0x80, 0x01, 0x94, 0x8c, 0x26, 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c,
+  0x26, 0x0c, 0xc2, 0x68, 0x02, 0x31, 0x18, 0x91, 0xc8, 0xc7, 0x88, 0x44,
+  0x3e, 0x46, 0x24, 0xf2, 0x31, 0x22, 0x91, 0xcf, 0x88, 0x41, 0x02, 0x80,
+  0x20, 0x18, 0x20, 0x6d, 0x70, 0xa5, 0x41, 0x1a, 0x84, 0x01, 0x31, 0x62,
+  0x90, 0x00, 0x20, 0x08, 0x06, 0x48, 0x1b, 0x5c, 0x69, 0x90, 0x06, 0xd3,
+  0x30, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x48, 0x1b, 0x5c, 0x69, 0x90,
+  0x06, 0x60, 0x20, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0xd2, 0x06,
+  0x57, 0x1a, 0xa4, 0x01, 0x15, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};

+ 50 - 0
src/render/sdlgpu/shaders/texture_rgba.frag.spv.h

@@ -0,0 +1,50 @@
+const unsigned char texture_rgba_frag_spv[] = {
+  0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0d, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x15, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x57, 0x00, 0x05, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x85, 0x00, 0x05, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x17, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+};
+const unsigned int texture_rgba_frag_spv_len = 564;

+ 17 - 0
src/render/sdlgpu/shaders/tri_color.vert

@@ -0,0 +1,17 @@
+#version 450
+
+layout(location = 0) in vec2 a_position;
+layout(location = 1) in vec4 a_color;
+
+layout(location = 0) out vec4 v_color;
+
+layout(set = 1, binding = 0) uniform Context {
+    mat4 mvp;
+    vec4 color;  /* XXX unused */
+    vec2 texture_size;  /* XXX unused */
+} u_context;
+
+void main() {
+    gl_Position = u_context.mvp * vec4(a_position, 0, 1);
+    v_color = a_color;
+}

+ 48 - 0
src/render/sdlgpu/shaders/tri_color.vert.metal.h

@@ -0,0 +1,48 @@
+const unsigned char tri_color_vert_metal[] = {
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65,
+  0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a,
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 0x69,
+  0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a,
+  0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+  0x61, 0x63, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a,
+  0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x31, 0x38, 0x0a, 0x7b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78,
+  0x34, 0x20, 0x5f, 0x6d, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x5f, 0x6d, 0x31, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x5f, 0x6d,
+  0x32, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63,
+  0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x6f, 0x75, 0x74, 0x0a,
+  0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
+  0x20, 0x6d, 0x5f, 0x33, 0x35, 0x20, 0x5b, 0x5b, 0x75, 0x73, 0x65, 0x72,
+  0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x67, 0x6c,
+  0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5b, 0x5b,
+  0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5d, 0x5d, 0x3b, 0x0a,
+  0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6d,
+  0x61, 0x69, 0x6e, 0x30, 0x5f, 0x69, 0x6e, 0x0a, 0x7b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6d, 0x5f, 0x32,
+  0x35, 0x20, 0x5b, 0x5b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
+  0x65, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x6d, 0x5f, 0x33, 0x37, 0x20,
+  0x5b, 0x5b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28,
+  0x31, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x76, 0x65,
+  0x72, 0x74, 0x65, 0x78, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x6f,
+  0x75, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x28, 0x6d, 0x61, 0x69,
+  0x6e, 0x30, 0x5f, 0x69, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x5b, 0x5b, 0x73,
+  0x74, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x6e, 0x5d, 0x5d, 0x2c, 0x20, 0x63,
+  0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x5f, 0x31, 0x38, 0x26,
+  0x20, 0x5f, 0x32, 0x30, 0x20, 0x5b, 0x5b, 0x62, 0x75, 0x66, 0x66, 0x65,
+  0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x6f, 0x75, 0x74, 0x20,
+  0x6f, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x3b, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73,
+  0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x5f, 0x32, 0x30, 0x2e,
+  0x5f, 0x6d, 0x30, 0x20, 0x2a, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
+  0x28, 0x69, 0x6e, 0x2e, 0x6d, 0x5f, 0x32, 0x35, 0x2c, 0x20, 0x30, 0x2e,
+  0x30, 0x2c, 0x20, 0x31, 0x2e, 0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x6f, 0x75, 0x74, 0x2e, 0x6d, 0x5f, 0x33, 0x35, 0x20, 0x3d, 0x20,
+  0x69, 0x6e, 0x2e, 0x6d, 0x5f, 0x33, 0x37, 0x3b, 0x0a, 0x20, 0x20, 0x20,
+  0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x3b,
+  0x0a, 0x7d, 0x0a, 0x0a
+};
+const unsigned int tri_color_vert_metal_len = 532;

+ 178 - 0
src/render/sdlgpu/shaders/tri_color.vert.sm50.dxbc.h

@@ -0,0 +1,178 @@
+const unsigned char tri_color_vert_sm50_dxbc[] =
+{
+  68,  88,  66,  67, -99,  -1,
+ -83, -50,  75, -96,  -1,  28,
+-104, -33, 121,   1,-117, -87,
+  -7,-107,   1,   0,   0,   0,
+  20,   4,   0,   0,   5,   0,
+   0,   0,  52,   0,   0,   0,
+ -12,   1,   0,   0,  64,   2,
+   0,   0,-104,   2,   0,   0,
+ 120,   3,   0,   0,  82,  68,
+  69,  70, -72,   1,   0,   0,
+   1,   0,   0,   0, 100,   0,
+   0,   0,   1,   0,   0,   0,
+  60,   0,   0,   0,   0,   5,
+  -2,  -1,   0,   1,   0,   0,
+-112,   1,   0,   0,  82,  68,
+  49,  49,  60,   0,   0,   0,
+  24,   0,   0,   0,  32,   0,
+   0,   0,  40,   0,   0,   0,
+  36,   0,   0,   0,  12,   0,
+   0,   0,   0,   0,   0,   0,
+  92,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   1,   0,
+   0,   0,  95,  49,  56,  95,
+  50,  48,   0, -85,  92,   0,
+   0,   0,   3,   0,   0,   0,
+ 124,   0,   0,   0,  96,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0, -12,   0,
+   0,   0,   0,   0,   0,   0,
+  64,   0,   0,   0,   2,   0,
+   0,   0,   4,   1,   0,   0,
+   0,   0,   0,   0,  -1,  -1,
+  -1,  -1,   0,   0,   0,   0,
+  -1,  -1,  -1,  -1,   0,   0,
+   0,   0,  40,   1,   0,   0,
+  64,   0,   0,   0,  16,   0,
+   0,   0,   0,   0,   0,   0,
+  56,   1,   0,   0,   0,   0,
+   0,   0,  -1,  -1,  -1,  -1,
+   0,   0,   0,   0,  -1,  -1,
+  -1,  -1,   0,   0,   0,   0,
+  92,   1,   0,   0,  80,   0,
+   0,   0,   8,   0,   0,   0,
+   0,   0,   0,   0, 108,   1,
+   0,   0,   0,   0,   0,   0,
+  -1,  -1,  -1,  -1,   0,   0,
+   0,   0,  -1,  -1,  -1,  -1,
+   0,   0,   0,   0,  95,  50,
+  48,  95, 109,  48,   0, 102,
+ 108, 111,  97, 116,  52, 120,
+  52,   0,   2,   0,   3,   0,
+   4,   0,   4,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,  -5,   0,
+   0,   0,  95,  50,  48,  95,
+ 109,  49,   0, 102, 108, 111,
+  97, 116,  52,   0, -85, -85,
+   1,   0,   3,   0,   1,   0,
+   4,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,  47,   1,   0,   0,
+  95,  50,  48,  95, 109,  50,
+   0, 102, 108, 111,  97, 116,
+  50,   0, -85, -85,   1,   0,
+   3,   0,   1,   0,   2,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+  99,   1,   0,   0,  77, 105,
+  99, 114, 111, 115, 111, 102,
+ 116,  32,  40,  82,  41,  32,
+  72,  76,  83,  76,  32,  83,
+ 104,  97, 100, 101, 114,  32,
+  67, 111, 109, 112, 105, 108,
+ 101, 114,  32,  49,  48,  46,
+  49,   0,  73,  83,  71,  78,
+  68,   0,   0,   0,   2,   0,
+   0,   0,   8,   0,   0,   0,
+  56,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,   0,   0,
+   0,   0,   3,   3,   0,   0,
+  56,   0,   0,   0,   1,   0,
+   0,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,   1,   0,
+   0,   0,  15,  15,   0,   0,
+  84,  69,  88,  67,  79,  79,
+  82,  68,   0, -85, -85, -85,
+  79,  83,  71,  78,  80,   0,
+   0,   0,   2,   0,   0,   0,
+   8,   0,   0,   0,  56,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   3,   0,
+   0,   0,   0,   0,   0,   0,
+  15,   0,   0,   0,  65,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   3,   0,
+   0,   0,   1,   0,   0,   0,
+  15,   0,   0,   0,  84,  69,
+  88,  67,  79,  79,  82,  68,
+   0,  83,  86,  95,  80, 111,
+ 115, 105, 116, 105, 111, 110,
+   0, -85, -85, -85,  83,  72,
+  69,  88, -40,   0,   0,   0,
+  80,   0,   1,   0,  54,   0,
+   0,   0, 106,   8,   0,   1,
+  89,   0,   0,   4,  70,-114,
+  32,   0,   0,   0,   0,   0,
+   4,   0,   0,   0,  95,   0,
+   0,   3,  50,  16,  16,   0,
+   0,   0,   0,   0,  95,   0,
+   0,   3, -14,  16,  16,   0,
+   1,   0,   0,   0, 101,   0,
+   0,   3, -14,  32,  16,   0,
+   0,   0,   0,   0, 103,   0,
+   0,   4, -14,  32,  16,   0,
+   1,   0,   0,   0,   1,   0,
+   0,   0, 104,   0,   0,   2,
+   1,   0,   0,   0,  54,   0,
+   0,   5, -14,  32,  16,   0,
+   0,   0,   0,   0,  70,  30,
+  16,   0,   1,   0,   0,   0,
+  56,   0,   0,   8, -14,   0,
+  16,   0,   0,   0,   0,   0,
+  86,  21,  16,   0,   0,   0,
+   0,   0,  70,-114,  32,   0,
+   0,   0,   0,   0,   1,   0,
+   0,   0,  50,   0,   0,  10,
+ -14,   0,  16,   0,   0,   0,
+   0,   0,   6,  16,  16,   0,
+   0,   0,   0,   0,  70,-114,
+  32,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,  70,  14,
+  16,   0,   0,   0,   0,   0,
+   0,   0,   0,   8, -14,  32,
+  16,   0,   1,   0,   0,   0,
+  70,  14,  16,   0,   0,   0,
+   0,   0,  70,-114,  32,   0,
+   0,   0,   0,   0,   3,   0,
+   0,   0,  62,   0,   0,   1,
+  83,  84,  65,  84,-108,   0,
+   0,   0,   5,   0,   0,   0,
+   1,   0,   0,   0,   0,   0,
+   0,   0,   4,   0,   0,   0,
+   3,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0
+
+};

+ 515 - 0
src/render/sdlgpu/shaders/tri_color.vert.sm60.dxil.h

@@ -0,0 +1,515 @@
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xy          0     NONE   float   xy  
+; TEXCOORD                 1   xyzw        1     NONE   float   xyzw
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xyzw        0     NONE   float   xyzw
+; SV_Position              0   xyzw        1      POS   float   xyzw
+;
+; shader hash: f13b1cc9b87e560da744659dd5d39dcb
+;
+; Pipeline Runtime Information: 
+;
+; Vertex Shader
+; OutputPositionPresent=1
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                              
+; TEXCOORD                 1                              
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; SV_Position              0          noperspective       
+;
+; Buffer Definitions:
+;
+; cbuffer _18_20
+; {
+;
+;   struct hostlayout._18_20
+;   {
+;
+;       row_major float4x4 _20_m0;                    ; Offset:    0
+;       float4 _20_m1;                                ; Offset:   64
+;       float2 _20_m2;                                ; Offset:   80
+;   
+;   } _18_20;                                         ; Offset:    0 Size:    88
+;
+; }
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; _18_20                            cbuffer      NA          NA     CB0     cb0,space1     1
+;
+;
+; ViewId state:
+;
+; Number of inputs: 8, outputs: 8
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 4 }
+;   output 1 depends on inputs: { 5 }
+;   output 2 depends on inputs: { 6 }
+;   output 3 depends on inputs: { 7 }
+;   output 4 depends on inputs: { 0, 1 }
+;   output 5 depends on inputs: { 0, 1 }
+;   output 6 depends on inputs: { 0, 1 }
+;   output 7 depends on inputs: { 0, 1 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+%dx.types.Handle = type { i8* }
+%dx.types.CBufRet.f32 = type { float, float, float, float }
+%hostlayout._18_20 = type { [4 x <4 x float>], <4 x float>, <2 x float> }
+
+define void @main() {
+  %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %2 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %3 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 2, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %5 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 3, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %6 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %7 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %8 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 0)  ; CBufferLoadLegacy(handle,regIndex)
+  %9 = extractvalue %dx.types.CBufRet.f32 %8, 0
+  %10 = extractvalue %dx.types.CBufRet.f32 %8, 1
+  %11 = extractvalue %dx.types.CBufRet.f32 %8, 2
+  %12 = extractvalue %dx.types.CBufRet.f32 %8, 3
+  %13 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %14 = extractvalue %dx.types.CBufRet.f32 %13, 0
+  %15 = extractvalue %dx.types.CBufRet.f32 %13, 1
+  %16 = extractvalue %dx.types.CBufRet.f32 %13, 2
+  %17 = extractvalue %dx.types.CBufRet.f32 %13, 3
+  %18 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 3)  ; CBufferLoadLegacy(handle,regIndex)
+  %19 = extractvalue %dx.types.CBufRet.f32 %18, 0
+  %20 = extractvalue %dx.types.CBufRet.f32 %18, 1
+  %21 = extractvalue %dx.types.CBufRet.f32 %18, 2
+  %22 = extractvalue %dx.types.CBufRet.f32 %18, 3
+  %23 = fmul fast float %9, %6
+  %24 = call float @dx.op.tertiary.f32(i32 46, float %7, float %14, float %23)  ; FMad(a,b,c)
+  %25 = fadd fast float %19, %24
+  %26 = fmul fast float %10, %6
+  %27 = call float @dx.op.tertiary.f32(i32 46, float %7, float %15, float %26)  ; FMad(a,b,c)
+  %28 = fadd fast float %27, %20
+  %29 = fmul fast float %11, %6
+  %30 = call float @dx.op.tertiary.f32(i32 46, float %7, float %16, float %29)  ; FMad(a,b,c)
+  %31 = fadd fast float %30, %21
+  %32 = fmul fast float %12, %6
+  %33 = call float @dx.op.tertiary.f32(i32 46, float %7, float %17, float %32)  ; FMad(a,b,c)
+  %34 = fadd fast float %33, %22
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %2)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %3)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %4)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %5)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 0, float %25)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 1, float %28)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 2, float %31)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 3, float %34)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.tertiary.f32(i32, float, float, float) #0
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.resources = !{!4}
+!dx.viewIdState = !{!7}
+!dx.entryPoints = !{!8}
+
+!0 = !{!"dxc(private) 1.8.0.4662 (416fab6b5)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 8}
+!3 = !{!"vs", i32 6, i32 0}
+!4 = !{null, null, !5, null}
+!5 = !{!6}
+!6 = !{i32 0, %hostlayout._18_20* undef, !"", i32 1, i32 0, i32 1, i32 88, null}
+!7 = !{[10 x i32] [i32 8, i32 8, i32 240, i32 240, i32 0, i32 0, i32 1, i32 2, i32 4, i32 8]}
+!8 = !{void ()* @main, !"main", !9, !4, null}
+!9 = !{!10, !17, null}
+!10 = !{!11, !14}
+!11 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !12, i8 0, i32 1, i8 2, i32 0, i8 0, !13}
+!12 = !{i32 0}
+!13 = !{i32 3, i32 3}
+!14 = !{i32 1, !"TEXCOORD", i8 9, i8 0, !15, i8 0, i32 1, i8 4, i32 1, i8 0, !16}
+!15 = !{i32 1}
+!16 = !{i32 3, i32 15}
+!17 = !{!18, !19}
+!18 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !12, i8 2, i32 1, i8 4, i32 0, i8 0, !16}
+!19 = !{i32 1, !"SV_Position", i8 9, i8 3, !12, i8 4, i32 1, i8 4, i32 1, i8 0, !16}
+
+#endif
+
+const unsigned char tri_color_vert_sm60_dxil[] = {
+  0x44, 0x58, 0x42, 0x43, 0xeb, 0x11, 0xa0, 0x76, 0xea, 0x69, 0xbc, 0x28,
+  0xcd, 0xbc, 0x0c, 0xab, 0x14, 0x5d, 0xfa, 0x53, 0x01, 0x00, 0x00, 0x00,
+  0x98, 0x0f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00,
+  0x08, 0x02, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, 0x8c, 0x08, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x54, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x00,
+  0x4f, 0x53, 0x47, 0x31, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43,
+  0x4f, 0x4f, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69,
+  0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x56, 0x30,
+  0xf0, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x54, 0x45,
+  0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f,
+  0x4f, 0x52, 0x44, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x42, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x44, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x00,
+  0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x01, 0x44, 0x03, 0x03, 0x04, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
+  0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0x60, 0x06, 0x00, 0x00,
+  0x60, 0x00, 0x01, 0x00, 0x98, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c,
+  0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x06, 0x00, 0x00,
+  0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x00,
+  0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39,
+  0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
+  0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14,
+  0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20,
+  0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90,
+  0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a,
+  0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d,
+  0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06,
+  0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x6c, 0x23, 0x00, 0x25, 0x00, 0x14, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x20, 0x84, 0x14,
+  0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1, 0xa3, 0x86, 0xcb, 0x9f,
+  0xb0, 0x87, 0x90, 0x7c, 0x6e, 0xa3, 0x8a, 0x95, 0x98, 0xfc, 0xe2, 0xb6,
+  0x11, 0x31, 0xc6, 0x18, 0x54, 0xee, 0x19, 0x2e, 0x7f, 0xc2, 0x1e, 0x42,
+  0xf2, 0x43, 0xa0, 0x19, 0x16, 0x02, 0x05, 0xab, 0x10, 0x8a, 0x30, 0x42,
+  0xad, 0x14, 0x83, 0x8c, 0x31, 0xe8, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0xa4,
+  0x10, 0x12, 0x49, 0x0e, 0x04, 0x0c, 0x23, 0x10, 0x43, 0x12, 0xd4, 0x61,
+  0x04, 0x61, 0xb8, 0xe8, 0x70, 0xa4, 0x69, 0x01, 0x30, 0x87, 0x9a, 0xfc,
+  0xbf, 0xe6, 0x7f, 0x9b, 0x46, 0x83, 0xad, 0x97, 0x70, 0x2a, 0x10, 0x00,
+  0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79,
+  0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e,
+  0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e,
+  0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20,
+  0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34,
+  0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4,
+  0x79, 0x80, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+  0xc8, 0x23, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x40, 0x16, 0x08, 0x00, 0x13, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22,
+  0x25, 0x30, 0x02, 0x50, 0x0c, 0x05, 0x1b, 0x50, 0x04, 0x85, 0x50, 0x06,
+  0xe5, 0x50, 0x12, 0x05, 0x18, 0x50, 0x1a, 0x05, 0x1a, 0x50, 0x1e, 0x05,
+  0x51, 0x56, 0x54, 0x4a, 0x62, 0x04, 0xa0, 0x08, 0x0a, 0xa1, 0x0c, 0x28,
+  0xd6, 0x00, 0xe1, 0x19, 0x00, 0xca, 0x33, 0x00, 0xa4, 0xc7, 0x52, 0x10,
+  0x04, 0x3e, 0xe0, 0x03, 0x00, 0x02, 0x81, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90,
+  0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b,
+  0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71,
+  0xa1, 0xb1, 0xb1, 0x91, 0x01, 0x41, 0xa1, 0x89, 0xb1, 0x31, 0x0b, 0x13,
+  0xb3, 0x11, 0xab, 0x49, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xc2, 0x98, 0x20,
+  0x10, 0xc7, 0x06, 0x61, 0x20, 0x36, 0x08, 0x04, 0x41, 0xc1, 0x6e, 0x6e,
+  0x82, 0x40, 0x20, 0x1b, 0x86, 0x03, 0x21, 0x26, 0x08, 0x19, 0x47, 0xe3,
+  0x2b, 0x06, 0xe7, 0x4b, 0x06, 0x66, 0x82, 0x40, 0x24, 0x1b, 0x10, 0x42,
+  0x59, 0x06, 0x62, 0x60, 0x80, 0x0d, 0x41, 0xb3, 0x81, 0x00, 0x00, 0x07,
+  0x98, 0x20, 0x60, 0x1b, 0x8d, 0x2f, 0x19, 0x98, 0xaf, 0x36, 0x98, 0x09,
+  0x02, 0xa1, 0x4c, 0x10, 0x88, 0x65, 0xc3, 0x30, 0x4d, 0xc3, 0x04, 0x81,
+  0x60, 0x26, 0x08, 0x44, 0x33, 0x41, 0x20, 0x9c, 0x09, 0x42, 0xa4, 0x6d,
+  0x50, 0x90, 0x48, 0xa2, 0x2a, 0xc2, 0xba, 0x2e, 0x8c, 0xc6, 0x97, 0x0c,
+  0xcc, 0x57, 0x5b, 0xcc, 0x04, 0x81, 0x78, 0x26, 0x08, 0x04, 0xb4, 0x01,
+  0x41, 0xb4, 0x6a, 0xb3, 0x2e, 0x6e, 0xa2, 0xf1, 0x25, 0x03, 0xf3, 0xd5,
+  0x26, 0x33, 0x41, 0x20, 0xa2, 0x0d, 0x08, 0xe2, 0x55, 0x9f, 0x75, 0x71,
+  0xd2, 0x06, 0x82, 0xc9, 0x3a, 0x30, 0xd8, 0x30, 0x10, 0x50, 0x18, 0x4c,
+  0x10, 0x04, 0x60, 0x03, 0xb0, 0x61, 0x20, 0xc8, 0x80, 0x0c, 0x36, 0x04,
+  0x65, 0xb0, 0x61, 0x18, 0xc6, 0xc0, 0x0c, 0x26, 0x08, 0x5a, 0xb7, 0x21,
+  0x40, 0x03, 0x12, 0x6d, 0x61, 0x69, 0x6e, 0x44, 0xa8, 0x8a, 0xb0, 0x86,
+  0x9e, 0x9e, 0xa4, 0x88, 0x26, 0x08, 0x45, 0x35, 0x41, 0x28, 0xac, 0x0d,
+  0x01, 0x31, 0x41, 0x28, 0xae, 0x0d, 0x42, 0x55, 0x6d, 0x58, 0x88, 0x35,
+  0x60, 0x83, 0x36, 0x70, 0x83, 0x36, 0x18, 0xde, 0x80, 0x68, 0x03, 0x38,
+  0xd8, 0x10, 0x0c, 0x13, 0x84, 0x02, 0x9b, 0x20, 0x10, 0xd2, 0x06, 0xa1,
+  0xa2, 0x83, 0x0d, 0xcb, 0xb0, 0x06, 0x6c, 0xd0, 0x06, 0x72, 0xd0, 0x06,
+  0xc3, 0x1c, 0x0c, 0x6d, 0x50, 0x07, 0x1b, 0x84, 0x38, 0xb0, 0x83, 0x0d,
+  0x0b, 0xb1, 0x06, 0x6c, 0xd0, 0x06, 0x6e, 0xf0, 0x06, 0xc3, 0x1c, 0x10,
+  0x6d, 0x50, 0x07, 0x5c, 0xa6, 0xac, 0xbe, 0xa0, 0xde, 0xe6, 0xd2, 0xe8,
+  0xd2, 0xde, 0xdc, 0x26, 0x08, 0x45, 0xb6, 0x61, 0x19, 0xf2, 0x80, 0x0d,
+  0xf4, 0xc0, 0x0d, 0xe6, 0x60, 0x98, 0x83, 0xa1, 0x0d, 0xea, 0x60, 0x83,
+  0x80, 0x07, 0x7b, 0xb0, 0x61, 0xb8, 0x03, 0x3e, 0x00, 0x36, 0x14, 0x63,
+  0xa0, 0x06, 0x7d, 0xf0, 0x00, 0x34, 0xcc, 0xd8, 0xde, 0xc2, 0xe8, 0xe6,
+  0x26, 0x08, 0xc4, 0xc4, 0x22, 0xcd, 0x6d, 0x8e, 0x6e, 0x6e, 0x82, 0x40,
+  0x50, 0x34, 0xe6, 0xd2, 0xce, 0xbe, 0xd8, 0xc8, 0x68, 0xcc, 0xa5, 0x9d,
+  0x7d, 0xcd, 0xd1, 0x6d, 0x40, 0xfe, 0x00, 0x14, 0x42, 0x41, 0x14, 0x46,
+  0x01, 0x21, 0x05, 0x50, 0xa8, 0xc2, 0xc6, 0x66, 0xd7, 0xe6, 0x92, 0x46,
+  0x56, 0xe6, 0x46, 0x37, 0x25, 0x08, 0xaa, 0x90, 0xe1, 0xb9, 0xd8, 0x95,
+  0xc9, 0xcd, 0xa5, 0xbd, 0xb9, 0x4d, 0x09, 0x88, 0x26, 0x64, 0x78, 0x2e,
+  0x76, 0x61, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x82, 0xa2, 0x0e, 0x19, 0x9e,
+  0xcb, 0x1c, 0x5a, 0x18, 0x59, 0x99, 0x5c, 0xd3, 0x1b, 0x59, 0x19, 0xdb,
+  0x94, 0x00, 0x29, 0x43, 0x86, 0xe7, 0x22, 0x57, 0x36, 0xf7, 0x56, 0x27,
+  0x37, 0x56, 0x36, 0x37, 0x25, 0x70, 0x2a, 0x91, 0xe1, 0xb9, 0xd0, 0xe5,
+  0xc1, 0x95, 0x05, 0xb9, 0xb9, 0xbd, 0xd1, 0x85, 0xd1, 0xa5, 0xbd, 0xb9,
+  0xcd, 0x4d, 0x11, 0xc2, 0xc0, 0x0c, 0xea, 0x90, 0xe1, 0xb9, 0xd8, 0xa5,
+  0x95, 0xdd, 0x25, 0x91, 0x4d, 0xd1, 0x85, 0xd1, 0x95, 0x4d, 0x09, 0xd0,
+  0xa0, 0x0e, 0x19, 0x9e, 0x4b, 0x99, 0x1b, 0x9d, 0x5c, 0x1e, 0xd4, 0x5b,
+  0x9a, 0x1b, 0xdd, 0xdc, 0x94, 0xa0, 0x0f, 0xba, 0x90, 0xe1, 0xb9, 0x8c,
+  0xbd, 0xd5, 0xb9, 0xd1, 0x95, 0xc9, 0xcd, 0x4d, 0x09, 0x48, 0x01, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c,
+  0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3,
+  0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6,
+  0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03,
+  0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48,
+  0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20,
+  0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e,
+  0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d,
+  0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89,
+  0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83,
+  0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78,
+  0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98,
+  0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5,
+  0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c,
+  0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43,
+  0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82,
+  0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70,
+  0x03, 0x72, 0x10, 0x87, 0x73, 0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60,
+  0x87, 0x70, 0xc8, 0x87, 0x77, 0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4,
+  0x80, 0x0f, 0x6e, 0x40, 0x0f, 0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00,
+  0x71, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x36, 0xb0, 0x0d, 0x97,
+  0xef, 0x3c, 0xbe, 0x10, 0x50, 0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25,
+  0x61, 0x00, 0x02, 0xe6, 0x17, 0xb7, 0x6d, 0x05, 0xd2, 0x70, 0xf9, 0xce,
+  0xe3, 0x0b, 0x11, 0x01, 0x4c, 0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0xc0,
+  0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x8b, 0x03, 0x0c, 0x62, 0xf3, 0x50, 0x93,
+  0x5f, 0xdc, 0xb6, 0x09, 0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x4d, 0x4e,
+  0x44, 0xa0, 0xd4, 0xf4, 0x50, 0x93, 0x5f, 0xdc, 0xb6, 0x11, 0x48, 0xc3,
+  0xe5, 0x3b, 0x8f, 0x3f, 0x11, 0xd1, 0x84, 0x00, 0x11, 0xe6, 0x17, 0xb7,
+  0x6d, 0x00, 0x04, 0x03, 0x20, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf1, 0x3b, 0x1c, 0xc9, 0xb8, 0x7e, 0x56, 0x0d, 0xa7, 0x44, 0x65, 0x9d,
+  0xd5, 0xd3, 0x9d, 0xcb, 0x44, 0x58, 0x49, 0x4c, 0x04, 0x07, 0x00, 0x00,
+  0x60, 0x00, 0x01, 0x00, 0xc1, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c,
+  0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xec, 0x06, 0x00, 0x00,
+  0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00,
+  0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39,
+  0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
+  0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14,
+  0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20,
+  0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90,
+  0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a,
+  0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d,
+  0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06,
+  0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x6c, 0x23, 0x00, 0x25, 0x00, 0x14, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x20, 0x84, 0x14,
+  0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1, 0xa3, 0x86, 0xcb, 0x9f,
+  0xb0, 0x87, 0x90, 0x7c, 0x6e, 0xa3, 0x8a, 0x95, 0x98, 0xfc, 0xe2, 0xb6,
+  0x11, 0x31, 0xc6, 0x18, 0x54, 0xee, 0x19, 0x2e, 0x7f, 0xc2, 0x1e, 0x42,
+  0xf2, 0x43, 0xa0, 0x19, 0x16, 0x02, 0x05, 0xab, 0x10, 0x8a, 0x30, 0x42,
+  0xad, 0x14, 0x83, 0x8c, 0x31, 0xe8, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0xa4,
+  0x10, 0x12, 0x49, 0x0e, 0x04, 0x0c, 0x23, 0x10, 0x43, 0x12, 0xd4, 0x61,
+  0x04, 0x61, 0xb8, 0xe8, 0x70, 0xa4, 0x69, 0x01, 0x30, 0x87, 0x9a, 0xfc,
+  0xbf, 0xe6, 0x7f, 0x9b, 0x46, 0x83, 0xad, 0x97, 0x70, 0x2a, 0x10, 0x00,
+  0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79,
+  0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e,
+  0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e,
+  0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20,
+  0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34,
+  0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4,
+  0x79, 0x80, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+  0xc8, 0x23, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x40, 0x16, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22,
+  0x25, 0x30, 0x02, 0x50, 0x10, 0xc5, 0x50, 0xb0, 0x01, 0x65, 0x50, 0x1e,
+  0x54, 0x4a, 0x62, 0x04, 0xa0, 0x08, 0x0a, 0xa1, 0x0c, 0x28, 0xcf, 0x00,
+  0x90, 0x1e, 0x4b, 0x41, 0x10, 0xf8, 0x80, 0x0f, 0x00, 0x08, 0x04, 0x02,
+  0x01, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00,
+  0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b,
+  0x43, 0x81, 0x93, 0x4b, 0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71,
+  0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb1, 0xb1, 0x91, 0x01, 0x41, 0xa1, 0x89,
+  0xb1, 0x31, 0x0b, 0x13, 0xb3, 0x11, 0xab, 0x49, 0xd9, 0x10, 0x04, 0x13,
+  0x04, 0xc2, 0x98, 0x20, 0x10, 0xc7, 0x06, 0x61, 0x20, 0x26, 0x08, 0x04,
+  0xb2, 0x41, 0x18, 0x0c, 0x0a, 0x76, 0x73, 0x13, 0x04, 0x22, 0xd9, 0x30,
+  0x20, 0x09, 0x31, 0x41, 0xc8, 0x24, 0x02, 0x13, 0x04, 0x42, 0xd9, 0x80,
+  0x10, 0x0b, 0x33, 0x10, 0x43, 0x03, 0x6c, 0x08, 0x9c, 0x0d, 0x04, 0x00,
+  0x3c, 0xc0, 0x04, 0x41, 0x9b, 0x36, 0x04, 0xd1, 0x04, 0x41, 0x00, 0x48,
+  0xb4, 0x85, 0xa5, 0xb9, 0x11, 0xa1, 0x2a, 0xc2, 0x1a, 0x7a, 0x7a, 0x92,
+  0x22, 0x9a, 0x20, 0x14, 0xcd, 0x04, 0xa1, 0x70, 0x36, 0x04, 0xc4, 0x04,
+  0xa1, 0x78, 0x26, 0x08, 0xc4, 0xb2, 0x41, 0xd0, 0xb4, 0x0d, 0x0b, 0x51,
+  0x59, 0x17, 0x76, 0x0d, 0x19, 0x71, 0x6d, 0x1b, 0x82, 0x61, 0x82, 0x50,
+  0x40, 0x13, 0x04, 0x82, 0xd9, 0x20, 0x68, 0xdf, 0x86, 0x65, 0xa8, 0xac,
+  0xab, 0xbb, 0x06, 0x6f, 0xb8, 0xc0, 0x60, 0x83, 0xc0, 0x85, 0xc1, 0x86,
+  0x85, 0xa8, 0xac, 0x0b, 0xcb, 0x06, 0x8f, 0xb8, 0xc0, 0x80, 0xcb, 0x94,
+  0xd5, 0x17, 0xd4, 0xdb, 0x5c, 0x1a, 0x5d, 0xda, 0x9b, 0xdb, 0x04, 0xa1,
+  0x88, 0x36, 0x2c, 0x03, 0x19, 0x58, 0x65, 0x80, 0x79, 0x83, 0x37, 0x5c,
+  0x60, 0xb0, 0x41, 0x18, 0x03, 0x33, 0xd8, 0x30, 0x88, 0xc1, 0x19, 0x00,
+  0x1b, 0x8a, 0x89, 0x42, 0x03, 0x08, 0xa8, 0xc2, 0xc6, 0x66, 0xd7, 0xe6,
+  0x92, 0x46, 0x56, 0xe6, 0x46, 0x37, 0x25, 0x08, 0xaa, 0x90, 0xe1, 0xb9,
+  0xd8, 0x95, 0xc9, 0xcd, 0xa5, 0xbd, 0xb9, 0x4d, 0x09, 0x88, 0x26, 0x64,
+  0x78, 0x2e, 0x76, 0x61, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x02, 0xa3, 0x0e,
+  0x19, 0x9e, 0xcb, 0x1c, 0x5a, 0x18, 0x59, 0x99, 0x5c, 0xd3, 0x1b, 0x59,
+  0x19, 0xdb, 0x94, 0x20, 0x29, 0x43, 0x86, 0xe7, 0x22, 0x57, 0x36, 0xf7,
+  0x56, 0x27, 0x37, 0x56, 0x36, 0x37, 0x25, 0x78, 0xea, 0x90, 0xe1, 0xb9,
+  0xd8, 0xa5, 0x95, 0xdd, 0x25, 0x91, 0x4d, 0xd1, 0x85, 0xd1, 0x95, 0x4d,
+  0x09, 0xa2, 0x3a, 0x64, 0x78, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50,
+  0x6f, 0x69, 0x6e, 0x74, 0x73, 0x53, 0x02, 0x34, 0x00, 0x00, 0x00, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c,
+  0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3,
+  0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6,
+  0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03,
+  0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48,
+  0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20,
+  0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e,
+  0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d,
+  0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89,
+  0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83,
+  0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78,
+  0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98,
+  0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5,
+  0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c,
+  0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43,
+  0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82,
+  0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70,
+  0x03, 0x72, 0x10, 0x87, 0x73, 0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60,
+  0x87, 0x70, 0xc8, 0x87, 0x77, 0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4,
+  0x80, 0x0f, 0x6e, 0x40, 0x0f, 0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00,
+  0x71, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x36, 0xb0, 0x0d, 0x97,
+  0xef, 0x3c, 0xbe, 0x10, 0x50, 0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25,
+  0x61, 0x00, 0x02, 0xe6, 0x17, 0xb7, 0x6d, 0x05, 0xd2, 0x70, 0xf9, 0xce,
+  0xe3, 0x0b, 0x11, 0x01, 0x4c, 0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0xc0,
+  0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x8b, 0x03, 0x0c, 0x62, 0xf3, 0x50, 0x93,
+  0x5f, 0xdc, 0xb6, 0x09, 0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x4d, 0x4e,
+  0x44, 0xa0, 0xd4, 0xf4, 0x50, 0x93, 0x5f, 0xdc, 0xb6, 0x11, 0x48, 0xc3,
+  0xe5, 0x3b, 0x8f, 0x3f, 0x11, 0xd1, 0x84, 0x00, 0x11, 0xe6, 0x17, 0xb7,
+  0x6d, 0x00, 0x04, 0x03, 0x20, 0x0d, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00,
+  0x63, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x44, 0x4a, 0xa1, 0x10, 0x66, 0x00, 0x8a, 0xab,
+  0xec, 0x4a, 0x8e, 0x4a, 0x09, 0x50, 0x1c, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x20, 0x5d, 0x43, 0x53, 0x55, 0xc1,
+  0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x1c, 0x72, 0x59, 0xcf, 0x31,
+  0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x46, 0x97, 0x60, 0x17, 0x81, 0x8c,
+  0x18, 0x24, 0x00, 0x08, 0x82, 0x81, 0xe1, 0x29, 0x19, 0x06, 0x25, 0x23,
+  0x06, 0x09, 0x00, 0x82, 0x60, 0x60, 0x7c, 0x8b, 0x96, 0x3d, 0xca, 0x88,
+  0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x60, 0xc0, 0x68, 0xda, 0xb4, 0x8c,
+  0x18, 0x24, 0x00, 0x08, 0x82, 0x81, 0x11, 0x06, 0xcd, 0xb6, 0x21, 0xcc,
+  0x88, 0xc1, 0x01, 0x80, 0x20, 0x18, 0x34, 0x60, 0xb0, 0x1c, 0xdc, 0x68,
+  0x42, 0x00, 0x8c, 0x26, 0x08, 0xc1, 0x68, 0xc2, 0x20, 0x8c, 0x26, 0x10,
+  0xc3, 0x88, 0xc1, 0x01, 0x80, 0x20, 0x18, 0x34, 0x65, 0x00, 0x31, 0x62,
+  0x30, 0x9a, 0x10, 0x00, 0xa3, 0x09, 0x42, 0x30, 0x9a, 0x30, 0x08, 0xa3,
+  0x09, 0xc4, 0x30, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x8d, 0x1a, 0x54,
+  0x91, 0x18, 0x8c, 0x26, 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c, 0x26, 0x0c,
+  0xc2, 0x68, 0x02, 0x31, 0x98, 0x13, 0xc9, 0x67, 0xc4, 0x00, 0x01, 0x40,
+  0x10, 0x0c, 0x9e, 0x37, 0xe0, 0x22, 0x25, 0x30, 0x23, 0x80, 0x8e, 0x41,
+  0x94, 0x7c, 0x46, 0x0c, 0x10, 0x00, 0x04, 0xc1, 0xe0, 0x91, 0x83, 0x8f,
+  0x62, 0x02, 0x0b, 0x10, 0xe8, 0x98, 0x74, 0xc9, 0x67, 0xc4, 0x00, 0x01,
+  0x40, 0x10, 0x0c, 0x9e, 0x3a, 0x10, 0x83, 0xcb, 0x09, 0x2c, 0x50, 0xa0,
+  0x63, 0x94, 0x26, 0x9f, 0x11, 0x03, 0x04, 0x00, 0x41, 0x30, 0x78, 0xf0,
+  0xa0, 0x0c, 0x34, 0x28, 0xb0, 0x80, 0x81, 0xce, 0x88, 0x41, 0x02, 0x80,
+  0x20, 0x18, 0x20, 0x7c, 0xa0, 0x06, 0x77, 0x70, 0x07, 0x70, 0x10, 0x06,
+  0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x80, 0xf0, 0x81, 0x1a, 0xdc, 0xc1,
+  0x1d, 0x90, 0x01, 0x18, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0xc2,
+  0x07, 0x6a, 0x70, 0x07, 0x77, 0xf0, 0x06, 0xdf, 0x88, 0x41, 0x02, 0x80,
+  0x20, 0x18, 0x20, 0x7c, 0xa0, 0x06, 0x77, 0x70, 0x07, 0x6d, 0xe0, 0x8d,
+  0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0xc2, 0x07, 0x6a, 0x80, 0x07, 0x77,
+  0x00, 0x07, 0xca, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x7c, 0xa0,
+  0x06, 0x78, 0x70, 0x07, 0x64, 0x70, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82,
+  0x01, 0xc2, 0x07, 0x6a, 0x80, 0x07, 0x77, 0xf0, 0x06, 0xc4, 0x88, 0x41,
+  0x02, 0x80, 0x20, 0x18, 0x20, 0x7c, 0xa0, 0x06, 0x78, 0x70, 0x07, 0x6d,
+  0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};

+ 89 - 0
src/render/sdlgpu/shaders/tri_color.vert.spv.h

@@ -0,0 +1,89 @@
+const unsigned char tri_color_vert_spv[] = {
+  0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00,
+  0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x03, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x04, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x03, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x19, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x23, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x02, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x05, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x20, 0x00, 0x04, 0x00,
+  0x21, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x1a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x91, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
+  0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+};
+const unsigned int tri_color_vert_spv_len = 1028;

+ 20 - 0
src/render/sdlgpu/shaders/tri_texture.vert

@@ -0,0 +1,20 @@
+#version 450
+
+layout(location = 0) in vec2 a_position;
+layout(location = 1) in vec4 a_color;
+layout(location = 2) in vec2 a_uv;
+
+layout(location = 0) out vec4 v_color;
+layout(location = 1) out vec2 v_uv;
+
+layout(set = 1, binding = 0) uniform Context {
+    mat4 mvp;
+    vec4 color;  /* XXX unused */
+    vec2 texture_size;
+} u_context;
+
+void main() {
+    gl_Position = u_context.mvp * vec4(a_position, 0, 1);
+    v_color = a_color;
+    v_uv = a_uv / u_context.texture_size;
+}

+ 56 - 0
src/render/sdlgpu/shaders/tri_texture.vert.metal.h

@@ -0,0 +1,56 @@
+const unsigned char tri_texture_vert_metal[] = {
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x6d, 0x65,
+  0x74, 0x61, 0x6c, 0x5f, 0x73, 0x74, 0x64, 0x6c, 0x69, 0x62, 0x3e, 0x0a,
+  0x23, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x3c, 0x73, 0x69,
+  0x6d, 0x64, 0x2f, 0x73, 0x69, 0x6d, 0x64, 0x2e, 0x68, 0x3e, 0x0a, 0x0a,
+  0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70,
+  0x61, 0x63, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x0a,
+  0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x31, 0x38, 0x0a, 0x7b,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78,
+  0x34, 0x20, 0x5f, 0x6d, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x5f, 0x6d, 0x31, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x5f, 0x6d,
+  0x32, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63,
+  0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x6f, 0x75, 0x74, 0x0a,
+  0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34,
+  0x20, 0x6d, 0x5f, 0x33, 0x35, 0x20, 0x5b, 0x5b, 0x75, 0x73, 0x65, 0x72,
+  0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6d, 0x5f,
+  0x34, 0x30, 0x20, 0x5b, 0x5b, 0x75, 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f,
+  0x63, 0x6e, 0x31, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f,
+  0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5b, 0x5b, 0x70, 0x6f, 0x73,
+  0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5d, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a,
+  0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x6d, 0x61, 0x69, 0x6e,
+  0x30, 0x5f, 0x69, 0x6e, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x32, 0x20, 0x6d, 0x5f, 0x32, 0x35, 0x20, 0x5b,
+  0x5b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x30,
+  0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f,
+  0x61, 0x74, 0x34, 0x20, 0x6d, 0x5f, 0x33, 0x37, 0x20, 0x5b, 0x5b, 0x61,
+  0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x31, 0x29, 0x5d,
+  0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x32, 0x20, 0x6d, 0x5f, 0x34, 0x31, 0x20, 0x5b, 0x5b, 0x61, 0x74, 0x74,
+  0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x32, 0x29, 0x5d, 0x5d, 0x3b,
+  0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20,
+  0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x6f, 0x75, 0x74, 0x20, 0x6d, 0x61,
+  0x69, 0x6e, 0x30, 0x28, 0x6d, 0x61, 0x69, 0x6e, 0x30, 0x5f, 0x69, 0x6e,
+  0x20, 0x69, 0x6e, 0x20, 0x5b, 0x5b, 0x73, 0x74, 0x61, 0x67, 0x65, 0x5f,
+  0x69, 0x6e, 0x5d, 0x5d, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61,
+  0x6e, 0x74, 0x20, 0x5f, 0x31, 0x38, 0x26, 0x20, 0x5f, 0x32, 0x30, 0x20,
+  0x5b, 0x5b, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x28, 0x30, 0x29, 0x5d,
+  0x5d, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x69,
+  0x6e, 0x30, 0x5f, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x3d,
+  0x20, 0x7b, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74,
+  0x2e, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+  0x20, 0x3d, 0x20, 0x5f, 0x32, 0x30, 0x2e, 0x5f, 0x6d, 0x30, 0x20, 0x2a,
+  0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x28, 0x69, 0x6e, 0x2e, 0x6d,
+  0x5f, 0x32, 0x35, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x2c, 0x20, 0x31, 0x2e,
+  0x30, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e,
+  0x6d, 0x5f, 0x33, 0x35, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x2e, 0x6d, 0x5f,
+  0x33, 0x37, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x75, 0x74, 0x2e,
+  0x6d, 0x5f, 0x34, 0x30, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x2e, 0x6d, 0x5f,
+  0x34, 0x31, 0x20, 0x2f, 0x20, 0x5f, 0x32, 0x30, 0x2e, 0x5f, 0x6d, 0x32,
+  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
+  0x20, 0x6f, 0x75, 0x74, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a
+};
+const unsigned int tri_texture_vert_metal_len = 633;

+ 195 - 0
src/render/sdlgpu/shaders/tri_texture.vert.sm50.dxbc.h

@@ -0,0 +1,195 @@
+const unsigned char tri_texture_vert_sm50_dxbc[] =
+{
+  68,  88,  66,  67, 108, 113,
+-108,  81,  -2,  27,  41,  94,
+ -47,  10, -97, -76, -86, -88,
+  -2,  29,   1,   0,   0,   0,
+ 124,   4,   0,   0,   5,   0,
+   0,   0,  52,   0,   0,   0,
+ -12,   1,   0,   0,  88,   2,
+   0,   0, -56,   2,   0,   0,
+ -32,   3,   0,   0,  82,  68,
+  69,  70, -72,   1,   0,   0,
+   1,   0,   0,   0, 100,   0,
+   0,   0,   1,   0,   0,   0,
+  60,   0,   0,   0,   0,   5,
+  -2,  -1,   0,   1,   0,   0,
+-112,   1,   0,   0,  82,  68,
+  49,  49,  60,   0,   0,   0,
+  24,   0,   0,   0,  32,   0,
+   0,   0,  40,   0,   0,   0,
+  36,   0,   0,   0,  12,   0,
+   0,   0,   0,   0,   0,   0,
+  92,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   1,   0,
+   0,   0,  95,  49,  56,  95,
+  50,  48,   0, -85,  92,   0,
+   0,   0,   3,   0,   0,   0,
+ 124,   0,   0,   0,  96,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0, -12,   0,
+   0,   0,   0,   0,   0,   0,
+  64,   0,   0,   0,   2,   0,
+   0,   0,   4,   1,   0,   0,
+   0,   0,   0,   0,  -1,  -1,
+  -1,  -1,   0,   0,   0,   0,
+  -1,  -1,  -1,  -1,   0,   0,
+   0,   0,  40,   1,   0,   0,
+  64,   0,   0,   0,  16,   0,
+   0,   0,   0,   0,   0,   0,
+  56,   1,   0,   0,   0,   0,
+   0,   0,  -1,  -1,  -1,  -1,
+   0,   0,   0,   0,  -1,  -1,
+  -1,  -1,   0,   0,   0,   0,
+  92,   1,   0,   0,  80,   0,
+   0,   0,   8,   0,   0,   0,
+   2,   0,   0,   0, 108,   1,
+   0,   0,   0,   0,   0,   0,
+  -1,  -1,  -1,  -1,   0,   0,
+   0,   0,  -1,  -1,  -1,  -1,
+   0,   0,   0,   0,  95,  50,
+  48,  95, 109,  48,   0, 102,
+ 108, 111,  97, 116,  52, 120,
+  52,   0,   2,   0,   3,   0,
+   4,   0,   4,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,  -5,   0,
+   0,   0,  95,  50,  48,  95,
+ 109,  49,   0, 102, 108, 111,
+  97, 116,  52,   0, -85, -85,
+   1,   0,   3,   0,   1,   0,
+   4,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,  47,   1,   0,   0,
+  95,  50,  48,  95, 109,  50,
+   0, 102, 108, 111,  97, 116,
+  50,   0, -85, -85,   1,   0,
+   3,   0,   1,   0,   2,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+  99,   1,   0,   0,  77, 105,
+  99, 114, 111, 115, 111, 102,
+ 116,  32,  40,  82,  41,  32,
+  72,  76,  83,  76,  32,  83,
+ 104,  97, 100, 101, 114,  32,
+  67, 111, 109, 112, 105, 108,
+ 101, 114,  32,  49,  48,  46,
+  49,   0,  73,  83,  71,  78,
+  92,   0,   0,   0,   3,   0,
+   0,   0,   8,   0,   0,   0,
+  80,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,   0,   0,
+   0,   0,   3,   3,   0,   0,
+  80,   0,   0,   0,   1,   0,
+   0,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,   1,   0,
+   0,   0,  15,  15,   0,   0,
+  80,   0,   0,   0,   2,   0,
+   0,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,   2,   0,
+   0,   0,   3,   3,   0,   0,
+  84,  69,  88,  67,  79,  79,
+  82,  68,   0, -85, -85, -85,
+  79,  83,  71,  78, 104,   0,
+   0,   0,   3,   0,   0,   0,
+   8,   0,   0,   0,  80,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   3,   0,
+   0,   0,   0,   0,   0,   0,
+  15,   0,   0,   0,  80,   0,
+   0,   0,   1,   0,   0,   0,
+   0,   0,   0,   0,   3,   0,
+   0,   0,   1,   0,   0,   0,
+   3,  12,   0,   0,  89,   0,
+   0,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,   3,   0,
+   0,   0,   2,   0,   0,   0,
+  15,   0,   0,   0,  84,  69,
+  88,  67,  79,  79,  82,  68,
+   0,  83,  86,  95,  80, 111,
+ 115, 105, 116, 105, 111, 110,
+   0, -85, -85, -85,  83,  72,
+  69,  88,  16,   1,   0,   0,
+  80,   0,   1,   0,  68,   0,
+   0,   0, 106,   8,   0,   1,
+  89,   0,   0,   4,  70,-114,
+  32,   0,   0,   0,   0,   0,
+   6,   0,   0,   0,  95,   0,
+   0,   3,  50,  16,  16,   0,
+   0,   0,   0,   0,  95,   0,
+   0,   3, -14,  16,  16,   0,
+   1,   0,   0,   0,  95,   0,
+   0,   3,  50,  16,  16,   0,
+   2,   0,   0,   0, 101,   0,
+   0,   3, -14,  32,  16,   0,
+   0,   0,   0,   0, 101,   0,
+   0,   3,  50,  32,  16,   0,
+   1,   0,   0,   0, 103,   0,
+   0,   4, -14,  32,  16,   0,
+   2,   0,   0,   0,   1,   0,
+   0,   0, 104,   0,   0,   2,
+   1,   0,   0,   0,  54,   0,
+   0,   5, -14,  32,  16,   0,
+   0,   0,   0,   0,  70,  30,
+  16,   0,   1,   0,   0,   0,
+  14,   0,   0,   8,  50,  32,
+  16,   0,   1,   0,   0,   0,
+  70,  16,  16,   0,   2,   0,
+   0,   0,  70,-128,  32,   0,
+   0,   0,   0,   0,   5,   0,
+   0,   0,  56,   0,   0,   8,
+ -14,   0,  16,   0,   0,   0,
+   0,   0,  86,  21,  16,   0,
+   0,   0,   0,   0,  70,-114,
+  32,   0,   0,   0,   0,   0,
+   1,   0,   0,   0,  50,   0,
+   0,  10, -14,   0,  16,   0,
+   0,   0,   0,   0,   6,  16,
+  16,   0,   0,   0,   0,   0,
+  70,-114,  32,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+  70,  14,  16,   0,   0,   0,
+   0,   0,   0,   0,   0,   8,
+ -14,  32,  16,   0,   2,   0,
+   0,   0,  70,  14,  16,   0,
+   0,   0,   0,   0,  70,-114,
+  32,   0,   0,   0,   0,   0,
+   3,   0,   0,   0,  62,   0,
+   0,   1,  83,  84,  65,  84,
+-108,   0,   0,   0,   6,   0,
+   0,   0,   1,   0,   0,   0,
+   0,   0,   0,   0,   6,   0,
+   0,   0,   4,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   1,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   1,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,
+   0,   0
+};

+ 558 - 0
src/render/sdlgpu/shaders/tri_texture.vert.sm60.dxil.h

@@ -0,0 +1,558 @@
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xy          0     NONE   float   xy  
+; TEXCOORD                 1   xyzw        1     NONE   float   xyzw
+; TEXCOORD                 2   xy          2     NONE   float   xy  
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xyzw        0     NONE   float   xyzw
+; TEXCOORD                 1   xy          1     NONE   float   xy  
+; SV_Position              0   xyzw        2      POS   float   xyzw
+;
+; shader hash: c10d07e0100207069cb29b72a35d05b6
+;
+; Pipeline Runtime Information: 
+;
+; Vertex Shader
+; OutputPositionPresent=1
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                              
+; TEXCOORD                 1                              
+; TEXCOORD                 2                              
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; TEXCOORD                 1                 linear       
+; SV_Position              0          noperspective       
+;
+; Buffer Definitions:
+;
+; cbuffer _18_20
+; {
+;
+;   struct hostlayout._18_20
+;   {
+;
+;       row_major float4x4 _20_m0;                    ; Offset:    0
+;       float4 _20_m1;                                ; Offset:   64
+;       float2 _20_m2;                                ; Offset:   80
+;   
+;   } _18_20;                                         ; Offset:    0 Size:    88
+;
+; }
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; _18_20                            cbuffer      NA          NA     CB0     cb0,space1     1
+;
+;
+; ViewId state:
+;
+; Number of inputs: 10, outputs: 12
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 4 }
+;   output 1 depends on inputs: { 5 }
+;   output 2 depends on inputs: { 6 }
+;   output 3 depends on inputs: { 7 }
+;   output 4 depends on inputs: { 8 }
+;   output 5 depends on inputs: { 9 }
+;   output 8 depends on inputs: { 0, 1 }
+;   output 9 depends on inputs: { 0, 1 }
+;   output 10 depends on inputs: { 0, 1 }
+;   output 11 depends on inputs: { 0, 1 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+%dx.types.Handle = type { i8* }
+%dx.types.CBufRet.f32 = type { float, float, float, float }
+%hostlayout._18_20 = type { [4 x <4 x float>], <4 x float>, <2 x float> }
+
+define void @main() {
+  %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %2 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %3 = call float @dx.op.loadInput.f32(i32 4, i32 2, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %5 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %6 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 2, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %7 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 3, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %8 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %9 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %10 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 0)  ; CBufferLoadLegacy(handle,regIndex)
+  %11 = extractvalue %dx.types.CBufRet.f32 %10, 0
+  %12 = extractvalue %dx.types.CBufRet.f32 %10, 1
+  %13 = extractvalue %dx.types.CBufRet.f32 %10, 2
+  %14 = extractvalue %dx.types.CBufRet.f32 %10, 3
+  %15 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %16 = extractvalue %dx.types.CBufRet.f32 %15, 0
+  %17 = extractvalue %dx.types.CBufRet.f32 %15, 1
+  %18 = extractvalue %dx.types.CBufRet.f32 %15, 2
+  %19 = extractvalue %dx.types.CBufRet.f32 %15, 3
+  %20 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 3)  ; CBufferLoadLegacy(handle,regIndex)
+  %21 = extractvalue %dx.types.CBufRet.f32 %20, 0
+  %22 = extractvalue %dx.types.CBufRet.f32 %20, 1
+  %23 = extractvalue %dx.types.CBufRet.f32 %20, 2
+  %24 = extractvalue %dx.types.CBufRet.f32 %20, 3
+  %25 = fmul fast float %11, %8
+  %26 = call float @dx.op.tertiary.f32(i32 46, float %9, float %16, float %25)  ; FMad(a,b,c)
+  %27 = fadd fast float %21, %26
+  %28 = fmul fast float %12, %8
+  %29 = call float @dx.op.tertiary.f32(i32 46, float %9, float %17, float %28)  ; FMad(a,b,c)
+  %30 = fadd fast float %29, %22
+  %31 = fmul fast float %13, %8
+  %32 = call float @dx.op.tertiary.f32(i32 46, float %9, float %18, float %31)  ; FMad(a,b,c)
+  %33 = fadd fast float %32, %23
+  %34 = fmul fast float %14, %8
+  %35 = call float @dx.op.tertiary.f32(i32 46, float %9, float %19, float %34)  ; FMad(a,b,c)
+  %36 = fadd fast float %35, %24
+  %37 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 5)  ; CBufferLoadLegacy(handle,regIndex)
+  %38 = extractvalue %dx.types.CBufRet.f32 %37, 0
+  %39 = extractvalue %dx.types.CBufRet.f32 %37, 1
+  %40 = fdiv fast float %2, %38
+  %41 = fdiv fast float %3, %39
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %4)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %5)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %6)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %7)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 0, float %40)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 1, float %41)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 2, i32 0, i8 0, float %27)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 2, i32 0, i8 1, float %30)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 2, i32 0, i8 2, float %33)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 2, i32 0, i8 3, float %36)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.tertiary.f32(i32, float, float, float) #0
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.resources = !{!4}
+!dx.viewIdState = !{!7}
+!dx.entryPoints = !{!8}
+
+!0 = !{!"dxc(private) 1.8.0.4662 (416fab6b5)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 8}
+!3 = !{!"vs", i32 6, i32 0}
+!4 = !{null, null, !5, null}
+!5 = !{!6}
+!6 = !{i32 0, %hostlayout._18_20* undef, !"", i32 1, i32 0, i32 1, i32 88, null}
+!7 = !{[12 x i32] [i32 10, i32 12, i32 3840, i32 3840, i32 0, i32 0, i32 1, i32 2, i32 4, i32 8, i32 16, i32 32]}
+!8 = !{void ()* @main, !"main", !9, !4, null}
+!9 = !{!10, !19, null}
+!10 = !{!11, !14, !17}
+!11 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !12, i8 0, i32 1, i8 2, i32 0, i8 0, !13}
+!12 = !{i32 0}
+!13 = !{i32 3, i32 3}
+!14 = !{i32 1, !"TEXCOORD", i8 9, i8 0, !15, i8 0, i32 1, i8 4, i32 1, i8 0, !16}
+!15 = !{i32 1}
+!16 = !{i32 3, i32 15}
+!17 = !{i32 2, !"TEXCOORD", i8 9, i8 0, !18, i8 0, i32 1, i8 2, i32 2, i8 0, !13}
+!18 = !{i32 2}
+!19 = !{!20, !21, !22}
+!20 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !12, i8 2, i32 1, i8 4, i32 0, i8 0, !16}
+!21 = !{i32 1, !"TEXCOORD", i8 9, i8 0, !15, i8 2, i32 1, i8 2, i32 1, i8 0, !13}
+!22 = !{i32 2, !"SV_Position", i8 9, i8 3, !12, i8 4, i32 1, i8 4, i32 2, i8 0, !16}
+
+#endif
+
+const unsigned char tri_texture_vert_sm60_dxil[] = {
+  0x44, 0x58, 0x42, 0x43, 0x1d, 0x39, 0x3a, 0xc6, 0x32, 0xb6, 0x8e, 0x58,
+  0x41, 0xa6, 0x3b, 0x02, 0xc5, 0x3c, 0xcc, 0x94, 0x01, 0x00, 0x00, 0x00,
+  0xc8, 0x10, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00,
+  0x8c, 0x02, 0x00, 0x00, 0x24, 0x09, 0x00, 0x00, 0x40, 0x09, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x74, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43,
+  0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x47, 0x31,
+  0x80, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x68, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5f,
+  0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x50, 0x53, 0x56, 0x30, 0x34, 0x01, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x01, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x34, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52,
+  0x44, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x54,
+  0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x54, 0x45, 0x58, 0x43,
+  0x4f, 0x4f, 0x52, 0x44, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52,
+  0x44, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x42, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x44, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x42, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x44, 0x00, 0x03, 0x02, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x42, 0x00, 0x03, 0x02, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x03,
+  0x03, 0x04, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0x90, 0x06, 0x00, 0x00,
+  0x60, 0x00, 0x01, 0x00, 0xa4, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c,
+  0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x78, 0x06, 0x00, 0x00,
+  0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x9b, 0x01, 0x00, 0x00,
+  0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39,
+  0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
+  0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14,
+  0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20,
+  0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90,
+  0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a,
+  0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d,
+  0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06,
+  0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x6c, 0x23, 0x00, 0x25, 0x00, 0x14, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x20, 0x84, 0x14,
+  0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1, 0xa3, 0x86, 0xcb, 0x9f,
+  0xb0, 0x87, 0x90, 0x7c, 0x6e, 0xa3, 0x8a, 0x95, 0x98, 0xfc, 0xe2, 0xb6,
+  0x11, 0x31, 0xc6, 0x18, 0x54, 0xee, 0x19, 0x2e, 0x7f, 0xc2, 0x1e, 0x42,
+  0xf2, 0x43, 0xa0, 0x19, 0x16, 0x02, 0x05, 0xab, 0x10, 0x8a, 0x30, 0x42,
+  0xad, 0x14, 0x83, 0x8c, 0x31, 0xe8, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0xa4,
+  0x10, 0x12, 0x49, 0x0e, 0x04, 0x0c, 0x23, 0x10, 0x43, 0x12, 0xd4, 0x61,
+  0x04, 0x61, 0xb8, 0xe8, 0x70, 0xa4, 0x69, 0x01, 0x30, 0x87, 0x9a, 0xfc,
+  0xbf, 0xe6, 0x7f, 0x9b, 0x46, 0x83, 0xad, 0x97, 0x70, 0x32, 0x10, 0x00,
+  0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79,
+  0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e,
+  0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e,
+  0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20,
+  0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34,
+  0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4,
+  0x79, 0x80, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+  0xc8, 0x23, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x40, 0x16, 0x08, 0x00, 0x14, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22,
+  0x25, 0x30, 0x02, 0x50, 0x0c, 0x05, 0x1b, 0x50, 0x04, 0x85, 0x50, 0x06,
+  0xe5, 0x50, 0x12, 0x05, 0x18, 0x50, 0x1a, 0x05, 0x1a, 0x50, 0x1e, 0x45,
+  0x51, 0x68, 0x05, 0x41, 0xa5, 0x24, 0x46, 0x00, 0x8a, 0xa0, 0x10, 0xca,
+  0x80, 0x62, 0x0d, 0x10, 0x9e, 0x01, 0xa0, 0x3c, 0x03, 0x40, 0x7a, 0x2c,
+  0x46, 0x61, 0x40, 0x7c, 0x00, 0xf1, 0x01, 0x00, 0x02, 0x81, 0x40, 0x20,
+  0x30, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00,
+  0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b,
+  0x43, 0x81, 0x93, 0x4b, 0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71,
+  0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb1, 0xb1, 0x91, 0x01, 0x41, 0xa1, 0x89,
+  0xb1, 0x31, 0x0b, 0x13, 0xb3, 0x11, 0xab, 0x49, 0xd9, 0x10, 0x04, 0x13,
+  0x04, 0xc2, 0x98, 0x20, 0x10, 0xc7, 0x06, 0x61, 0x20, 0x36, 0x08, 0x04,
+  0x41, 0xc1, 0x6e, 0x6e, 0x82, 0x40, 0x20, 0x1b, 0x86, 0x03, 0x21, 0x26,
+  0x08, 0x59, 0x47, 0xe3, 0x2b, 0x06, 0xe7, 0x4b, 0x06, 0x66, 0x82, 0x40,
+  0x24, 0x1b, 0x10, 0x42, 0x59, 0x06, 0x62, 0x60, 0x80, 0x0d, 0x41, 0xb3,
+  0x81, 0x00, 0x00, 0x07, 0x98, 0x20, 0x60, 0x1c, 0x8d, 0x2f, 0x19, 0x98,
+  0xaf, 0x36, 0x98, 0x09, 0x02, 0xa1, 0x4c, 0x10, 0x88, 0x65, 0xc3, 0x30,
+  0x4d, 0xc3, 0x04, 0x81, 0x60, 0x26, 0x08, 0x44, 0x33, 0x41, 0x20, 0x9c,
+  0x09, 0x42, 0xb4, 0x6d, 0x50, 0x90, 0x48, 0xa2, 0x2a, 0xc2, 0xba, 0x2e,
+  0x8c, 0xc6, 0x97, 0x0c, 0xcc, 0x57, 0x5b, 0xcc, 0x04, 0x81, 0x78, 0x26,
+  0x08, 0x04, 0xb4, 0x01, 0x41, 0xb4, 0x6a, 0xb3, 0x2e, 0x6e, 0xa2, 0xf1,
+  0x25, 0x03, 0xf3, 0xd5, 0x26, 0x33, 0x41, 0x20, 0xa2, 0x0d, 0x0a, 0xe2,
+  0x55, 0x9f, 0x75, 0x5d, 0x18, 0x27, 0x6d, 0x20, 0x98, 0xac, 0x03, 0x83,
+  0x0d, 0x03, 0x01, 0x85, 0xc1, 0x04, 0x41, 0x00, 0x36, 0x00, 0x1b, 0x06,
+  0x82, 0x0c, 0xc8, 0x60, 0x43, 0x50, 0x06, 0x1b, 0x86, 0x61, 0x0c, 0xcc,
+  0x60, 0x82, 0xa0, 0x79, 0x1b, 0x02, 0x34, 0x20, 0xd1, 0x16, 0x96, 0xe6,
+  0x46, 0x84, 0xaa, 0x08, 0x6b, 0xe8, 0xe9, 0x49, 0x8a, 0x68, 0x82, 0x50,
+  0x58, 0x13, 0x84, 0xe2, 0xda, 0x10, 0x10, 0x13, 0x84, 0x02, 0xdb, 0x20,
+  0x54, 0xd5, 0x86, 0x85, 0x58, 0x03, 0x36, 0x68, 0x03, 0x37, 0x68, 0x83,
+  0xe1, 0x0d, 0x88, 0x36, 0x80, 0x83, 0x0d, 0xc1, 0x30, 0x41, 0x28, 0xb2,
+  0x09, 0x02, 0x21, 0x6d, 0x10, 0x2a, 0x3a, 0xd8, 0xb0, 0x0c, 0x6b, 0xc0,
+  0x06, 0x6d, 0x20, 0x07, 0x6d, 0x30, 0xcc, 0xc1, 0xd0, 0x06, 0x75, 0xb0,
+  0x21, 0x90, 0x36, 0x2c, 0xd2, 0x1a, 0xb0, 0x41, 0x1b, 0xdc, 0x41, 0x1b,
+  0x0c, 0x6f, 0x20, 0xb5, 0x01, 0x1c, 0x6c, 0x18, 0xe2, 0xc0, 0x0e, 0xf0,
+  0x60, 0xc3, 0x42, 0xac, 0x01, 0x1b, 0xb4, 0x81, 0x1b, 0xbc, 0xc1, 0x30,
+  0x07, 0x44, 0x1b, 0xd4, 0xc1, 0x86, 0x65, 0x58, 0x03, 0x36, 0x68, 0x03,
+  0x39, 0x78, 0x83, 0xe1, 0x0d, 0x86, 0x36, 0x80, 0x03, 0x2e, 0x53, 0x56,
+  0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x13, 0x84, 0x42,
+  0xdb, 0xb0, 0x48, 0x7c, 0xc0, 0x06, 0x7d, 0xe0, 0x06, 0x73, 0x30, 0xcc,
+  0x81, 0xd4, 0x06, 0x75, 0xb0, 0x61, 0xd0, 0x83, 0x3d, 0xf0, 0x83, 0x0d,
+  0x43, 0x1e, 0xfc, 0x01, 0xb0, 0xa1, 0x18, 0x03, 0x35, 0x00, 0x85, 0x07,
+  0xa0, 0x61, 0xc6, 0xf6, 0x16, 0x46, 0x37, 0x37, 0x41, 0x20, 0x26, 0x16,
+  0x69, 0x6e, 0x73, 0x74, 0x73, 0x13, 0x04, 0x82, 0xa2, 0x31, 0x97, 0x76,
+  0xf6, 0xc5, 0x46, 0x36, 0x41, 0x20, 0x2a, 0x1a, 0x73, 0x69, 0x67, 0x5f,
+  0x73, 0x74, 0x1b, 0x10, 0x51, 0x18, 0x05, 0x52, 0x28, 0x05, 0x53, 0x38,
+  0x05, 0x54, 0x18, 0x85, 0x2a, 0x6c, 0x6c, 0x76, 0x6d, 0x2e, 0x69, 0x64,
+  0x65, 0x6e, 0x74, 0x53, 0x82, 0xa0, 0x0a, 0x19, 0x9e, 0x8b, 0x5d, 0x99,
+  0xdc, 0x5c, 0xda, 0x9b, 0xdb, 0x94, 0x80, 0x68, 0x42, 0x86, 0xe7, 0x62,
+  0x17, 0xc6, 0x66, 0x57, 0x26, 0x37, 0x25, 0x28, 0xea, 0x90, 0xe1, 0xb9,
+  0xcc, 0xa1, 0x85, 0x91, 0x95, 0xc9, 0x35, 0xbd, 0x91, 0x95, 0xb1, 0x4d,
+  0x09, 0x90, 0x32, 0x64, 0x78, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72,
+  0x63, 0x65, 0x73, 0x53, 0x02, 0xa7, 0x12, 0x19, 0x9e, 0x0b, 0x5d, 0x1e,
+  0x5c, 0x59, 0x90, 0x9b, 0xdb, 0x1b, 0x5d, 0x18, 0x5d, 0xda, 0x9b, 0xdb,
+  0xdc, 0x14, 0x21, 0x0c, 0xcc, 0xa0, 0x0e, 0x19, 0x9e, 0x8b, 0x5d, 0x5a,
+  0xd9, 0x5d, 0x12, 0xd9, 0x14, 0x5d, 0x18, 0x5d, 0xd9, 0x94, 0x00, 0x0d,
+  0xea, 0x90, 0xe1, 0xb9, 0x94, 0xb9, 0xd1, 0xc9, 0xe5, 0x41, 0xbd, 0xa5,
+  0xb9, 0xd1, 0xcd, 0x4d, 0x09, 0x40, 0xa1, 0x0b, 0x19, 0x9e, 0xcb, 0xd8,
+  0x5b, 0x9d, 0x1b, 0x5d, 0x99, 0xdc, 0xdc, 0x94, 0x00, 0x15, 0x00, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c,
+  0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3,
+  0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6,
+  0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03,
+  0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48,
+  0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20,
+  0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e,
+  0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d,
+  0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89,
+  0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83,
+  0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78,
+  0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98,
+  0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5,
+  0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c,
+  0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43,
+  0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82,
+  0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70,
+  0x03, 0x72, 0x10, 0x87, 0x73, 0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60,
+  0x87, 0x70, 0xc8, 0x87, 0x77, 0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4,
+  0x80, 0x0f, 0x6e, 0x40, 0x0f, 0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00,
+  0x71, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x36, 0xb0, 0x0d, 0x97,
+  0xef, 0x3c, 0xbe, 0x10, 0x50, 0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25,
+  0x61, 0x00, 0x02, 0xe6, 0x17, 0xb7, 0x6d, 0x05, 0xd2, 0x70, 0xf9, 0xce,
+  0xe3, 0x0b, 0x11, 0x01, 0x4c, 0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0xc0,
+  0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x8b, 0x03, 0x0c, 0x62, 0xf3, 0x50, 0x93,
+  0x5f, 0xdc, 0xb6, 0x09, 0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x4d, 0x4e,
+  0x44, 0xa0, 0xd4, 0xf4, 0x50, 0x93, 0x5f, 0xdc, 0xb6, 0x11, 0x48, 0xc3,
+  0xe5, 0x3b, 0x8f, 0x3f, 0x11, 0xd1, 0x84, 0x00, 0x11, 0xe6, 0x17, 0xb7,
+  0x6d, 0x00, 0x04, 0x03, 0x20, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc1, 0x0d, 0x07, 0xe0, 0x10, 0x02, 0x07, 0x06, 0x9c, 0xb2, 0x9b, 0x72,
+  0xa3, 0x5d, 0x05, 0xb6, 0x44, 0x58, 0x49, 0x4c, 0x80, 0x07, 0x00, 0x00,
+  0x60, 0x00, 0x01, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c,
+  0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x68, 0x07, 0x00, 0x00,
+  0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xd7, 0x01, 0x00, 0x00,
+  0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39,
+  0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
+  0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14,
+  0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20,
+  0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90,
+  0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a,
+  0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d,
+  0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06,
+  0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x6c, 0x23, 0x00, 0x25, 0x00, 0x14, 0x66,
+  0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x20, 0x84, 0x14,
+  0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1, 0xa3, 0x86, 0xcb, 0x9f,
+  0xb0, 0x87, 0x90, 0x7c, 0x6e, 0xa3, 0x8a, 0x95, 0x98, 0xfc, 0xe2, 0xb6,
+  0x11, 0x31, 0xc6, 0x18, 0x54, 0xee, 0x19, 0x2e, 0x7f, 0xc2, 0x1e, 0x42,
+  0xf2, 0x43, 0xa0, 0x19, 0x16, 0x02, 0x05, 0xab, 0x10, 0x8a, 0x30, 0x42,
+  0xad, 0x14, 0x83, 0x8c, 0x31, 0xe8, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0xa4,
+  0x10, 0x12, 0x49, 0x0e, 0x04, 0x0c, 0x23, 0x10, 0x43, 0x12, 0xd4, 0x61,
+  0x04, 0x61, 0xb8, 0xe8, 0x70, 0xa4, 0x69, 0x01, 0x30, 0x87, 0x9a, 0xfc,
+  0xbf, 0xe6, 0x7f, 0x9b, 0x46, 0x83, 0xad, 0x97, 0x70, 0x32, 0x10, 0x00,
+  0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79,
+  0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e,
+  0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e,
+  0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20,
+  0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34,
+  0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4,
+  0x79, 0x80, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+  0xc8, 0x23, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x40, 0x16, 0x08, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14,
+  0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22,
+  0x25, 0x30, 0x02, 0x50, 0x10, 0xc5, 0x50, 0xb0, 0x01, 0x65, 0x50, 0x1e,
+  0x45, 0x40, 0xa5, 0x24, 0x46, 0x00, 0x8a, 0xa0, 0x10, 0xca, 0x80, 0xf2,
+  0x0c, 0x00, 0xe9, 0xb1, 0x18, 0x85, 0x01, 0xf1, 0x01, 0xc4, 0x07, 0x00,
+  0x08, 0x04, 0x02, 0x81, 0xc0, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00,
+  0x5f, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4,
+  0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b, 0xb3, 0x0b, 0xa3, 0x2b,
+  0x4b, 0x01, 0x89, 0x71, 0xc1, 0x71, 0x81, 0x71, 0xa1, 0xb1, 0xb1, 0x91,
+  0x01, 0x41, 0xa1, 0x89, 0xb1, 0x31, 0x0b, 0x13, 0xb3, 0x11, 0xab, 0x49,
+  0xd9, 0x10, 0x04, 0x13, 0x04, 0xc2, 0x98, 0x20, 0x10, 0xc7, 0x06, 0x61,
+  0x20, 0x26, 0x08, 0x04, 0xb2, 0x41, 0x18, 0x0c, 0x0a, 0x76, 0x73, 0x13,
+  0x04, 0x22, 0xd9, 0x30, 0x20, 0x09, 0x31, 0x41, 0xc8, 0x26, 0x02, 0x13,
+  0x04, 0x42, 0xd9, 0x80, 0x10, 0x0b, 0x33, 0x10, 0x43, 0x03, 0x6c, 0x08,
+  0x9c, 0x0d, 0x04, 0x00, 0x3c, 0xc0, 0x04, 0x41, 0xa3, 0x36, 0x04, 0xd1,
+  0x04, 0x41, 0x00, 0x48, 0xb4, 0x85, 0xa5, 0xb9, 0x11, 0xa1, 0x2a, 0xc2,
+  0x1a, 0x7a, 0x7a, 0x92, 0x22, 0x9a, 0x20, 0x14, 0xce, 0x04, 0xa1, 0x78,
+  0x36, 0x04, 0xc4, 0x04, 0xa1, 0x80, 0x26, 0x08, 0xc4, 0xb2, 0x41, 0xd0,
+  0xb4, 0x0d, 0x0b, 0x51, 0x59, 0x17, 0x76, 0x0d, 0x19, 0x71, 0x6d, 0x1b,
+  0x82, 0x61, 0x82, 0x50, 0x44, 0x13, 0x04, 0x82, 0xd9, 0x20, 0x68, 0xdf,
+  0x86, 0x65, 0xa8, 0xac, 0xab, 0xbb, 0x06, 0x6f, 0xb8, 0xc0, 0x60, 0x82,
+  0x40, 0x34, 0x1b, 0x02, 0x31, 0xd8, 0xb0, 0x88, 0x41, 0x65, 0x5d, 0x63,
+  0x70, 0x0d, 0x99, 0x18, 0x5c, 0xdb, 0x86, 0x81, 0x0b, 0x03, 0x32, 0xd8,
+  0xb0, 0x10, 0x95, 0x75, 0x61, 0xd9, 0xe0, 0x11, 0x17, 0x18, 0x6c, 0x58,
+  0x86, 0xca, 0xba, 0xba, 0x6c, 0xc8, 0x86, 0x6b, 0xe3, 0x32, 0x65, 0xf5,
+  0x05, 0xf5, 0x36, 0x97, 0x46, 0x97, 0xf6, 0xe6, 0x36, 0x41, 0x28, 0xa4,
+  0x0d, 0x8b, 0x18, 0xa0, 0x81, 0x95, 0x06, 0x98, 0x37, 0x78, 0x62, 0x70,
+  0x81, 0xc1, 0x86, 0xc1, 0x0c, 0xce, 0x40, 0x0d, 0x36, 0x0c, 0x65, 0xb0,
+  0x06, 0xc0, 0x86, 0x62, 0xa2, 0xd8, 0x00, 0x02, 0xaa, 0xb0, 0xb1, 0xd9,
+  0xb5, 0xb9, 0xa4, 0x91, 0x95, 0xb9, 0xd1, 0x4d, 0x09, 0x82, 0x2a, 0x64,
+  0x78, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x02, 0xa2,
+  0x09, 0x19, 0x9e, 0x8b, 0x5d, 0x18, 0x9b, 0x5d, 0x99, 0xdc, 0x94, 0xc0,
+  0xa8, 0x43, 0x86, 0xe7, 0x32, 0x87, 0x16, 0x46, 0x56, 0x26, 0xd7, 0xf4,
+  0x46, 0x56, 0xc6, 0x36, 0x25, 0x48, 0xca, 0x90, 0xe1, 0xb9, 0xc8, 0x95,
+  0xcd, 0xbd, 0xd5, 0xc9, 0x8d, 0x95, 0xcd, 0x4d, 0x09, 0x9e, 0x3a, 0x64,
+  0x78, 0x2e, 0x76, 0x69, 0x65, 0x77, 0x49, 0x64, 0x53, 0x74, 0x61, 0x74,
+  0x65, 0x53, 0x82, 0xa8, 0x0e, 0x19, 0x9e, 0x4b, 0x99, 0x1b, 0x9d, 0x5c,
+  0x1e, 0xd4, 0x5b, 0x9a, 0x1b, 0xdd, 0xdc, 0x94, 0x80, 0x0d, 0x00, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c,
+  0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3,
+  0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6,
+  0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03,
+  0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48,
+  0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20,
+  0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e,
+  0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d,
+  0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89,
+  0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83,
+  0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78,
+  0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98,
+  0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5,
+  0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c,
+  0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43,
+  0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82,
+  0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70,
+  0x03, 0x72, 0x10, 0x87, 0x73, 0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60,
+  0x87, 0x70, 0xc8, 0x87, 0x77, 0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4,
+  0x80, 0x0f, 0x6e, 0x40, 0x0f, 0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00,
+  0x71, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x36, 0xb0, 0x0d, 0x97,
+  0xef, 0x3c, 0xbe, 0x10, 0x50, 0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25,
+  0x61, 0x00, 0x02, 0xe6, 0x17, 0xb7, 0x6d, 0x05, 0xd2, 0x70, 0xf9, 0xce,
+  0xe3, 0x0b, 0x11, 0x01, 0x4c, 0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0xc0,
+  0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x8b, 0x03, 0x0c, 0x62, 0xf3, 0x50, 0x93,
+  0x5f, 0xdc, 0xb6, 0x09, 0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x4d, 0x4e,
+  0x44, 0xa0, 0xd4, 0xf4, 0x50, 0x93, 0x5f, 0xdc, 0xb6, 0x11, 0x48, 0xc3,
+  0xe5, 0x3b, 0x8f, 0x3f, 0x11, 0xd1, 0x84, 0x00, 0x11, 0xe6, 0x17, 0xb7,
+  0x6d, 0x00, 0x04, 0x03, 0x20, 0x0d, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00,
+  0x79, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x44, 0x4a, 0xa1, 0x10, 0x66, 0x00, 0xca, 0xae,
+  0xb8, 0x4a, 0x8e, 0x4a, 0x09, 0x50, 0x1c, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x20, 0x61, 0x43, 0x63, 0x59, 0xc1,
+  0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x1d, 0x12, 0x5d, 0xcf, 0x31,
+  0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x86, 0x97, 0x48, 0x18, 0x81, 0x8c,
+  0x18, 0x24, 0x00, 0x08, 0x82, 0x81, 0xf1, 0x29, 0x5a, 0x16, 0x25, 0x23,
+  0x06, 0x09, 0x00, 0x82, 0x60, 0x60, 0x80, 0xc1, 0xb2, 0x69, 0x86, 0x32,
+  0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x46, 0x18, 0x30, 0xdc, 0x26, 0x2d,
+  0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x60, 0x88, 0x41, 0xd3, 0x71, 0x11,
+  0x33, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xc6, 0x18, 0x38, 0x5d, 0x57,
+  0x35, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x60, 0x90, 0xc1, 0xe3, 0x79,
+  0x8a, 0x33, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0xcd, 0x18, 0x38, 0xc9,
+  0x37, 0x9a, 0x10, 0x00, 0xa3, 0x09, 0x42, 0x30, 0x9a, 0x30, 0x08, 0xa3,
+  0x09, 0xc4, 0x30, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x0d, 0x1a, 0x4c,
+  0x4e, 0x19, 0x8c, 0x26, 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c, 0x26, 0x0c,
+  0xc2, 0x68, 0x02, 0x31, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0x41, 0xd3,
+  0x06, 0xd8, 0x54, 0x06, 0xa3, 0x09, 0x01, 0x30, 0x9a, 0x20, 0x04, 0xa3,
+  0x09, 0x83, 0x30, 0x9a, 0x40, 0x0c, 0xe6, 0x44, 0xf2, 0x19, 0x31, 0x40,
+  0x00, 0x10, 0x04, 0x83, 0x47, 0x0e, 0xba, 0x48, 0x09, 0xcc, 0x08, 0xa0,
+  0x63, 0x10, 0x25, 0x9f, 0x11, 0x03, 0x04, 0x00, 0x41, 0x30, 0x78, 0xea,
+  0x00, 0x0c, 0x28, 0x26, 0xb0, 0x00, 0x81, 0x8e, 0x49, 0x97, 0x7c, 0x46,
+  0x0c, 0x10, 0x00, 0x04, 0xc1, 0xe0, 0xc1, 0x83, 0x31, 0xb8, 0x9c, 0xc0,
+  0x02, 0x05, 0x3a, 0x46, 0x69, 0xf2, 0x19, 0x31, 0x40, 0x00, 0x10, 0x04,
+  0x83, 0x67, 0x0f, 0xcc, 0x40, 0x83, 0x02, 0x0b, 0x18, 0xe8, 0x8c, 0x18,
+  0x1c, 0x00, 0x08, 0x82, 0x41, 0xe3, 0x07, 0x69, 0x40, 0x06, 0x6c, 0x30,
+  0x9a, 0x10, 0x00, 0xa3, 0x09, 0x42, 0x60, 0x66, 0x20, 0xd0, 0xc7, 0xcc,
+  0x40, 0xa0, 0xcf, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xa4, 0x10,
+  0x07, 0x7f, 0xf0, 0x07, 0x77, 0x60, 0x06, 0x23, 0x06, 0x09, 0x00, 0x82,
+  0x60, 0x80, 0x90, 0x42, 0x1c, 0xfc, 0xc1, 0x1f, 0xac, 0x41, 0x19, 0x8c,
+  0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x42, 0x0a, 0x71, 0xf0, 0x07, 0x7f,
+  0x60, 0x07, 0x64, 0x30, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x08, 0x29,
+  0xc4, 0xc1, 0x1f, 0xfc, 0x01, 0x1d, 0x8c, 0xc1, 0x88, 0x41, 0x02, 0x80,
+  0x20, 0x18, 0x20, 0xa4, 0x10, 0x07, 0xa0, 0xf0, 0x07, 0x77, 0x20, 0x8c,
+  0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x42, 0x0a, 0x71, 0x00, 0x0a, 0x7f,
+  0xb0, 0x06, 0xc1, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0xa4, 0x10,
+  0x07, 0x79, 0xf0, 0x07, 0x77, 0xf0, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82,
+  0x01, 0x42, 0x0a, 0x71, 0x90, 0x07, 0x7f, 0xb0, 0x06, 0xcc, 0x88, 0x41,
+  0x02, 0x80, 0x20, 0x18, 0x20, 0xa4, 0x10, 0x07, 0x79, 0xf0, 0x07, 0x76,
+  0x90, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x42, 0x0a, 0x71, 0x90,
+  0x07, 0x7f, 0x40, 0x07, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};

+ 106 - 0
src/render/sdlgpu/shaders/tri_texture.vert.spv.h

@@ -0,0 +1,106 @@
+const unsigned char tri_texture_vert_spv[] = {
+  0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x25, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00,
+  0x12, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x14, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x25, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x28, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x29, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x15, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x06, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
+  0x0e, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
+  0x11, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x05, 0x00, 0x12, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+  0x20, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x21, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x27, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x27, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x1a, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x91, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x03, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x23, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
+  0x29, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x2c, 0x00, 0x00, 0x00,
+  0x2d, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
+  0x2d, 0x00, 0x00, 0x00, 0x88, 0x00, 0x05, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x2f, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x28, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00,
+  0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+};
+const unsigned int tri_texture_vert_spv_len = 1232;

+ 11 - 0
src/video/directx/SDL_d3d12.h

@@ -75,6 +75,12 @@
 #ifndef D3D12_TEXTURE_DATA_PITCH_ALIGNMENT
 #define D3D12_TEXTURE_DATA_PITCH_ALIGNMENT 256
 #endif
+#ifndef D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE
+#define D3D12_RESOURCE_STATE_ALL_SHADER_RESOURCE ((D3D12_RESOURCE_STATES) (0x40 | 0x80))
+#endif
+#ifndef D3D12_HEAP_TYPE_GPU_UPLOAD
+#define D3D12_HEAP_TYPE_GPU_UPLOAD ((D3D12_HEAP_TYPE) 5)
+#endif
 
 // DXGI_PRESENT flags are removed on Xbox
 #define DXGI_PRESENT_ALLOW_TEARING 0
@@ -82,6 +88,11 @@
 // Xbox D3D12 does not define the COBJMACROS, so we need to define them ourselves
 #include "SDL_d3d12_xbox_cmacros.h"
 
+// They don't even define the CMACROS for ID3DBlob, come on man
+#define ID3D10Blob_GetBufferPointer(blob) blob->GetBufferPointer()
+#define ID3D10Blob_GetBufferSize(blob) blob->GetBufferSize()
+#define ID3D10Blob_Release(blob) blob->Release()
+
 /* Xbox's D3D12 ABI actually varies from Windows, if a function does not exist
  * in the above header then you need to use this instead :(
  */

+ 1 - 0
test/CMakeLists.txt

@@ -401,6 +401,7 @@ add_sdl_test_executable(testcontroller TESTUTILS SOURCES testcontroller.c gamepa
 add_sdl_test_executable(testgeometry TESTUTILS SOURCES testgeometry.c)
 add_sdl_test_executable(testgl SOURCES testgl.c)
 add_sdl_test_executable(testgles SOURCES testgles.c)
+add_sdl_test_executable(testgpu_spinning_cube SOURCES testgpu_spinning_cube.c)
 if(ANDROID)
     target_link_libraries(testgles PRIVATE GLESv1_CM)
 elseif(IOS OR TVOS)

+ 103 - 0
test/testgpu/build-shaders.sh

@@ -0,0 +1,103 @@
+# Rebuilds the shaders needed for the GPU cube test.
+# For SPIR-V: requires glslangValidator and spirv-cross, which can be obtained from the LunarG Vulkan SDK.
+# For DXBC compilation: requires FXC, which is part of the Windows SDK.
+# For DXIL compilation, requires DXC, which can be obtained via the Windows SDK or via here: https://github.com/microsoft/DirectXShaderCompiler/releases
+# For Metal compilation: requires Xcode
+
+# On Windows, run this via Git Bash.
+# To add the Windows SDK (FXC/DXC) to your path, run the command:
+#   `export PATH=$PATH:/c/Program\ Files\ \(x86\)/Windows\ Kits/10/bin/x.x.x.x/x64/`
+
+export MSYS_NO_PATHCONV=1
+
+# SPIR-V
+glslangValidator cube.glsl -V -S vert -o cube.vert.spv --quiet -DVERTEX
+glslangValidator cube.glsl -V -S frag -o cube.frag.spv --quiet
+xxd -i cube.vert.spv | perl -w -p -e 's/\Aunsigned /const unsigned /;' > cube.vert.h
+xxd -i cube.frag.spv | perl -w -p -e 's/\Aunsigned /const unsigned /;' > cube.frag.h
+cat cube.vert.h cube.frag.h > testgpu_spirv.h
+rm -f cube.vert.h cube.frag.h cube.vert.spv cube.frag.spv
+
+# Platform-specific compilation
+if [[ "$OSTYPE" == "darwin"* ]]; then
+
+    # FIXME: Needs to be updated!
+
+    # Xcode
+    generate_shaders()
+    {
+        fileplatform=$1
+        compileplatform=$2
+        sdkplatform=$3
+        minversion=$4
+
+        xcrun -sdk $sdkplatform metal -c -std=$compileplatform-metal1.1 -m$sdkplatform-version-min=$minversion -Wall -O3 -DVERTEX=1 -o ./cube.vert.air ./cube.metal || exit $?
+        xcrun -sdk $sdkplatform metal -c -std=$compileplatform-metal1.1 -m$sdkplatform-version-min=$minversion -Wall -O3 -o ./cube.frag.air ./cube.metal || exit $?
+
+        xcrun -sdk $sdkplatform metallib -o cube.vert.metallib cube.vert.air || exit $?
+        xcrun -sdk $sdkplatform metallib -o cube.frag.metallib cube.frag.air || exit $?
+
+        xxd -i cube.vert.metallib | perl -w -p -e 's/\Aunsigned /const unsigned /;' >./cube.vert_$fileplatform.h
+        xxd -i cube.frag.metallib | perl -w -p -e 's/\Aunsigned /const unsigned /;' >./cube.frag_$fileplatform.h
+
+        rm -f cube.vert.air cube.vert.metallib
+        rm -f cube.frag.air cube.frag.metallib
+    }
+
+    generate_shaders macos macos macosx 10.11
+    generate_shaders ios ios iphoneos 8.0
+    generate_shaders iphonesimulator ios iphonesimulator 8.0
+    generate_shaders tvos ios appletvos 9.0
+    generate_shaders tvsimulator ios appletvsimulator 9.0
+
+    # Bundle together one mega-header
+    rm -f testgpu_metallib.h
+    echo "#if defined(SDL_PLATFORM_IOS)" >> testgpu_metallib.h
+        echo "#if TARGET_OS_SIMULATOR" >> testgpu_metallib.h
+            cat cube.vert_iphonesimulator.h >> testgpu_metallib.h
+            cat cube.frag_iphonesimulator.h >> testgpu_metallib.h
+        echo "#else" >> testgpu_metallib.h
+            cat cube.vert_ios.h >> testgpu_metallib.h
+            cat cube.frag_ios.h >> testgpu_metallib.h
+        echo "#endif" >> testgpu_metallib.h
+    echo "#elif defined(SDL_PLATFORM_TVOS)" >> testgpu_metallib.h
+        echo "#if TARGET_OS_SIMULATOR" >> testgpu_metallib.h
+            cat cube.vert_tvsimulator.h >> testgpu_metallib.h
+            cat cube.frag_tvsimulator.h >> testgpu_metallib.h
+        echo "#else" >> testgpu_metallib.h
+            cat cube.vert_tvos.h >> testgpu_metallib.h
+            cat cube.frag_tvos.h >> testgpu_metallib.h
+        echo "#endif" >> testgpu_metallib.h
+    echo "#else" >> testgpu_metallib.h
+        cat cube.vert_macos.h >> testgpu_metallib.h
+        cat cube.frag_macos.h >> testgpu_metallib.h
+    echo "#endif" >> testgpu_metallib.h
+
+    # Clean up
+    rm -f cube.vert_macos.h cube.frag_macos.h
+    rm -f cube.vert_iphonesimulator.h cube.frag_iphonesimulator.h
+    rm -f cube.vert_tvsimulator.h cube.frag_tvsimulator.h
+    rm -f cube.vert_ios.h cube.frag_ios.h
+    rm -f cube.vert_tvos.h cube.frag_tvos.h
+
+elif [[ "$OSTYPE" == "cygwin"* ]] || [[ "$OSTYPE" == "msys"* ]]; then
+
+    # FXC
+    fxc cube.hlsl /E VSMain /T vs_5_0 /Fh cube.vert.h
+    fxc cube.hlsl /E PSMain /T ps_5_0 /Fh cube.frag.h
+
+    cat cube.vert.h | perl -w -p -e 's/BYTE/unsigned char/;s/g_VSMain/D3D11_CubeVert/;' > cube.vert.temp.h
+    cat cube.frag.h | perl -w -p -e 's/BYTE/unsigned char/;s/g_PSMain/D3D11_CubeFrag/;' > cube.frag.temp.h
+    cat cube.vert.temp.h cube.frag.temp.h > testgpu_dxbc.h
+    rm -f cube.vert.h cube.frag.h cube.vert.temp.h cube.frag.temp.h
+
+    # DXC
+    dxc cube.hlsl /E VSMain /T vs_6_0 /Fh cube.vert.h /D D3D12=1
+    dxc cube.hlsl /E PSMain /T ps_6_0 /Fh cube.frag.h /D D3D12=1
+
+    cat cube.vert.h | perl -w -p -e 's/BYTE/unsigned char/;s/g_VSMain/D3D12_CubeVert/;' > cube.vert.temp.h
+    cat cube.frag.h | perl -w -p -e 's/BYTE/unsigned char/;s/g_PSMain/D3D12_CubeFrag/;' > cube.frag.temp.h
+    cat cube.vert.temp.h cube.frag.temp.h > testgpu_dxil.h
+    rm -f cube.vert.h cube.frag.h cube.vert.temp.h cube.frag.temp.h
+
+fi

+ 31 - 0
test/testgpu/cube.glsl

@@ -0,0 +1,31 @@
+#version 450
+
+#ifdef VERTEX
+
+layout (location = 0) in vec3 in_position;
+layout (location = 1) in vec3 in_color;
+
+layout (location = 0) out vec4 out_color;
+
+layout (set = 1, binding = 0) uniform UBO
+{
+    mat4x4 modelViewProj;
+};
+
+void main()
+{
+    out_color = vec4(in_color, 1.0);
+    gl_Position = modelViewProj * vec4(in_position, 1.0);
+}
+
+#else
+
+layout (location = 0) in vec4 in_color;
+layout (location = 0) out vec4 out_color;
+
+void main()
+{
+    out_color = in_color;
+}
+
+#endif

+ 35 - 0
test/testgpu/cube.hlsl

@@ -0,0 +1,35 @@
+#if D3D12
+#define REG(reg, space) register(reg, space)
+#else
+#define REG(reg, space) register(reg)
+#endif
+
+cbuffer UBO : REG(b0, space1)
+{
+    float4x4 ModelViewProj;
+};
+
+struct VSInput
+{
+    float3 Position : TEXCOORD0;
+    float3 Color : TEXCOORD1;
+};
+
+struct VSOutput
+{
+    float4 Color : TEXCOORD0;
+    float4 Position : SV_Position;
+};
+
+VSOutput VSMain(VSInput input)
+{
+    VSOutput output;
+    output.Color = float4(input.Color, 1.0f);
+    output.Position = mul(ModelViewProj, float4(input.Position, 1.0f));
+    return output;
+}
+
+float4 PSMain(VSOutput input) : SV_Target0
+{
+    return input.Color;
+}

+ 38 - 0
test/testgpu/cube.metal

@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+using namespace metal;
+
+struct VSOutput
+{
+    float4 color [[user(locn0)]];
+    float4 position [[position]];
+};
+
+#ifdef VERTEX
+
+struct UBO
+{
+    float4x4 modelViewProj;
+};
+
+struct VSInput
+{
+    float3 position [[attribute(0)]];
+    float3 color [[attribute(1)]];
+};
+
+vertex VSOutput vs_main(VSInput input [[stage_in]], constant UBO& ubo [[buffer(0)]])
+{
+    VSOutput output;
+    output.color = float4(input.color, 1.0);
+    output.position = ubo.modelViewProj * float4(input.position, 1.0);
+    return output;
+}
+
+#else
+
+fragment float4 fs_main(VSOutput input [[stage_in]])
+{
+    return input.color;
+}
+
+#endif

+ 333 - 0
test/testgpu/testgpu_dxbc.h

@@ -0,0 +1,333 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions: 
+//
+// cbuffer UBO
+// {
+//
+//   float4x4 ModelViewProj;            // Offset:    0 Size:    64
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name                                 Type  Format         Dim      HLSL Bind  Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// UBO                               cbuffer      NA          NA            cb0      1 
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// TEXCOORD                 0   xyz         0     NONE   float   xyz 
+// TEXCOORD                 1   xyz         1     NONE   float   xyz 
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// TEXCOORD                 0   xyzw        0     NONE   float   xyzw
+// SV_Position              0   xyzw        1      POS   float   xyzw
+//
+vs_5_0
+dcl_globalFlags refactoringAllowed
+dcl_constantbuffer CB0[4], immediateIndexed
+dcl_input v0.xyz
+dcl_input v1.xyz
+dcl_output o0.xyzw
+dcl_output_siv o1.xyzw, position
+dcl_temps 1
+mov o0.xyz, v1.xyzx
+mov o0.w, l(1.000000)
+mul r0.xyzw, v0.yyyy, cb0[1].xyzw
+mad r0.xyzw, cb0[0].xyzw, v0.xxxx, r0.xyzw
+mad r0.xyzw, cb0[2].xyzw, v0.zzzz, r0.xyzw
+add o1.xyzw, r0.xyzw, cb0[3].xyzw
+ret 
+// Approximately 7 instruction slots used
+#endif
+
+const unsigned char D3D11_CubeVert[] =
+{
+     68,  88,  66,  67, 114,  13, 
+     37,  16,  19,   3, 132,  73, 
+    243,  18,  23, 177, 140, 169, 
+     19, 240,   1,   0,   0,   0, 
+    156,   3,   0,   0,   5,   0, 
+      0,   0,  52,   0,   0,   0, 
+     64,   1,   0,   0, 140,   1, 
+      0,   0, 228,   1,   0,   0, 
+      0,   3,   0,   0,  82,  68, 
+     69,  70,   4,   1,   0,   0, 
+      1,   0,   0,   0,  96,   0, 
+      0,   0,   1,   0,   0,   0, 
+     60,   0,   0,   0,   0,   5, 
+    254, 255,   0,   1,   0,   0, 
+    220,   0,   0,   0,  82,  68, 
+     49,  49,  60,   0,   0,   0, 
+     24,   0,   0,   0,  32,   0, 
+      0,   0,  40,   0,   0,   0, 
+     36,   0,   0,   0,  12,   0, 
+      0,   0,   0,   0,   0,   0, 
+     92,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0,  85,  66,  79,   0, 
+     92,   0,   0,   0,   1,   0, 
+      0,   0, 120,   0,   0,   0, 
+     64,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    160,   0,   0,   0,   0,   0, 
+      0,   0,  64,   0,   0,   0, 
+      2,   0,   0,   0, 184,   0, 
+      0,   0,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0,  77, 111, 
+    100, 101, 108,  86, 105, 101, 
+    119,  80, 114, 111, 106,   0, 
+    102, 108, 111,  97, 116,  52, 
+    120,  52,   0, 171,   3,   0, 
+      3,   0,   4,   0,   4,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    174,   0,   0,   0,  77, 105, 
+     99, 114, 111, 115, 111, 102, 
+    116,  32,  40,  82,  41,  32, 
+     72,  76,  83,  76,  32,  83, 
+    104,  97, 100, 101, 114,  32, 
+     67, 111, 109, 112, 105, 108, 
+    101, 114,  32,  49,  48,  46, 
+     49,   0,  73,  83,  71,  78, 
+     68,   0,   0,   0,   2,   0, 
+      0,   0,   8,   0,   0,   0, 
+     56,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,   7,   7,   0,   0, 
+     56,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   1,   0, 
+      0,   0,   7,   7,   0,   0, 
+     84,  69,  88,  67,  79,  79, 
+     82,  68,   0, 171, 171, 171, 
+     79,  83,  71,  78,  80,   0, 
+      0,   0,   2,   0,   0,   0, 
+      8,   0,   0,   0,  56,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+     15,   0,   0,   0,  65,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+     15,   0,   0,   0,  84,  69, 
+     88,  67,  79,  79,  82,  68, 
+      0,  83,  86,  95,  80, 111, 
+    115, 105, 116, 105, 111, 110, 
+      0, 171, 171, 171,  83,  72, 
+     69,  88,  20,   1,   0,   0, 
+     80,   0,   1,   0,  69,   0, 
+      0,   0, 106,   8,   0,   1, 
+     89,   0,   0,   4,  70, 142, 
+     32,   0,   0,   0,   0,   0, 
+      4,   0,   0,   0,  95,   0, 
+      0,   3, 114,  16,  16,   0, 
+      0,   0,   0,   0,  95,   0, 
+      0,   3, 114,  16,  16,   0, 
+      1,   0,   0,   0, 101,   0, 
+      0,   3, 242,  32,  16,   0, 
+      0,   0,   0,   0, 103,   0, 
+      0,   4, 242,  32,  16,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0, 104,   0,   0,   2, 
+      1,   0,   0,   0,  54,   0, 
+      0,   5, 114,  32,  16,   0, 
+      0,   0,   0,   0,  70,  18, 
+     16,   0,   1,   0,   0,   0, 
+     54,   0,   0,   5, 130,  32, 
+     16,   0,   0,   0,   0,   0, 
+      1,  64,   0,   0,   0,   0, 
+    128,  63,  56,   0,   0,   8, 
+    242,   0,  16,   0,   0,   0, 
+      0,   0,  86,  21,  16,   0, 
+      0,   0,   0,   0,  70, 142, 
+     32,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  50,   0, 
+      0,  10, 242,   0,  16,   0, 
+      0,   0,   0,   0,  70, 142, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   6,  16, 
+     16,   0,   0,   0,   0,   0, 
+     70,  14,  16,   0,   0,   0, 
+      0,   0,  50,   0,   0,  10, 
+    242,   0,  16,   0,   0,   0, 
+      0,   0,  70, 142,  32,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0, 166,  26,  16,   0, 
+      0,   0,   0,   0,  70,  14, 
+     16,   0,   0,   0,   0,   0, 
+      0,   0,   0,   8, 242,  32, 
+     16,   0,   1,   0,   0,   0, 
+     70,  14,  16,   0,   0,   0, 
+      0,   0,  70, 142,  32,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,  62,   0,   0,   1, 
+     83,  84,  65,  84, 148,   0, 
+      0,   0,   7,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   4,   0,   0,   0, 
+      4,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0
+};
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// TEXCOORD                 0   xyzw        0     NONE   float   xyzw
+// SV_Position              0   xyzw        1      POS   float       
+//
+//
+// Output signature:
+//
+// Name                 Index   Mask Register SysValue  Format   Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target                0   xyzw        0   TARGET   float   xyzw
+//
+ps_5_0
+dcl_globalFlags refactoringAllowed
+dcl_input_ps linear v0.xyzw
+dcl_output o0.xyzw
+mov o0.xyzw, v0.xyzw
+ret 
+// Approximately 2 instruction slots used
+#endif
+
+const unsigned char D3D11_CubeFrag[] =
+{
+     68,  88,  66,  67, 100,  36, 
+     97,  53, 102, 218, 120, 105, 
+     57,  43, 222, 229,  58,  45, 
+    195, 237,   1,   0,   0,   0, 
+     12,   2,   0,   0,   5,   0, 
+      0,   0,  52,   0,   0,   0, 
+    160,   0,   0,   0, 248,   0, 
+      0,   0,  44,   1,   0,   0, 
+    112,   1,   0,   0,  82,  68, 
+     69,  70, 100,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     60,   0,   0,   0,   0,   5, 
+    255, 255,   0,   1,   0,   0, 
+     60,   0,   0,   0,  82,  68, 
+     49,  49,  60,   0,   0,   0, 
+     24,   0,   0,   0,  32,   0, 
+      0,   0,  40,   0,   0,   0, 
+     36,   0,   0,   0,  12,   0, 
+      0,   0,   0,   0,   0,   0, 
+     77, 105,  99, 114, 111, 115, 
+    111, 102, 116,  32,  40,  82, 
+     41,  32,  72,  76,  83,  76, 
+     32,  83, 104,  97, 100, 101, 
+    114,  32,  67, 111, 109, 112, 
+    105, 108, 101, 114,  32,  49, 
+     48,  46,  49,   0,  73,  83, 
+     71,  78,  80,   0,   0,   0, 
+      2,   0,   0,   0,   8,   0, 
+      0,   0,  56,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      0,   0,   0,   0,  15,  15, 
+      0,   0,  65,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   3,   0,   0,   0, 
+      1,   0,   0,   0,  15,   0, 
+      0,   0,  84,  69,  88,  67, 
+     79,  79,  82,  68,   0,  83, 
+     86,  95,  80, 111, 115, 105, 
+    116, 105, 111, 110,   0, 171, 
+    171, 171,  79,  83,  71,  78, 
+     44,   0,   0,   0,   1,   0, 
+      0,   0,   8,   0,   0,   0, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,  15,   0,   0,   0, 
+     83,  86,  95,  84,  97, 114, 
+    103, 101, 116,   0, 171, 171, 
+     83,  72,  69,  88,  60,   0, 
+      0,   0,  80,   0,   0,   0, 
+     15,   0,   0,   0, 106,   8, 
+      0,   1,  98,  16,   0,   3, 
+    242,  16,  16,   0,   0,   0, 
+      0,   0, 101,   0,   0,   3, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0,  54,   0,   0,   5, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0,  70,  30,  16,   0, 
+      0,   0,   0,   0,  62,   0, 
+      0,   1,  83,  84,  65,  84, 
+    148,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0
+};

+ 876 - 0
test/testgpu/testgpu_dxil.h

@@ -0,0 +1,876 @@
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xyz         0     NONE   float   xyz 
+; TEXCOORD                 1   xyz         1     NONE   float   xyz 
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xyzw        0     NONE   float   xyzw
+; SV_Position              0   xyzw        1      POS   float   xyzw
+;
+; shader hash: c5bd114f25804a8a068a89dafb8ca2d1
+;
+; Pipeline Runtime Information: 
+;
+; Vertex Shader
+; OutputPositionPresent=1
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                              
+; TEXCOORD                 1                              
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; SV_Position              0          noperspective       
+;
+; Buffer Definitions:
+;
+; cbuffer UBO
+; {
+;
+;   struct hostlayout.UBO
+;   {
+;
+;       column_major float4x4 ModelViewProj;          ; Offset:    0
+;   
+;   } UBO;                                            ; Offset:    0 Size:    64
+;
+; }
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+; UBO                               cbuffer      NA          NA     CB0     cb0,space1     1
+;
+;
+; ViewId state:
+;
+; Number of inputs: 7, outputs: 8
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 4 }
+;   output 1 depends on inputs: { 5 }
+;   output 2 depends on inputs: { 6 }
+;   output 4 depends on inputs: { 0, 1, 2 }
+;   output 5 depends on inputs: { 0, 1, 2 }
+;   output 6 depends on inputs: { 0, 1, 2 }
+;   output 7 depends on inputs: { 0, 1, 2 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+%dx.types.Handle = type { i8* }
+%dx.types.CBufRet.f32 = type { float, float, float, float }
+%hostlayout.UBO = type { [4 x <4 x float>] }
+
+define void @VSMain() {
+  %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false)  ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex)
+  %2 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %3 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 2, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %6 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %7 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 2, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %8 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 0)  ; CBufferLoadLegacy(handle,regIndex)
+  %9 = extractvalue %dx.types.CBufRet.f32 %8, 0
+  %10 = extractvalue %dx.types.CBufRet.f32 %8, 1
+  %11 = extractvalue %dx.types.CBufRet.f32 %8, 2
+  %12 = extractvalue %dx.types.CBufRet.f32 %8, 3
+  %13 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 1)  ; CBufferLoadLegacy(handle,regIndex)
+  %14 = extractvalue %dx.types.CBufRet.f32 %13, 0
+  %15 = extractvalue %dx.types.CBufRet.f32 %13, 1
+  %16 = extractvalue %dx.types.CBufRet.f32 %13, 2
+  %17 = extractvalue %dx.types.CBufRet.f32 %13, 3
+  %18 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 2)  ; CBufferLoadLegacy(handle,regIndex)
+  %19 = extractvalue %dx.types.CBufRet.f32 %18, 0
+  %20 = extractvalue %dx.types.CBufRet.f32 %18, 1
+  %21 = extractvalue %dx.types.CBufRet.f32 %18, 2
+  %22 = extractvalue %dx.types.CBufRet.f32 %18, 3
+  %23 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %1, i32 3)  ; CBufferLoadLegacy(handle,regIndex)
+  %24 = extractvalue %dx.types.CBufRet.f32 %23, 0
+  %25 = extractvalue %dx.types.CBufRet.f32 %23, 1
+  %26 = extractvalue %dx.types.CBufRet.f32 %23, 2
+  %27 = extractvalue %dx.types.CBufRet.f32 %23, 3
+  %28 = fmul fast float %9, %5
+  %29 = call float @dx.op.tertiary.f32(i32 46, float %14, float %6, float %28)  ; FMad(a,b,c)
+  %30 = call float @dx.op.tertiary.f32(i32 46, float %19, float %7, float %29)  ; FMad(a,b,c)
+  %31 = fadd fast float %30, %24
+  %32 = fmul fast float %10, %5
+  %33 = call float @dx.op.tertiary.f32(i32 46, float %15, float %6, float %32)  ; FMad(a,b,c)
+  %34 = call float @dx.op.tertiary.f32(i32 46, float %20, float %7, float %33)  ; FMad(a,b,c)
+  %35 = fadd fast float %34, %25
+  %36 = fmul fast float %11, %5
+  %37 = call float @dx.op.tertiary.f32(i32 46, float %16, float %6, float %36)  ; FMad(a,b,c)
+  %38 = call float @dx.op.tertiary.f32(i32 46, float %21, float %7, float %37)  ; FMad(a,b,c)
+  %39 = fadd fast float %38, %26
+  %40 = fmul fast float %12, %5
+  %41 = call float @dx.op.tertiary.f32(i32 46, float %17, float %6, float %40)  ; FMad(a,b,c)
+  %42 = call float @dx.op.tertiary.f32(i32 46, float %22, float %7, float %41)  ; FMad(a,b,c)
+  %43 = fadd fast float %42, %27
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %2)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %3)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %4)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float 1.000000e+00)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 0, float %31)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 1, float %35)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 2, float %39)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 3, float %43)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+; Function Attrs: nounwind readonly
+declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.tertiary.f32(i32, float, float, float) #0
+
+; Function Attrs: nounwind readonly
+declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind readonly }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.resources = !{!4}
+!dx.viewIdState = !{!7}
+!dx.entryPoints = !{!8}
+
+!0 = !{!"dxc(private) 1.7.0.3896 (021f8f3e1)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 6}
+!3 = !{!"vs", i32 6, i32 0}
+!4 = !{null, null, !5, null}
+!5 = !{!6}
+!6 = !{i32 0, %hostlayout.UBO* undef, !"", i32 1, i32 0, i32 1, i32 64, null}
+!7 = !{[9 x i32] [i32 7, i32 8, i32 240, i32 240, i32 240, i32 0, i32 1, i32 2, i32 4]}
+!8 = !{void ()* @VSMain, !"VSMain", !9, !4, null}
+!9 = !{!10, !16, null}
+!10 = !{!11, !14}
+!11 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !12, i8 0, i32 1, i8 3, i32 0, i8 0, !13}
+!12 = !{i32 0}
+!13 = !{i32 3, i32 7}
+!14 = !{i32 1, !"TEXCOORD", i8 9, i8 0, !15, i8 0, i32 1, i8 3, i32 1, i8 0, !13}
+!15 = !{i32 1}
+!16 = !{!17, !19}
+!17 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !12, i8 2, i32 1, i8 4, i32 0, i8 0, !18}
+!18 = !{i32 3, i32 15}
+!19 = !{i32 1, !"SV_Position", i8 9, i8 3, !12, i8 4, i32 1, i8 4, i32 1, i8 0, !18}
+
+#endif
+
+const unsigned char D3D12_CubeVert[] = {
+  0x44, 0x58, 0x42, 0x43, 0xd9, 0x52, 0xf4, 0xa2, 0x04, 0x60, 0xc4, 0x95,
+  0x5b, 0x00, 0x57, 0x3a, 0x22, 0x9c, 0xc9, 0x7e, 0x01, 0x00, 0x00, 0x00,
+  0xa3, 0x0f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00,
+  0xff, 0x01, 0x00, 0x00, 0x27, 0x08, 0x00, 0x00, 0x43, 0x08, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x5a, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x54, 0x45, 0x58,
+  0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x31, 0x5d, 0x00,
+  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00,
+  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x53,
+  0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x50,
+  0x53, 0x56, 0x30, 0xe4, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x54, 0x45, 0x58,
+  0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f,
+  0x52, 0x44, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x43, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x43, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x44, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x01, 0x44, 0x03, 0x03, 0x04, 0x00, 0x00, 0xf0,
+  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0x20,
+  0x06, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x88, 0x01, 0x00, 0x00, 0x44,
+  0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08,
+  0x06, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x7f,
+  0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13,
+  0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06,
+  0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e,
+  0x04, 0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4,
+  0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48,
+  0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4,
+  0x48, 0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1,
+  0x83, 0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40,
+  0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d,
+  0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49,
+  0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20,
+  0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x23,
+  0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93,
+  0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12,
+  0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x68, 0x23, 0x00, 0x25,
+  0x00, 0x14, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6,
+  0x20, 0x84, 0x14, 0x42, 0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1, 0xa3,
+  0x86, 0xcb, 0x9f, 0xb0, 0x87, 0x90, 0x7c, 0x6e, 0xa3, 0x8a, 0x95, 0x98,
+  0xfc, 0xe2, 0xb6, 0x11, 0x31, 0xc6, 0x18, 0x54, 0xee, 0x19, 0x2e, 0x7f,
+  0xc2, 0x1e, 0x42, 0xf2, 0x43, 0xa0, 0x19, 0x16, 0x02, 0x05, 0xab, 0x10,
+  0x8a, 0x30, 0x42, 0xad, 0x14, 0x83, 0x8c, 0x31, 0xe8, 0xcd, 0x11, 0x04,
+  0xc5, 0x60, 0xa4, 0x10, 0x12, 0x49, 0x0e, 0x04, 0x0c, 0x23, 0x10, 0x43,
+  0x12, 0xd4, 0x73, 0x0e, 0x47, 0x9a, 0x16, 0x00, 0x73, 0xa8, 0xc9, 0x77,
+  0x37, 0x14, 0x05, 0x96, 0x6e, 0x26, 0x10, 0x00, 0x00, 0x00, 0x00, 0x13,
+  0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68,
+  0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a,
+  0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71,
+  0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d,
+  0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40,
+  0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x79,
+  0x80, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8,
+  0x23, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+  0x16, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19,
+  0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x25,
+  0x30, 0x02, 0x50, 0x0c, 0x05, 0x18, 0x50, 0x04, 0x85, 0x50, 0x06, 0xe5,
+  0x50, 0x12, 0xe5, 0x51, 0x10, 0x85, 0x46, 0xa5, 0x24, 0x46, 0x00, 0xca,
+  0xa0, 0x08, 0x0a, 0x81, 0xee, 0x0c, 0x00, 0xe1, 0x19, 0x00, 0xca, 0x63,
+  0x25, 0x07, 0x02, 0x1f, 0xf0, 0x01, 0x1f, 0x40, 0x20, 0x10, 0x00, 0x79,
+  0x18, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46,
+  0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b, 0xb3,
+  0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xb9, 0x71, 0x81, 0x71, 0x99,
+  0xc1, 0xc9, 0xb1, 0x01, 0x41, 0x81, 0x91, 0x89, 0x31, 0xc3, 0x31, 0x9b,
+  0x29, 0x8b, 0x49, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xc2, 0x98, 0x20, 0x10,
+  0xc7, 0x06, 0x61, 0x20, 0x36, 0x08, 0x04, 0x41, 0xc1, 0x6e, 0x6e, 0x82,
+  0x40, 0x20, 0x1b, 0x86, 0x03, 0x21, 0x26, 0x08, 0x18, 0xc6, 0xa1, 0x4a,
+  0xe8, 0x69, 0x82, 0x40, 0x24, 0x1b, 0x10, 0x42, 0x59, 0x06, 0x62, 0x60,
+  0x80, 0x0d, 0x41, 0xb3, 0x81, 0x00, 0x00, 0x07, 0x98, 0x20, 0x5c, 0x17,
+  0x9b, 0xa6, 0x37, 0xb2, 0x32, 0x36, 0xab, 0xb4, 0xb2, 0x3b, 0x28, 0xb9,
+  0x37, 0xb5, 0x09, 0x02, 0xa1, 0x4c, 0x10, 0x88, 0x65, 0xc3, 0x30, 0x4d,
+  0xd2, 0x04, 0x81, 0x60, 0x26, 0x08, 0x44, 0x33, 0x41, 0x20, 0x9c, 0x0d,
+  0x08, 0x12, 0x49, 0x54, 0x45, 0x58, 0xd7, 0x06, 0x81, 0xc1, 0x36, 0x0c,
+  0x04, 0x94, 0x4d, 0x10, 0x04, 0x60, 0x03, 0xb0, 0x61, 0x20, 0x38, 0x6e,
+  0x43, 0xd0, 0x6d, 0x18, 0x86, 0xcd, 0x9b, 0x20, 0x64, 0xd9, 0x86, 0x00,
+  0x0c, 0x68, 0x58, 0x4d, 0x35, 0x85, 0xa5, 0xb9, 0x11, 0xa1, 0x2a, 0xc2,
+  0x1a, 0x7a, 0x7a, 0x92, 0x22, 0x9a, 0x20, 0x14, 0xd2, 0x04, 0xa1, 0x98,
+  0x36, 0x04, 0xc4, 0x04, 0xa1, 0xa0, 0x36, 0x08, 0x95, 0xb5, 0x61, 0x21,
+  0xc6, 0x80, 0x0c, 0xca, 0xc0, 0x0c, 0xca, 0x60, 0x38, 0x03, 0xa2, 0x0c,
+  0xd0, 0x60, 0x43, 0x30, 0x6c, 0x58, 0x86, 0x31, 0x20, 0x83, 0x32, 0x50,
+  0x83, 0x32, 0x18, 0xce, 0x60, 0x28, 0x03, 0x34, 0xd8, 0x20, 0xa4, 0xc1,
+  0x1a, 0x4c, 0x10, 0x8a, 0x6a, 0x82, 0x50, 0x58, 0x13, 0x04, 0xe2, 0xd9,
+  0x20, 0x54, 0x6f, 0xb0, 0x61, 0x21, 0xc6, 0x80, 0x0c, 0xca, 0xc0, 0x0c,
+  0xda, 0x60, 0x70, 0x03, 0xa2, 0x0c, 0xe0, 0x80, 0xcb, 0x94, 0xd5, 0x17,
+  0xd4, 0xdb, 0x5c, 0x1a, 0x5d, 0xda, 0x9b, 0xdb, 0x86, 0x65, 0x90, 0x03,
+  0x32, 0x38, 0x03, 0x33, 0x70, 0x83, 0xc1, 0x0d, 0x86, 0x32, 0x80, 0x83,
+  0x0d, 0x42, 0x1c, 0xcc, 0xc1, 0x86, 0x81, 0x0d, 0xe8, 0x00, 0xd8, 0x50,
+  0x6c, 0x62, 0x50, 0x07, 0x0f, 0x40, 0xc3, 0x8c, 0xed, 0x2d, 0x8c, 0x6e,
+  0x6e, 0x82, 0x40, 0x40, 0x2c, 0xd2, 0xdc, 0xe6, 0xe8, 0xe6, 0x26, 0x08,
+  0x44, 0x44, 0x63, 0x2e, 0xed, 0xec, 0x8b, 0x8d, 0x8c, 0xc6, 0x5c, 0xda,
+  0xd9, 0xd7, 0x1c, 0xdd, 0x06, 0xe4, 0x0e, 0xf0, 0x20, 0x0f, 0xf4, 0x60,
+  0x0f, 0x10, 0x3e, 0xc0, 0x83, 0x2a, 0x6c, 0x6c, 0x76, 0x6d, 0x2e, 0x69,
+  0x64, 0x65, 0x6e, 0x74, 0x53, 0x82, 0xa0, 0x0a, 0x19, 0x9e, 0x8b, 0x5d,
+  0x99, 0xdc, 0x5c, 0xda, 0x9b, 0xdb, 0x94, 0x80, 0x68, 0x42, 0x86, 0xe7,
+  0x62, 0x17, 0xc6, 0x66, 0x57, 0x26, 0x37, 0x25, 0x28, 0xea, 0x90, 0xe1,
+  0xb9, 0xcc, 0xa1, 0x85, 0x91, 0x95, 0xc9, 0x35, 0xbd, 0x91, 0x95, 0xb1,
+  0x4d, 0x09, 0x90, 0x32, 0x64, 0x78, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75,
+  0x72, 0x63, 0x65, 0x73, 0x53, 0x02, 0xa7, 0x12, 0x19, 0x9e, 0x0b, 0x5d,
+  0x1e, 0x5c, 0x59, 0x90, 0x9b, 0xdb, 0x1b, 0x5d, 0x18, 0x5d, 0xda, 0x9b,
+  0xdb, 0xdc, 0x14, 0x21, 0xf3, 0xea, 0x90, 0xe1, 0xb9, 0xd8, 0xa5, 0x95,
+  0xdd, 0x25, 0x91, 0x4d, 0xd1, 0x85, 0xd1, 0x95, 0x4d, 0x09, 0xc0, 0xa0,
+  0x0e, 0x19, 0x9e, 0x4b, 0x99, 0x1b, 0x9d, 0x5c, 0x1e, 0xd4, 0x5b, 0x9a,
+  0x1b, 0xdd, 0xdc, 0x94, 0xa0, 0x0e, 0xba, 0x90, 0xe1, 0xb9, 0x8c, 0xbd,
+  0xd5, 0xb9, 0xd1, 0x95, 0xc9, 0xcd, 0x4d, 0x09, 0xf8, 0x00, 0x00, 0x79,
+  0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4,
+  0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c,
+  0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00,
+  0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2,
+  0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38,
+  0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d,
+  0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87,
+  0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87,
+  0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30,
+  0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde,
+  0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b,
+  0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c,
+  0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07,
+  0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87,
+  0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87,
+  0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87,
+  0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0,
+  0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc,
+  0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4,
+  0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39,
+  0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38,
+  0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b,
+  0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70, 0x03,
+  0x72, 0x10, 0x87, 0x73, 0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60, 0x87,
+  0x70, 0xc8, 0x87, 0x77, 0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4, 0x80,
+  0x0f, 0x6e, 0x40, 0x0f, 0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x71,
+  0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x06, 0x60, 0xbc, 0xac, 0x09,
+  0x20, 0x8d, 0x0d, 0x6c, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x04, 0x54, 0x51,
+  0x10, 0x51, 0xe9, 0x00, 0x43, 0x49, 0x18, 0x80, 0x80, 0xf9, 0xc5, 0x6d,
+  0x5b, 0x81, 0x34, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x44, 0x00, 0x13, 0x11,
+  0x02, 0xcd, 0xb0, 0x10, 0x16, 0x30, 0x0d, 0x97, 0xef, 0x3c, 0xfe, 0xe2,
+  0x00, 0x83, 0xd8, 0x3c, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x02, 0xd5, 0x70,
+  0xf9, 0xce, 0xe3, 0x4b, 0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4,
+  0x17, 0xb7, 0x6d, 0x04, 0xd2, 0x70, 0xf9, 0xce, 0xe3, 0x4f, 0x44, 0x34,
+  0x21, 0x40, 0x84, 0xf9, 0xc5, 0x6d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x48,
+  0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5,
+  0xbd, 0x11, 0x4f, 0x25, 0x80, 0x4a, 0x8a, 0x06, 0x8a, 0x89, 0xda, 0xfb,
+  0x8c, 0xa2, 0xd1, 0x44, 0x58, 0x49, 0x4c, 0x58, 0x07, 0x00, 0x00, 0x60,
+  0x00, 0x01, 0x00, 0xd6, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00,
+  0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x40, 0x07, 0x00, 0x00, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xcd, 0x01, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43,
+  0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x91,
+  0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04,
+  0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b,
+  0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84,
+  0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04,
+  0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b,
+  0x84, 0xa4, 0x4c, 0x10, 0x68, 0x23, 0x00, 0x25, 0x00, 0x14, 0x66, 0x00,
+  0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x20, 0x84, 0x14, 0x42,
+  0xa6, 0x18, 0x80, 0x10, 0x52, 0x06, 0xa1, 0xa3, 0x86, 0xcb, 0x9f, 0xb0,
+  0x87, 0x90, 0x7c, 0x6e, 0xa3, 0x8a, 0x95, 0x98, 0xfc, 0xe2, 0xb6, 0x11,
+  0x31, 0xc6, 0x18, 0x54, 0xee, 0x19, 0x2e, 0x7f, 0xc2, 0x1e, 0x42, 0xf2,
+  0x43, 0xa0, 0x19, 0x16, 0x02, 0x05, 0xab, 0x10, 0x8a, 0x30, 0x42, 0xad,
+  0x14, 0x83, 0x8c, 0x31, 0xe8, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0xa4, 0x10,
+  0x12, 0x49, 0x0e, 0x04, 0x0c, 0x23, 0x10, 0x43, 0x12, 0xd4, 0x73, 0x0e,
+  0x47, 0x9a, 0x16, 0x00, 0x73, 0xa8, 0xc9, 0x77, 0x37, 0x14, 0x05, 0x96,
+  0x6e, 0x26, 0x10, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87,
+  0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87,
+  0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00,
+  0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0,
+  0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60,
+  0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60,
+  0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0,
+  0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x79, 0x80, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, 0x23, 0x01, 0x01, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x16, 0x08, 0x00, 0x0e,
+  0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c,
+  0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x25, 0x30, 0x02, 0x50, 0x0c,
+  0x05, 0x18, 0x50, 0x06, 0xe5, 0x50, 0x1e, 0x54, 0x4a, 0x62, 0x04, 0xa0,
+  0x0c, 0x8a, 0xa0, 0x10, 0x08, 0xcf, 0x00, 0x50, 0x1e, 0x2b, 0x39, 0x10,
+  0xf8, 0x80, 0x0f, 0xf8, 0x00, 0x02, 0x81, 0x00, 0x00, 0x00, 0x00, 0x79,
+  0x18, 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46,
+  0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43, 0x81, 0x93, 0x4b, 0xb3,
+  0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xb9, 0x71, 0x81, 0x71, 0x99,
+  0xc1, 0xc9, 0xb1, 0x01, 0x41, 0x81, 0x91, 0x89, 0x31, 0xc3, 0x31, 0x9b,
+  0x29, 0x8b, 0x49, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xc2, 0x98, 0x20, 0x10,
+  0xc7, 0x06, 0x61, 0x20, 0x26, 0x08, 0x04, 0xb2, 0x41, 0x18, 0x0c, 0x0a,
+  0x76, 0x73, 0x1b, 0x06, 0xc4, 0x20, 0x26, 0x08, 0x98, 0x44, 0x60, 0x82,
+  0x40, 0x24, 0x1b, 0x10, 0x42, 0x59, 0x06, 0x62, 0x60, 0x80, 0x0d, 0x41,
+  0xb3, 0x81, 0x00, 0x00, 0x07, 0x98, 0x20, 0x64, 0xd3, 0x86, 0x00, 0x9a,
+  0x20, 0x08, 0x00, 0x0d, 0xab, 0xa9, 0xa6, 0xb0, 0x34, 0x37, 0x22, 0x54,
+  0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x13, 0x84, 0xa2, 0x99, 0x20,
+  0x14, 0xce, 0x86, 0x80, 0x98, 0x20, 0x14, 0xcf, 0x04, 0x81, 0x50, 0x26,
+  0x08, 0xc4, 0xb2, 0x41, 0xc8, 0xb4, 0x0d, 0x0b, 0x41, 0x55, 0xd6, 0x65,
+  0x0d, 0x18, 0x61, 0x6d, 0x1b, 0x82, 0x61, 0xc3, 0x32, 0x50, 0x95, 0xd5,
+  0x59, 0x03, 0x36, 0x58, 0xdb, 0x06, 0x81, 0xf3, 0x26, 0x08, 0x05, 0x34,
+  0x41, 0x28, 0xa2, 0x09, 0x02, 0xc1, 0x6c, 0x10, 0x32, 0x31, 0xd8, 0xb0,
+  0x10, 0x54, 0x65, 0x5d, 0x60, 0x30, 0x84, 0x01, 0x61, 0x8d, 0x01, 0x97,
+  0x29, 0xab, 0x2f, 0xa8, 0xb7, 0xb9, 0x34, 0xba, 0xb4, 0x37, 0xb7, 0x0d,
+  0xcb, 0x50, 0x06, 0x15, 0x76, 0x85, 0xc1, 0x10, 0x06, 0x83, 0x35, 0x06,
+  0x1b, 0x04, 0x32, 0x30, 0x83, 0x0d, 0xc3, 0x77, 0x06, 0xc0, 0x86, 0x42,
+  0x9a, 0xd0, 0xe0, 0x01, 0xaa, 0xb0, 0xb1, 0xd9, 0xb5, 0xb9, 0xa4, 0x91,
+  0x95, 0xb9, 0xd1, 0x4d, 0x09, 0x82, 0x2a, 0x64, 0x78, 0x2e, 0x76, 0x65,
+  0x72, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x02, 0xa2, 0x09, 0x19, 0x9e, 0x8b,
+  0x5d, 0x18, 0x9b, 0x5d, 0x99, 0xdc, 0x94, 0xc0, 0xa8, 0x43, 0x86, 0xe7,
+  0x32, 0x87, 0x16, 0x46, 0x56, 0x26, 0xd7, 0xf4, 0x46, 0x56, 0xc6, 0x36,
+  0x25, 0x40, 0xca, 0x90, 0xe1, 0xb9, 0xc8, 0x95, 0xcd, 0xbd, 0xd5, 0xc9,
+  0x8d, 0x95, 0xcd, 0x4d, 0x09, 0x9c, 0x3a, 0x64, 0x78, 0x2e, 0x76, 0x69,
+  0x65, 0x77, 0x49, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x02, 0xa8,
+  0x0e, 0x19, 0x9e, 0x4b, 0x99, 0x1b, 0x9d, 0x5c, 0x1e, 0xd4, 0x5b, 0x9a,
+  0x1b, 0xdd, 0xdc, 0x94, 0x00, 0x0d, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x8c, 0xc8, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x72, 0x10, 0x87, 0x73,
+  0x70, 0x03, 0x7b, 0x08, 0x07, 0x79, 0x60, 0x87, 0x70, 0xc8, 0x87, 0x77,
+  0xa8, 0x07, 0x7a, 0x98, 0x81, 0x3c, 0xe4, 0x80, 0x0f, 0x6e, 0x40, 0x0f,
+  0xe5, 0xd0, 0x0e, 0xf0, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x18,
+  0x00, 0x00, 0x00, 0x06, 0x60, 0xbc, 0xac, 0x09, 0x20, 0x8d, 0x0d, 0x6c,
+  0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x04, 0x54, 0x51, 0x10, 0x51, 0xe9, 0x00,
+  0x43, 0x49, 0x18, 0x80, 0x80, 0xf9, 0xc5, 0x6d, 0x5b, 0x81, 0x34, 0x5c,
+  0xbe, 0xf3, 0xf8, 0x42, 0x44, 0x00, 0x13, 0x11, 0x02, 0xcd, 0xb0, 0x10,
+  0x16, 0x30, 0x0d, 0x97, 0xef, 0x3c, 0xfe, 0xe2, 0x00, 0x83, 0xd8, 0x3c,
+  0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x02, 0xd5, 0x70, 0xf9, 0xce, 0xe3, 0x4b,
+  0x93, 0x13, 0x11, 0x28, 0x35, 0x3d, 0xd4, 0xe4, 0x17, 0xb7, 0x6d, 0x04,
+  0xd2, 0x70, 0xf9, 0xce, 0xe3, 0x4f, 0x44, 0x34, 0x21, 0x40, 0x84, 0xf9,
+  0xc5, 0x6d, 0x03, 0x61, 0x20, 0x00, 0x00, 0x79, 0x00, 0x00, 0x00, 0x13,
+  0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x14,
+  0x47, 0x00, 0x88, 0x14, 0x57, 0x29, 0x14, 0xc2, 0x0c, 0x40, 0xd9, 0x95,
+  0x5c, 0x11, 0x50, 0x29, 0x01, 0x1a, 0x63, 0x04, 0x20, 0x08, 0x82, 0xf8,
+  0x07, 0x00, 0x00, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x20, 0x65, 0x84,
+  0x73, 0x5d, 0xca, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x1e, 0x92,
+  0x61, 0xd1, 0x31, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xc6, 0x97, 0x68,
+  0x19, 0x81, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x81, 0x01, 0x06, 0xca,
+  0xa6, 0x45, 0xc9, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x61, 0xb0,
+  0x6c, 0x1b, 0xa5, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x81, 0x21, 0x06,
+  0x0c, 0xc7, 0x1d, 0xcb, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x63,
+  0xd0, 0x74, 0x1d, 0xc5, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0x41, 0x23,
+  0x06, 0xcc, 0xe1, 0x8d, 0x26, 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c, 0x26,
+  0x0c, 0xc2, 0x68, 0x02, 0x31, 0x8c, 0x18, 0x1c, 0x00, 0x08, 0x82, 0x41,
+  0x73, 0x06, 0x11, 0x43, 0x06, 0xa3, 0x09, 0x01, 0x30, 0x9a, 0x20, 0x04,
+  0xa3, 0x09, 0x83, 0x30, 0x9a, 0x40, 0x0c, 0x23, 0x06, 0x07, 0x00, 0x82,
+  0x60, 0xd0, 0xb0, 0x81, 0x15, 0x51, 0xa3, 0x09, 0x01, 0x30, 0x9a, 0x20,
+  0x04, 0xa3, 0x09, 0x83, 0x30, 0x9a, 0x40, 0x0c, 0x23, 0x06, 0x07, 0x00,
+  0x82, 0x60, 0xd0, 0xc4, 0xc1, 0x66, 0xa9, 0xc1, 0x68, 0x42, 0x00, 0x8c,
+  0x26, 0x08, 0xc1, 0x68, 0xc2, 0x20, 0x8c, 0x26, 0x10, 0x83, 0x4d, 0x97,
+  0x7c, 0x46, 0x0c, 0x10, 0x00, 0x04, 0xc1, 0xe0, 0xb1, 0x83, 0x32, 0x78,
+  0xae, 0x60, 0xc4, 0x00, 0x01, 0x40, 0x10, 0x0c, 0x9e, 0x3b, 0x30, 0x83,
+  0xe5, 0x0a, 0x2c, 0x38, 0xa0, 0x63, 0xd6, 0x26, 0x9f, 0x11, 0x03, 0x04,
+  0x00, 0x41, 0x30, 0x78, 0xf4, 0x20, 0x0d, 0xa4, 0x2d, 0x18, 0x31, 0x40,
+  0x00, 0x10, 0x04, 0x83, 0x67, 0x0f, 0xd4, 0xc0, 0xd9, 0x02, 0x0b, 0x14,
+  0xe8, 0x58, 0xf6, 0xc9, 0x67, 0xc4, 0x00, 0x01, 0x40, 0x10, 0x0c, 0x1e,
+  0x3f, 0x68, 0x83, 0xea, 0x0b, 0x46, 0x0c, 0x10, 0x00, 0x04, 0xc1, 0xe0,
+  0xf9, 0x03, 0x37, 0x88, 0xbe, 0xc0, 0x82, 0x06, 0x3a, 0xc6, 0x8d, 0x81,
+  0x7c, 0x46, 0x0c, 0x10, 0x00, 0x04, 0xc1, 0xe0, 0x11, 0x85, 0x38, 0xc0,
+  0xc6, 0x20, 0x18, 0x31, 0x40, 0x00, 0x10, 0x04, 0x83, 0x67, 0x14, 0xe4,
+  0x80, 0x1a, 0x83, 0xc0, 0x02, 0x08, 0x3a, 0x23, 0x06, 0x09, 0x00, 0x82,
+  0x60, 0x80, 0x9c, 0xc2, 0x1c, 0x88, 0x82, 0x28, 0xec, 0x81, 0x1a, 0x8c,
+  0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x72, 0x0a, 0x73, 0x20, 0x0a, 0xa2,
+  0xd0, 0x06, 0x69, 0x30, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xc8, 0x29,
+  0xcc, 0x81, 0x28, 0x88, 0x42, 0x1e, 0xa0, 0xc1, 0x88, 0x41, 0x02, 0x80,
+  0x20, 0x18, 0x20, 0xa7, 0x30, 0x07, 0xa2, 0x20, 0x0a, 0x7a, 0xc0, 0x06,
+  0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x80, 0x9c, 0xc2, 0x1c, 0x8c, 0x82,
+  0x28, 0xec, 0x41, 0x33, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xc8, 0x29,
+  0xcc, 0xc1, 0x28, 0x88, 0x42, 0x1b, 0x24, 0x23, 0x06, 0x09, 0x00, 0x82,
+  0x60, 0x80, 0x9c, 0xc2, 0x1c, 0x8c, 0x82, 0x28, 0xe4, 0x41, 0x31, 0x62,
+  0x90, 0x00, 0x20, 0x08, 0x06, 0xc8, 0x29, 0xcc, 0xc1, 0x28, 0x88, 0x82,
+  0x1e, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00
+};
+#if 0
+;
+; Input signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; TEXCOORD                 0   xyzw        0     NONE   float   xyzw
+; SV_Position              0   xyzw        1      POS   float       
+;
+;
+; Output signature:
+;
+; Name                 Index   Mask Register SysValue  Format   Used
+; -------------------- ----- ------ -------- -------- ------- ------
+; SV_Target                0   xyzw        0   TARGET   float   xyzw
+;
+; shader hash: a10908b314d7c2de5d684fdf3768659c
+;
+; Pipeline Runtime Information: 
+;
+; Pixel Shader
+; DepthOutput=0
+; SampleFrequency=0
+;
+;
+; Input signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; TEXCOORD                 0                 linear       
+; SV_Position              0          noperspective       
+;
+; Output signature:
+;
+; Name                 Index             InterpMode DynIdx
+; -------------------- ----- ---------------------- ------
+; SV_Target                0                              
+;
+; Buffer Definitions:
+;
+;
+; Resource Bindings:
+;
+; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
+;
+;
+; ViewId state:
+;
+; Number of inputs: 8, outputs: 4
+; Outputs dependent on ViewId: {  }
+; Inputs contributing to computation of Outputs:
+;   output 0 depends on inputs: { 0 }
+;   output 1 depends on inputs: { 1 }
+;   output 2 depends on inputs: { 2 }
+;   output 3 depends on inputs: { 3 }
+;
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-ms-dx"
+
+define void @PSMain() {
+  %1 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %2 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %3 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 2, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 3, i32 undef)  ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %1)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %2)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %3)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %4)  ; StoreOutput(outputSigId,rowIndex,colIndex,value)
+  ret void
+}
+
+; Function Attrs: nounwind readnone
+declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0
+
+; Function Attrs: nounwind
+declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+
+!llvm.ident = !{!0}
+!dx.version = !{!1}
+!dx.valver = !{!2}
+!dx.shaderModel = !{!3}
+!dx.viewIdState = !{!4}
+!dx.entryPoints = !{!5}
+
+!0 = !{!"dxc(private) 1.7.0.3896 (021f8f3e1)"}
+!1 = !{i32 1, i32 0}
+!2 = !{i32 1, i32 6}
+!3 = !{!"ps", i32 6, i32 0}
+!4 = !{[10 x i32] [i32 8, i32 4, i32 1, i32 2, i32 4, i32 8, i32 0, i32 0, i32 0, i32 0]}
+!5 = !{void ()* @PSMain, !"PSMain", !6, null, null}
+!6 = !{!7, !12, null}
+!7 = !{!8, !11}
+!8 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !9, i8 2, i32 1, i8 4, i32 0, i8 0, !10}
+!9 = !{i32 0}
+!10 = !{i32 3, i32 15}
+!11 = !{i32 1, !"SV_Position", i8 9, i8 3, !9, i8 4, i32 1, i8 4, i32 1, i8 0, null}
+!12 = !{!13}
+!13 = !{i32 0, !"SV_Target", i8 9, i8 16, !9, i8 0, i32 1, i8 4, i32 0, i8 0, !10}
+
+#endif
+
+const unsigned char D3D12_CubeFrag[] = {
+  0x44, 0x58, 0x42, 0x43, 0x55, 0xdd, 0xea, 0x5b, 0x70, 0xf7, 0xd6, 0x72,
+  0x11, 0x2b, 0x82, 0xd4, 0x62, 0x33, 0xa4, 0xa4, 0x01, 0x00, 0x00, 0x00,
+  0x93, 0x0b, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00,
+  0x97, 0x01, 0x00, 0x00, 0x77, 0x06, 0x00, 0x00, 0x93, 0x06, 0x00, 0x00,
+  0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, 0x5d, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x53, 0x56, 0x5f,
+  0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x4f, 0x53, 0x47,
+  0x31, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f,
+  0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x50, 0x53, 0x56, 0x30, 0xa4,
+  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+  0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x44, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x01, 0x44, 0x03, 0x03, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x10, 0x03,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04,
+  0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53,
+  0x54, 0x41, 0x54, 0xd8, 0x04, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x36,
+  0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0xc0, 0x04, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21,
+  0x0c, 0x00, 0x00, 0x2d, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41,
+  0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25,
+  0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, 0x42,
+  0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a,
+  0x32, 0x42, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00,
+  0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x22, 0xc4, 0x50, 0x41,
+  0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, 0x06, 0x51,
+  0x18, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff,
+  0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff,
+  0xff, 0x03, 0x20, 0x01, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x00, 0x00, 0x00, 0x89,
+  0x20, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, 0x20,
+  0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, 0x84,
+  0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10,
+  0x30, 0x23, 0x00, 0x25, 0x00, 0x8a, 0x19, 0x80, 0x39, 0x02, 0x30, 0x98,
+  0x23, 0x40, 0x8a, 0x31, 0x44, 0x54, 0x44, 0x56, 0x0c, 0x20, 0xa2, 0x1a,
+  0xc2, 0x81, 0x80, 0x54, 0x20, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87,
+  0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87,
+  0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00,
+  0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90,
+  0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0,
+  0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60,
+  0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60,
+  0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0,
+  0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc8, 0x02, 0x01, 0x0d, 0x00, 0x00, 0x00, 0x32,
+  0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6,
+  0x04, 0x43, 0xa2, 0x12, 0x18, 0x01, 0x28, 0x86, 0x32, 0x28, 0x8f, 0x92,
+  0x28, 0x04, 0xaa, 0x92, 0x18, 0x01, 0x28, 0x82, 0x42, 0x28, 0x83, 0x02,
+  0xa1, 0x1d, 0x4b, 0x41, 0x88, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x1a,
+  0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43,
+  0x81, 0x93, 0x4b, 0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xb9,
+  0x71, 0x81, 0x71, 0x99, 0xc1, 0xc9, 0xb1, 0x01, 0x41, 0x81, 0x91, 0x89,
+  0x31, 0xc3, 0x31, 0x9b, 0x29, 0x8b, 0x49, 0xd9, 0x10, 0x04, 0x13, 0x04,
+  0x62, 0x98, 0x20, 0x10, 0xc4, 0x06, 0x61, 0x20, 0x36, 0x08, 0x04, 0x41,
+  0x01, 0x6e, 0x6e, 0x82, 0x40, 0x14, 0x1b, 0x86, 0x03, 0x21, 0x26, 0x08,
+  0x02, 0xb0, 0x01, 0xd8, 0x30, 0x10, 0xcb, 0xb2, 0x21, 0x60, 0x36, 0x0c,
+  0x83, 0xd2, 0x4c, 0x10, 0x16, 0x68, 0x43, 0xf0, 0xd0, 0x80, 0x9a, 0x6a,
+  0x0a, 0x4b, 0x73, 0x23, 0x42, 0x55, 0x84, 0x35, 0xf4, 0xf4, 0x24, 0x45,
+  0x34, 0x41, 0x28, 0x94, 0x09, 0x42, 0xb1, 0x6c, 0x08, 0x88, 0x09, 0x42,
+  0xc1, 0x4c, 0x10, 0x8a, 0x66, 0x82, 0x40, 0x18, 0x13, 0x04, 0xe2, 0xd8,
+  0x20, 0x60, 0xd9, 0x86, 0x85, 0x90, 0x26, 0xaa, 0xb2, 0x86, 0x8b, 0xa0,
+  0x34, 0x2e, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
+  0x6e, 0x13, 0x84, 0xc2, 0xd9, 0xb0, 0x0c, 0xdc, 0xd4, 0x55, 0xd7, 0x70,
+  0x0d, 0x14, 0xb0, 0x41, 0xd8, 0x3c, 0x26, 0x53, 0x56, 0x5f, 0x54, 0x61,
+  0x72, 0x67, 0x65, 0x74, 0x13, 0x84, 0xe2, 0xd9, 0xb0, 0x10, 0x60, 0x30,
+  0x85, 0x41, 0x45, 0x0d, 0x17, 0x41, 0x69, 0x1b, 0x02, 0x31, 0xd8, 0x30,
+  0x7c, 0x63, 0x00, 0x6c, 0x28, 0x94, 0x88, 0x0c, 0x00, 0x80, 0x45, 0x9a,
+  0xdb, 0x1c, 0xdd, 0xdc, 0x04, 0x81, 0x40, 0x68, 0xcc, 0xa5, 0x9d, 0x7d,
+  0xb1, 0x91, 0x4d, 0x10, 0x88, 0x84, 0xc6, 0x5c, 0xda, 0xd9, 0xd7, 0x1c,
+  0xdd, 0x06, 0xc3, 0x0c, 0xce, 0x00, 0x0d, 0xd2, 0x40, 0x0d, 0xd2, 0xa0,
+  0x0a, 0x1b, 0x9b, 0x5d, 0x9b, 0x4b, 0x1a, 0x59, 0x99, 0x1b, 0xdd, 0x94,
+  0x20, 0xa8, 0x42, 0x86, 0xe7, 0x62, 0x57, 0x26, 0x37, 0x97, 0xf6, 0xe6,
+  0x36, 0x25, 0x20, 0x9a, 0x90, 0xe1, 0xb9, 0xd8, 0x85, 0xb1, 0xd9, 0x95,
+  0xc9, 0x4d, 0x09, 0x8a, 0x3a, 0x64, 0x78, 0x2e, 0x73, 0x68, 0x61, 0x64,
+  0x65, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x53, 0x02, 0xa4, 0x12, 0x19,
+  0x9e, 0x0b, 0x5d, 0x1e, 0x5c, 0x59, 0x90, 0x9b, 0xdb, 0x1b, 0x5d, 0x18,
+  0x5d, 0xda, 0x9b, 0xdb, 0xdc, 0x94, 0xa0, 0xa9, 0x43, 0x86, 0xe7, 0x62,
+  0x97, 0x56, 0x76, 0x97, 0x44, 0x36, 0x45, 0x17, 0x46, 0x57, 0x36, 0x25,
+  0x78, 0xea, 0x90, 0xe1, 0xb9, 0x94, 0xb9, 0xd1, 0xc9, 0xe5, 0x41, 0xbd,
+  0xa5, 0xb9, 0xd1, 0xcd, 0x4d, 0x09, 0xc8, 0xa0, 0x0b, 0x19, 0x9e, 0xcb,
+  0xd8, 0x5b, 0x9d, 0x1b, 0x5d, 0x99, 0xdc, 0xdc, 0x94, 0x40, 0x0d, 0x00,
+  0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33,
+  0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98,
+  0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33,
+  0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05,
+  0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43,
+  0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08,
+  0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78,
+  0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1,
+  0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33,
+  0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e,
+  0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03,
+  0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60,
+  0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80,
+  0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8,
+  0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18,
+  0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee,
+  0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c,
+  0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43,
+  0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3,
+  0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83,
+  0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21,
+  0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1,
+  0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6,
+  0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4,
+  0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x06,
+  0x60, 0xa4, 0xac, 0x09, 0x20, 0x8d, 0x05, 0x4c, 0xc3, 0xe5, 0x3b, 0x8f,
+  0xbf, 0x38, 0xc0, 0x20, 0x36, 0x0f, 0x35, 0xf9, 0xc5, 0x6d, 0x9b, 0x40,
+  0x35, 0x5c, 0xbe, 0xf3, 0xf8, 0xd2, 0xe4, 0x44, 0x04, 0x4a, 0x4d, 0x0f,
+  0x35, 0xf9, 0xc5, 0x6d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
+  0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1,
+  0x09, 0x08, 0xb3, 0x14, 0xd7, 0xc2, 0xde, 0x5d, 0x68, 0x4f, 0xdf, 0x37,
+  0x68, 0x65, 0x9c, 0x44, 0x58, 0x49, 0x4c, 0xf8, 0x04, 0x00, 0x00, 0x60,
+  0x00, 0x00, 0x00, 0x3e, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00,
+  0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe0, 0x04, 0x00, 0x00, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x35, 0x01, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43,
+  0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11,
+  0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04,
+  0x21, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b,
+  0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84,
+  0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x01, 0x00, 0x00, 0x00, 0x49,
+  0x18, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20,
+  0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04,
+  0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b,
+  0x84, 0x84, 0x4c, 0x10, 0x30, 0x23, 0x00, 0x25, 0x00, 0x8a, 0x19, 0x80,
+  0x39, 0x02, 0x30, 0x98, 0x23, 0x40, 0x8a, 0x31, 0x44, 0x54, 0x44, 0x56,
+  0x0c, 0x20, 0xa2, 0x1a, 0xc2, 0x81, 0x80, 0x54, 0x20, 0x00, 0x00, 0x13,
+  0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68,
+  0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a,
+  0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d,
+  0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71,
+  0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d,
+  0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x02, 0x01, 0x0c,
+  0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c,
+  0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0xa2, 0x12, 0x18, 0x01, 0x28, 0x86,
+  0x32, 0x28, 0x0f, 0xaa, 0x92, 0x18, 0x01, 0x28, 0x82, 0x42, 0x28, 0x83,
+  0x02, 0xa1, 0x1d, 0x4b, 0x41, 0x88, 0x40, 0x20, 0x10, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x1a,
+  0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0xc4, 0x31, 0x20, 0xc3, 0x1b, 0x43,
+  0x81, 0x93, 0x4b, 0xb3, 0x0b, 0xa3, 0x2b, 0x4b, 0x01, 0x89, 0x71, 0xb9,
+  0x71, 0x81, 0x71, 0x99, 0xc1, 0xc9, 0xb1, 0x01, 0x41, 0x81, 0x91, 0x89,
+  0x31, 0xc3, 0x31, 0x9b, 0x29, 0x8b, 0x49, 0xd9, 0x10, 0x04, 0x13, 0x04,
+  0x62, 0x98, 0x20, 0x10, 0xc4, 0x06, 0x61, 0x20, 0x26, 0x08, 0x44, 0xb1,
+  0x41, 0x18, 0x0c, 0x0a, 0x70, 0x73, 0x1b, 0x06, 0xc4, 0x20, 0x26, 0x08,
+  0x8b, 0xb3, 0x21, 0x50, 0x26, 0x08, 0x02, 0x40, 0x03, 0x6a, 0xaa, 0x29,
+  0x2c, 0xcd, 0x8d, 0x08, 0x55, 0x11, 0xd6, 0xd0, 0xd3, 0x93, 0x14, 0xd1,
+  0x04, 0xa1, 0x40, 0x26, 0x08, 0x45, 0xb2, 0x21, 0x20, 0x26, 0x08, 0x85,
+  0x32, 0x41, 0x28, 0x96, 0x09, 0x02, 0x61, 0x4c, 0x10, 0x88, 0x63, 0x83,
+  0x40, 0x55, 0x1b, 0x16, 0xc2, 0x79, 0xa0, 0x48, 0x1a, 0x26, 0x02, 0xb2,
+  0xb8, 0x4c, 0x59, 0x7d, 0x41, 0xbd, 0xcd, 0xa5, 0xd1, 0xa5, 0xbd, 0xb9,
+  0x4d, 0x10, 0x0a, 0x66, 0xc3, 0x32, 0x60, 0x4f, 0x16, 0x4d, 0xc3, 0x34,
+  0x40, 0xc0, 0x06, 0xe1, 0xd2, 0x98, 0x4c, 0x59, 0x7d, 0x51, 0x85, 0xc9,
+  0x9d, 0x95, 0xd1, 0x4d, 0x10, 0x8a, 0x66, 0xc3, 0x42, 0x70, 0x4f, 0x17,
+  0x41, 0xc3, 0x44, 0x40, 0xd6, 0x86, 0xc0, 0xdb, 0x30, 0x6c, 0x1f, 0xb0,
+  0xa1, 0x60, 0x1a, 0x30, 0x00, 0x80, 0x2a, 0x6c, 0x6c, 0x76, 0x6d, 0x2e,
+  0x69, 0x64, 0x65, 0x6e, 0x74, 0x53, 0x82, 0xa0, 0x0a, 0x19, 0x9e, 0x8b,
+  0x5d, 0x99, 0xdc, 0x5c, 0xda, 0x9b, 0xdb, 0x94, 0x80, 0x68, 0x42, 0x86,
+  0xe7, 0x62, 0x17, 0xc6, 0x66, 0x57, 0x26, 0x37, 0x25, 0x30, 0xea, 0x90,
+  0xe1, 0xb9, 0xcc, 0xa1, 0x85, 0x91, 0x95, 0xc9, 0x35, 0xbd, 0x91, 0x95,
+  0xb1, 0x4d, 0x09, 0x90, 0x3a, 0x64, 0x78, 0x2e, 0x76, 0x69, 0x65, 0x77,
+  0x49, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x02, 0xa5, 0x0e, 0x19,
+  0x9e, 0x4b, 0x99, 0x1b, 0x9d, 0x5c, 0x1e, 0xd4, 0x5b, 0x9a, 0x1b, 0xdd,
+  0xdc, 0x94, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76,
+  0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e,
+  0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f,
+  0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x0b,
+  0x00, 0x00, 0x00, 0x06, 0x60, 0xa4, 0xac, 0x09, 0x20, 0x8d, 0x05, 0x4c,
+  0xc3, 0xe5, 0x3b, 0x8f, 0xbf, 0x38, 0xc0, 0x20, 0x36, 0x0f, 0x35, 0xf9,
+  0xc5, 0x6d, 0x9b, 0x40, 0x35, 0x5c, 0xbe, 0xf3, 0xf8, 0xd2, 0xe4, 0x44,
+  0x04, 0x4a, 0x4d, 0x0f, 0x35, 0xf9, 0xc5, 0x6d, 0x03, 0x00, 0x00, 0x61,
+  0x20, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x44, 0x85, 0x30, 0x03, 0x50,
+  0x0a, 0x54, 0x25, 0x00, 0x00, 0x00, 0x00, 0x23, 0x06, 0x09, 0x00, 0x82,
+  0x60, 0x60, 0x48, 0xc4, 0xf3, 0x28, 0xc3, 0x88, 0x41, 0x02, 0x80, 0x20,
+  0x18, 0x18, 0x53, 0x01, 0x41, 0x02, 0x31, 0x62, 0x90, 0x00, 0x20, 0x08,
+  0x06, 0x06, 0x65, 0x44, 0xd1, 0x52, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82,
+  0x81, 0x51, 0x1d, 0x92, 0xa4, 0x18, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60,
+  0x80, 0x54, 0xc6, 0x34, 0x39, 0xc4, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18,
+  0x20, 0x95, 0x31, 0x4d, 0xc5, 0x30, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06,
+  0x48, 0x65, 0x4c, 0x53, 0x23, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01,
+  0x52, 0x19, 0xd3, 0xb4, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
+};

+ 2584 - 0
test/testgpu/testgpu_metallib.h

@@ -0,0 +1,2584 @@
+#if defined(SDL_PLATFORM_IOS)
+#if TARGET_OS_SIMULATOR
+const unsigned char cube_vert_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x42, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x08, 0x00, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x00, 0x48, 0x41, 0x53,
+  0x48, 0x20, 0x00, 0x9f, 0x34, 0xf2, 0x23, 0x6f, 0x4a, 0x7c, 0x53, 0xed,
+  0x26, 0x8f, 0xf1, 0x95, 0xca, 0x20, 0xce, 0x21, 0xe9, 0xdd, 0xef, 0xbc,
+  0x8c, 0x8d, 0x0d, 0xab, 0xad, 0x10, 0x40, 0x59, 0x61, 0x1c, 0x25, 0x4d,
+  0x44, 0x53, 0x5a, 0x08, 0x00, 0x30, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08,
+  0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44,
+  0x54, 0x45, 0x4e, 0x44, 0x54, 0x29, 0x00, 0x00, 0x00, 0x56, 0x41, 0x54,
+  0x54, 0x15, 0x00, 0x02, 0x00, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
+  0x6e, 0x00, 0x00, 0x80, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x01, 0x80,
+  0x56, 0x41, 0x54, 0x59, 0x04, 0x00, 0x02, 0x00, 0x05, 0x05, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0,
+  0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x0d,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x35, 0x14,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x0c, 0x30, 0x24, 0x80, 0x10,
+  0x05, 0xc8, 0x14, 0x00, 0x00, 0x00, 0x21, 0x0c, 0x00, 0x00, 0x0b, 0x03,
+  0x00, 0x00, 0x0b, 0x02, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00,
+  0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10,
+  0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04,
+  0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10,
+  0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90,
+  0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0x04, 0x49,
+  0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83,
+  0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x71, 0x00,
+  0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80,
+  0x03, 0x40, 0x02, 0x28, 0x22, 0x1c, 0xe0, 0x01, 0x1e, 0xe4, 0xe1, 0x1d,
+  0xf0, 0xa1, 0x0d, 0xcc, 0xa1, 0x1e, 0xdc, 0x61, 0x1c, 0xda, 0xc0, 0x1c,
+  0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90,
+  0x87, 0x7a, 0x28, 0x07, 0x80, 0x68, 0x87, 0x74, 0x70, 0x87, 0x36, 0x60,
+  0x87, 0x72, 0x38, 0x87, 0x70, 0x60, 0x87, 0x36, 0xb0, 0x87, 0x72, 0x18,
+  0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x83, 0x7b, 0x48, 0x07, 0x72, 0xa0,
+  0x07, 0x74, 0x00, 0xe2, 0x40, 0x0e, 0xf0, 0x00, 0x18, 0xdc, 0xe1, 0x1d,
+  0xda, 0x40, 0x1c, 0xea, 0x21, 0x1d, 0xd8, 0x81, 0x1e, 0xd2, 0xc1, 0x1d,
+  0xe6, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c,
+  0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e,
+  0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0x01, 0xa0,
+  0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30,
+  0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48,
+  0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48,
+  0x87, 0x76, 0x68, 0x03, 0x77, 0x78, 0x07, 0x77, 0x68, 0x03, 0x76, 0x28,
+  0x87, 0x70, 0x30, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20,
+  0xdc, 0xe1, 0x1d, 0xda, 0x20, 0x1d, 0xdc, 0xc1, 0x1c, 0xe6, 0xa1, 0x0d,
+  0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0,
+  0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x70,
+  0x87, 0x70, 0x70, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68,
+  0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c,
+  0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xce, 0xc1, 0x1d,
+  0xca, 0x81, 0x1c, 0xda, 0x40, 0x1f, 0xca, 0x41, 0x1e, 0xde, 0x61, 0x1e,
+  0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68,
+  0x03, 0x7a, 0x90, 0x87, 0x70, 0x80, 0x07, 0x78, 0x48, 0x07, 0x77, 0x38,
+  0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e,
+  0xea, 0xa1, 0x1c, 0x00, 0x62, 0x1e, 0xe8, 0x21, 0x1c, 0xc6, 0x61, 0x1d,
+  0xda, 0x00, 0x1e, 0xe4, 0xe1, 0x1d, 0xe8, 0xa1, 0x1c, 0xc6, 0x81, 0x1e,
+  0xde, 0x41, 0x1e, 0xda, 0x40, 0x1c, 0xea, 0xc1, 0x1c, 0xcc, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xf4, 0xa1, 0x1c, 0x00, 0x3c, 0x00,
+  0x88, 0x7a, 0x70, 0x87, 0x79, 0x08, 0x07, 0x73, 0x28, 0x87, 0x36, 0x30,
+  0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e,
+  0xe4, 0xa1, 0x1e, 0xca, 0x01, 0xd8, 0xe0, 0x09, 0x03, 0xb0, 0x00, 0x55,
+  0x90, 0x06, 0xa0, 0x30, 0x84, 0x43, 0x3a, 0xc8, 0x43, 0x1b, 0x88, 0x43,
+  0x3d, 0x98, 0x83, 0x39, 0x94, 0x83, 0x3c, 0xb4, 0x81, 0x3b, 0xbc, 0x43,
+  0x1b, 0x84, 0x03, 0x3b, 0xa4, 0x43, 0x38, 0xcc, 0x03, 0x00, 0x49, 0x18,
+  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x84, 0x40, 0x00, 0x89, 0x20,
+  0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64,
+  0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1,
+  0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x44,
+  0x33, 0x00, 0xc3, 0x08, 0x04, 0x60, 0x85, 0x10, 0x86, 0x11, 0x06, 0x20,
+  0x09, 0xc2, 0x4c, 0xd4, 0x3c, 0xd0, 0x83, 0x3c, 0xd4, 0xc3, 0x38, 0xd0,
+  0x83, 0x1b, 0xb4, 0x43, 0x39, 0xd0, 0x43, 0x38, 0xb0, 0x83, 0x1e, 0xe8,
+  0x41, 0x3b, 0x84, 0x03, 0x3d, 0xc8, 0x43, 0x3a, 0xe0, 0x03, 0x0a, 0xc8,
+  0x29, 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xbb, 0x1b, 0x8a, 0x82, 0x32, 0x88,
+  0x60, 0x08, 0x85, 0x10, 0x63, 0x1c, 0x42, 0x03, 0x01, 0x73, 0x04, 0x60,
+  0x90, 0x02, 0x6b, 0x18, 0x81, 0x58, 0xe6, 0x08, 0x40, 0x61, 0x10, 0x21,
+  0x10, 0x46, 0x00, 0x00, 0x00, 0x00, 0x13, 0xbe, 0x70, 0x48, 0x07, 0x79,
+  0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72,
+  0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0x88, 0x83, 0x39, 0x70, 0x03, 0x38,
+  0x70, 0x03, 0x38, 0x68, 0x83, 0x79, 0x48, 0x87, 0x76, 0xa8, 0x07, 0x76,
+  0x08, 0x07, 0x7a, 0x78, 0x07, 0x79, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06,
+  0xf0, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07,
+  0x78, 0xd0, 0x06, 0xe9, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07,
+  0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x6d, 0x90, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x60, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x60, 0x0f, 0x74, 0x80, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07,
+  0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07,
+  0x6d, 0x60, 0x0f, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07,
+  0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07,
+  0x79, 0x20, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07,
+  0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07,
+  0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06,
+  0xf6, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07,
+  0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07,
+  0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07,
+  0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x11, 0xc2, 0x90, 0x47,
+  0x25, 0xfd, 0x0c, 0x80, 0x34, 0x43, 0x22, 0xe0, 0x40, 0x00, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x62, 0x83, 0x40, 0xd1,
+  0x86, 0x01, 0x00, 0x80, 0x2c, 0x10, 0x09, 0x00, 0x00, 0x00, 0x32, 0x1e,
+  0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04,
+  0x43, 0x5a, 0x45, 0x50, 0x02, 0x85, 0x30, 0x02, 0x50, 0x80, 0x01, 0x05,
+  0x42, 0x6e, 0x04, 0x80, 0xd8, 0x58, 0x42, 0x24, 0x00, 0x00, 0xb1, 0x18,
+  0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1,
+  0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42,
+  0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f,
+  0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1,
+  0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84,
+  0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc,
+  0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70,
+  0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19,
+  0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f,
+  0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21,
+  0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc,
+  0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84,
+  0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37,
+  0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70,
+  0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77,
+  0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79,
+  0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e,
+  0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1,
+  0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81,
+  0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98,
+  0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88,
+  0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4,
+  0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72,
+  0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74,
+  0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e,
+  0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e,
+  0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21,
+  0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01,
+  0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc,
+  0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77,
+  0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e,
+  0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1,
+  0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61,
+  0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0,
+  0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0,
+  0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74,
+  0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e,
+  0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41,
+  0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48,
+  0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c,
+  0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4,
+  0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71,
+  0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f,
+  0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f,
+  0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f,
+  0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23,
+  0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21,
+  0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21,
+  0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94,
+  0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a,
+  0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e,
+  0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e,
+  0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74,
+  0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74,
+  0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78,
+  0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00, 0x00, 0xbd, 0x00,
+  0x00, 0x00, 0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c, 0x27, 0x46, 0x46,
+  0xc8, 0x11, 0x32, 0x64, 0xd4, 0x3a, 0x4c, 0x76, 0x00, 0x00, 0x8b, 0xf2,
+  0x06, 0xc5, 0xc6, 0x91, 0x41, 0xb4, 0x44, 0x06, 0x53, 0x30, 0x08, 0x24,
+  0x79, 0x86, 0xf2, 0x20, 0x14, 0xd2, 0x44, 0xd7, 0x30, 0x00, 0x53, 0x44,
+  0x4b, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x77, 0x63, 0x68,
+  0x61, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65,
+  0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69,
+  0x6f, 0x6e, 0x20, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x20,
+  0x28, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x66, 0x65, 0x2d, 0x33, 0x32, 0x30,
+  0x32, 0x33, 0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65, 0x74, 0x61, 0x6c, 0x61,
+  0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x64,
+  0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62,
+  0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c,
+  0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f,
+  0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f,
+  0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x62,
+  0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f,
+  0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x65,
+  0x72, 0x74, 0x65, 0x78, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x75,
+  0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x30, 0x29, 0x61, 0x69,
+  0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e,
+  0x61, 0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x61, 0x69, 0x72,
+  0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6f, 0x6c,
+  0x6f, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69,
+  0x6f, 0x6e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x69,
+  0x72, 0x2e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x6e, 0x70,
+  0x75, 0x74, 0x61, 0x69, 0x72, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
+  0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x67, 0x65, 0x6e, 0x65,
+  0x72, 0x61, 0x74, 0x65, 0x64, 0x28, 0x5f, 0x5f, 0x61, 0x69, 0x72, 0x5f,
+  0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x5f,
+  0x5f, 0x29, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x61, 0x69, 0x72, 0x2e,
+  0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x62, 0x75,
+  0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61, 0x69, 0x72,
+  0x2e, 0x72, 0x65, 0x61, 0x64, 0x61, 0x69, 0x72, 0x2e, 0x73, 0x74, 0x72,
+  0x75, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x69, 0x6e, 0x66,
+  0x6f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x6d, 0x6f, 0x64,
+  0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x61, 0x69,
+  0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x73,
+  0x69, 0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74,
+  0x79, 0x70, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x5f, 0x73, 0x69,
+  0x7a, 0x65, 0x55, 0x42, 0x4f, 0x75, 0x62, 0x6f, 0x00, 0x00, 0x23, 0x08,
+  0x4b, 0x30, 0x82, 0xc0, 0x20, 0x23, 0x08, 0x8b, 0x30, 0x82, 0xb0, 0x0c,
+  0x23, 0x08, 0x0b, 0x31, 0x82, 0x90, 0x00, 0x23, 0x08, 0x4b, 0x31, 0x82,
+  0xb0, 0x18, 0x33, 0x0c, 0x5e, 0xf0, 0xcd, 0x30, 0x80, 0x81, 0x10, 0x06,
+  0x33, 0x04, 0xc3, 0x0c, 0x83, 0xe7, 0x89, 0xc1, 0x0c, 0x04, 0x01, 0x06,
+  0x60, 0x20, 0x06, 0x33, 0x04, 0xc5, 0x0c, 0x81, 0x31, 0x43, 0x70, 0xcc,
+  0x60, 0x20, 0x89, 0xb2, 0x30, 0xcd, 0x0c, 0x85, 0xa3, 0x2c, 0xcc, 0x33,
+  0x83, 0xe0, 0x06, 0x6f, 0x30, 0x83, 0x22, 0x06, 0x50, 0x24, 0x06, 0x60,
+  0x20, 0x29, 0x13, 0xf3, 0xcc, 0xa0, 0x80, 0x01, 0x14, 0x81, 0x01, 0x18,
+  0x48, 0xca, 0xc4, 0x34, 0x33, 0x14, 0x62, 0x40, 0x06, 0x62, 0x80, 0x65,
+  0x33, 0x48, 0x1e, 0x55, 0x91, 0x41, 0x24, 0x06, 0x60, 0x60, 0x5d, 0x73,
+  0xa0, 0x91, 0xc1, 0x56, 0x06, 0x0a, 0xc7, 0x74, 0x33, 0x0c, 0x71, 0x20,
+  0x07, 0x74, 0x30, 0xc3, 0x30, 0x06, 0x70, 0x50, 0x07, 0x32, 0x12, 0x98,
+  0xa0, 0x8b, 0xd8, 0xd8, 0xec, 0xda, 0x5c, 0xda, 0xde, 0xc8, 0xea, 0xd8,
+  0xca, 0x5c, 0xcc, 0xd8, 0xc2, 0xce, 0xe6, 0x46, 0x11, 0xca, 0xc0, 0x0c,
+  0x4e, 0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3, 0x1b,
+  0x25, 0x38, 0x83, 0x5b, 0xc2, 0xd2, 0xe4, 0x5c, 0xec, 0xca, 0xe4, 0xe6,
+  0xd2, 0xde, 0xdc, 0x46, 0x09, 0xd0, 0xe0, 0xa8, 0xb0, 0x34, 0x39, 0x17,
+  0xb6, 0x30, 0xb7, 0xb3, 0xba, 0xb0, 0xb3, 0xb2, 0x2f, 0xbb, 0x32, 0xb9,
+  0xb9, 0xb4, 0x37, 0xb7, 0x51, 0x82, 0x34, 0xb8, 0x29, 0x2c, 0x4d, 0xce,
+  0x65, 0xec, 0xad, 0x0d, 0x2e, 0x8d, 0xad, 0xec, 0xeb, 0x0d, 0x8e, 0x2e,
+  0xed, 0xcd, 0x6d, 0x6e, 0x94, 0x41, 0x0d, 0xd6, 0x80, 0x0d, 0x4e, 0x09,
+  0x4b, 0x93, 0x73, 0xb1, 0x2b, 0x93, 0xa3, 0x2b, 0xc3, 0x1b, 0x25, 0xa8,
+  0x03, 0x00, 0xa9, 0x18, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0b, 0x0a,
+  0x72, 0x28, 0x87, 0x77, 0x80, 0x07, 0x7a, 0x58, 0x70, 0x98, 0x43, 0x3d,
+  0xb8, 0xc3, 0x38, 0xb0, 0x43, 0x39, 0xd0, 0xc3, 0x82, 0xe6, 0x1c, 0xc6,
+  0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2, 0xc1, 0x1d, 0xe6, 0x21, 0x1d, 0xe8,
+  0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x16, 0x34, 0xe3, 0x60, 0x0e, 0xe7, 0x50,
+  0x0f, 0xe1, 0x20, 0x0f, 0xe4, 0x40, 0x0f, 0xe1, 0x20, 0x0f, 0xe7, 0x50,
+  0x0e, 0xf4, 0xb0, 0x80, 0x81, 0x07, 0x79, 0x28, 0x87, 0x70, 0x60, 0x07,
+  0x76, 0x78, 0x87, 0x71, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x58, 0x70,
+  0x9c, 0xc3, 0x38, 0xb4, 0x01, 0x3b, 0xa4, 0x83, 0x3d, 0x94, 0xc3, 0x02,
+  0x6b, 0x1c, 0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c, 0xdc, 0x20, 0x1c, 0xe4,
+  0x61, 0x1c, 0xdc, 0x20, 0x1c, 0xe8, 0x81, 0x1e, 0xc2, 0x61, 0x1c, 0xd0,
+  0xa1, 0x1c, 0xc8, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0x61, 0xc1, 0x01,
+  0x0f, 0xf4, 0x20, 0x0f, 0xe1, 0x50, 0x0f, 0xf4, 0x80, 0x0e, 0x00, 0x00,
+  0x00, 0x00, 0xd1, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0xcc,
+  0x3c, 0xa4, 0x83, 0x3b, 0x9c, 0x03, 0x3b, 0x94, 0x03, 0x3d, 0xa0, 0x83,
+  0x3c, 0x94, 0x43, 0x38, 0x90, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x61, 0x20,
+  0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00,
+  0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0xb4, 0x66, 0x00, 0xa8, 0xcd, 0x41,
+  0x10, 0x42, 0xc0, 0x8c, 0x00, 0x8c, 0x45, 0x04, 0x41, 0x10, 0x8c, 0x45,
+  0x08, 0x82, 0x20, 0x90, 0x2b, 0x83, 0x12, 0x28, 0x02, 0x02, 0x63, 0x04,
+  0x20, 0x08, 0x82, 0xf8, 0x47, 0x62, 0x06, 0x80, 0xc6, 0x0c, 0xc0, 0x0c,
+  0x00, 0x00, 0xf1, 0x30, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x22, 0x47,
+  0xc8, 0x90, 0x51, 0x12, 0x44, 0x2c, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x93,
+  0x59, 0x00, 0x6f, 0x6d, 0x6e, 0x69, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74,
+  0x20, 0x63, 0x68, 0x61, 0x72, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20,
+  0x43, 0x2b, 0x2b, 0x20, 0x54, 0x42, 0x41, 0x41, 0x61, 0x69, 0x72, 0x2d,
+  0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73,
+  0x28, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x29, 0x61, 0x69, 0x72,
+  0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70, 0x65,
+  0x2d, 0x61, 0x72, 0x67, 0x28, 0x32, 0x29, 0x00, 0x00, 0x00, 0x13, 0x04,
+  0xe7, 0x58, 0x21, 0xf0, 0x41, 0x1e, 0xac, 0x18, 0xfa, 0x80, 0x0f, 0xf4,
+  0x60, 0x43, 0x80, 0x07, 0x1b, 0x86, 0x3b, 0xf0, 0x83, 0x3d, 0xd8, 0x30,
+  0xfc, 0xc1, 0x1f, 0xec, 0xc1, 0x86, 0xa0, 0x0f, 0x00, 0x00, 0x83, 0x0c,
+  0x4e, 0xb0, 0xcc, 0x31, 0x04, 0x05, 0xb2, 0x4d, 0xf1, 0x4c, 0x96, 0x35,
+  0x51, 0x10, 0xca, 0x20, 0xc3, 0x64, 0x38, 0x26, 0x04, 0xe2, 0xbf, 0x4d,
+  0x31, 0x5d, 0x9a, 0xc6, 0x50, 0x10, 0xca, 0x20, 0xc3, 0xa5, 0x44, 0x26,
+  0x04, 0xe2, 0x6f, 0x41, 0x01, 0xfe, 0xdb, 0x14, 0x18, 0xf7, 0x7d, 0x10,
+  0x05, 0xa1, 0x0c, 0x32, 0x70, 0x4f, 0x65, 0x42, 0x20, 0xfe, 0x56, 0x04,
+  0xe0, 0xbf, 0x4d, 0xd1, 0x85, 0x01, 0x19, 0x90, 0xc1, 0x45, 0x41, 0x28,
+  0x36, 0x04, 0xe0, 0x3f, 0xdb, 0x60, 0x49, 0xc0, 0x6c, 0x43, 0x20, 0x04,
+  0x19, 0x04, 0xc4, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x5b, 0x8a,
+  0x21, 0xf8, 0x83, 0x03, 0x14, 0xb6, 0x14, 0x47, 0xf0, 0x07, 0x07, 0x28,
+  0x6c, 0x29, 0x98, 0xe0, 0x0f, 0x0e, 0x50, 0xd8, 0x52, 0x44, 0xc1, 0x1f,
+  0x1c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x32, 0x0e, 0x10, 0x22, 0x84, 0x00,
+  0xb9, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x0c,
+  0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0xf0, 0x00, 0x00,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00,
+  0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
+  0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x0c,
+  0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0x6e, 0x00, 0x00,
+  0x00, 0x00, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x33, 0x32, 0x30,
+  0x32, 0x33, 0x2e, 0x39, 0x38, 0x61, 0x69, 0x72, 0x36, 0x34, 0x2d, 0x61,
+  0x70, 0x70, 0x6c, 0x65, 0x2d, 0x69, 0x6f, 0x73, 0x31, 0x33, 0x2e, 0x30,
+  0x2e, 0x30, 0x2d, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 0x72,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00
+};
+const unsigned int cube_vert_metallib_len = 3650;
+const unsigned char cube_frag_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xad, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0a, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x08, 0x00, 0x66, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01, 0x48, 0x41, 0x53,
+  0x48, 0x20, 0x00, 0xb1, 0x5b, 0xd6, 0x7f, 0x39, 0x5b, 0x5d, 0x77, 0x3c,
+  0x0b, 0x97, 0x90, 0xdc, 0xc0, 0xb9, 0x79, 0xce, 0x64, 0x1b, 0x4c, 0x72,
+  0xbe, 0xf1, 0xe4, 0x47, 0x45, 0x71, 0x06, 0x02, 0x63, 0x68, 0x57, 0x4d,
+  0x44, 0x53, 0x5a, 0x08, 0x00, 0xc0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08,
+  0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44,
+  0x54, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44,
+  0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17,
+  0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa4, 0x0a, 0x00,
+  0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x35, 0x14, 0x00,
+  0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x0c, 0x30, 0x24, 0x80, 0x10, 0x05,
+  0xc8, 0x14, 0x00, 0x00, 0x00, 0x21, 0x0c, 0x00, 0x00, 0x6f, 0x02, 0x00,
+  0x00, 0x0b, 0x02, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00,
+  0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32,
+  0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b,
+  0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32,
+  0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14,
+  0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0x04, 0x49, 0x0e,
+  0x90, 0x11, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5,
+  0x8a, 0x04, 0x21, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x69, 0x00, 0x00,
+  0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0x03,
+  0x40, 0x02, 0x28, 0x22, 0x1c, 0xe0, 0x01, 0x1e, 0xe4, 0xe1, 0x1d, 0xf0,
+  0xa1, 0x0d, 0xcc, 0xa1, 0x1e, 0xdc, 0x61, 0x1c, 0xda, 0xc0, 0x1c, 0xe0,
+  0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87,
+  0x7a, 0x28, 0x07, 0x80, 0x68, 0x87, 0x74, 0x70, 0x87, 0x36, 0x60, 0x87,
+  0x72, 0x38, 0x87, 0x70, 0x60, 0x87, 0x36, 0xb0, 0x87, 0x72, 0x18, 0x07,
+  0x7a, 0x78, 0x07, 0x79, 0x68, 0x83, 0x7b, 0x48, 0x07, 0x72, 0xa0, 0x07,
+  0x74, 0x00, 0xe2, 0x40, 0x0e, 0xf0, 0x00, 0x18, 0xdc, 0xe1, 0x1d, 0xda,
+  0x40, 0x1c, 0xea, 0x21, 0x1d, 0xd8, 0x81, 0x1e, 0xd2, 0xc1, 0x1d, 0xe6,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c, 0xda,
+  0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e, 0xca,
+  0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0x01, 0xa0, 0x07,
+  0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30, 0x07,
+  0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48, 0x07,
+  0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48, 0x87,
+  0x76, 0x68, 0x03, 0x77, 0x78, 0x07, 0x77, 0x68, 0x03, 0x76, 0x28, 0x87,
+  0x70, 0x30, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc,
+  0xe1, 0x1d, 0xda, 0x20, 0x1d, 0xdc, 0xc1, 0x1c, 0xe6, 0xa1, 0x0d, 0xcc,
+  0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07,
+  0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x70, 0x87,
+  0x70, 0x70, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87,
+  0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00,
+  0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xce, 0xc1, 0x1d, 0xca,
+  0x81, 0x1c, 0xda, 0x40, 0x1f, 0xca, 0x41, 0x1e, 0xde, 0x61, 0x1e, 0xda,
+  0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x03,
+  0x7a, 0x90, 0x87, 0x70, 0x80, 0x07, 0x78, 0x48, 0x07, 0x77, 0x38, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0x62, 0x1e, 0xe8, 0x21, 0x1c, 0xc6, 0x61, 0x1d, 0xda,
+  0x00, 0x1e, 0xe4, 0xe1, 0x1d, 0xe8, 0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde,
+  0x41, 0x1e, 0xda, 0x40, 0x1c, 0xea, 0xc1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xf4, 0xa1, 0x1c, 0x00, 0x3c, 0x00, 0x88,
+  0x7a, 0x70, 0x87, 0x79, 0x08, 0x07, 0x73, 0x28, 0x87, 0x36, 0x30, 0x07,
+  0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4,
+  0xa1, 0x1e, 0xca, 0x01, 0xd8, 0x40, 0x08, 0x01, 0x60, 0x01, 0x00, 0x00,
+  0x00, 0x49, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x84, 0x40,
+  0x00, 0x89, 0x20, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08,
+  0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22,
+  0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84,
+  0x4c, 0x10, 0x20, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x50, 0x86, 0x88, 0x20,
+  0x19, 0x08, 0x98, 0x23, 0x00, 0x83, 0x14, 0xa8, 0x11, 0x00, 0x00, 0x00,
+  0x00, 0x13, 0xbe, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83,
+  0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87,
+  0x79, 0x88, 0x83, 0x39, 0x70, 0x03, 0x38, 0x70, 0x03, 0x38, 0x68, 0x83,
+  0x79, 0x48, 0x87, 0x76, 0xa8, 0x07, 0x76, 0x08, 0x07, 0x7a, 0x78, 0x07,
+  0x79, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06, 0xf0, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x90,
+  0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9, 0x80,
+  0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60,
+  0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x90,
+  0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20,
+  0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0,
+  0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x76, 0x40,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60,
+  0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60,
+  0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0,
+  0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x73, 0x20, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x74, 0x80,
+  0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60,
+  0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40,
+  0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80,
+  0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x20,
+  0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20,
+  0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x79, 0x20, 0x07, 0x7a, 0x20,
+  0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60,
+  0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0,
+  0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x50, 0x07, 0x71, 0x20,
+  0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20,
+  0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10,
+  0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40,
+  0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30,
+  0x07, 0x72, 0xa0, 0x11, 0xc2, 0x90, 0x47, 0x21, 0xfd, 0x0c, 0x80, 0x34,
+  0x43, 0x22, 0xe0, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x40, 0x62, 0x83, 0x40, 0xd1, 0x38, 0x01, 0x00, 0x80, 0x2c,
+  0x10, 0x07, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x0c, 0x19, 0x11, 0x4c,
+  0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0xaa, 0x22, 0x28, 0x81,
+  0x42, 0x18, 0x01, 0x20, 0x1b, 0x4b, 0x88, 0x04, 0x00, 0xb1, 0x18, 0x00,
+  0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c,
+  0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80,
+  0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed,
+  0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d,
+  0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83,
+  0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78,
+  0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70,
+  0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc,
+  0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3,
+  0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c,
+  0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83,
+  0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03,
+  0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68,
+  0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60,
+  0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80,
+  0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98,
+  0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec,
+  0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d,
+  0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43,
+  0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03,
+  0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03,
+  0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70,
+  0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0,
+  0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4,
+  0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33,
+  0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c,
+  0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e,
+  0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50,
+  0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78,
+  0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33,
+  0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d,
+  0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06,
+  0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43,
+  0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3,
+  0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08,
+  0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec,
+  0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e,
+  0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19,
+  0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43,
+  0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03,
+  0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08,
+  0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed,
+  0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6,
+  0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3,
+  0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2,
+  0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d,
+  0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f,
+  0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83,
+  0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08,
+  0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5,
+  0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3,
+  0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90,
+  0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78,
+  0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00, 0x00, 0x8c, 0x00, 0x00,
+  0x00, 0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c, 0x27, 0x46, 0x46, 0xc8,
+  0x11, 0x32, 0x64, 0xd4, 0x26, 0x28, 0x55, 0x00, 0x00, 0x8b, 0xf2, 0x06,
+  0xc5, 0xc6, 0x91, 0x41, 0x14, 0x19, 0xd2, 0xa2, 0x3c, 0x4c, 0xc1, 0x48,
+  0x08, 0x53, 0x44, 0x4b, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+  0x77, 0x63, 0x68, 0x61, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41, 0x70,
+  0x70, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x20, 0x76, 0x65,
+  0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e,
+  0x39, 0x38, 0x20, 0x28, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x66, 0x65, 0x2d,
+  0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65, 0x74,
+  0x61, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c,
+  0x65, 0x2e, 0x64, 0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64, 0x69,
+  0x73, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
+  0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61,
+  0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72,
+  0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72, 0x61,
+  0x6d, 0x65, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x74,
+  0x63, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72,
+  0x2e, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x72, 0x67,
+  0x65, 0x74, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79,
+  0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x34, 0x61, 0x69, 0x72, 0x2e, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e,
+  0x74, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x75, 0x73, 0x65, 0x72, 0x28,
+  0x6c, 0x6f, 0x63, 0x6e, 0x30, 0x29, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x65,
+  0x6e, 0x74, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x70, 0x65, 0x72, 0x73,
+  0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x61,
+  0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+  0x61, 0x69, 0x72, 0x2e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
+  0x61, 0x69, 0x72, 0x2e, 0x6e, 0x6f, 0x5f, 0x70, 0x65, 0x72, 0x73, 0x70,
+  0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69,
+  0x6f, 0x6e, 0x00, 0x00, 0x00, 0x23, 0x08, 0x45, 0x30, 0x82, 0x60, 0x14,
+  0x23, 0x08, 0x85, 0x30, 0x82, 0x50, 0x0c, 0x23, 0x08, 0x05, 0x31, 0x82,
+  0x30, 0x00, 0x33, 0x0c, 0x54, 0x50, 0xcd, 0x30, 0x58, 0xc2, 0x35, 0x43,
+  0x30, 0xcc, 0x30, 0x50, 0x14, 0x36, 0x03, 0x41, 0x58, 0x16, 0x36, 0x43,
+  0x50, 0xcc, 0x10, 0x18, 0x33, 0x04, 0xc7, 0x0c, 0x05, 0x82, 0x61, 0x89,
+  0x32, 0x43, 0x20, 0x06, 0x33, 0x24, 0xd8, 0xc2, 0x34, 0x4e, 0xa2, 0x3c,
+  0xd0, 0x0c, 0x88, 0x15, 0x35, 0x52, 0xa2, 0x3c, 0xd3, 0x0c, 0x02, 0x19,
+  0x94, 0xc1, 0x0c, 0x43, 0x36, 0x06, 0x66, 0x20, 0x23, 0x81, 0x09, 0xba,
+  0x88, 0x8d, 0xcd, 0xae, 0xcd, 0xa5, 0xed, 0x8d, 0xac, 0x8e, 0xad, 0xcc,
+  0xc5, 0x8c, 0x2d, 0xec, 0x6c, 0x6e, 0x14, 0x21, 0xd3, 0x4e, 0x61, 0x63,
+  0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3, 0x1b, 0x25, 0xd8, 0x6e,
+  0x09, 0x4b, 0x93, 0x73, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x1b,
+  0x25, 0xe0, 0x8e, 0x0a, 0x4b, 0x93, 0x73, 0x61, 0x0b, 0x73, 0x3b, 0xab,
+  0x0b, 0x3b, 0x2b, 0xfb, 0xb2, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x1b,
+  0x25, 0xe8, 0x6e, 0x0a, 0x4b, 0x93, 0x73, 0x19, 0x7b, 0x6b, 0x83, 0x4b,
+  0x63, 0x2b, 0xfb, 0x7a, 0x83, 0xa3, 0x4b, 0x7b, 0x73, 0x9b, 0x1b, 0x65,
+  0xf0, 0x3e, 0x30, 0x38, 0x26, 0x2c, 0x4d, 0xce, 0xc5, 0x4c, 0x2e, 0xec,
+  0xac, 0xad, 0xcc, 0x8d, 0x6e, 0x94, 0xc0, 0x0c, 0x00, 0xa9, 0x18, 0x00,
+  0x00, 0x25, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x72, 0x28, 0x87, 0x77, 0x80,
+  0x07, 0x7a, 0x58, 0x70, 0x98, 0x43, 0x3d, 0xb8, 0xc3, 0x38, 0xb0, 0x43,
+  0x39, 0xd0, 0xc3, 0x82, 0xe6, 0x1c, 0xc6, 0xa1, 0x0d, 0xe8, 0x41, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xe6, 0x21, 0x1d, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d,
+  0x16, 0x34, 0xe3, 0x60, 0x0e, 0xe7, 0x50, 0x0f, 0xe1, 0x20, 0x0f, 0xe4,
+  0x40, 0x0f, 0xe1, 0x20, 0x0f, 0xe7, 0x50, 0x0e, 0xf4, 0xb0, 0x80, 0x81,
+  0x07, 0x79, 0x28, 0x87, 0x70, 0x60, 0x07, 0x76, 0x78, 0x87, 0x71, 0x08,
+  0x07, 0x7a, 0x28, 0x07, 0x72, 0x58, 0x70, 0x9c, 0xc3, 0x38, 0xb4, 0x01,
+  0x3b, 0xa4, 0x83, 0x3d, 0x94, 0xc3, 0x02, 0x6b, 0x1c, 0xd8, 0x21, 0x1c,
+  0xdc, 0xe1, 0x1c, 0xdc, 0x20, 0x1c, 0xe4, 0x61, 0x1c, 0xdc, 0x20, 0x1c,
+  0xe8, 0x81, 0x1e, 0xc2, 0x61, 0x1c, 0xd0, 0xa1, 0x1c, 0xc8, 0x61, 0x1c,
+  0xc2, 0x81, 0x1d, 0xd8, 0x61, 0xc1, 0x01, 0x0f, 0xf4, 0x20, 0x0f, 0xe1,
+  0x50, 0x0f, 0xf4, 0x80, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x10, 0x00,
+  0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0xcc, 0x3c, 0xa4, 0x83, 0x3b, 0x9c,
+  0x03, 0x3b, 0x94, 0x03, 0x3d, 0xa0, 0x83, 0x3c, 0x94, 0x43, 0x38, 0x90,
+  0xc3, 0x01, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00,
+  0x00, 0x13, 0x04, 0x41, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00,
+  0x00, 0x03, 0x00, 0x00, 0x00, 0x32, 0x0e, 0x10, 0x22, 0x84, 0x00, 0xed,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x0c, 0x00,
+  0x00, 0x1f, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0xf0, 0x00, 0x00, 0x00,
+  0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00,
+  0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+  0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x0c, 0x00,
+  0x00, 0x0f, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94, 0x6e, 0x00, 0x00, 0x00,
+  0x00, 0x66, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x33, 0x32, 0x30, 0x32,
+  0x33, 0x2e, 0x39, 0x38, 0x61, 0x69, 0x72, 0x36, 0x34, 0x2d, 0x61, 0x70,
+  0x70, 0x6c, 0x65, 0x2d, 0x69, 0x6f, 0x73, 0x31, 0x33, 0x2e, 0x30, 0x2e,
+  0x30, 0x2d, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 0x72, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00
+};
+const unsigned int cube_frag_metallib_len = 2989;
+#else
+const unsigned char cube_vert_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x08, 0x00, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x00, 0x48, 0x41, 0x53,
+  0x48, 0x20, 0x00, 0x3c, 0x44, 0xfd, 0x7c, 0xda, 0x9f, 0x5b, 0xd6, 0x40,
+  0xbc, 0x7e, 0xb5, 0x95, 0x8e, 0x07, 0x17, 0x23, 0x1d, 0x77, 0xe1, 0x11,
+  0xdb, 0x6d, 0x6e, 0xed, 0xc4, 0x2e, 0x2e, 0x2f, 0xb0, 0x34, 0x71, 0x4f,
+  0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01,
+  0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x29,
+  0x00, 0x00, 0x00, 0x56, 0x41, 0x54, 0x54, 0x15, 0x00, 0x02, 0x00, 0x70,
+  0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x80, 0x63, 0x6f,
+  0x6c, 0x6f, 0x72, 0x00, 0x01, 0x80, 0x56, 0x41, 0x54, 0x59, 0x04, 0x00,
+  0x02, 0x00, 0x05, 0x05, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x6c, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00,
+  0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39,
+  0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
+  0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14,
+  0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a, 0x90, 0x21,
+  0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07, 0xc8, 0x48,
+  0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00,
+  0x51, 0x18, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x1b, 0x7e, 0x24, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0x01, 0x90, 0x00, 0x8a, 0x08, 0x07, 0x78, 0x80,
+  0x07, 0x79, 0x78, 0x07, 0x7c, 0x68, 0x03, 0x73, 0xa8, 0x07, 0x77, 0x18,
+  0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40,
+  0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xda, 0x21, 0x1d,
+  0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d,
+  0xec, 0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e,
+  0xd2, 0x81, 0x1c, 0xe8, 0x01, 0x1d, 0x80, 0x38, 0x90, 0x03, 0x3c, 0x00,
+  0x06, 0x77, 0x78, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x48, 0x07, 0x76, 0xa0,
+  0x87, 0x74, 0x70, 0x87, 0x79, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30,
+  0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48,
+  0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48,
+  0x87, 0x76, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d,
+  0xde, 0xa1, 0x0d, 0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d, 0xca, 0xa1, 0x0d,
+  0xe0, 0xe1, 0x1d, 0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d,
+  0xca, 0x81, 0x1d, 0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d, 0xde, 0xc1, 0x1d,
+  0xda, 0x80, 0x1d, 0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0, 0x07, 0x79, 0xa8,
+  0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x48, 0x07, 0x77, 0x30,
+  0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0,
+  0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d,
+  0xde, 0xa1, 0x0d, 0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e, 0xda, 0xc0, 0x1c,
+  0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90,
+  0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83, 0x79, 0x48,
+  0x87, 0x73, 0x70, 0x87, 0x72, 0x20, 0x87, 0x36, 0xd0, 0x87, 0x72, 0x90,
+  0x87, 0x77, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08,
+  0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20,
+  0xdc, 0xe1, 0x1d, 0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c, 0xe0, 0x01, 0x1e,
+  0xd2, 0xc1, 0x1d, 0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x98, 0x07, 0x7a, 0x08,
+  0x87, 0x71, 0x58, 0x87, 0x36, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7a, 0x28,
+  0x87, 0x71, 0xa0, 0x87, 0x77, 0x90, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x30,
+  0x07, 0x73, 0x28, 0x07, 0x79, 0x68, 0x83, 0x79, 0x48, 0x07, 0x7d, 0x28,
+  0x07, 0x00, 0x0f, 0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e, 0xc2, 0xc1, 0x1c,
+  0xca, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e,
+  0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x36, 0x6c, 0xc2,
+  0x00, 0x2c, 0x40, 0x35, 0x84, 0x43, 0x3a, 0xc8, 0x43, 0x1b, 0x88, 0x43,
+  0x3d, 0x98, 0x83, 0x39, 0x94, 0x83, 0x3c, 0xb4, 0x81, 0x3b, 0xbc, 0x43,
+  0x1b, 0x84, 0x03, 0x3b, 0xa4, 0x43, 0x38, 0xcc, 0x03, 0x00, 0x00, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x84, 0x40, 0x00,
+  0x89, 0x20, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09,
+  0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3,
+  0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c,
+  0x10, 0x44, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x60, 0x85, 0x10, 0x86, 0x11,
+  0x06, 0x20, 0x09, 0xc2, 0x4c, 0xd4, 0x3c, 0xd0, 0x83, 0x3c, 0xd4, 0xc3,
+  0x38, 0xd0, 0x83, 0x1b, 0xb4, 0x43, 0x39, 0xd0, 0x43, 0x38, 0xb0, 0x83,
+  0x1e, 0xe8, 0x41, 0x3b, 0x84, 0x03, 0x3d, 0xc8, 0x43, 0x3a, 0xe0, 0x03,
+  0x0a, 0xc8, 0x29, 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xbb, 0x1b, 0x8a, 0x82,
+  0x32, 0x88, 0x60, 0x08, 0x85, 0x10, 0x63, 0x1c, 0x42, 0x03, 0x01, 0x73,
+  0x04, 0x60, 0x90, 0x02, 0x6b, 0x18, 0x81, 0x58, 0xe6, 0x08, 0x40, 0x61,
+  0x10, 0x21, 0x10, 0x46, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa8, 0x70, 0x48,
+  0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60,
+  0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8, 0x03, 0x37, 0x80,
+  0x03, 0x37, 0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d, 0x00, 0x0f, 0x7a,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d,
+  0x90, 0x0e, 0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9,
+  0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a,
+  0x10, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6,
+  0x40, 0x07, 0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76, 0xa0, 0x07, 0x71,
+  0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6,
+  0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a,
+  0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x90, 0x07, 0x72,
+  0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76,
+  0xd0, 0x06, 0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75,
+  0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x75,
+  0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75,
+  0x10, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74,
+  0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70,
+  0x20, 0x07, 0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x43, 0x98, 0x04, 0x00, 0x80, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x32, 0x1e, 0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47,
+  0xc6, 0x04, 0x43, 0x5a, 0x25, 0x30, 0x02, 0x50, 0x80, 0x01, 0x45, 0x50,
+  0x08, 0x05, 0x51, 0x20, 0xe4, 0x46, 0x00, 0x88, 0x8d, 0x25, 0x44, 0x02,
+  0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00,
+  0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9,
+  0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x42, 0x28, 0x00, 0x93, 0x50, 0xb9,
+  0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x2c,
+  0x81, 0x22, 0x2c, 0x05, 0xdf, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4,
+  0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd,
+  0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x07, 0x04, 0xa5,
+  0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46, 0x66,
+  0xc6, 0x25, 0x07, 0x27, 0x65, 0x88, 0xa0, 0x10, 0x43, 0x8c, 0x25, 0x58,
+  0x8c, 0x45, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04, 0x51, 0x8e,
+  0x25, 0x58, 0x82, 0x45, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6,
+  0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36,
+  0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44, 0x50, 0x12,
+  0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+  0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65,
+  0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x65, 0x21, 0x19, 0x84, 0xa5,
+  0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9,
+  0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95,
+  0xd1, 0x8d, 0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11,
+  0x94, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5d, 0x99, 0x1c, 0x5d, 0x19,
+  0xde, 0xd7, 0x5b, 0x1d, 0x1d, 0x5c, 0x1d, 0x1d, 0x97, 0xba, 0xb9, 0x32,
+  0x39, 0x14, 0xb6, 0xb7, 0x31, 0x37, 0x98, 0x14, 0x46, 0x61, 0x69, 0x72,
+  0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61,
+  0x6d, 0x65, 0x34, 0xcc, 0xd8, 0xde, 0xc2, 0xe8, 0x68, 0xc8, 0x84, 0xa5,
+  0xc9, 0xb9, 0x84, 0xc9, 0x9d, 0x7d, 0xb9, 0x85, 0xb5, 0x95, 0xb1, 0x18,
+  0x7b, 0x63, 0x7b, 0x93, 0x1b, 0xc2, 0x28, 0x8f, 0x02, 0x29, 0x91, 0x22,
+  0x29, 0x93, 0x42, 0x91, 0x09, 0x4b, 0x93, 0x73, 0x81, 0x7b, 0x9b, 0x4b,
+  0xa3, 0x4b, 0x7b, 0x73, 0x23, 0x02, 0xf7, 0x36, 0x97, 0x46, 0x97, 0xf6,
+  0xe6, 0x36, 0x44, 0x51, 0x2c, 0x25, 0x52, 0x24, 0x65, 0x52, 0xae, 0x21,
+  0x84, 0x52, 0x29, 0x18, 0xa1, 0xb0, 0x34, 0x39, 0x17, 0xbb, 0x32, 0x39,
+  0xba, 0x32, 0xbc, 0xaf, 0x34, 0x37, 0xb8, 0x3a, 0x3a, 0x4a, 0x61, 0x69,
+  0x72, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69,
+  0x6e, 0x64, 0x65, 0x78, 0xf4, 0xce, 0xca, 0xdc, 0xca, 0xe4, 0xc2, 0xe8,
+  0xca, 0xc8, 0x50, 0xbe, 0xbe, 0xc2, 0xd2, 0xe4, 0xbe, 0xe0, 0xd8, 0xc2,
+  0xc6, 0xca, 0xd0, 0xde, 0xd8, 0xc8, 0xca, 0xe4, 0xbe, 0xbe, 0x52, 0x68,
+  0x98, 0xb1, 0xbd, 0x85, 0xd1, 0xcd, 0x0c, 0xa1, 0x16, 0x41, 0xd1, 0x94,
+  0x6d, 0x11, 0x96, 0x40, 0xe1, 0x94, 0x48, 0xe9, 0x94, 0x49, 0xb9, 0x86,
+  0x50, 0x4b, 0xa0, 0x68, 0xca, 0xb6, 0x04, 0x4b, 0xa0, 0x70, 0x4a, 0xa4,
+  0x74, 0xca, 0xa4, 0x50, 0x54, 0xc2, 0xd2, 0xe4, 0x5c, 0xc4, 0xea, 0xcc,
+  0xcc, 0xca, 0xe4, 0xf8, 0x84, 0xa5, 0xc9, 0xb9, 0x88, 0xd5, 0x99, 0x99,
+  0x95, 0xc9, 0x7d, 0xcd, 0xa5, 0xe9, 0x95, 0x11, 0x09, 0x4b, 0x93, 0x73,
+  0x91, 0x2b, 0x0b, 0x23, 0x23, 0x15, 0x96, 0x26, 0xe7, 0x32, 0x47, 0x27,
+  0x57, 0x37, 0x46, 0xf7, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x95, 0xe6, 0x66,
+  0xf6, 0x46, 0xc4, 0x8c, 0xed, 0x2d, 0x8c, 0x8e, 0x06, 0x8f, 0x86, 0x4d,
+  0xdb, 0x1b, 0x59, 0x19, 0x9b, 0x55, 0x5a, 0xd9, 0x1d, 0x94, 0xdc, 0x9b,
+  0xda, 0x10, 0x65, 0x11, 0x96, 0x61, 0x11, 0x14, 0x32, 0x50, 0xca, 0x80,
+  0x51, 0x58, 0x9a, 0x9c, 0x4b, 0x98, 0xdc, 0xd9, 0x17, 0x5d, 0x1e, 0x5c,
+  0xd9, 0xd7, 0x5c, 0x9a, 0x5e, 0x19, 0xaf, 0xb0, 0x34, 0x39, 0x97, 0x30,
+  0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0xaf, 0x30, 0xb6, 0xb4, 0x33,
+  0xb7, 0xaf, 0xb9, 0x34, 0xbd, 0x32, 0x0e, 0x55, 0x42, 0x4f, 0x1c, 0xea,
+  0xc4, 0xde, 0x86, 0x90, 0xc1, 0x42, 0x28, 0x60, 0xa0, 0x84, 0xc1, 0x32,
+  0x28, 0xdb, 0x22, 0x2c, 0x81, 0x22, 0x06, 0xca, 0x18, 0x28, 0x66, 0xa0,
+  0x9c, 0xc1, 0x32, 0x28, 0x68, 0xb0, 0x1c, 0x4a, 0xa4, 0xa4, 0x81, 0x32,
+  0x29, 0x6a, 0x30, 0xc4, 0x50, 0x3c, 0xe5, 0x53, 0xd6, 0x60, 0x88, 0x91,
+  0x00, 0x4a, 0xa6, 0xb0, 0x01, 0x9f, 0xb7, 0x36, 0xb7, 0x34, 0xb8, 0x37,
+  0xba, 0x32, 0x37, 0x3a, 0x90, 0x31, 0xb4, 0x30, 0x39, 0x3e, 0x53, 0x69,
+  0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x54, 0x42, 0x41,
+  0x41, 0x43, 0x04, 0xe5, 0x0d, 0x86, 0x18, 0x8a, 0x1b, 0x28, 0x70, 0xe0,
+  0x20, 0x43, 0x0c, 0x25, 0x0e, 0x94, 0x38, 0x70, 0x10, 0x66, 0x61, 0x69,
+  0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70,
+  0x65, 0x73, 0x28, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x29, 0x43,
+  0x08, 0x85, 0x0e, 0x94, 0x39, 0xa0, 0x15, 0x96, 0x26, 0xd7, 0x12, 0xc6,
+  0x96, 0x16, 0x36, 0xd7, 0x32, 0x37, 0xf6, 0x06, 0x57, 0xd6, 0x12, 0x26,
+  0x77, 0x86, 0x22, 0x93, 0x32, 0xc4, 0x50, 0xec, 0x40, 0xa1, 0x03, 0xa5,
+  0x0e, 0x86, 0x08, 0x8a, 0x1d, 0x8c, 0x88, 0xd8, 0x81, 0x1d, 0xec, 0xa1,
+  0x1d, 0xdc, 0xa0, 0x1d, 0xde, 0x81, 0x1c, 0xea, 0x81, 0x1d, 0xca, 0xc1,
+  0x0d, 0xcc, 0x81, 0x1d, 0xc2, 0xe1, 0x1c, 0xe6, 0x61, 0x8a, 0x10, 0x0c,
+  0x23, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x48, 0x07, 0x72,
+  0x28, 0x07, 0x77, 0xa0, 0x87, 0x29, 0x41, 0x31, 0x62, 0x09, 0x87, 0x74,
+  0x90, 0x07, 0x37, 0xb0, 0x87, 0x72, 0x90, 0x87, 0x79, 0x48, 0x87, 0x77,
+  0x70, 0x87, 0x29, 0x81, 0x31, 0x82, 0x0a, 0x87, 0x74, 0x90, 0x07, 0x37,
+  0x60, 0x87, 0x70, 0x70, 0x87, 0x73, 0xa8, 0x87, 0x70, 0x38, 0x87, 0x72,
+  0xf8, 0x05, 0x7b, 0x28, 0x07, 0x79, 0x98, 0x87, 0x74, 0x78, 0x07, 0x77,
+  0x98, 0x12, 0x20, 0x23, 0xa6, 0x70, 0x48, 0x07, 0x79, 0x70, 0x83, 0x71,
+  0x78, 0x87, 0x76, 0x80, 0x87, 0x74, 0x60, 0x87, 0x72, 0xf8, 0x85, 0x77,
+  0x80, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x79, 0x98, 0x32, 0x28,
+  0x8c, 0x33, 0x42, 0x09, 0x87, 0x74, 0x90, 0x07, 0x37, 0xb0, 0x87, 0x72,
+  0x90, 0x07, 0x7a, 0x28, 0x07, 0x7c, 0x98, 0x12, 0xb4, 0x01, 0x00, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c,
+  0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3,
+  0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6,
+  0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03,
+  0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48,
+  0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20,
+  0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e,
+  0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d,
+  0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89,
+  0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83,
+  0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78,
+  0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98,
+  0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5,
+  0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c,
+  0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43,
+  0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82,
+  0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58,
+  0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18,
+  0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2,
+  0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec,
+  0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e,
+  0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d,
+  0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83,
+  0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60,
+  0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0,
+  0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d,
+  0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d,
+  0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43,
+  0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3,
+  0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18,
+  0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3,
+  0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1,
+  0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e,
+  0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3,
+  0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3,
+  0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60,
+  0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec,
+  0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5,
+  0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5,
+  0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8,
+  0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17,
+  0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d,
+  0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03,
+  0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78,
+  0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce,
+  0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef,
+  0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08,
+  0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0,
+  0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8,
+  0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x06, 0x70, 0x54, 0xd2, 0xcf, 0x00, 0x48, 0x03,
+  0x61, 0x20, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c,
+  0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xe4, 0xca, 0xa0, 0x08,
+  0x4a, 0x80, 0xda, 0x58, 0x84, 0x20, 0x08, 0x02, 0xad, 0x19, 0x80, 0x32,
+  0xa0, 0x36, 0x07, 0x21, 0x04, 0x44, 0x34, 0x02, 0x30, 0x16, 0x11, 0x04,
+  0x41, 0x40, 0x63, 0x06, 0x60, 0x06, 0x80, 0xc4, 0x0c, 0x00, 0x81, 0x31,
+  0x02, 0x10, 0x04, 0x41, 0xfc, 0x03, 0x00, 0x00, 0x83, 0x0c, 0x0f, 0x71,
+  0xcc, 0x31, 0x04, 0x42, 0x32, 0x5e, 0x01, 0x51, 0x9a, 0x46, 0x51, 0x50,
+  0x06, 0x19, 0xa8, 0x43, 0x31, 0x21, 0x90, 0xcf, 0x78, 0x05, 0x85, 0x79,
+  0x5e, 0x44, 0x41, 0x19, 0x64, 0xc0, 0x96, 0xc6, 0x84, 0x40, 0x3e, 0x16,
+  0x14, 0xf0, 0x19, 0xaf, 0xc8, 0xba, 0x31, 0x18, 0x83, 0x8b, 0x82, 0x32,
+  0xc8, 0xd0, 0x41, 0x97, 0x09, 0x81, 0x7c, 0xac, 0x08, 0xe0, 0x33, 0x5e,
+  0xe1, 0x89, 0x01, 0x1a, 0xa0, 0x41, 0x47, 0x41, 0xb1, 0x21, 0x80, 0xcf,
+  0x6c, 0x43, 0x25, 0x01, 0xb3, 0x0d, 0x81, 0x10, 0x64, 0x10, 0x10, 0x03,
+  0x08, 0x00, 0x00, 0x00, 0x5b, 0x8a, 0x21, 0x90, 0x83, 0xe3, 0x0e, 0xb6,
+  0x14, 0x47, 0x20, 0x07, 0xc7, 0x1d, 0x6c, 0x29, 0x98, 0x40, 0x0e, 0x8e,
+  0x3b, 0xd8, 0x52, 0x44, 0x81, 0x1c, 0x1c, 0x77, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int cube_vert_metallib_len = 3200;
+const unsigned char cube_frag_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfb, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x09, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x08, 0x00, 0x66, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01, 0x48, 0x41, 0x53,
+  0x48, 0x20, 0x00, 0x29, 0xbb, 0xc2, 0x87, 0x30, 0x03, 0x9b, 0xc2, 0x29,
+  0xf0, 0xd6, 0x9a, 0x0e, 0x55, 0xa4, 0xf4, 0xb6, 0xd7, 0x55, 0x10, 0xd8,
+  0x1c, 0x85, 0xfd, 0xae, 0x53, 0xe4, 0xeb, 0x05, 0xa4, 0xee, 0xca, 0x4f,
+  0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01,
+  0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04,
+  0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45,
+  0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14,
+  0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x3e, 0x02, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a, 0x90, 0x21, 0x23,
+  0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07, 0xc8, 0x08, 0x11,
+  0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x51,
+  0x18, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x1b, 0x7e, 0x24, 0xf8, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x90, 0x00, 0x8a, 0x08, 0x07, 0x78, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x7c, 0x68, 0x03, 0x73, 0xa8, 0x07, 0x77, 0x18, 0x87,
+  0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07,
+  0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xda, 0x21, 0x1d, 0xdc,
+  0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d, 0xec,
+  0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e, 0xd2,
+  0x81, 0x1c, 0xe8, 0x01, 0x1d, 0x80, 0x38, 0x90, 0x03, 0x3c, 0x00, 0x06,
+  0x77, 0x78, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x48, 0x07, 0x76, 0xa0, 0x87,
+  0x74, 0x70, 0x87, 0x79, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30, 0x07,
+  0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48, 0x07,
+  0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48, 0x87,
+  0x76, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde,
+  0xa1, 0x0d, 0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d, 0xca, 0xa1, 0x0d, 0xe0,
+  0xe1, 0x1d, 0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xca,
+  0x81, 0x1d, 0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d, 0xde, 0xc1, 0x1d, 0xda,
+  0x80, 0x1d, 0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87,
+  0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x48, 0x07, 0x77, 0x30, 0x87,
+  0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07,
+  0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde,
+  0xa1, 0x0d, 0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0,
+  0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87,
+  0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83, 0x79, 0x48, 0x87,
+  0x73, 0x70, 0x87, 0x72, 0x20, 0x87, 0x36, 0xd0, 0x87, 0x72, 0x90, 0x87,
+  0x77, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07,
+  0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc,
+  0xe1, 0x1d, 0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c, 0xe0, 0x01, 0x1e, 0xd2,
+  0xc1, 0x1d, 0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x98, 0x07, 0x7a, 0x08, 0x87,
+  0x71, 0x58, 0x87, 0x36, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7a, 0x28, 0x87,
+  0x71, 0xa0, 0x87, 0x77, 0x90, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x30, 0x07,
+  0x73, 0x28, 0x07, 0x79, 0x68, 0x83, 0x79, 0x48, 0x07, 0x7d, 0x28, 0x07,
+  0x00, 0x0f, 0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e, 0xc2, 0xc1, 0x1c, 0xca,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x36, 0x10, 0x42, 0x00,
+  0x58, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13,
+  0x84, 0x40, 0x00, 0x89, 0x20, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04,
+  0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b,
+  0x84, 0x84, 0x4c, 0x10, 0x20, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x50, 0x86,
+  0x88, 0x20, 0x19, 0x08, 0x98, 0x23, 0x00, 0x83, 0x14, 0xa8, 0x11, 0x00,
+  0x00, 0x00, 0x00, 0x13, 0xa8, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a,
+  0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x74,
+  0x78, 0x87, 0x79, 0xc8, 0x03, 0x37, 0x80, 0x03, 0x37, 0x80, 0x83, 0x0d,
+  0xb7, 0x51, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe9, 0x10, 0x07,
+  0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07,
+  0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06, 0xe9, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06,
+  0xe9, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07,
+  0x74, 0xd0, 0x06, 0xe6, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06,
+  0xf6, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xd0, 0x06, 0xf6, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x40, 0x07, 0x78, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06,
+  0xf6, 0x90, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07,
+  0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x72, 0x80, 0x07,
+  0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07,
+  0x6d, 0x60, 0x0f, 0x71, 0x90, 0x07, 0x72, 0xa0, 0x07, 0x72, 0x50, 0x07,
+  0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07,
+  0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07,
+  0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07,
+  0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xd0, 0x06,
+  0xf6, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07,
+  0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xd0, 0x06,
+  0xee, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x43, 0x98, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c,
+  0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x0c, 0x19,
+  0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0xaa, 0x12,
+  0x18, 0x01, 0x28, 0x82, 0x42, 0x28, 0x08, 0xb2, 0xb1, 0x84, 0x48, 0x00,
+  0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x1a,
+  0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9, 0xb9,
+  0xb4, 0x37, 0xb7, 0x21, 0x46, 0x31, 0x10, 0x80, 0x61, 0x50, 0xb9, 0x1b,
+  0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x14, 0x01,
+  0x21, 0x14, 0x04, 0xdf, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4, 0xad,
+  0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x0d,
+  0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x07, 0x04, 0xa5, 0xad,
+  0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46, 0x66, 0xc6,
+  0x25, 0x07, 0x27, 0x65, 0x88, 0x40, 0x10, 0x43, 0x8c, 0x22, 0x28, 0x8a,
+  0x42, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04, 0x21, 0x8e, 0x22,
+  0x28, 0x82, 0x42, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6, 0x06,
+  0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36, 0xf7,
+  0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44, 0x20, 0x12, 0x72,
+  0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e,
+  0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e,
+  0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x62, 0x21, 0x19, 0x84, 0xa5, 0xc9,
+  0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9, 0x85,
+  0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95, 0xd1,
+  0x8d, 0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11, 0x88,
+  0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99, 0x1b, 0x59, 0x99, 0xdc,
+  0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3, 0xb0, 0x34, 0x39, 0x97,
+  0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0x2f, 0xb7, 0xb0, 0xb6,
+  0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x43, 0x10, 0xe2, 0x29,
+  0x04, 0x02, 0x22, 0xa2, 0x21, 0x02, 0x21, 0x51, 0x0a, 0x4b, 0x93, 0x73,
+  0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0xfb, 0x4a, 0x73, 0x83,
+  0xab, 0xa3, 0xe3, 0x52, 0x37, 0x57, 0x26, 0x87, 0xc2, 0xf6, 0x36, 0xe6,
+  0x06, 0x93, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d, 0xae,
+  0x4c, 0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c, 0x5c,
+  0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x99, 0xb0, 0x34, 0x39, 0x97, 0x30,
+  0xb9, 0xb3, 0x2f, 0xb7, 0xb0, 0xb6, 0x32, 0x16, 0x63, 0x6f, 0x6c, 0x6f,
+  0x72, 0x43, 0xa4, 0x42, 0x20, 0x28, 0xa2, 0x22, 0x2c, 0xe2, 0x22, 0x20,
+  0x22, 0x22, 0x30, 0x22, 0x23, 0x13, 0x96, 0x26, 0xe7, 0x02, 0xf7, 0x36,
+  0x97, 0x46, 0x97, 0xf6, 0xe6, 0x46, 0x29, 0x2c, 0x4d, 0xce, 0xc5, 0xed,
+  0xed, 0x0b, 0xae, 0x4c, 0x6e, 0x0e, 0xae, 0x6c, 0x8c, 0x2e, 0xcd, 0xae,
+  0x8c, 0x08, 0xdc, 0xdb, 0x5c, 0x1a, 0x5d, 0xda, 0x9b, 0xdb, 0x10, 0xa8,
+  0x08, 0x88, 0x8d, 0xb0, 0x08, 0x8e, 0x80, 0x88, 0x88, 0xc0, 0x88, 0x6e,
+  0x08, 0x41, 0x68, 0x84, 0x37, 0xc4, 0x18, 0x00, 0x62, 0x22, 0xbe, 0x11,
+  0x11, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0xb4, 0xc3, 0x3b, 0x90,
+  0x43, 0x3d, 0xb0, 0x43, 0x39, 0xb8, 0x81, 0x39, 0xb0, 0x43, 0x38, 0x9c,
+  0xc3, 0x3c, 0x4c, 0x11, 0x82, 0x61, 0x84, 0xc2, 0x0e, 0xec, 0x60, 0x0f,
+  0xed, 0xe0, 0x06, 0xe9, 0x40, 0x0e, 0xe5, 0xe0, 0x0e, 0xf4, 0x30, 0x25,
+  0x28, 0x46, 0x2c, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e,
+  0xf2, 0x30, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x25, 0x30, 0x46, 0x50,
+  0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xec, 0x10, 0x0e, 0xee, 0x70, 0x0e,
+  0xf5, 0x10, 0x0e, 0xe7, 0x50, 0x0e, 0xbf, 0x60, 0x0f, 0xe5, 0x20, 0x0f,
+  0xf3, 0x90, 0x0e, 0xef, 0xe0, 0x0e, 0x53, 0x02, 0x64, 0xc4, 0x14, 0x0e,
+  0xe9, 0x20, 0x0f, 0x6e, 0x30, 0x0e, 0xef, 0xd0, 0x0e, 0xf0, 0x90, 0x0e,
+  0xec, 0x50, 0x0e, 0xbf, 0xf0, 0x0e, 0xf0, 0x40, 0x0f, 0xe9, 0xf0, 0x0e,
+  0xee, 0x30, 0x0f, 0x53, 0x06, 0x85, 0x71, 0x46, 0x30, 0xe1, 0x90, 0x0e,
+  0xf2, 0xe0, 0x06, 0xe6, 0x20, 0x0f, 0xe1, 0x70, 0x0e, 0xed, 0x50, 0x0e,
+  0xee, 0x40, 0x0f, 0x53, 0x02, 0x30, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74,
+  0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19,
+  0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e,
+  0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28,
+  0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81,
+  0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18,
+  0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78,
+  0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a,
+  0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01,
+  0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85,
+  0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc,
+  0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5,
+  0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a,
+  0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e,
+  0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1,
+  0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0,
+  0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc,
+  0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc,
+  0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71,
+  0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06,
+  0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e,
+  0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06,
+  0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61,
+  0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21,
+  0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20,
+  0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc,
+  0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a,
+  0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e,
+  0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e,
+  0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37,
+  0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77,
+  0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06,
+  0x70, 0x14, 0xd2, 0xcf, 0x00, 0x48, 0x03, 0x61, 0x20, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int cube_frag_metallib_len = 2555;
+#endif
+#elif defined(SDL_PLATFORM_TVOS)
+#if TARGET_OS_SIMULATOR
+const unsigned char cube_vert_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x42, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0d, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x08, 0x00, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x00, 0x48, 0x41, 0x53,
+  0x48, 0x20, 0x00, 0x83, 0x69, 0xec, 0x76, 0x0b, 0x77, 0xa9, 0x9d, 0x73,
+  0x62, 0xb7, 0x05, 0xac, 0xd5, 0x65, 0x7a, 0xad, 0x0a, 0xbb, 0x4d, 0x13,
+  0x1c, 0xe3, 0xf7, 0xcb, 0x72, 0xbc, 0x27, 0xba, 0xe5, 0x05, 0x7a, 0x4d,
+  0x44, 0x53, 0x5a, 0x08, 0x00, 0x30, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08,
+  0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44,
+  0x54, 0x45, 0x4e, 0x44, 0x54, 0x29, 0x00, 0x00, 0x00, 0x56, 0x41, 0x54,
+  0x54, 0x15, 0x00, 0x02, 0x00, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
+  0x6e, 0x00, 0x00, 0x80, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x01, 0x80,
+  0x56, 0x41, 0x54, 0x59, 0x04, 0x00, 0x02, 0x00, 0x05, 0x05, 0x45, 0x4e,
+  0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0,
+  0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x0d,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x35, 0x14,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x0c, 0x30, 0x24, 0x80, 0x10,
+  0x05, 0xc8, 0x14, 0x00, 0x00, 0x00, 0x21, 0x0c, 0x00, 0x00, 0x0c, 0x03,
+  0x00, 0x00, 0x0b, 0x02, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00,
+  0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10,
+  0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04,
+  0x8b, 0x62, 0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10,
+  0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x52, 0x88, 0x48, 0x90,
+  0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0x04, 0x49,
+  0x0e, 0x90, 0x91, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83,
+  0xe5, 0x8a, 0x04, 0x29, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x71, 0x00,
+  0x00, 0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80,
+  0x03, 0x40, 0x02, 0x28, 0x22, 0x1c, 0xe0, 0x01, 0x1e, 0xe4, 0xe1, 0x1d,
+  0xf0, 0xa1, 0x0d, 0xcc, 0xa1, 0x1e, 0xdc, 0x61, 0x1c, 0xda, 0xc0, 0x1c,
+  0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90,
+  0x87, 0x7a, 0x28, 0x07, 0x80, 0x68, 0x87, 0x74, 0x70, 0x87, 0x36, 0x60,
+  0x87, 0x72, 0x38, 0x87, 0x70, 0x60, 0x87, 0x36, 0xb0, 0x87, 0x72, 0x18,
+  0x07, 0x7a, 0x78, 0x07, 0x79, 0x68, 0x83, 0x7b, 0x48, 0x07, 0x72, 0xa0,
+  0x07, 0x74, 0x00, 0xe2, 0x40, 0x0e, 0xf0, 0x00, 0x18, 0xdc, 0xe1, 0x1d,
+  0xda, 0x40, 0x1c, 0xea, 0x21, 0x1d, 0xd8, 0x81, 0x1e, 0xd2, 0xc1, 0x1d,
+  0xe6, 0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c,
+  0xda, 0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e,
+  0xca, 0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0x01, 0xa0,
+  0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30,
+  0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48,
+  0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48,
+  0x87, 0x76, 0x68, 0x03, 0x77, 0x78, 0x07, 0x77, 0x68, 0x03, 0x76, 0x28,
+  0x87, 0x70, 0x30, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20,
+  0xdc, 0xe1, 0x1d, 0xda, 0x20, 0x1d, 0xdc, 0xc1, 0x1c, 0xe6, 0xa1, 0x0d,
+  0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0,
+  0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x70,
+  0x87, 0x70, 0x70, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68,
+  0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c,
+  0x00, 0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xce, 0xc1, 0x1d,
+  0xca, 0x81, 0x1c, 0xda, 0x40, 0x1f, 0xca, 0x41, 0x1e, 0xde, 0x61, 0x1e,
+  0xda, 0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68,
+  0x03, 0x7a, 0x90, 0x87, 0x70, 0x80, 0x07, 0x78, 0x48, 0x07, 0x77, 0x38,
+  0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e,
+  0xea, 0xa1, 0x1c, 0x00, 0x62, 0x1e, 0xe8, 0x21, 0x1c, 0xc6, 0x61, 0x1d,
+  0xda, 0x00, 0x1e, 0xe4, 0xe1, 0x1d, 0xe8, 0xa1, 0x1c, 0xc6, 0x81, 0x1e,
+  0xde, 0x41, 0x1e, 0xda, 0x40, 0x1c, 0xea, 0xc1, 0x1c, 0xcc, 0xa1, 0x1c,
+  0xe4, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xf4, 0xa1, 0x1c, 0x00, 0x3c, 0x00,
+  0x88, 0x7a, 0x70, 0x87, 0x79, 0x08, 0x07, 0x73, 0x28, 0x87, 0x36, 0x30,
+  0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e,
+  0xe4, 0xa1, 0x1e, 0xca, 0x01, 0xd8, 0xe0, 0x09, 0x03, 0xb0, 0x00, 0x55,
+  0x90, 0x06, 0xa0, 0x30, 0x84, 0x43, 0x3a, 0xc8, 0x43, 0x1b, 0x88, 0x43,
+  0x3d, 0x98, 0x83, 0x39, 0x94, 0x83, 0x3c, 0xb4, 0x81, 0x3b, 0xbc, 0x43,
+  0x1b, 0x84, 0x03, 0x3b, 0xa4, 0x43, 0x38, 0xcc, 0x03, 0x00, 0x49, 0x18,
+  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x84, 0x40, 0x00, 0x89, 0x20,
+  0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09, 0x20, 0x64,
+  0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1,
+  0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x44,
+  0x33, 0x00, 0xc3, 0x08, 0x04, 0x60, 0x85, 0x10, 0x86, 0x11, 0x06, 0x20,
+  0x09, 0xc2, 0x4c, 0xd4, 0x3c, 0xd0, 0x83, 0x3c, 0xd4, 0xc3, 0x38, 0xd0,
+  0x83, 0x1b, 0xb4, 0x43, 0x39, 0xd0, 0x43, 0x38, 0xb0, 0x83, 0x1e, 0xe8,
+  0x41, 0x3b, 0x84, 0x03, 0x3d, 0xc8, 0x43, 0x3a, 0xe0, 0x03, 0x0a, 0xc8,
+  0x29, 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xbb, 0x1b, 0x8a, 0x82, 0x32, 0x88,
+  0x60, 0x08, 0x85, 0x10, 0x63, 0x1c, 0x42, 0x03, 0x01, 0x73, 0x04, 0x60,
+  0x90, 0x02, 0x6b, 0x18, 0x81, 0x58, 0xe6, 0x08, 0x40, 0x61, 0x10, 0x21,
+  0x10, 0x46, 0x00, 0x00, 0x00, 0x00, 0x13, 0xc0, 0x20, 0x1c, 0xd2, 0x41,
+  0x1e, 0xec, 0x80, 0x0e, 0xda, 0x20, 0x1c, 0xe0, 0x01, 0x1e, 0xd8, 0xa1,
+  0x1c, 0xda, 0x80, 0x1e, 0xec, 0xe1, 0x1d, 0xe6, 0x21, 0x0e, 0xe6, 0xc0,
+  0x0d, 0xe0, 0xc0, 0x0d, 0xe0, 0xa0, 0x0d, 0xe6, 0x21, 0x1d, 0xda, 0xa1,
+  0x1e, 0xd8, 0x21, 0x1c, 0xe8, 0xe1, 0x1d, 0xe4, 0x61, 0xc3, 0x6d, 0x94,
+  0x43, 0x1b, 0xc0, 0x83, 0x1e, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0,
+  0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x41, 0x3a, 0xc4, 0x81, 0x1e, 0xe0,
+  0x81, 0x1e, 0xe0, 0x41, 0x1b, 0xa4, 0x03, 0x1e, 0xe8, 0x01, 0x1e, 0xe8,
+  0x01, 0x1e, 0xb4, 0x41, 0x3a, 0xc4, 0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xd8,
+  0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xb4, 0x41, 0x3a, 0xcc, 0x81, 0x1c, 0xe8,
+  0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x41, 0x3a, 0xd8,
+  0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4,
+  0x81, 0x39, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc,
+  0x81, 0x1c, 0xb4, 0x81, 0x39, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0,
+  0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xc4, 0x81, 0x1d, 0xe8,
+  0x41, 0x1c, 0xd8, 0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xb4, 0x81, 0x3d, 0xc8,
+  0x01, 0x1d, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4,
+  0x81, 0x3d, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc,
+  0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xd0, 0x01, 0x1e, 0xe8, 0x81, 0x1d, 0xd0,
+  0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xd8, 0x01, 0x1d, 0xe8,
+  0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xe4,
+  0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xc8, 0x01, 0x1e, 0xe8, 0x41, 0x1c, 0xc8,
+  0x01, 0x1e, 0xb4, 0x81, 0x3d, 0xc4, 0x81, 0x1c, 0xe0, 0x81, 0x1e, 0xc4,
+  0x81, 0x1c, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1c, 0xe0, 0x41, 0x1b, 0xd8,
+  0x43, 0x1c, 0xe4, 0x81, 0x1c, 0xe8, 0x81, 0x1c, 0xd4, 0x81, 0x1d, 0xe8,
+  0x81, 0x1c, 0xd4, 0x81, 0x1d, 0xb4, 0x81, 0x3d, 0xc8, 0x41, 0x1d, 0xd8,
+  0x81, 0x1e, 0xc8, 0x41, 0x1d, 0xd8, 0x81, 0x1e, 0xc8, 0x41, 0x1d, 0xd8,
+  0x41, 0x1b, 0xd8, 0x43, 0x1d, 0xc4, 0x81, 0x1c, 0xe8, 0x41, 0x1d, 0xc4,
+  0x81, 0x1c, 0xe8, 0x41, 0x1d, 0xc4, 0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xc4,
+  0x01, 0x1c, 0xc8, 0x01, 0x1d, 0xe8, 0x41, 0x1c, 0xc0, 0x81, 0x1c, 0xd0,
+  0x81, 0x1e, 0xc4, 0x01, 0x1c, 0xc8, 0x01, 0x1d, 0xb4, 0x81, 0x3b, 0xe0,
+  0x81, 0x1e, 0xc4, 0x81, 0x1d, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x46, 0x08,
+  0x43, 0x1e, 0x95, 0xf4, 0x33, 0x00, 0xd2, 0x0c, 0x89, 0x80, 0x03, 0x01,
+  0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x89, 0x0d,
+  0x02, 0x45, 0x1d, 0x06, 0x00, 0x00, 0xb2, 0x40, 0x00, 0x00, 0x09, 0x00,
+  0x00, 0x00, 0x32, 0x1e, 0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09,
+  0x26, 0x47, 0xc6, 0x04, 0x43, 0x5a, 0x45, 0x50, 0x02, 0x85, 0x30, 0x02,
+  0x50, 0x80, 0x01, 0x05, 0x42, 0x6e, 0x04, 0x80, 0xd8, 0x58, 0x42, 0x24,
+  0x00, 0x00, 0xb1, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08,
+  0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38,
+  0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71,
+  0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c,
+  0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d,
+  0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d,
+  0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07,
+  0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87,
+  0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30,
+  0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10,
+  0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66,
+  0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c,
+  0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07,
+  0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87,
+  0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05,
+  0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87,
+  0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0,
+  0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca,
+  0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38,
+  0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c,
+  0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87,
+  0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87,
+  0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00,
+  0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20,
+  0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2,
+  0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4,
+  0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a,
+  0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07,
+  0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90,
+  0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8,
+  0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc,
+  0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b,
+  0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b,
+  0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87,
+  0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81,
+  0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30,
+  0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde,
+  0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b,
+  0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39,
+  0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07,
+  0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6,
+  0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30,
+  0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30,
+  0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50,
+  0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8,
+  0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8,
+  0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d,
+  0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07,
+  0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87,
+  0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0,
+  0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28,
+  0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87,
+  0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87,
+  0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x20,
+  0x00, 0x00, 0xbd, 0x00, 0x00, 0x00, 0x32, 0x9a, 0x08, 0x14, 0x02, 0x85,
+  0x8c, 0x27, 0x46, 0x46, 0xc8, 0x11, 0x32, 0x64, 0xd4, 0x3a, 0x4c, 0x76,
+  0x00, 0x00, 0x8b, 0xf2, 0x06, 0xc5, 0xc6, 0x91, 0x41, 0xb4, 0x44, 0x06,
+  0x53, 0x30, 0x08, 0x24, 0x79, 0x86, 0xf2, 0x20, 0x14, 0xd2, 0x44, 0xd7,
+  0x30, 0x00, 0x53, 0x44, 0x4b, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
+  0x6e, 0x77, 0x63, 0x68, 0x61, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x41,
+  0x70, 0x70, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x20, 0x76,
+  0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x32, 0x30, 0x32, 0x33,
+  0x2e, 0x39, 0x38, 0x20, 0x28, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x66, 0x65,
+  0x2d, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x29, 0x4d, 0x65,
+  0x74, 0x61, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69,
+  0x6c, 0x65, 0x2e, 0x64, 0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x73, 0x5f, 0x64,
+  0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f,
+  0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d,
+  0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69,
+  0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x72,
+  0x61, 0x6d, 0x65, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x66, 0x65,
+  0x74, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69,
+  0x72, 0x2e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x5f, 0x6f, 0x75, 0x74,
+  0x70, 0x75, 0x74, 0x75, 0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e,
+  0x30, 0x29, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79,
+  0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x66, 0x6c, 0x6f, 0x61, 0x74,
+  0x34, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d,
+  0x65, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x70, 0x6f,
+  0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69,
+  0x6f, 0x6e, 0x61, 0x69, 0x72, 0x2e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78,
+  0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x61, 0x69, 0x72, 0x2e, 0x6c, 0x6f,
+  0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78,
+  0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x28, 0x5f, 0x5f,
+  0x61, 0x69, 0x72, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c,
+  0x64, 0x65, 0x72, 0x5f, 0x5f, 0x29, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33,
+  0x61, 0x69, 0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x61, 0x69,
+  0x72, 0x2e, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a,
+  0x65, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x61, 0x64, 0x61, 0x69, 0x72,
+  0x2e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65,
+  0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78,
+  0x34, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72,
+  0x6f, 0x6a, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79,
+  0x70, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x61, 0x69, 0x72, 0x2e, 0x61,
+  0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x61, 0x6c, 0x69, 0x67,
+  0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x55, 0x42, 0x4f, 0x75, 0x62, 0x6f,
+  0x00, 0x00, 0x23, 0x08, 0x4b, 0x30, 0x82, 0xc0, 0x20, 0x23, 0x08, 0x8b,
+  0x30, 0x82, 0xb0, 0x0c, 0x23, 0x08, 0x0b, 0x31, 0x82, 0x90, 0x00, 0x23,
+  0x08, 0x4b, 0x31, 0x82, 0xb0, 0x18, 0x33, 0x0c, 0x5e, 0xf0, 0xcd, 0x30,
+  0x80, 0x81, 0x10, 0x06, 0x33, 0x04, 0xc3, 0x0c, 0x83, 0xe7, 0x89, 0xc1,
+  0x0c, 0x04, 0x01, 0x06, 0x60, 0x20, 0x06, 0x33, 0x04, 0xc5, 0x0c, 0x81,
+  0x31, 0x43, 0x70, 0xcc, 0x60, 0x20, 0x89, 0xb2, 0x30, 0xcd, 0x0c, 0x85,
+  0xa3, 0x2c, 0xcc, 0x33, 0x83, 0xe0, 0x06, 0x6f, 0x30, 0x83, 0x22, 0x06,
+  0x50, 0x24, 0x06, 0x60, 0x20, 0x29, 0x13, 0xf3, 0xcc, 0xa0, 0x80, 0x01,
+  0x14, 0x81, 0x01, 0x18, 0x48, 0xca, 0xc4, 0x34, 0x33, 0x14, 0x62, 0x40,
+  0x06, 0x62, 0x80, 0x65, 0x33, 0x48, 0x1e, 0x55, 0x91, 0x41, 0x24, 0x06,
+  0x60, 0x60, 0x5d, 0x73, 0xa0, 0x91, 0xc1, 0x56, 0x06, 0x0a, 0xc7, 0x74,
+  0x33, 0x0c, 0x71, 0x20, 0x07, 0x74, 0x30, 0xc3, 0x30, 0x06, 0x70, 0x50,
+  0x07, 0x32, 0x12, 0x98, 0xa0, 0x8b, 0xd8, 0xd8, 0xec, 0xda, 0x5c, 0xda,
+  0xde, 0xc8, 0xea, 0xd8, 0xca, 0x5c, 0xcc, 0xd8, 0xc2, 0xce, 0xe6, 0x46,
+  0x11, 0xca, 0xc0, 0x0c, 0x4e, 0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23,
+  0x2b, 0x73, 0xa3, 0x1b, 0x25, 0x38, 0x83, 0x5b, 0xc2, 0xd2, 0xe4, 0x5c,
+  0xec, 0xca, 0xe4, 0xe6, 0xd2, 0xde, 0xdc, 0x46, 0x09, 0xd0, 0xe0, 0xa8,
+  0xb0, 0x34, 0x39, 0x17, 0xb6, 0x30, 0xb7, 0xb3, 0xba, 0xb0, 0xb3, 0xb2,
+  0x2f, 0xbb, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x51, 0x82, 0x34, 0xb8,
+  0x29, 0x2c, 0x4d, 0xce, 0x65, 0xec, 0xad, 0x0d, 0x2e, 0x8d, 0xad, 0xec,
+  0xeb, 0x0d, 0x8e, 0x2e, 0xed, 0xcd, 0x6d, 0x6e, 0x94, 0x41, 0x0d, 0xd6,
+  0x80, 0x0d, 0x4e, 0x09, 0x4b, 0x93, 0x73, 0xb1, 0x2b, 0x93, 0xa3, 0x2b,
+  0xc3, 0x1b, 0x25, 0xa8, 0x03, 0x00, 0xa9, 0x18, 0x00, 0x00, 0x25, 0x00,
+  0x00, 0x00, 0x0b, 0x0a, 0x72, 0x28, 0x87, 0x77, 0x80, 0x07, 0x7a, 0x58,
+  0x70, 0x98, 0x43, 0x3d, 0xb8, 0xc3, 0x38, 0xb0, 0x43, 0x39, 0xd0, 0xc3,
+  0x82, 0xe6, 0x1c, 0xc6, 0xa1, 0x0d, 0xe8, 0x41, 0x1e, 0xc2, 0xc1, 0x1d,
+  0xe6, 0x21, 0x1d, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x16, 0x34, 0xe3,
+  0x60, 0x0e, 0xe7, 0x50, 0x0f, 0xe1, 0x20, 0x0f, 0xe4, 0x40, 0x0f, 0xe1,
+  0x20, 0x0f, 0xe7, 0x50, 0x0e, 0xf4, 0xb0, 0x80, 0x81, 0x07, 0x79, 0x28,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x78, 0x87, 0x71, 0x08, 0x07, 0x7a, 0x28,
+  0x07, 0x72, 0x58, 0x70, 0x9c, 0xc3, 0x38, 0xb4, 0x01, 0x3b, 0xa4, 0x83,
+  0x3d, 0x94, 0xc3, 0x02, 0x6b, 0x1c, 0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c,
+  0xdc, 0x20, 0x1c, 0xe4, 0x61, 0x1c, 0xdc, 0x20, 0x1c, 0xe8, 0x81, 0x1e,
+  0xc2, 0x61, 0x1c, 0xd0, 0xa1, 0x1c, 0xc8, 0x61, 0x1c, 0xc2, 0x81, 0x1d,
+  0xd8, 0x61, 0xc1, 0x01, 0x0f, 0xf4, 0x20, 0x0f, 0xe1, 0x50, 0x0f, 0xf4,
+  0x80, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xd1, 0x10, 0x00, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0x07, 0xcc, 0x3c, 0xa4, 0x83, 0x3b, 0x9c, 0x03, 0x3b, 0x94,
+  0x03, 0x3d, 0xa0, 0x83, 0x3c, 0x94, 0x43, 0x38, 0x90, 0xc3, 0x01, 0x00,
+  0x00, 0x00, 0x61, 0x20, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x13, 0x04,
+  0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0xb4, 0x66,
+  0x00, 0xa8, 0xcd, 0x41, 0x10, 0x42, 0xc0, 0x8c, 0x00, 0x8c, 0x45, 0x04,
+  0x41, 0x10, 0x8c, 0x45, 0x08, 0x82, 0x20, 0x90, 0x2b, 0x83, 0x12, 0x28,
+  0x02, 0x02, 0x63, 0x04, 0x20, 0x08, 0x82, 0xf8, 0x47, 0x62, 0x06, 0x80,
+  0xc6, 0x0c, 0xc0, 0x0c, 0x00, 0x00, 0xf1, 0x30, 0x00, 0x00, 0x21, 0x00,
+  0x00, 0x00, 0x22, 0x47, 0xc8, 0x90, 0x51, 0x12, 0x44, 0x2c, 0x00, 0x00,
+  0x00, 0x00, 0xcf, 0x93, 0x59, 0x00, 0x6f, 0x6d, 0x6e, 0x69, 0x70, 0x6f,
+  0x74, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x53, 0x69, 0x6d,
+  0x70, 0x6c, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x54, 0x42, 0x41, 0x41,
+  0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63,
+  0x6f, 0x70, 0x65, 0x73, 0x28, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
+  0x29, 0x61, 0x69, 0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73,
+  0x63, 0x6f, 0x70, 0x65, 0x2d, 0x61, 0x72, 0x67, 0x28, 0x32, 0x29, 0x00,
+  0x00, 0x00, 0x13, 0x04, 0xe7, 0x58, 0x21, 0xf0, 0x41, 0x1e, 0xac, 0x18,
+  0xfa, 0x80, 0x0f, 0xf4, 0x60, 0x43, 0x80, 0x07, 0x1b, 0x86, 0x3b, 0xf0,
+  0x83, 0x3d, 0xd8, 0x30, 0xfc, 0xc1, 0x1f, 0xec, 0xc1, 0x86, 0xa0, 0x0f,
+  0x00, 0x00, 0x83, 0x0c, 0x4e, 0xb0, 0xcc, 0x31, 0x04, 0x05, 0xb2, 0x4d,
+  0xf1, 0x4c, 0x96, 0x35, 0x51, 0x10, 0xca, 0x20, 0xc3, 0x64, 0x38, 0x26,
+  0x04, 0xe2, 0xbf, 0x4d, 0x31, 0x5d, 0x9a, 0xc6, 0x50, 0x10, 0xca, 0x20,
+  0xc3, 0xa5, 0x44, 0x26, 0x04, 0xe2, 0x6f, 0x41, 0x01, 0xfe, 0xdb, 0x14,
+  0x18, 0xf7, 0x7d, 0x10, 0x05, 0xa1, 0x0c, 0x32, 0x70, 0x4f, 0x65, 0x42,
+  0x20, 0xfe, 0x56, 0x04, 0xe0, 0xbf, 0x4d, 0xd1, 0x85, 0x01, 0x19, 0x90,
+  0xc1, 0x45, 0x41, 0x28, 0x36, 0x04, 0xe0, 0x3f, 0xdb, 0x60, 0x49, 0xc0,
+  0x6c, 0x43, 0x20, 0x04, 0x19, 0x04, 0xc4, 0x00, 0x00, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x5b, 0x8a, 0x21, 0xf8, 0x83, 0x03, 0x14, 0xb6, 0x14, 0x47,
+  0xf0, 0x07, 0x07, 0x28, 0x6c, 0x29, 0x98, 0xe0, 0x0f, 0x0e, 0x50, 0xd8,
+  0x52, 0x44, 0xc1, 0x1f, 0x1c, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x32, 0x0e,
+  0x10, 0x22, 0x84, 0x00, 0xba, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x65, 0x0c, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x12, 0x03,
+  0x94, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00,
+  0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00,
+  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x5d, 0x0c, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x12, 0x03,
+  0x94, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x61, 0x69, 0x72,
+  0x36, 0x34, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2d, 0x74, 0x76, 0x6f,
+  0x73, 0x31, 0x33, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x73, 0x69, 0x6d, 0x75,
+  0x6c, 0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00
+};
+const unsigned int cube_vert_metallib_len = 3650;
+const unsigned char cube_frag_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xad, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xed, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0a, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x08, 0x00, 0x66, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01, 0x48, 0x41, 0x53,
+  0x48, 0x20, 0x00, 0x75, 0xbd, 0x3a, 0xd4, 0x20, 0x60, 0xcd, 0x61, 0x74,
+  0xed, 0x2f, 0xea, 0xab, 0xfc, 0xc1, 0x96, 0xeb, 0x6f, 0x22, 0xa2, 0xb2,
+  0xd6, 0x23, 0x2a, 0x90, 0x49, 0xb9, 0x98, 0x16, 0x23, 0x5b, 0x16, 0x4d,
+  0x44, 0x53, 0x5a, 0x08, 0x00, 0xc0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x4f, 0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08,
+  0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44,
+  0x54, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44,
+  0x54, 0x04, 0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17,
+  0x0b, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xa8, 0x0a, 0x00,
+  0x00, 0xff, 0xff, 0xff, 0xff, 0x42, 0x43, 0xc0, 0xde, 0x35, 0x14, 0x00,
+  0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x0c, 0x30, 0x24, 0x80, 0x10, 0x05,
+  0xc8, 0x14, 0x00, 0x00, 0x00, 0x21, 0x0c, 0x00, 0x00, 0x70, 0x02, 0x00,
+  0x00, 0x0b, 0x02, 0x21, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00,
+  0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32,
+  0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b,
+  0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32,
+  0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14,
+  0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0x04, 0x49, 0x0e,
+  0x90, 0x11, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5,
+  0x8a, 0x04, 0x21, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x69, 0x00, 0x00,
+  0x00, 0x1b, 0xc2, 0x24, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0x03,
+  0x40, 0x02, 0x28, 0x22, 0x1c, 0xe0, 0x01, 0x1e, 0xe4, 0xe1, 0x1d, 0xf0,
+  0xa1, 0x0d, 0xcc, 0xa1, 0x1e, 0xdc, 0x61, 0x1c, 0xda, 0xc0, 0x1c, 0xe0,
+  0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87,
+  0x7a, 0x28, 0x07, 0x80, 0x68, 0x87, 0x74, 0x70, 0x87, 0x36, 0x60, 0x87,
+  0x72, 0x38, 0x87, 0x70, 0x60, 0x87, 0x36, 0xb0, 0x87, 0x72, 0x18, 0x07,
+  0x7a, 0x78, 0x07, 0x79, 0x68, 0x83, 0x7b, 0x48, 0x07, 0x72, 0xa0, 0x07,
+  0x74, 0x00, 0xe2, 0x40, 0x0e, 0xf0, 0x00, 0x18, 0xdc, 0xe1, 0x1d, 0xda,
+  0x40, 0x1c, 0xea, 0x21, 0x1d, 0xd8, 0x81, 0x1e, 0xd2, 0xc1, 0x1d, 0xe6,
+  0x01, 0x20, 0xdc, 0xe1, 0x1d, 0xda, 0xc0, 0x1c, 0xe4, 0x21, 0x1c, 0xda,
+  0xa1, 0x1c, 0xda, 0x00, 0x1e, 0xde, 0x21, 0x1d, 0xdc, 0x81, 0x1e, 0xca,
+  0x41, 0x1e, 0xda, 0xa0, 0x1c, 0xd8, 0x21, 0x1d, 0xda, 0x01, 0xa0, 0x07,
+  0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30, 0x07,
+  0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48, 0x07,
+  0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48, 0x87,
+  0x76, 0x68, 0x03, 0x77, 0x78, 0x07, 0x77, 0x68, 0x03, 0x76, 0x28, 0x87,
+  0x70, 0x30, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc,
+  0xe1, 0x1d, 0xda, 0x20, 0x1d, 0xdc, 0xc1, 0x1c, 0xe6, 0xa1, 0x0d, 0xcc,
+  0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0, 0x01, 0xa0, 0x07,
+  0x79, 0xa8, 0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x70, 0x87,
+  0x70, 0x70, 0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87,
+  0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00,
+  0xc2, 0x1d, 0xde, 0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xce, 0xc1, 0x1d, 0xca,
+  0x81, 0x1c, 0xda, 0x40, 0x1f, 0xca, 0x41, 0x1e, 0xde, 0x61, 0x1e, 0xda,
+  0xc0, 0x1c, 0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x03,
+  0x7a, 0x90, 0x87, 0x70, 0x80, 0x07, 0x78, 0x48, 0x07, 0x77, 0x38, 0x87,
+  0x36, 0x68, 0x87, 0x70, 0xa0, 0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea,
+  0xa1, 0x1c, 0x00, 0x62, 0x1e, 0xe8, 0x21, 0x1c, 0xc6, 0x61, 0x1d, 0xda,
+  0x00, 0x1e, 0xe4, 0xe1, 0x1d, 0xe8, 0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde,
+  0x41, 0x1e, 0xda, 0x40, 0x1c, 0xea, 0xc1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x0d, 0xe6, 0x21, 0x1d, 0xf4, 0xa1, 0x1c, 0x00, 0x3c, 0x00, 0x88,
+  0x7a, 0x70, 0x87, 0x79, 0x08, 0x07, 0x73, 0x28, 0x87, 0x36, 0x30, 0x07,
+  0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4,
+  0xa1, 0x1e, 0xca, 0x01, 0xd8, 0x40, 0x08, 0x01, 0x60, 0x01, 0x00, 0x00,
+  0x00, 0x49, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x84, 0x40,
+  0x00, 0x89, 0x20, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08,
+  0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22,
+  0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84,
+  0x4c, 0x10, 0x20, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x50, 0x86, 0x88, 0x20,
+  0x19, 0x08, 0x98, 0x23, 0x00, 0x83, 0x14, 0xa8, 0x11, 0x00, 0x00, 0x00,
+  0x00, 0x13, 0xc0, 0x20, 0x1c, 0xd2, 0x41, 0x1e, 0xec, 0x80, 0x0e, 0xda,
+  0x20, 0x1c, 0xe0, 0x01, 0x1e, 0xd8, 0xa1, 0x1c, 0xda, 0x80, 0x1e, 0xec,
+  0xe1, 0x1d, 0xe6, 0x21, 0x0e, 0xe6, 0xc0, 0x0d, 0xe0, 0xc0, 0x0d, 0xe0,
+  0xa0, 0x0d, 0xe6, 0x21, 0x1d, 0xda, 0xa1, 0x1e, 0xd8, 0x21, 0x1c, 0xe8,
+  0xe1, 0x1d, 0xe4, 0x61, 0xc3, 0x6d, 0x94, 0x43, 0x1b, 0xc0, 0x83, 0x1e,
+  0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d,
+  0xb4, 0x41, 0x3a, 0xc4, 0x81, 0x1e, 0xe0, 0x81, 0x1e, 0xe0, 0x41, 0x1b,
+  0xa4, 0x03, 0x1e, 0xe8, 0x01, 0x1e, 0xe8, 0x01, 0x1e, 0xb4, 0x41, 0x3a,
+  0xc4, 0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xd8, 0x81, 0x1e, 0xc4, 0x81, 0x1d,
+  0xb4, 0x41, 0x3a, 0xcc, 0x81, 0x1c, 0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e,
+  0xcc, 0x81, 0x1c, 0xb4, 0x41, 0x3a, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d,
+  0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x39, 0xcc, 0x81, 0x1c,
+  0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81, 0x39,
+  0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d,
+  0xb4, 0x81, 0x3d, 0xc4, 0x81, 0x1d, 0xe8, 0x41, 0x1c, 0xd8, 0x81, 0x1e,
+  0xc4, 0x81, 0x1d, 0xb4, 0x81, 0x3d, 0xc8, 0x01, 0x1d, 0xe8, 0xc1, 0x1c,
+  0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xcc, 0x81, 0x1c,
+  0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x1e, 0xcc, 0x81, 0x1c, 0xb4, 0x81, 0x3d,
+  0xd0, 0x01, 0x1e, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e, 0xd8, 0x01, 0x1d,
+  0xb4, 0x81, 0x3d, 0xd8, 0x01, 0x1d, 0xe8, 0x81, 0x1d, 0xd0, 0x81, 0x1e,
+  0xd8, 0x01, 0x1d, 0xb4, 0x81, 0x3d, 0xe4, 0x81, 0x1d, 0xe8, 0x41, 0x1c,
+  0xc8, 0x01, 0x1e, 0xe8, 0x41, 0x1c, 0xc8, 0x01, 0x1e, 0xb4, 0x81, 0x3d,
+  0xc4, 0x81, 0x1c, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1c, 0xe0, 0x81, 0x1e,
+  0xc4, 0x81, 0x1c, 0xe0, 0x41, 0x1b, 0xd8, 0x43, 0x1c, 0xe4, 0x81, 0x1c,
+  0xe8, 0x81, 0x1c, 0xd4, 0x81, 0x1d, 0xe8, 0x81, 0x1c, 0xd4, 0x81, 0x1d,
+  0xb4, 0x81, 0x3d, 0xc8, 0x41, 0x1d, 0xd8, 0x81, 0x1e, 0xc8, 0x41, 0x1d,
+  0xd8, 0x81, 0x1e, 0xc8, 0x41, 0x1d, 0xd8, 0x41, 0x1b, 0xd8, 0x43, 0x1d,
+  0xc4, 0x81, 0x1c, 0xe8, 0x41, 0x1d, 0xc4, 0x81, 0x1c, 0xe8, 0x41, 0x1d,
+  0xc4, 0x81, 0x1c, 0xb4, 0x81, 0x3d, 0xc4, 0x01, 0x1c, 0xc8, 0x01, 0x1d,
+  0xe8, 0x41, 0x1c, 0xc0, 0x81, 0x1c, 0xd0, 0x81, 0x1e, 0xc4, 0x01, 0x1c,
+  0xc8, 0x01, 0x1d, 0xb4, 0x81, 0x3b, 0xe0, 0x81, 0x1e, 0xc4, 0x81, 0x1d,
+  0xe8, 0xc1, 0x1c, 0xc8, 0x81, 0x46, 0x08, 0x43, 0x1e, 0x85, 0xf4, 0x33,
+  0x00, 0xd2, 0x0c, 0x89, 0x80, 0x43, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x89, 0x0d, 0x02, 0x45, 0xe5, 0x04, 0x00,
+  0x00, 0xb2, 0x40, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98,
+  0x0c, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43,
+  0xaa, 0x22, 0x28, 0x81, 0x42, 0x18, 0x01, 0x20, 0x1b, 0x4b, 0x88, 0x04,
+  0x00, 0xb1, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80,
+  0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84,
+  0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c,
+  0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42,
+  0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88,
+  0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c,
+  0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79,
+  0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70,
+  0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f,
+  0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4,
+  0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30,
+  0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc,
+  0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b,
+  0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70,
+  0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76,
+  0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72,
+  0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e,
+  0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21,
+  0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94,
+  0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc,
+  0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70,
+  0x58, 0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74,
+  0x18, 0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f,
+  0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e,
+  0xec, 0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41,
+  0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1,
+  0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c,
+  0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37,
+  0x60, 0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f,
+  0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21,
+  0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21,
+  0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0,
+  0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88,
+  0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77,
+  0x18, 0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c,
+  0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23,
+  0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01,
+  0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84,
+  0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8,
+  0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76,
+  0x60, 0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e,
+  0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f,
+  0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e,
+  0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e,
+  0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1,
+  0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21,
+  0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8,
+  0x03, 0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77,
+  0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19,
+  0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e,
+  0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30,
+  0x08, 0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71,
+  0xa0, 0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77,
+  0xa8, 0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x20, 0x00,
+  0x00, 0x8c, 0x00, 0x00, 0x00, 0x32, 0x9a, 0x08, 0x14, 0x02, 0x85, 0x8c,
+  0x27, 0x46, 0x46, 0xc8, 0x11, 0x32, 0x64, 0xd4, 0x26, 0x28, 0x55, 0x00,
+  0x00, 0x8b, 0xf2, 0x06, 0xc5, 0xc6, 0x91, 0x41, 0x14, 0x19, 0xd2, 0xa2,
+  0x3c, 0x4c, 0xc1, 0x48, 0x08, 0x53, 0x44, 0x4b, 0x20, 0x56, 0x65, 0x72,
+  0x73, 0x69, 0x6f, 0x6e, 0x77, 0x63, 0x68, 0x61, 0x72, 0x5f, 0x73, 0x69,
+  0x7a, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61,
+  0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x33, 0x32,
+  0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x20, 0x28, 0x6d, 0x65, 0x74, 0x61,
+  0x6c, 0x66, 0x65, 0x2d, 0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38,
+  0x29, 0x4d, 0x65, 0x74, 0x61, 0x6c, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f,
+  0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x64, 0x65, 0x6e, 0x6f, 0x72, 0x6d,
+  0x73, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x61, 0x69, 0x72,
+  0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73,
+  0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c,
+  0x65, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+  0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72,
+  0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c,
+  0x65, 0x61, 0x69, 0x72, 0x2e, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x5f,
+  0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x61, 0x69, 0x72, 0x2e, 0x61, 0x72,
+  0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x66,
+  0x6c, 0x6f, 0x61, 0x74, 0x34, 0x61, 0x69, 0x72, 0x2e, 0x66, 0x72, 0x61,
+  0x67, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x75,
+  0x73, 0x65, 0x72, 0x28, 0x6c, 0x6f, 0x63, 0x6e, 0x30, 0x29, 0x61, 0x69,
+  0x72, 0x2e, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x61, 0x69, 0x72, 0x2e,
+  0x70, 0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x61,
+  0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x63,
+  0x6f, 0x6c, 0x6f, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x70, 0x6f, 0x73, 0x69,
+  0x74, 0x69, 0x6f, 0x6e, 0x61, 0x69, 0x72, 0x2e, 0x6e, 0x6f, 0x5f, 0x70,
+  0x65, 0x72, 0x73, 0x70, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x70, 0x6f,
+  0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x23, 0x08, 0x45,
+  0x30, 0x82, 0x60, 0x14, 0x23, 0x08, 0x85, 0x30, 0x82, 0x50, 0x0c, 0x23,
+  0x08, 0x05, 0x31, 0x82, 0x30, 0x00, 0x33, 0x0c, 0x54, 0x50, 0xcd, 0x30,
+  0x58, 0xc2, 0x35, 0x43, 0x30, 0xcc, 0x30, 0x50, 0x14, 0x36, 0x03, 0x41,
+  0x58, 0x16, 0x36, 0x43, 0x50, 0xcc, 0x10, 0x18, 0x33, 0x04, 0xc7, 0x0c,
+  0x05, 0x82, 0x61, 0x89, 0x32, 0x43, 0x20, 0x06, 0x33, 0x24, 0xd8, 0xc2,
+  0x34, 0x4e, 0xa2, 0x3c, 0xd0, 0x0c, 0x88, 0x15, 0x35, 0x52, 0xa2, 0x3c,
+  0xd3, 0x0c, 0x02, 0x19, 0x94, 0xc1, 0x0c, 0x43, 0x36, 0x06, 0x66, 0x20,
+  0x23, 0x81, 0x09, 0xba, 0x88, 0x8d, 0xcd, 0xae, 0xcd, 0xa5, 0xed, 0x8d,
+  0xac, 0x8e, 0xad, 0xcc, 0xc5, 0x8c, 0x2d, 0xec, 0x6c, 0x6e, 0x14, 0x21,
+  0xd3, 0x4e, 0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3,
+  0x1b, 0x25, 0xd8, 0x6e, 0x09, 0x4b, 0x93, 0x73, 0xb1, 0x2b, 0x93, 0x9b,
+  0x4b, 0x7b, 0x73, 0x1b, 0x25, 0xe0, 0x8e, 0x0a, 0x4b, 0x93, 0x73, 0x61,
+  0x0b, 0x73, 0x3b, 0xab, 0x0b, 0x3b, 0x2b, 0xfb, 0xb2, 0x2b, 0x93, 0x9b,
+  0x4b, 0x7b, 0x73, 0x1b, 0x25, 0xe8, 0x6e, 0x0a, 0x4b, 0x93, 0x73, 0x19,
+  0x7b, 0x6b, 0x83, 0x4b, 0x63, 0x2b, 0xfb, 0x7a, 0x83, 0xa3, 0x4b, 0x7b,
+  0x73, 0x9b, 0x1b, 0x65, 0xf0, 0x3e, 0x30, 0x38, 0x26, 0x2c, 0x4d, 0xce,
+  0xc5, 0x4c, 0x2e, 0xec, 0xac, 0xad, 0xcc, 0x8d, 0x6e, 0x94, 0xc0, 0x0c,
+  0x00, 0xa9, 0x18, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x72,
+  0x28, 0x87, 0x77, 0x80, 0x07, 0x7a, 0x58, 0x70, 0x98, 0x43, 0x3d, 0xb8,
+  0xc3, 0x38, 0xb0, 0x43, 0x39, 0xd0, 0xc3, 0x82, 0xe6, 0x1c, 0xc6, 0xa1,
+  0x0d, 0xe8, 0x41, 0x1e, 0xc2, 0xc1, 0x1d, 0xe6, 0x21, 0x1d, 0xe8, 0x21,
+  0x1d, 0xde, 0xc1, 0x1d, 0x16, 0x34, 0xe3, 0x60, 0x0e, 0xe7, 0x50, 0x0f,
+  0xe1, 0x20, 0x0f, 0xe4, 0x40, 0x0f, 0xe1, 0x20, 0x0f, 0xe7, 0x50, 0x0e,
+  0xf4, 0xb0, 0x80, 0x81, 0x07, 0x79, 0x28, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x78, 0x87, 0x71, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x58, 0x70, 0x9c,
+  0xc3, 0x38, 0xb4, 0x01, 0x3b, 0xa4, 0x83, 0x3d, 0x94, 0xc3, 0x02, 0x6b,
+  0x1c, 0xd8, 0x21, 0x1c, 0xdc, 0xe1, 0x1c, 0xdc, 0x20, 0x1c, 0xe4, 0x61,
+  0x1c, 0xdc, 0x20, 0x1c, 0xe8, 0x81, 0x1e, 0xc2, 0x61, 0x1c, 0xd0, 0xa1,
+  0x1c, 0xc8, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0x61, 0xc1, 0x01, 0x0f,
+  0xf4, 0x20, 0x0f, 0xe1, 0x50, 0x0f, 0xf4, 0x80, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0xd1, 0x10, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0xcc, 0x3c,
+  0xa4, 0x83, 0x3b, 0x9c, 0x03, 0x3b, 0x94, 0x03, 0x3d, 0xa0, 0x83, 0x3c,
+  0x94, 0x43, 0x38, 0x90, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x61, 0x20, 0x00,
+  0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x0a, 0x00, 0x00, 0x00,
+  0x00, 0x71, 0x20, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x32, 0x0e, 0x10,
+  0x22, 0x84, 0x00, 0xee, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x65, 0x0c, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94,
+  0xf0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+  0x00, 0x08, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x0f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x07, 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+  0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x5d, 0x0c, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x12, 0x03, 0x94,
+  0x6f, 0x00, 0x00, 0x00, 0x00, 0x66, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e,
+  0x33, 0x32, 0x30, 0x32, 0x33, 0x2e, 0x39, 0x38, 0x61, 0x69, 0x72, 0x36,
+  0x34, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2d, 0x74, 0x76, 0x6f, 0x73,
+  0x31, 0x33, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x73, 0x69, 0x6d, 0x75, 0x6c,
+  0x61, 0x74, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00
+};
+const unsigned int cube_frag_metallib_len = 2989;
+#else
+const unsigned char cube_vert_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x08, 0x00, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x00, 0x48, 0x41, 0x53,
+  0x48, 0x20, 0x00, 0x3c, 0x44, 0xfd, 0x7c, 0xda, 0x9f, 0x5b, 0xd6, 0x40,
+  0xbc, 0x7e, 0xb5, 0x95, 0x8e, 0x07, 0x17, 0x23, 0x1d, 0x77, 0xe1, 0x11,
+  0xdb, 0x6d, 0x6e, 0xed, 0xc4, 0x2e, 0x2e, 0x2f, 0xb0, 0x34, 0x71, 0x4f,
+  0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01,
+  0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x29,
+  0x00, 0x00, 0x00, 0x56, 0x41, 0x54, 0x54, 0x15, 0x00, 0x02, 0x00, 0x70,
+  0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x80, 0x63, 0x6f,
+  0x6c, 0x6f, 0x72, 0x00, 0x01, 0x80, 0x56, 0x41, 0x54, 0x59, 0x04, 0x00,
+  0x02, 0x00, 0x05, 0x05, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x6c, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xd8, 0x02, 0x00, 0x00,
+  0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39,
+  0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
+  0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14,
+  0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a, 0x90, 0x21,
+  0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07, 0xc8, 0x48,
+  0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00,
+  0x51, 0x18, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x1b, 0x7e, 0x24, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0x01, 0x90, 0x00, 0x8a, 0x08, 0x07, 0x78, 0x80,
+  0x07, 0x79, 0x78, 0x07, 0x7c, 0x68, 0x03, 0x73, 0xa8, 0x07, 0x77, 0x18,
+  0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40,
+  0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xda, 0x21, 0x1d,
+  0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d,
+  0xec, 0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e,
+  0xd2, 0x81, 0x1c, 0xe8, 0x01, 0x1d, 0x80, 0x38, 0x90, 0x03, 0x3c, 0x00,
+  0x06, 0x77, 0x78, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x48, 0x07, 0x76, 0xa0,
+  0x87, 0x74, 0x70, 0x87, 0x79, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30,
+  0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48,
+  0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48,
+  0x87, 0x76, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d,
+  0xde, 0xa1, 0x0d, 0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d, 0xca, 0xa1, 0x0d,
+  0xe0, 0xe1, 0x1d, 0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d,
+  0xca, 0x81, 0x1d, 0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d, 0xde, 0xc1, 0x1d,
+  0xda, 0x80, 0x1d, 0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0, 0x07, 0x79, 0xa8,
+  0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x48, 0x07, 0x77, 0x30,
+  0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0,
+  0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d,
+  0xde, 0xa1, 0x0d, 0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e, 0xda, 0xc0, 0x1c,
+  0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90,
+  0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83, 0x79, 0x48,
+  0x87, 0x73, 0x70, 0x87, 0x72, 0x20, 0x87, 0x36, 0xd0, 0x87, 0x72, 0x90,
+  0x87, 0x77, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08,
+  0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20,
+  0xdc, 0xe1, 0x1d, 0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c, 0xe0, 0x01, 0x1e,
+  0xd2, 0xc1, 0x1d, 0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x98, 0x07, 0x7a, 0x08,
+  0x87, 0x71, 0x58, 0x87, 0x36, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7a, 0x28,
+  0x87, 0x71, 0xa0, 0x87, 0x77, 0x90, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x30,
+  0x07, 0x73, 0x28, 0x07, 0x79, 0x68, 0x83, 0x79, 0x48, 0x07, 0x7d, 0x28,
+  0x07, 0x00, 0x0f, 0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e, 0xc2, 0xc1, 0x1c,
+  0xca, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e,
+  0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x36, 0x6c, 0xc2,
+  0x00, 0x2c, 0x40, 0x35, 0x84, 0x43, 0x3a, 0xc8, 0x43, 0x1b, 0x88, 0x43,
+  0x3d, 0x98, 0x83, 0x39, 0x94, 0x83, 0x3c, 0xb4, 0x81, 0x3b, 0xbc, 0x43,
+  0x1b, 0x84, 0x03, 0x3b, 0xa4, 0x43, 0x38, 0xcc, 0x03, 0x00, 0x00, 0x00,
+  0x49, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x84, 0x40, 0x00,
+  0x89, 0x20, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x32, 0x22, 0x48, 0x09,
+  0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84, 0x04, 0x93, 0x22, 0xe3,
+  0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c, 0x0b, 0x84, 0xa4, 0x4c,
+  0x10, 0x44, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x60, 0x85, 0x10, 0x86, 0x11,
+  0x06, 0x20, 0x09, 0xc2, 0x4c, 0xd4, 0x3c, 0xd0, 0x83, 0x3c, 0xd4, 0xc3,
+  0x38, 0xd0, 0x83, 0x1b, 0xb4, 0x43, 0x39, 0xd0, 0x43, 0x38, 0xb0, 0x83,
+  0x1e, 0xe8, 0x41, 0x3b, 0x84, 0x03, 0x3d, 0xc8, 0x43, 0x3a, 0xe0, 0x03,
+  0x0a, 0xc8, 0x29, 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xbb, 0x1b, 0x8a, 0x82,
+  0x32, 0x88, 0x60, 0x08, 0x85, 0x10, 0x63, 0x1c, 0x42, 0x03, 0x01, 0x73,
+  0x04, 0x60, 0x90, 0x02, 0x6b, 0x18, 0x81, 0x58, 0xe6, 0x08, 0x40, 0x61,
+  0x10, 0x21, 0x10, 0x46, 0x00, 0x00, 0x00, 0x00, 0x13, 0xa8, 0x70, 0x48,
+  0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60,
+  0x87, 0x72, 0x68, 0x83, 0x74, 0x78, 0x87, 0x79, 0xc8, 0x03, 0x37, 0x80,
+  0x03, 0x37, 0x80, 0x83, 0x0d, 0xb7, 0x51, 0x0e, 0x6d, 0x00, 0x0f, 0x7a,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xe9, 0x10, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d,
+  0x90, 0x0e, 0x78, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9,
+  0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a,
+  0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76,
+  0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6,
+  0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xf6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a,
+  0x10, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x73,
+  0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x30, 0x07, 0x72,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6,
+  0x40, 0x07, 0x78, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74,
+  0xd0, 0x06, 0xf6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a,
+  0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x90, 0x07, 0x76, 0xa0, 0x07, 0x71,
+  0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6,
+  0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a,
+  0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x90, 0x07, 0x72,
+  0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76,
+  0xd0, 0x06, 0xf6, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75,
+  0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x75,
+  0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75,
+  0x10, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74,
+  0xa0, 0x07, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70,
+  0x20, 0x07, 0x74, 0xd0, 0x06, 0xee, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x76,
+  0xa0, 0x07, 0x73, 0x20, 0x07, 0x43, 0x98, 0x04, 0x00, 0x80, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x32, 0x1e, 0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47,
+  0xc6, 0x04, 0x43, 0x5a, 0x25, 0x30, 0x02, 0x50, 0x80, 0x01, 0x45, 0x50,
+  0x08, 0x05, 0x51, 0x20, 0xe4, 0x46, 0x00, 0x88, 0x8d, 0x25, 0x44, 0x02,
+  0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00,
+  0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9,
+  0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x42, 0x28, 0x00, 0x93, 0x50, 0xb9,
+  0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x2c,
+  0x81, 0x22, 0x2c, 0x05, 0xdf, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4,
+  0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd,
+  0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x07, 0x04, 0xa5,
+  0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46, 0x66,
+  0xc6, 0x25, 0x07, 0x27, 0x65, 0x88, 0xa0, 0x10, 0x43, 0x8c, 0x25, 0x58,
+  0x8c, 0x45, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04, 0x51, 0x8e,
+  0x25, 0x58, 0x82, 0x45, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6,
+  0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36,
+  0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44, 0x50, 0x12,
+  0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65,
+  0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65,
+  0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x65, 0x21, 0x19, 0x84, 0xa5,
+  0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9,
+  0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95,
+  0xd1, 0x8d, 0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11,
+  0x94, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5d, 0x99, 0x1c, 0x5d, 0x19,
+  0xde, 0xd7, 0x5b, 0x1d, 0x1d, 0x5c, 0x1d, 0x1d, 0x97, 0xba, 0xb9, 0x32,
+  0x39, 0x14, 0xb6, 0xb7, 0x31, 0x37, 0x98, 0x14, 0x46, 0x61, 0x69, 0x72,
+  0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61,
+  0x6d, 0x65, 0x34, 0xcc, 0xd8, 0xde, 0xc2, 0xe8, 0x68, 0xc8, 0x84, 0xa5,
+  0xc9, 0xb9, 0x84, 0xc9, 0x9d, 0x7d, 0xb9, 0x85, 0xb5, 0x95, 0xb1, 0x18,
+  0x7b, 0x63, 0x7b, 0x93, 0x1b, 0xc2, 0x28, 0x8f, 0x02, 0x29, 0x91, 0x22,
+  0x29, 0x93, 0x42, 0x91, 0x09, 0x4b, 0x93, 0x73, 0x81, 0x7b, 0x9b, 0x4b,
+  0xa3, 0x4b, 0x7b, 0x73, 0x23, 0x02, 0xf7, 0x36, 0x97, 0x46, 0x97, 0xf6,
+  0xe6, 0x36, 0x44, 0x51, 0x2c, 0x25, 0x52, 0x24, 0x65, 0x52, 0xae, 0x21,
+  0x84, 0x52, 0x29, 0x18, 0xa1, 0xb0, 0x34, 0x39, 0x17, 0xbb, 0x32, 0x39,
+  0xba, 0x32, 0xbc, 0xaf, 0x34, 0x37, 0xb8, 0x3a, 0x3a, 0x4a, 0x61, 0x69,
+  0x72, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69,
+  0x6e, 0x64, 0x65, 0x78, 0xf4, 0xce, 0xca, 0xdc, 0xca, 0xe4, 0xc2, 0xe8,
+  0xca, 0xc8, 0x50, 0xbe, 0xbe, 0xc2, 0xd2, 0xe4, 0xbe, 0xe0, 0xd8, 0xc2,
+  0xc6, 0xca, 0xd0, 0xde, 0xd8, 0xc8, 0xca, 0xe4, 0xbe, 0xbe, 0x52, 0x68,
+  0x98, 0xb1, 0xbd, 0x85, 0xd1, 0xcd, 0x0c, 0xa1, 0x16, 0x41, 0xd1, 0x94,
+  0x6d, 0x11, 0x96, 0x40, 0xe1, 0x94, 0x48, 0xe9, 0x94, 0x49, 0xb9, 0x86,
+  0x50, 0x4b, 0xa0, 0x68, 0xca, 0xb6, 0x04, 0x4b, 0xa0, 0x70, 0x4a, 0xa4,
+  0x74, 0xca, 0xa4, 0x50, 0x54, 0xc2, 0xd2, 0xe4, 0x5c, 0xc4, 0xea, 0xcc,
+  0xcc, 0xca, 0xe4, 0xf8, 0x84, 0xa5, 0xc9, 0xb9, 0x88, 0xd5, 0x99, 0x99,
+  0x95, 0xc9, 0x7d, 0xcd, 0xa5, 0xe9, 0x95, 0x11, 0x09, 0x4b, 0x93, 0x73,
+  0x91, 0x2b, 0x0b, 0x23, 0x23, 0x15, 0x96, 0x26, 0xe7, 0x32, 0x47, 0x27,
+  0x57, 0x37, 0x46, 0xf7, 0x45, 0x97, 0x07, 0x57, 0xf6, 0x95, 0xe6, 0x66,
+  0xf6, 0x46, 0xc4, 0x8c, 0xed, 0x2d, 0x8c, 0x8e, 0x06, 0x8f, 0x86, 0x4d,
+  0xdb, 0x1b, 0x59, 0x19, 0x9b, 0x55, 0x5a, 0xd9, 0x1d, 0x94, 0xdc, 0x9b,
+  0xda, 0x10, 0x65, 0x11, 0x96, 0x61, 0x11, 0x14, 0x32, 0x50, 0xca, 0x80,
+  0x51, 0x58, 0x9a, 0x9c, 0x4b, 0x98, 0xdc, 0xd9, 0x17, 0x5d, 0x1e, 0x5c,
+  0xd9, 0xd7, 0x5c, 0x9a, 0x5e, 0x19, 0xaf, 0xb0, 0x34, 0x39, 0x97, 0x30,
+  0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0xaf, 0x30, 0xb6, 0xb4, 0x33,
+  0xb7, 0xaf, 0xb9, 0x34, 0xbd, 0x32, 0x0e, 0x55, 0x42, 0x4f, 0x1c, 0xea,
+  0xc4, 0xde, 0x86, 0x90, 0xc1, 0x42, 0x28, 0x60, 0xa0, 0x84, 0xc1, 0x32,
+  0x28, 0xdb, 0x22, 0x2c, 0x81, 0x22, 0x06, 0xca, 0x18, 0x28, 0x66, 0xa0,
+  0x9c, 0xc1, 0x32, 0x28, 0x68, 0xb0, 0x1c, 0x4a, 0xa4, 0xa4, 0x81, 0x32,
+  0x29, 0x6a, 0x30, 0xc4, 0x50, 0x3c, 0xe5, 0x53, 0xd6, 0x60, 0x88, 0x91,
+  0x00, 0x4a, 0xa6, 0xb0, 0x01, 0x9f, 0xb7, 0x36, 0xb7, 0x34, 0xb8, 0x37,
+  0xba, 0x32, 0x37, 0x3a, 0x90, 0x31, 0xb4, 0x30, 0x39, 0x3e, 0x53, 0x69,
+  0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x54, 0x42, 0x41,
+  0x41, 0x43, 0x04, 0xe5, 0x0d, 0x86, 0x18, 0x8a, 0x1b, 0x28, 0x70, 0xe0,
+  0x20, 0x43, 0x0c, 0x25, 0x0e, 0x94, 0x38, 0x70, 0x10, 0x66, 0x61, 0x69,
+  0x72, 0x2d, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x2d, 0x73, 0x63, 0x6f, 0x70,
+  0x65, 0x73, 0x28, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x29, 0x43,
+  0x08, 0x85, 0x0e, 0x94, 0x39, 0xa0, 0x15, 0x96, 0x26, 0xd7, 0x12, 0xc6,
+  0x96, 0x16, 0x36, 0xd7, 0x32, 0x37, 0xf6, 0x06, 0x57, 0xd6, 0x12, 0x26,
+  0x77, 0x86, 0x22, 0x93, 0x32, 0xc4, 0x50, 0xec, 0x40, 0xa1, 0x03, 0xa5,
+  0x0e, 0x86, 0x08, 0x8a, 0x1d, 0x8c, 0x88, 0xd8, 0x81, 0x1d, 0xec, 0xa1,
+  0x1d, 0xdc, 0xa0, 0x1d, 0xde, 0x81, 0x1c, 0xea, 0x81, 0x1d, 0xca, 0xc1,
+  0x0d, 0xcc, 0x81, 0x1d, 0xc2, 0xe1, 0x1c, 0xe6, 0x61, 0x8a, 0x10, 0x0c,
+  0x23, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x48, 0x07, 0x72,
+  0x28, 0x07, 0x77, 0xa0, 0x87, 0x29, 0x41, 0x31, 0x62, 0x09, 0x87, 0x74,
+  0x90, 0x07, 0x37, 0xb0, 0x87, 0x72, 0x90, 0x87, 0x79, 0x48, 0x87, 0x77,
+  0x70, 0x87, 0x29, 0x81, 0x31, 0x82, 0x0a, 0x87, 0x74, 0x90, 0x07, 0x37,
+  0x60, 0x87, 0x70, 0x70, 0x87, 0x73, 0xa8, 0x87, 0x70, 0x38, 0x87, 0x72,
+  0xf8, 0x05, 0x7b, 0x28, 0x07, 0x79, 0x98, 0x87, 0x74, 0x78, 0x07, 0x77,
+  0x98, 0x12, 0x20, 0x23, 0xa6, 0x70, 0x48, 0x07, 0x79, 0x70, 0x83, 0x71,
+  0x78, 0x87, 0x76, 0x80, 0x87, 0x74, 0x60, 0x87, 0x72, 0xf8, 0x85, 0x77,
+  0x80, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x79, 0x98, 0x32, 0x28,
+  0x8c, 0x33, 0x42, 0x09, 0x87, 0x74, 0x90, 0x07, 0x37, 0xb0, 0x87, 0x72,
+  0x90, 0x07, 0x7a, 0x28, 0x07, 0x7c, 0x98, 0x12, 0xb4, 0x01, 0x00, 0x00,
+  0x79, 0x18, 0x00, 0x00, 0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c,
+  0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3,
+  0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6,
+  0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e,
+  0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43,
+  0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03,
+  0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48,
+  0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20,
+  0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e,
+  0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d,
+  0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89,
+  0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83,
+  0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68,
+  0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90,
+  0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78,
+  0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98,
+  0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5,
+  0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c,
+  0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c,
+  0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43,
+  0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43,
+  0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82,
+  0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58,
+  0x87, 0x72, 0x70, 0x83, 0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18,
+  0x87, 0x74, 0xa0, 0x87, 0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2,
+  0x50, 0x0e, 0xe4, 0x90, 0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec,
+  0x50, 0x0e, 0x33, 0x20, 0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e,
+  0xd2, 0x21, 0x1c, 0xdc, 0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d,
+  0xea, 0x01, 0x1e, 0x66, 0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83,
+  0x3b, 0xcc, 0x50, 0x24, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60,
+  0x87, 0x77, 0x78, 0x07, 0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0,
+  0x50, 0x0e, 0x33, 0x1e, 0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d,
+  0xde, 0xc1, 0x1d, 0x7e, 0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d,
+  0xf0, 0x61, 0x06, 0x54, 0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43,
+  0x3d, 0xd0, 0x43, 0x39, 0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3,
+  0x3b, 0xb0, 0xc3, 0x8c, 0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18,
+  0x87, 0x74, 0x08, 0x07, 0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3,
+  0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1,
+  0xd2, 0x41, 0x1e, 0xe4, 0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e,
+  0x66, 0x48, 0x19, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3,
+  0x38, 0x8c, 0x43, 0x39, 0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3,
+  0x3b, 0xd4, 0x03, 0x3c, 0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60,
+  0x07, 0x71, 0x08, 0x87, 0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec,
+  0x60, 0x0f, 0xed, 0xe0, 0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5,
+  0x20, 0x0f, 0xf6, 0x50, 0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5,
+  0x30, 0x0f, 0xf3, 0xe0, 0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8,
+  0x30, 0x23, 0xe2, 0xec, 0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17,
+  0xec, 0x21, 0x1d, 0xe6, 0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d,
+  0xe8, 0x21, 0x1f, 0x66, 0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03,
+  0x39, 0x94, 0x83, 0x39, 0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78,
+  0x07, 0x7a, 0x08, 0x07, 0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce,
+  0x87, 0x0e, 0xe5, 0x10, 0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef,
+  0x30, 0x0e, 0xf3, 0x90, 0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08,
+  0x87, 0x74, 0x90, 0x07, 0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0,
+  0x87, 0x74, 0x78, 0x07, 0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8,
+  0x07, 0x78, 0x98, 0x07, 0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x06, 0x70, 0x54, 0xd2, 0xcf, 0x00, 0x48, 0x03,
+  0x61, 0x20, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c,
+  0x10, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xe4, 0xca, 0xa0, 0x08,
+  0x4a, 0x80, 0xda, 0x58, 0x84, 0x20, 0x08, 0x02, 0xad, 0x19, 0x80, 0x32,
+  0xa0, 0x36, 0x07, 0x21, 0x04, 0x44, 0x34, 0x02, 0x30, 0x16, 0x11, 0x04,
+  0x41, 0x40, 0x63, 0x06, 0x60, 0x06, 0x80, 0xc4, 0x0c, 0x00, 0x81, 0x31,
+  0x02, 0x10, 0x04, 0x41, 0xfc, 0x03, 0x00, 0x00, 0x83, 0x0c, 0x0f, 0x71,
+  0xcc, 0x31, 0x04, 0x42, 0x32, 0x5e, 0x01, 0x51, 0x9a, 0x46, 0x51, 0x50,
+  0x06, 0x19, 0xa8, 0x43, 0x31, 0x21, 0x90, 0xcf, 0x78, 0x05, 0x85, 0x79,
+  0x5e, 0x44, 0x41, 0x19, 0x64, 0xc0, 0x96, 0xc6, 0x84, 0x40, 0x3e, 0x16,
+  0x14, 0xf0, 0x19, 0xaf, 0xc8, 0xba, 0x31, 0x18, 0x83, 0x8b, 0x82, 0x32,
+  0xc8, 0xd0, 0x41, 0x97, 0x09, 0x81, 0x7c, 0xac, 0x08, 0xe0, 0x33, 0x5e,
+  0xe1, 0x89, 0x01, 0x1a, 0xa0, 0x41, 0x47, 0x41, 0xb1, 0x21, 0x80, 0xcf,
+  0x6c, 0x43, 0x25, 0x01, 0xb3, 0x0d, 0x81, 0x10, 0x64, 0x10, 0x10, 0x03,
+  0x08, 0x00, 0x00, 0x00, 0x5b, 0x8a, 0x21, 0x90, 0x83, 0xe3, 0x0e, 0xb6,
+  0x14, 0x47, 0x20, 0x07, 0xc7, 0x1d, 0x6c, 0x29, 0x98, 0x40, 0x0e, 0x8e,
+  0x3b, 0xd8, 0x52, 0x44, 0x81, 0x1c, 0x1c, 0x77, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int cube_vert_metallib_len = 3200;
+const unsigned char cube_frag_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfb, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x09, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x08, 0x00, 0x66, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01, 0x48, 0x41, 0x53,
+  0x48, 0x20, 0x00, 0x29, 0xbb, 0xc2, 0x87, 0x30, 0x03, 0x9b, 0xc2, 0x29,
+  0xf0, 0xd6, 0x9a, 0x0e, 0x55, 0xa4, 0xf4, 0xb6, 0xd7, 0x55, 0x10, 0xd8,
+  0x1c, 0x85, 0xfd, 0xae, 0x53, 0xe4, 0xeb, 0x05, 0xa4, 0xee, 0xca, 0x4f,
+  0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01,
+  0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04,
+  0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45,
+  0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14,
+  0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x3e, 0x02, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a, 0x90, 0x21, 0x23,
+  0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07, 0xc8, 0x08, 0x11,
+  0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x51,
+  0x18, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x1b, 0x7e, 0x24, 0xf8, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x90, 0x00, 0x8a, 0x08, 0x07, 0x78, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x7c, 0x68, 0x03, 0x73, 0xa8, 0x07, 0x77, 0x18, 0x87,
+  0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07,
+  0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xda, 0x21, 0x1d, 0xdc,
+  0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d, 0xec,
+  0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e, 0xd2,
+  0x81, 0x1c, 0xe8, 0x01, 0x1d, 0x80, 0x38, 0x90, 0x03, 0x3c, 0x00, 0x06,
+  0x77, 0x78, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x48, 0x07, 0x76, 0xa0, 0x87,
+  0x74, 0x70, 0x87, 0x79, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30, 0x07,
+  0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48, 0x07,
+  0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48, 0x87,
+  0x76, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde,
+  0xa1, 0x0d, 0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d, 0xca, 0xa1, 0x0d, 0xe0,
+  0xe1, 0x1d, 0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xca,
+  0x81, 0x1d, 0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d, 0xde, 0xc1, 0x1d, 0xda,
+  0x80, 0x1d, 0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87,
+  0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x48, 0x07, 0x77, 0x30, 0x87,
+  0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07,
+  0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde,
+  0xa1, 0x0d, 0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0,
+  0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87,
+  0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83, 0x79, 0x48, 0x87,
+  0x73, 0x70, 0x87, 0x72, 0x20, 0x87, 0x36, 0xd0, 0x87, 0x72, 0x90, 0x87,
+  0x77, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07,
+  0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc,
+  0xe1, 0x1d, 0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c, 0xe0, 0x01, 0x1e, 0xd2,
+  0xc1, 0x1d, 0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x98, 0x07, 0x7a, 0x08, 0x87,
+  0x71, 0x58, 0x87, 0x36, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7a, 0x28, 0x87,
+  0x71, 0xa0, 0x87, 0x77, 0x90, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x30, 0x07,
+  0x73, 0x28, 0x07, 0x79, 0x68, 0x83, 0x79, 0x48, 0x07, 0x7d, 0x28, 0x07,
+  0x00, 0x0f, 0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e, 0xc2, 0xc1, 0x1c, 0xca,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x36, 0x10, 0x42, 0x00,
+  0x58, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13,
+  0x84, 0x40, 0x00, 0x89, 0x20, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04,
+  0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b,
+  0x84, 0x84, 0x4c, 0x10, 0x20, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x50, 0x86,
+  0x88, 0x20, 0x19, 0x08, 0x98, 0x23, 0x00, 0x83, 0x14, 0xa8, 0x11, 0x00,
+  0x00, 0x00, 0x00, 0x13, 0xa8, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a,
+  0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x74,
+  0x78, 0x87, 0x79, 0xc8, 0x03, 0x37, 0x80, 0x03, 0x37, 0x80, 0x83, 0x0d,
+  0xb7, 0x51, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe9, 0x10, 0x07,
+  0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07,
+  0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06, 0xe9, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06, 0xe9, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06,
+  0xe9, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07,
+  0x74, 0xd0, 0x06, 0xe6, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xd0, 0x06,
+  0xf6, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xd0, 0x06, 0xf6, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xf6, 0x40, 0x07, 0x78, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xf6, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06,
+  0xf6, 0x90, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07,
+  0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x72, 0x80, 0x07,
+  0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07,
+  0x6d, 0x60, 0x0f, 0x71, 0x90, 0x07, 0x72, 0xa0, 0x07, 0x72, 0x50, 0x07,
+  0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x20, 0x07,
+  0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07,
+  0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x75, 0x10, 0x07, 0x72, 0xa0, 0x07,
+  0x75, 0x10, 0x07, 0x72, 0xa0, 0x07, 0x75, 0x10, 0x07, 0x72, 0xd0, 0x06,
+  0xf6, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07,
+  0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xd0, 0x06,
+  0xee, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x43, 0x98, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c,
+  0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x0c, 0x19,
+  0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0xaa, 0x12,
+  0x18, 0x01, 0x28, 0x82, 0x42, 0x28, 0x08, 0xb2, 0xb1, 0x84, 0x48, 0x00,
+  0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x95, 0x00, 0x00, 0x00, 0x1a,
+  0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9, 0xb9,
+  0xb4, 0x37, 0xb7, 0x21, 0x46, 0x31, 0x10, 0x80, 0x61, 0x50, 0xb9, 0x1b,
+  0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x14, 0x01,
+  0x21, 0x14, 0x04, 0xdf, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4, 0xad,
+  0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x0d,
+  0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x07, 0x07, 0x04, 0xa5, 0xad,
+  0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46, 0x66, 0xc6,
+  0x25, 0x07, 0x27, 0x65, 0x88, 0x40, 0x10, 0x43, 0x8c, 0x22, 0x28, 0x8a,
+  0x42, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04, 0x21, 0x8e, 0x22,
+  0x28, 0x82, 0x42, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6, 0x06,
+  0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36, 0xf7,
+  0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44, 0x20, 0x12, 0x72,
+  0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e,
+  0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e,
+  0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x62, 0x21, 0x19, 0x84, 0xa5, 0xc9,
+  0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9, 0x85,
+  0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95, 0xd1,
+  0x8d, 0xa1, 0x7d, 0x95, 0xb9, 0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11, 0x88,
+  0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99, 0x1b, 0x59, 0x99, 0xdc,
+  0x17, 0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3, 0xb0, 0x34, 0x39, 0x97,
+  0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0x2f, 0xb7, 0xb0, 0xb6,
+  0x32, 0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x43, 0x10, 0xe2, 0x29,
+  0x04, 0x02, 0x22, 0xa2, 0x21, 0x02, 0x21, 0x51, 0x0a, 0x4b, 0x93, 0x73,
+  0x31, 0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0xfb, 0x4a, 0x73, 0x83,
+  0xab, 0xa3, 0xe3, 0x52, 0x37, 0x57, 0x26, 0x87, 0xc2, 0xf6, 0x36, 0xe6,
+  0x06, 0x93, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d, 0xae,
+  0x4c, 0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c, 0x5c,
+  0xd9, 0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x99, 0xb0, 0x34, 0x39, 0x97, 0x30,
+  0xb9, 0xb3, 0x2f, 0xb7, 0xb0, 0xb6, 0x32, 0x16, 0x63, 0x6f, 0x6c, 0x6f,
+  0x72, 0x43, 0xa4, 0x42, 0x20, 0x28, 0xa2, 0x22, 0x2c, 0xe2, 0x22, 0x20,
+  0x22, 0x22, 0x30, 0x22, 0x23, 0x13, 0x96, 0x26, 0xe7, 0x02, 0xf7, 0x36,
+  0x97, 0x46, 0x97, 0xf6, 0xe6, 0x46, 0x29, 0x2c, 0x4d, 0xce, 0xc5, 0xed,
+  0xed, 0x0b, 0xae, 0x4c, 0x6e, 0x0e, 0xae, 0x6c, 0x8c, 0x2e, 0xcd, 0xae,
+  0x8c, 0x08, 0xdc, 0xdb, 0x5c, 0x1a, 0x5d, 0xda, 0x9b, 0xdb, 0x10, 0xa8,
+  0x08, 0x88, 0x8d, 0xb0, 0x08, 0x8e, 0x80, 0x88, 0x88, 0xc0, 0x88, 0x6e,
+  0x08, 0x41, 0x68, 0x84, 0x37, 0xc4, 0x18, 0x00, 0x62, 0x22, 0xbe, 0x11,
+  0x11, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0xb4, 0xc3, 0x3b, 0x90,
+  0x43, 0x3d, 0xb0, 0x43, 0x39, 0xb8, 0x81, 0x39, 0xb0, 0x43, 0x38, 0x9c,
+  0xc3, 0x3c, 0x4c, 0x11, 0x82, 0x61, 0x84, 0xc2, 0x0e, 0xec, 0x60, 0x0f,
+  0xed, 0xe0, 0x06, 0xe9, 0x40, 0x0e, 0xe5, 0xe0, 0x0e, 0xf4, 0x30, 0x25,
+  0x28, 0x46, 0x2c, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e,
+  0xf2, 0x30, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x25, 0x30, 0x46, 0x50,
+  0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xec, 0x10, 0x0e, 0xee, 0x70, 0x0e,
+  0xf5, 0x10, 0x0e, 0xe7, 0x50, 0x0e, 0xbf, 0x60, 0x0f, 0xe5, 0x20, 0x0f,
+  0xf3, 0x90, 0x0e, 0xef, 0xe0, 0x0e, 0x53, 0x02, 0x64, 0xc4, 0x14, 0x0e,
+  0xe9, 0x20, 0x0f, 0x6e, 0x30, 0x0e, 0xef, 0xd0, 0x0e, 0xf0, 0x90, 0x0e,
+  0xec, 0x50, 0x0e, 0xbf, 0xf0, 0x0e, 0xf0, 0x40, 0x0f, 0xe9, 0xf0, 0x0e,
+  0xee, 0x30, 0x0f, 0x53, 0x06, 0x85, 0x71, 0x46, 0x30, 0xe1, 0x90, 0x0e,
+  0xf2, 0xe0, 0x06, 0xe6, 0x20, 0x0f, 0xe1, 0x70, 0x0e, 0xed, 0x50, 0x0e,
+  0xee, 0x40, 0x0f, 0x53, 0x02, 0x30, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74,
+  0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19,
+  0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e,
+  0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28,
+  0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81,
+  0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18,
+  0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78,
+  0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a,
+  0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01,
+  0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85,
+  0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc,
+  0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5,
+  0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a,
+  0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e,
+  0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1,
+  0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0,
+  0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc,
+  0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc,
+  0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71,
+  0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06,
+  0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e,
+  0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06,
+  0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61,
+  0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21,
+  0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20,
+  0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc,
+  0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a,
+  0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e,
+  0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e,
+  0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37,
+  0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77,
+  0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06,
+  0x70, 0x14, 0xd2, 0xcf, 0x00, 0x48, 0x03, 0x61, 0x20, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int cube_frag_metallib_len = 2555;
+#endif
+#else
+const unsigned char cube_vert_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x20, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0b, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x08, 0x00, 0x76, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x00, 0x48, 0x41, 0x53,
+  0x48, 0x20, 0x00, 0x24, 0x4c, 0xb9, 0x70, 0xfa, 0x59, 0x48, 0x5e, 0xfe,
+  0x11, 0x40, 0x36, 0xc9, 0xf9, 0x9d, 0x89, 0xe1, 0x76, 0xcb, 0x69, 0x62,
+  0x92, 0x76, 0xfa, 0x01, 0xcf, 0x50, 0x46, 0x27, 0x33, 0xb3, 0xef, 0x4f,
+  0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01,
+  0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x29,
+  0x00, 0x00, 0x00, 0x56, 0x41, 0x54, 0x54, 0x15, 0x00, 0x02, 0x00, 0x70,
+  0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x80, 0x63, 0x6f,
+  0x6c, 0x6f, 0x72, 0x00, 0x01, 0x80, 0x56, 0x41, 0x54, 0x59, 0x04, 0x00,
+  0x02, 0x00, 0x05, 0x05, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00,
+  0x45, 0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x08, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xbf, 0x02, 0x00, 0x00,
+  0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39,
+  0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62,
+  0x80, 0x14, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xa4, 0x10, 0x32, 0x14,
+  0x38, 0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a, 0x90, 0x21,
+  0x23, 0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07, 0xc8, 0x48,
+  0x11, 0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00,
+  0x51, 0x18, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x1b, 0x7e, 0x24, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0x01, 0x90, 0x00, 0x8a, 0x08, 0x07, 0x78, 0x80,
+  0x07, 0x79, 0x78, 0x07, 0x7c, 0x68, 0x03, 0x73, 0xa8, 0x07, 0x77, 0x18,
+  0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40,
+  0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xda, 0x21, 0x1d,
+  0xdc, 0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d,
+  0xec, 0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e,
+  0xd2, 0x81, 0x1c, 0xe8, 0x01, 0x1d, 0x80, 0x38, 0x90, 0x03, 0x3c, 0x00,
+  0x06, 0x77, 0x78, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x48, 0x07, 0x76, 0xa0,
+  0x87, 0x74, 0x70, 0x87, 0x79, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30,
+  0x07, 0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48,
+  0x07, 0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48,
+  0x87, 0x76, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d,
+  0xde, 0xa1, 0x0d, 0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d, 0xca, 0xa1, 0x0d,
+  0xe0, 0xe1, 0x1d, 0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d,
+  0xca, 0x81, 0x1d, 0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d, 0xde, 0xc1, 0x1d,
+  0xda, 0x80, 0x1d, 0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0, 0x07, 0x79, 0xa8,
+  0x87, 0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x48, 0x07, 0x77, 0x30,
+  0x87, 0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0,
+  0x07, 0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d,
+  0xde, 0xa1, 0x0d, 0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e, 0xda, 0xc0, 0x1c,
+  0xe0, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90,
+  0x87, 0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83, 0x79, 0x48,
+  0x87, 0x73, 0x70, 0x87, 0x72, 0x20, 0x87, 0x36, 0xd0, 0x87, 0x72, 0x90,
+  0x87, 0x77, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08,
+  0x07, 0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20,
+  0xdc, 0xe1, 0x1d, 0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c, 0xe0, 0x01, 0x1e,
+  0xd2, 0xc1, 0x1d, 0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d,
+  0x00, 0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x98, 0x07, 0x7a, 0x08,
+  0x87, 0x71, 0x58, 0x87, 0x36, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7a, 0x28,
+  0x87, 0x71, 0xa0, 0x87, 0x77, 0x90, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x30,
+  0x07, 0x73, 0x28, 0x07, 0x79, 0x68, 0x83, 0x79, 0x48, 0x07, 0x7d, 0x28,
+  0x07, 0x00, 0x0f, 0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e, 0xc2, 0xc1, 0x1c,
+  0xca, 0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e,
+  0xd0, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x36, 0x18, 0xc2,
+  0x00, 0x2c, 0x40, 0x05, 0x49, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x13, 0x84, 0x40, 0x00, 0x89, 0x20, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x32, 0x22, 0x48, 0x09, 0x20, 0x64, 0x85, 0x04, 0x93, 0x22, 0xa4, 0x84,
+  0x04, 0x93, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8a, 0x8c,
+  0x0b, 0x84, 0xa4, 0x4c, 0x10, 0x44, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x60,
+  0x85, 0x10, 0x86, 0x11, 0x06, 0x20, 0x09, 0xc2, 0x4c, 0xd4, 0x3c, 0xd0,
+  0x83, 0x3c, 0xd4, 0xc3, 0x38, 0xd0, 0x83, 0x1b, 0xb4, 0x43, 0x39, 0xd0,
+  0x43, 0x38, 0xb0, 0x83, 0x1e, 0xe8, 0x41, 0x3b, 0x84, 0x03, 0x3d, 0xc8,
+  0x43, 0x3a, 0xe0, 0x03, 0x0a, 0xc8, 0x29, 0xd2, 0x14, 0x51, 0xc2, 0xe4,
+  0xbb, 0x1b, 0x8a, 0x82, 0x32, 0x88, 0x60, 0x08, 0x85, 0x10, 0x63, 0x1c,
+  0x42, 0x03, 0x01, 0x73, 0x04, 0x60, 0x90, 0x02, 0x6b, 0x18, 0x81, 0x58,
+  0xe6, 0x08, 0x40, 0x61, 0x10, 0x21, 0x10, 0x46, 0x00, 0x00, 0x00, 0x00,
+  0x13, 0xb2, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a, 0x68, 0x83, 0x70,
+  0x80, 0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x76, 0x08, 0x87, 0x71,
+  0x78, 0x87, 0x79, 0xc0, 0x87, 0x38, 0x80, 0x03, 0x37, 0x88, 0x83, 0x38,
+  0x70, 0x03, 0x38, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06, 0xf0, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07, 0x78, 0xd0, 0x06,
+  0xe9, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x6d, 0x90, 0x0e,
+  0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x71, 0x60, 0x07,
+  0x6d, 0x90, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07,
+  0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e,
+  0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0x60, 0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x73, 0x20, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f,
+  0x74, 0x80, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07,
+  0x6d, 0x60, 0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07, 0x7a, 0x10, 0x07,
+  0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x6d, 0x60, 0x0f,
+  0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07,
+  0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07, 0x79, 0x20, 0x07,
+  0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07,
+  0x6d, 0x60, 0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07,
+  0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06, 0xf6, 0x50, 0x07,
+  0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07,
+  0x71, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07, 0x72, 0x40, 0x07,
+  0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07, 0x71, 0x00, 0x07,
+  0x72, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0x30, 0x84, 0x49, 0x00, 0x00, 0x08, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc8, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x32, 0x1e, 0x98, 0x10, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47,
+  0xc6, 0x04, 0x43, 0x5a, 0x25, 0x30, 0x02, 0x50, 0x80, 0x01, 0x45, 0x50,
+  0x08, 0x05, 0x51, 0x20, 0xe4, 0x46, 0x00, 0x88, 0x8d, 0x25, 0x38, 0x02,
+  0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00,
+  0x1a, 0x03, 0x4c, 0x10, 0x97, 0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9,
+  0xb9, 0xb4, 0x37, 0xb7, 0x21, 0xc6, 0x42, 0x28, 0x00, 0x93, 0x50, 0xb9,
+  0x1b, 0x43, 0x0b, 0x93, 0xfb, 0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x2c,
+  0x81, 0x22, 0x2c, 0x05, 0xe3, 0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4,
+  0xad, 0x8c, 0x2e, 0x8c, 0x0d, 0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd,
+  0x0d, 0x64, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x06, 0x26, 0x06, 0x04,
+  0xa5, 0xad, 0x8c, 0x2e, 0x8c, 0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46,
+  0x66, 0xc6, 0x25, 0x06, 0x26, 0x26, 0x65, 0x88, 0xa0, 0x10, 0x43, 0x8c,
+  0x25, 0x58, 0x8c, 0x45, 0x60, 0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04,
+  0x51, 0x8e, 0x25, 0x58, 0x82, 0x45, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32,
+  0xf6, 0xd6, 0x06, 0x97, 0xc6, 0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26,
+  0xd7, 0x36, 0xf7, 0x45, 0x96, 0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44,
+  0x50, 0x12, 0x72, 0x61, 0x69, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69,
+  0x6c, 0x65, 0x2e, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68,
+  0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x04, 0x65, 0x61, 0x19,
+  0x84, 0xa5, 0xc9, 0xb9, 0x8c, 0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9,
+  0x98, 0xc9, 0x85, 0xb5, 0x95, 0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d,
+  0x99, 0x95, 0xd1, 0x8d, 0xa1, 0x7d, 0x91, 0xa5, 0xcd, 0x85, 0x89, 0xb1,
+  0x95, 0x0d, 0x11, 0x94, 0x86, 0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5d, 0x99,
+  0x1c, 0x5d, 0x19, 0xde, 0xd7, 0x5b, 0x1d, 0x1d, 0x5c, 0x1d, 0x1d, 0x97,
+  0xba, 0xb9, 0x32, 0x39, 0x14, 0xb6, 0xb7, 0x31, 0x37, 0x98, 0x14, 0x46,
+  0x61, 0x69, 0x72, 0x2e, 0x61, 0x72, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65,
+  0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x34, 0xcc, 0xd8, 0xde, 0xc2, 0xe8, 0x68,
+  0xc8, 0x84, 0xa5, 0xc9, 0xb9, 0x84, 0xc9, 0x9d, 0x7d, 0xb9, 0x85, 0xb5,
+  0x95, 0xb1, 0x18, 0x7b, 0x63, 0x7b, 0x93, 0x1b, 0xc2, 0x28, 0x8f, 0x02,
+  0x29, 0x91, 0x22, 0x29, 0x93, 0x42, 0x91, 0x09, 0x4b, 0x93, 0x73, 0x81,
+  0x7b, 0x9b, 0x4b, 0xa3, 0x4b, 0x7b, 0x73, 0x23, 0x02, 0xf7, 0x36, 0x97,
+  0x46, 0x97, 0xf6, 0xe6, 0x36, 0x44, 0x51, 0x2c, 0x25, 0x52, 0x24, 0x65,
+  0x52, 0xae, 0x21, 0x84, 0x52, 0x29, 0x18, 0xa1, 0xb0, 0x34, 0x39, 0x17,
+  0xbb, 0x32, 0x39, 0xba, 0x32, 0xbc, 0xaf, 0x34, 0x37, 0xb8, 0x3a, 0x3a,
+  0x4a, 0x61, 0x69, 0x72, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
+  0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0xf4, 0xce, 0xca, 0xdc, 0xca,
+  0xe4, 0xc2, 0xe8, 0xca, 0xc8, 0x50, 0xbe, 0xbe, 0xc2, 0xd2, 0xe4, 0xbe,
+  0xe0, 0xd8, 0xc2, 0xc6, 0xca, 0xd0, 0xde, 0xd8, 0xc8, 0xca, 0xe4, 0xbe,
+  0xbe, 0x52, 0x68, 0x98, 0xb1, 0xbd, 0x85, 0xd1, 0xcd, 0x0c, 0xa1, 0x16,
+  0x41, 0xd1, 0x94, 0x6d, 0x11, 0x96, 0x40, 0xe1, 0x94, 0x48, 0xe9, 0x94,
+  0x49, 0xb9, 0x86, 0x50, 0x4b, 0xa0, 0x68, 0xca, 0xb6, 0x04, 0x4b, 0xa0,
+  0x70, 0x4a, 0xa4, 0x74, 0xca, 0xa4, 0x50, 0x54, 0xc2, 0xd2, 0xe4, 0x5c,
+  0xc4, 0xea, 0xcc, 0xcc, 0xca, 0xe4, 0xf8, 0x84, 0xa5, 0xc9, 0xb9, 0x88,
+  0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0xcd, 0xa5, 0xe9, 0x95, 0x11, 0x09,
+  0x4b, 0x93, 0x73, 0x91, 0x2b, 0x0b, 0x23, 0x23, 0x15, 0x96, 0x26, 0xe7,
+  0x32, 0x47, 0x27, 0x57, 0x37, 0x46, 0xf7, 0x45, 0x97, 0x07, 0x57, 0xf6,
+  0x95, 0xe6, 0x66, 0xf6, 0x46, 0xc4, 0x8c, 0xed, 0x2d, 0x8c, 0x8e, 0x06,
+  0x8f, 0x86, 0x4d, 0xdb, 0x1b, 0x59, 0x19, 0x9b, 0x55, 0x5a, 0xd9, 0x1d,
+  0x94, 0xdc, 0x9b, 0xda, 0x10, 0x65, 0x11, 0x96, 0x61, 0x11, 0x14, 0x32,
+  0x50, 0xca, 0x80, 0x51, 0x58, 0x9a, 0x9c, 0x4b, 0x98, 0xdc, 0xd9, 0x17,
+  0x5d, 0x1e, 0x5c, 0xd9, 0xd7, 0x5c, 0x9a, 0x5e, 0x19, 0xaf, 0xb0, 0x34,
+  0x39, 0x97, 0x30, 0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0xaf, 0x30,
+  0xb6, 0xb4, 0x33, 0xb7, 0xaf, 0xb9, 0x34, 0xbd, 0x32, 0x0e, 0x55, 0x42,
+  0x4f, 0x1c, 0xea, 0xc4, 0xde, 0x86, 0x90, 0xc1, 0x42, 0x28, 0x60, 0xa0,
+  0x84, 0xc1, 0x32, 0x28, 0xdb, 0x22, 0x2c, 0x81, 0x22, 0x06, 0xca, 0x18,
+  0x28, 0x66, 0xa0, 0x9c, 0xc1, 0x32, 0x28, 0x68, 0xb0, 0x1c, 0x4a, 0xa4,
+  0xa4, 0x81, 0x32, 0x29, 0x6a, 0x30, 0xc4, 0x50, 0x3c, 0xe5, 0x53, 0xd6,
+  0x60, 0x88, 0x91, 0x00, 0x4a, 0xa6, 0xb0, 0x01, 0x9f, 0xb7, 0x36, 0xb7,
+  0x34, 0xb8, 0x37, 0xba, 0x32, 0x37, 0x3a, 0x90, 0x31, 0xb4, 0x30, 0x39,
+  0x3e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20,
+  0x54, 0x42, 0x41, 0x41, 0x43, 0x04, 0xe5, 0x0d, 0x86, 0x18, 0x8a, 0x1b,
+  0x28, 0x70, 0xe0, 0x20, 0x43, 0x0c, 0x25, 0x0e, 0x94, 0x38, 0x70, 0x90,
+  0x11, 0x11, 0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0xb4, 0xc3, 0x3b,
+  0x90, 0x43, 0x3d, 0xb0, 0x43, 0x39, 0xb8, 0x81, 0x39, 0xb0, 0x43, 0x38,
+  0x9c, 0xc3, 0x3c, 0x4c, 0x11, 0x82, 0x61, 0x84, 0xc2, 0x0e, 0xec, 0x60,
+  0x0f, 0xed, 0xe0, 0x06, 0xe9, 0x40, 0x0e, 0xe5, 0xe0, 0x0e, 0xf4, 0x30,
+  0x25, 0x28, 0x46, 0x2c, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50,
+  0x0e, 0xf2, 0x30, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x25, 0x30, 0x46,
+  0x50, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xec, 0x10, 0x0e, 0xee, 0x70,
+  0x0e, 0xf5, 0x10, 0x0e, 0xe7, 0x50, 0x0e, 0xbf, 0x60, 0x0f, 0xe5, 0x20,
+  0x0f, 0xf3, 0x90, 0x0e, 0xef, 0xe0, 0x0e, 0x53, 0x02, 0x64, 0xc4, 0x14,
+  0x0e, 0xe9, 0x20, 0x0f, 0x6e, 0x30, 0x0e, 0xef, 0xd0, 0x0e, 0xf0, 0x90,
+  0x0e, 0xec, 0x50, 0x0e, 0xbf, 0xf0, 0x0e, 0xf0, 0x40, 0x0f, 0xe9, 0xf0,
+  0x0e, 0xee, 0x30, 0x0f, 0x53, 0x06, 0x85, 0x71, 0x46, 0x28, 0xe1, 0x90,
+  0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e, 0xf2, 0x40, 0x0f, 0xe5, 0x80,
+  0x0f, 0x53, 0x82, 0x36, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00,
+  0xa5, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66,
+  0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10,
+  0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce,
+  0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b,
+  0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c,
+  0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07,
+  0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11,
+  0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0,
+  0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8,
+  0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b,
+  0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b,
+  0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87,
+  0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07,
+  0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87,
+  0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81,
+  0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30,
+  0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4,
+  0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca,
+  0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39,
+  0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b,
+  0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b,
+  0xb0, 0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83,
+  0x74, 0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87,
+  0x19, 0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90,
+  0x0e, 0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20,
+  0x28, 0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc,
+  0x81, 0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66,
+  0x18, 0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24,
+  0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07,
+  0x78, 0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e,
+  0x6a, 0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e,
+  0x01, 0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54,
+  0x85, 0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39,
+  0xfc, 0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c,
+  0xc5, 0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07,
+  0x7a, 0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0,
+  0x0e, 0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4,
+  0xe1, 0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b,
+  0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39,
+  0xcc, 0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c,
+  0xcc, 0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87,
+  0x71, 0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0,
+  0x06, 0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50,
+  0x0e, 0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0,
+  0x06, 0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec,
+  0x61, 0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6,
+  0x21, 0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66,
+  0x20, 0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39,
+  0xcc, 0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07,
+  0x7a, 0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10,
+  0x0e, 0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90,
+  0x0e, 0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07,
+  0x37, 0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07,
+  0x77, 0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x06, 0x70, 0x54, 0xd2, 0xcf, 0x00, 0x48, 0x03, 0x61, 0x20, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0xe4, 0xca, 0xa0, 0x08, 0x4a, 0x80, 0xda, 0x58,
+  0x84, 0x20, 0x08, 0x02, 0xad, 0x19, 0x80, 0x32, 0xa0, 0x36, 0x07, 0x21,
+  0x04, 0x44, 0x34, 0x02, 0x30, 0x16, 0x11, 0x04, 0x41, 0x40, 0x63, 0x06,
+  0x60, 0x06, 0x80, 0xc4, 0x0c, 0x00, 0x81, 0x31, 0x02, 0x10, 0x04, 0x41,
+  0xfc, 0x03, 0x00, 0x00, 0x83, 0x0c, 0x0f, 0x71, 0xcc, 0x31, 0x04, 0x42,
+  0x32, 0x5e, 0x01, 0x51, 0x9a, 0x46, 0x51, 0x50, 0x06, 0x19, 0xa8, 0x43,
+  0x31, 0x21, 0x90, 0xcf, 0x78, 0x05, 0x85, 0x79, 0x5e, 0x44, 0x41, 0x19,
+  0x64, 0xc0, 0x96, 0xc6, 0x84, 0x40, 0x3e, 0x16, 0x14, 0xf0, 0x19, 0xaf,
+  0xc8, 0xba, 0x31, 0x18, 0x83, 0x8b, 0x82, 0x32, 0xc8, 0xd0, 0x41, 0x97,
+  0x09, 0x81, 0x7c, 0xac, 0x08, 0xe0, 0x33, 0x5e, 0xe1, 0x89, 0x01, 0x1a,
+  0xa0, 0x41, 0x47, 0x41, 0xb1, 0x21, 0x80, 0xcf, 0x6c, 0x43, 0x25, 0x01,
+  0xb3, 0x0d, 0x81, 0x10, 0x64, 0x10, 0x10, 0x03, 0x05, 0x00, 0x00, 0x00,
+  0x5b, 0x86, 0x21, 0x90, 0x83, 0x2d, 0xc3, 0x11, 0xc8, 0xc1, 0x96, 0x81,
+  0x09, 0xe4, 0x60, 0xcb, 0x10, 0x05, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+const unsigned int cube_vert_metallib_len = 3104;
+const unsigned char cube_frag_metallib[] = {
+  0x4d, 0x54, 0x4c, 0x42, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x09, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00,
+  0x4e, 0x41, 0x4d, 0x45, 0x08, 0x00, 0x66, 0x73, 0x5f, 0x6d, 0x61, 0x69,
+  0x6e, 0x00, 0x54, 0x59, 0x50, 0x45, 0x01, 0x00, 0x01, 0x48, 0x41, 0x53,
+  0x48, 0x20, 0x00, 0x34, 0xec, 0xae, 0x80, 0xf9, 0x6c, 0xc3, 0x95, 0x5c,
+  0x2b, 0x37, 0xa6, 0xe4, 0xa1, 0x39, 0x3d, 0x31, 0xfc, 0x84, 0xc2, 0x86,
+  0x79, 0x85, 0x6e, 0x85, 0xc6, 0x60, 0x8d, 0x42, 0x7d, 0x5e, 0xd0, 0x4f,
+  0x46, 0x46, 0x54, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x45, 0x52, 0x53, 0x08, 0x00, 0x01,
+  0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04,
+  0x00, 0x00, 0x00, 0x45, 0x4e, 0x44, 0x54, 0x04, 0x00, 0x00, 0x00, 0x45,
+  0x4e, 0x44, 0x54, 0xde, 0xc0, 0x17, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x14,
+  0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x42,
+  0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0x41, 0x02, 0x00, 0x00, 0x0b,
+  0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x07,
+  0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92,
+  0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80,
+  0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38,
+  0x08, 0x18, 0x49, 0x0a, 0x32, 0x44, 0x24, 0x48, 0x0a, 0x90, 0x21, 0x23,
+  0xc4, 0x52, 0x80, 0x0c, 0x19, 0x21, 0x72, 0x24, 0x07, 0xc8, 0x08, 0x11,
+  0x62, 0xa8, 0xa0, 0xa8, 0x40, 0xc6, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x51,
+  0x18, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x1b, 0x7e, 0x24, 0xf8, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x90, 0x00, 0x8a, 0x08, 0x07, 0x78, 0x80, 0x07,
+  0x79, 0x78, 0x07, 0x7c, 0x68, 0x03, 0x73, 0xa8, 0x07, 0x77, 0x18, 0x87,
+  0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07, 0x7a, 0x40, 0x07,
+  0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xda, 0x21, 0x1d, 0xdc,
+  0xa1, 0x0d, 0xd8, 0xa1, 0x1c, 0xce, 0x21, 0x1c, 0xd8, 0xa1, 0x0d, 0xec,
+  0xa1, 0x1c, 0xc6, 0x81, 0x1e, 0xde, 0x41, 0x1e, 0xda, 0xe0, 0x1e, 0xd2,
+  0x81, 0x1c, 0xe8, 0x01, 0x1d, 0x80, 0x38, 0x90, 0x03, 0x3c, 0x00, 0x06,
+  0x77, 0x78, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x48, 0x07, 0x76, 0xa0, 0x87,
+  0x74, 0x70, 0x87, 0x79, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x30, 0x07,
+  0x79, 0x08, 0x87, 0x76, 0x28, 0x87, 0x36, 0x80, 0x87, 0x77, 0x48, 0x07,
+  0x77, 0xa0, 0x87, 0x72, 0x90, 0x87, 0x36, 0x28, 0x07, 0x76, 0x48, 0x87,
+  0x76, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde,
+  0xa1, 0x0d, 0xcc, 0x41, 0x1e, 0xc2, 0xa1, 0x1d, 0xca, 0xa1, 0x0d, 0xe0,
+  0xe1, 0x1d, 0xd2, 0xc1, 0x1d, 0xe8, 0xa1, 0x1c, 0xe4, 0xa1, 0x0d, 0xca,
+  0x81, 0x1d, 0xd2, 0xa1, 0x1d, 0xda, 0xc0, 0x1d, 0xde, 0xc1, 0x1d, 0xda,
+  0x80, 0x1d, 0xca, 0x21, 0x1c, 0xcc, 0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87,
+  0x72, 0x00, 0x08, 0x77, 0x78, 0x87, 0x36, 0x48, 0x07, 0x77, 0x30, 0x87,
+  0x79, 0x68, 0x03, 0x73, 0x80, 0x87, 0x36, 0x68, 0x87, 0x70, 0xa0, 0x07,
+  0x74, 0x00, 0xe8, 0x41, 0x1e, 0xea, 0xa1, 0x1c, 0x00, 0xc2, 0x1d, 0xde,
+  0xa1, 0x0d, 0xdc, 0x21, 0x1c, 0xdc, 0x61, 0x1e, 0xda, 0xc0, 0x1c, 0xe0,
+  0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00, 0x7a, 0x90, 0x87,
+  0x7a, 0x28, 0x07, 0x80, 0x70, 0x87, 0x77, 0x68, 0x83, 0x79, 0x48, 0x87,
+  0x73, 0x70, 0x87, 0x72, 0x20, 0x87, 0x36, 0xd0, 0x87, 0x72, 0x90, 0x87,
+  0x77, 0x98, 0x87, 0x36, 0x30, 0x07, 0x78, 0x68, 0x83, 0x76, 0x08, 0x07,
+  0x7a, 0x40, 0x07, 0x80, 0x1e, 0xe4, 0xa1, 0x1e, 0xca, 0x01, 0x20, 0xdc,
+  0xe1, 0x1d, 0xda, 0x80, 0x1e, 0xe4, 0x21, 0x1c, 0xe0, 0x01, 0x1e, 0xd2,
+  0xc1, 0x1d, 0xce, 0xa1, 0x0d, 0xda, 0x21, 0x1c, 0xe8, 0x01, 0x1d, 0x00,
+  0x7a, 0x90, 0x87, 0x7a, 0x28, 0x07, 0x80, 0x98, 0x07, 0x7a, 0x08, 0x87,
+  0x71, 0x58, 0x87, 0x36, 0x80, 0x07, 0x79, 0x78, 0x07, 0x7a, 0x28, 0x87,
+  0x71, 0xa0, 0x87, 0x77, 0x90, 0x87, 0x36, 0x10, 0x87, 0x7a, 0x30, 0x07,
+  0x73, 0x28, 0x07, 0x79, 0x68, 0x83, 0x79, 0x48, 0x07, 0x7d, 0x28, 0x07,
+  0x00, 0x0f, 0x00, 0xa2, 0x1e, 0xdc, 0x61, 0x1e, 0xc2, 0xc1, 0x1c, 0xca,
+  0xa1, 0x0d, 0xcc, 0x01, 0x1e, 0xda, 0xa0, 0x1d, 0xc2, 0x81, 0x1e, 0xd0,
+  0x01, 0xa0, 0x07, 0x79, 0xa8, 0x87, 0x72, 0x00, 0x36, 0x10, 0x42, 0x00,
+  0x58, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13,
+  0x84, 0x40, 0x00, 0x89, 0x20, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x32,
+  0x22, 0x08, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04,
+  0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b,
+  0x84, 0x84, 0x4c, 0x10, 0x20, 0x33, 0x00, 0xc3, 0x08, 0x04, 0x50, 0x86,
+  0x88, 0x20, 0x19, 0x08, 0x98, 0x23, 0x00, 0x83, 0x14, 0xa8, 0x11, 0x00,
+  0x00, 0x00, 0x00, 0x13, 0xb2, 0x70, 0x48, 0x07, 0x79, 0xb0, 0x03, 0x3a,
+  0x68, 0x83, 0x70, 0x80, 0x07, 0x78, 0x60, 0x87, 0x72, 0x68, 0x83, 0x76,
+  0x08, 0x87, 0x71, 0x78, 0x87, 0x79, 0xc0, 0x87, 0x38, 0x80, 0x03, 0x37,
+  0x88, 0x83, 0x38, 0x70, 0x03, 0x38, 0xd8, 0x70, 0x1b, 0xe5, 0xd0, 0x06,
+  0xf0, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x78, 0xa0, 0x07,
+  0x78, 0xd0, 0x06, 0xe9, 0x80, 0x07, 0x7a, 0x80, 0x07, 0x7a, 0x80, 0x07,
+  0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07, 0x76, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x6d, 0x90, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07,
+  0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07,
+  0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0e,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x60, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x60, 0x07, 0x7a, 0x10, 0x07,
+  0x76, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x40, 0x07,
+  0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0f,
+  0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07,
+  0x6d, 0x60, 0x0f, 0x74, 0x80, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xa0, 0x07,
+  0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07,
+  0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0x60, 0x0f, 0x79, 0x60, 0x07,
+  0x7a, 0x10, 0x07, 0x72, 0x80, 0x07, 0x7a, 0x10, 0x07, 0x72, 0x80, 0x07,
+  0x6d, 0x60, 0x0f, 0x71, 0x20, 0x07, 0x78, 0xa0, 0x07, 0x71, 0x20, 0x07,
+  0x78, 0xa0, 0x07, 0x71, 0x20, 0x07, 0x78, 0xd0, 0x06, 0xf6, 0x10, 0x07,
+  0x79, 0x20, 0x07, 0x7a, 0x20, 0x07, 0x75, 0x60, 0x07, 0x7a, 0x20, 0x07,
+  0x75, 0x60, 0x07, 0x6d, 0x60, 0x0f, 0x72, 0x50, 0x07, 0x76, 0xa0, 0x07,
+  0x72, 0x50, 0x07, 0x76, 0xa0, 0x07, 0x72, 0x50, 0x07, 0x76, 0xd0, 0x06,
+  0xf6, 0x50, 0x07, 0x71, 0x20, 0x07, 0x7a, 0x50, 0x07, 0x71, 0x20, 0x07,
+  0x7a, 0x50, 0x07, 0x71, 0x20, 0x07, 0x6d, 0x60, 0x0f, 0x71, 0x00, 0x07,
+  0x72, 0x40, 0x07, 0x7a, 0x10, 0x07, 0x70, 0x20, 0x07, 0x74, 0xa0, 0x07,
+  0x71, 0x00, 0x07, 0x72, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07,
+  0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0x30, 0x84, 0x19, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x02, 0x01, 0x00, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x0c, 0x19, 0x11, 0x4c, 0x90, 0x8c,
+  0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0xaa, 0x12, 0x18, 0x01, 0x28, 0x82,
+  0x42, 0x28, 0x08, 0xb2, 0xb1, 0x04, 0x47, 0x00, 0x00, 0x00, 0x00, 0x79,
+  0x18, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x10, 0x97,
+  0x29, 0xa2, 0x25, 0x10, 0xab, 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x21,
+  0x46, 0x31, 0x10, 0x80, 0x61, 0x50, 0xb9, 0x1b, 0x43, 0x0b, 0x93, 0xfb,
+  0x9a, 0x4b, 0xd3, 0x2b, 0x1b, 0x62, 0x14, 0x01, 0x21, 0x14, 0x04, 0xe3,
+  0x20, 0x08, 0x0e, 0x8e, 0xad, 0x0c, 0xa4, 0xad, 0x8c, 0x2e, 0x8c, 0x0d,
+  0xc4, 0xae, 0x4c, 0x6e, 0x2e, 0xed, 0xcd, 0x0d, 0x64, 0x46, 0x06, 0x46,
+  0x66, 0xc6, 0x25, 0x06, 0x26, 0x06, 0x04, 0xa5, 0xad, 0x8c, 0x2e, 0x8c,
+  0xcd, 0xac, 0xac, 0x65, 0x46, 0x06, 0x46, 0x66, 0xc6, 0x25, 0x06, 0x26,
+  0x26, 0x65, 0x88, 0x40, 0x10, 0x43, 0x8c, 0x22, 0x28, 0x8a, 0x42, 0x60,
+  0xd1, 0x54, 0x46, 0x17, 0xc6, 0x36, 0x04, 0x21, 0x8e, 0x22, 0x28, 0x82,
+  0x42, 0xe0, 0x16, 0x96, 0x26, 0xe7, 0x32, 0xf6, 0xd6, 0x06, 0x97, 0xc6,
+  0x56, 0xe6, 0x42, 0x56, 0xe6, 0xf6, 0x26, 0xd7, 0x36, 0xf7, 0x45, 0x96,
+  0x36, 0x17, 0x26, 0xc6, 0x56, 0x36, 0x44, 0x20, 0x12, 0x72, 0x61, 0x69,
+  0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x66, 0x61,
+  0x73, 0x74, 0x5f, 0x6d, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x6e, 0x61, 0x62,
+  0x6c, 0x65, 0x43, 0x04, 0x62, 0x61, 0x19, 0x84, 0xa5, 0xc9, 0xb9, 0x8c,
+  0xbd, 0xb5, 0xc1, 0xa5, 0xb1, 0x95, 0xb9, 0x98, 0xc9, 0x85, 0xb5, 0x95,
+  0x89, 0xd5, 0x99, 0x99, 0x95, 0xc9, 0x7d, 0x99, 0x95, 0xd1, 0x8d, 0xa1,
+  0x7d, 0x91, 0xa5, 0xcd, 0x85, 0x89, 0xb1, 0x95, 0x0d, 0x11, 0x88, 0x86,
+  0x51, 0x58, 0x9a, 0x9c, 0x8b, 0x5c, 0x99, 0x1b, 0x59, 0x99, 0xdc, 0x17,
+  0x5d, 0x98, 0xdc, 0x59, 0x19, 0x1d, 0xa3, 0xb0, 0x34, 0x39, 0x97, 0x30,
+  0xb9, 0xb3, 0x2f, 0xba, 0x3c, 0xb8, 0xb2, 0x2f, 0xb7, 0xb0, 0xb6, 0x32,
+  0x1a, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x43, 0x10, 0xe2, 0x29, 0x04,
+  0x02, 0x22, 0xa2, 0x21, 0x02, 0x21, 0x51, 0x0a, 0x4b, 0x93, 0x73, 0x31,
+  0x93, 0x0b, 0x3b, 0x6b, 0x2b, 0x73, 0xa3, 0xfb, 0x4a, 0x73, 0x83, 0xab,
+  0xa3, 0xe3, 0x52, 0x37, 0x57, 0x26, 0x87, 0xc2, 0xf6, 0x36, 0xe6, 0x06,
+  0x93, 0x42, 0x25, 0x2c, 0x4d, 0xce, 0x65, 0xac, 0xcc, 0x8d, 0xae, 0x4c,
+  0x8e, 0x4f, 0x58, 0x9a, 0x9c, 0x0b, 0x5c, 0x99, 0xdc, 0x1c, 0x5c, 0xd9,
+  0x18, 0x5d, 0x9a, 0x5d, 0x19, 0x99, 0xb0, 0x34, 0x39, 0x97, 0x30, 0xb9,
+  0xb3, 0x2f, 0xb7, 0xb0, 0xb6, 0x32, 0x16, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+  0x43, 0xa4, 0x42, 0x20, 0x28, 0xa2, 0x22, 0x2c, 0xe2, 0x22, 0x20, 0x22,
+  0x22, 0x30, 0x22, 0x23, 0x13, 0x96, 0x26, 0xe7, 0x02, 0xf7, 0x36, 0x97,
+  0x46, 0x97, 0xf6, 0xe6, 0x46, 0x29, 0x2c, 0x4d, 0xce, 0xc5, 0xed, 0xed,
+  0x0b, 0xae, 0x4c, 0x6e, 0x0e, 0xae, 0x6c, 0x8c, 0x2e, 0xcd, 0xae, 0x8c,
+  0x08, 0xdc, 0xdb, 0x5c, 0x1a, 0x5d, 0xda, 0x9b, 0xdb, 0x10, 0xa8, 0x08,
+  0x88, 0x8d, 0xb0, 0x08, 0x8e, 0x80, 0x88, 0x88, 0xc0, 0x88, 0x6e, 0x08,
+  0x41, 0x68, 0x84, 0x37, 0xc4, 0x18, 0x00, 0x62, 0x22, 0xbe, 0x11, 0x11,
+  0x3b, 0xb0, 0x83, 0x3d, 0xb4, 0x83, 0x1b, 0xb4, 0xc3, 0x3b, 0x90, 0x43,
+  0x3d, 0xb0, 0x43, 0x39, 0xb8, 0x81, 0x39, 0xb0, 0x43, 0x38, 0x9c, 0xc3,
+  0x3c, 0x4c, 0x11, 0x82, 0x61, 0x84, 0xc2, 0x0e, 0xec, 0x60, 0x0f, 0xed,
+  0xe0, 0x06, 0xe9, 0x40, 0x0e, 0xe5, 0xe0, 0x0e, 0xf4, 0x30, 0x25, 0x28,
+  0x46, 0x2c, 0xe1, 0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xf6, 0x50, 0x0e, 0xf2,
+  0x30, 0x0f, 0xe9, 0xf0, 0x0e, 0xee, 0x30, 0x25, 0x30, 0x46, 0x50, 0xe1,
+  0x90, 0x0e, 0xf2, 0xe0, 0x06, 0xec, 0x10, 0x0e, 0xee, 0x70, 0x0e, 0xf5,
+  0x10, 0x0e, 0xe7, 0x50, 0x0e, 0xbf, 0x60, 0x0f, 0xe5, 0x20, 0x0f, 0xf3,
+  0x90, 0x0e, 0xef, 0xe0, 0x0e, 0x53, 0x02, 0x64, 0xc4, 0x14, 0x0e, 0xe9,
+  0x20, 0x0f, 0x6e, 0x30, 0x0e, 0xef, 0xd0, 0x0e, 0xf0, 0x90, 0x0e, 0xec,
+  0x50, 0x0e, 0xbf, 0xf0, 0x0e, 0xf0, 0x40, 0x0f, 0xe9, 0xf0, 0x0e, 0xee,
+  0x30, 0x0f, 0x53, 0x06, 0x85, 0x71, 0x46, 0x30, 0xe1, 0x90, 0x0e, 0xf2,
+  0xe0, 0x06, 0xe6, 0x20, 0x0f, 0xe1, 0x70, 0x0e, 0xed, 0x50, 0x0e, 0xee,
+  0x40, 0x0f, 0x53, 0x02, 0x30, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0xa5,
+  0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14,
+  0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79,
+  0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e,
+  0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1,
+  0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc,
+  0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74,
+  0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a,
+  0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e,
+  0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e,
+  0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21,
+  0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0,
+  0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc,
+  0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72,
+  0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76,
+  0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f,
+  0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c,
+  0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03,
+  0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1,
+  0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61,
+  0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8,
+  0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94,
+  0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0,
+  0xc3, 0x0c, 0xc7, 0x69, 0x87, 0x70, 0x58, 0x87, 0x72, 0x70, 0x83, 0x74,
+  0x68, 0x07, 0x78, 0x60, 0x87, 0x74, 0x18, 0x87, 0x74, 0xa0, 0x87, 0x19,
+  0xce, 0x53, 0x0f, 0xee, 0x00, 0x0f, 0xf2, 0x50, 0x0e, 0xe4, 0x90, 0x0e,
+  0xe3, 0x40, 0x0f, 0xe1, 0x20, 0x0e, 0xec, 0x50, 0x0e, 0x33, 0x20, 0x28,
+  0x1d, 0xdc, 0xc1, 0x1e, 0xc2, 0x41, 0x1e, 0xd2, 0x21, 0x1c, 0xdc, 0x81,
+  0x1e, 0xdc, 0xe0, 0x1c, 0xe4, 0xe1, 0x1d, 0xea, 0x01, 0x1e, 0x66, 0x18,
+  0x51, 0x38, 0xb0, 0x43, 0x3a, 0x9c, 0x83, 0x3b, 0xcc, 0x50, 0x24, 0x76,
+  0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x60, 0x87, 0x77, 0x78, 0x07, 0x78,
+  0x98, 0x51, 0x4c, 0xf4, 0x90, 0x0f, 0xf0, 0x50, 0x0e, 0x33, 0x1e, 0x6a,
+  0x1e, 0xca, 0x61, 0x1c, 0xe8, 0x21, 0x1d, 0xde, 0xc1, 0x1d, 0x7e, 0x01,
+  0x1e, 0xe4, 0xa1, 0x1c, 0xcc, 0x21, 0x1d, 0xf0, 0x61, 0x06, 0x54, 0x85,
+  0x83, 0x38, 0xcc, 0xc3, 0x3b, 0xb0, 0x43, 0x3d, 0xd0, 0x43, 0x39, 0xfc,
+  0xc2, 0x3c, 0xe4, 0x43, 0x3b, 0x88, 0xc3, 0x3b, 0xb0, 0xc3, 0x8c, 0xc5,
+  0x0a, 0x87, 0x79, 0x98, 0x87, 0x77, 0x18, 0x87, 0x74, 0x08, 0x07, 0x7a,
+  0x28, 0x07, 0x72, 0x98, 0x81, 0x5c, 0xe3, 0x10, 0x0e, 0xec, 0xc0, 0x0e,
+  0xe5, 0x50, 0x0e, 0xf3, 0x30, 0x23, 0xc1, 0xd2, 0x41, 0x1e, 0xe4, 0xe1,
+  0x17, 0xd8, 0xe1, 0x1d, 0xde, 0x01, 0x1e, 0x66, 0x48, 0x19, 0x3b, 0xb0,
+  0x83, 0x3d, 0xb4, 0x83, 0x1b, 0x84, 0xc3, 0x38, 0x8c, 0x43, 0x39, 0xcc,
+  0xc3, 0x3c, 0xb8, 0xc1, 0x39, 0xc8, 0xc3, 0x3b, 0xd4, 0x03, 0x3c, 0xcc,
+  0x48, 0xb4, 0x71, 0x08, 0x07, 0x76, 0x60, 0x07, 0x71, 0x08, 0x87, 0x71,
+  0x58, 0x87, 0x19, 0xdb, 0xc6, 0x0e, 0xec, 0x60, 0x0f, 0xed, 0xe0, 0x06,
+  0xf0, 0x20, 0x0f, 0xe5, 0x30, 0x0f, 0xe5, 0x20, 0x0f, 0xf6, 0x50, 0x0e,
+  0x6e, 0x10, 0x0e, 0xe3, 0x30, 0x0e, 0xe5, 0x30, 0x0f, 0xf3, 0xe0, 0x06,
+  0xe9, 0xe0, 0x0e, 0xe4, 0x50, 0x0e, 0xf8, 0x30, 0x23, 0xe2, 0xec, 0x61,
+  0x1c, 0xc2, 0x81, 0x1d, 0xd8, 0xe1, 0x17, 0xec, 0x21, 0x1d, 0xe6, 0x21,
+  0x1d, 0xc4, 0x21, 0x1d, 0xd8, 0x21, 0x1d, 0xe8, 0x21, 0x1f, 0x66, 0x20,
+  0x9d, 0x3b, 0xbc, 0x43, 0x3d, 0xb8, 0x03, 0x39, 0x94, 0x83, 0x39, 0xcc,
+  0x58, 0xbc, 0x70, 0x70, 0x07, 0x77, 0x78, 0x07, 0x7a, 0x08, 0x07, 0x7a,
+  0x48, 0x87, 0x77, 0x70, 0x87, 0x19, 0xce, 0x87, 0x0e, 0xe5, 0x10, 0x0e,
+  0xf0, 0x10, 0x0e, 0xec, 0xc0, 0x0e, 0xef, 0x30, 0x0e, 0xf3, 0x90, 0x0e,
+  0xf4, 0x50, 0x0e, 0x33, 0x28, 0x30, 0x08, 0x87, 0x74, 0x90, 0x07, 0x37,
+  0x30, 0x87, 0x7a, 0x70, 0x87, 0x71, 0xa0, 0x87, 0x74, 0x78, 0x07, 0x77,
+  0xf8, 0x85, 0x73, 0x90, 0x87, 0x77, 0xa8, 0x07, 0x78, 0x98, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06,
+  0x70, 0x14, 0xd2, 0xcf, 0x00, 0x48, 0x03, 0x61, 0x20, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00
+};
+const unsigned int cube_frag_metallib_len = 2571;
+#endif

+ 150 - 0
test/testgpu/testgpu_spirv.h

@@ -0,0 +1,150 @@
+const unsigned char cube_vert_spv[] = {
+  0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00,
+  0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0xc2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x5f, 0x63, 0x6f, 0x6c, 0x6f,
+  0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x50,
+  0x65, 0x72, 0x56, 0x65, 0x72, 0x74, 0x65, 0x78, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00,
+  0x06, 0x00, 0x07, 0x00, 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65,
+  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43, 0x6c, 0x69, 0x70, 0x44,
+  0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00, 0x06, 0x00, 0x07, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x67, 0x6c, 0x5f, 0x43,
+  0x75, 0x6c, 0x6c, 0x44, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x00,
+  0x05, 0x00, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x55, 0x42, 0x4f, 0x00,
+  0x06, 0x00, 0x07, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f,
+  0x6a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00,
+  0x69, 0x6e, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x05, 0x00, 0x16, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x47, 0x00, 0x03, 0x00, 0x16, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x05, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x03, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x47, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+  0x15, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x04, 0x00, 0x13, 0x00, 0x00, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x04, 0x00,
+  0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x06, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x16, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x17, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x15, 0x00, 0x04, 0x00,
+  0x19, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x2b, 0x00, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x03, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x1d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00, 0x1f, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x02, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x41, 0x00, 0x05, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x1b, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x3d, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x22, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x24, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x51, 0x00, 0x05, 0x00, 0x06, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x51, 0x00, 0x05, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x50, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x27, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
+  0x26, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x91, 0x00, 0x05, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
+  0x27, 0x00, 0x00, 0x00, 0x41, 0x00, 0x05, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x29, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x29, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+  0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+};
+const unsigned int cube_vert_spv_len = 1340;
+const unsigned char cube_frag_spv[] = {
+  0x03, 0x02, 0x23, 0x07, 0x00, 0x00, 0x01, 0x00, 0x0b, 0x00, 0x08, 0x00,
+  0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x47, 0x4c, 0x53, 0x4c, 0x2e, 0x73, 0x74, 0x64, 0x2e, 0x34, 0x35, 0x30,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00, 0x00, 0x05, 0x00, 0x04, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x05, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6f, 0x75, 0x74, 0x5f,
+  0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+  0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00, 0x09, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x04, 0x00,
+  0x0b, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x13, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x03, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x17, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x20, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x04, 0x00,
+  0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x3b, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0xf8, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x04, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
+  0x3e, 0x00, 0x03, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0xfd, 0x00, 0x01, 0x00, 0x38, 0x00, 0x01, 0x00
+};
+const unsigned int cube_frag_spv_len = 380;

+ 724 - 0
test/testgpu_spinning_cube.c

@@ -0,0 +1,724 @@
+/*
+  Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely.
+*/
+
+#include <stdlib.h>
+
+#ifdef __EMSCRIPTEN__
+#include <emscripten/emscripten.h>
+#endif
+
+#include <SDL3/SDL_test_common.h>
+#include <SDL3/SDL_gpu.h>
+#include <SDL3/SDL_main.h>
+
+/* Regenerate the shaders with testgpu/build-shaders.sh */
+#include "testgpu/testgpu_spirv.h"
+#include "testgpu/testgpu_dxbc.h"
+#include "testgpu/testgpu_dxil.h"
+#include "testgpu/testgpu_metallib.h"
+
+#define TESTGPU_SUPPORTED_FORMATS (SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXBC | SDL_GPU_SHADERFORMAT_DXIL | SDL_GPU_SHADERFORMAT_METALLIB)
+
+#define CHECK_CREATE(var, thing) { if (!(var)) { SDL_Log("Failed to create %s: %s\n", thing, SDL_GetError()); quit(2); } }
+
+static Uint32 frames = 0;
+
+typedef struct RenderState
+{
+    SDL_GpuBuffer *buf_vertex;
+    SDL_GpuGraphicsPipeline *pipeline;
+    SDL_GpuSampleCount sample_count;
+} RenderState;
+
+typedef struct WindowState
+{
+    int angle_x, angle_y, angle_z;
+    SDL_GpuTexture *tex_depth, *tex_msaa;
+    Uint32 prev_drawablew, prev_drawableh;
+} WindowState;
+
+static SDL_GpuDevice *gpu_device = NULL;
+static RenderState render_state;
+static SDLTest_CommonState *state = NULL;
+static WindowState *window_states = NULL;
+
+static void shutdownGpu(void)
+{
+    if (window_states) {
+        int i;
+        for (i = 0; i < state->num_windows; i++) {
+            WindowState *winstate = &window_states[i];
+            SDL_ReleaseGpuTexture(gpu_device, winstate->tex_depth);
+            SDL_ReleaseGpuTexture(gpu_device, winstate->tex_msaa);
+            SDL_UnclaimGpuWindow(gpu_device, state->windows[i]);
+        }
+        SDL_free(window_states);
+        window_states = NULL;
+    }
+
+    SDL_ReleaseGpuBuffer(gpu_device, render_state.buf_vertex);
+    SDL_ReleaseGpuGraphicsPipeline(gpu_device, render_state.pipeline);
+    SDL_DestroyGpuDevice(gpu_device);
+
+    SDL_zero(render_state);
+    gpu_device = NULL;
+}
+
+
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void
+quit(int rc)
+{
+    shutdownGpu();
+    SDLTest_CommonQuit(state);
+    exit(rc);
+}
+
+/*
+ * Simulates desktop's glRotatef. The matrix is returned in column-major
+ * order.
+ */
+static void
+rotate_matrix(float angle, float x, float y, float z, float *r)
+{
+    float radians, c, s, c1, u[3], length;
+    int i, j;
+
+    radians = angle * SDL_PI_F / 180.0f;
+
+    c = SDL_cosf(radians);
+    s = SDL_sinf(radians);
+
+    c1 = 1.0f - SDL_cosf(radians);
+
+    length = (float)SDL_sqrt(x * x + y * y + z * z);
+
+    u[0] = x / length;
+    u[1] = y / length;
+    u[2] = z / length;
+
+    for (i = 0; i < 16; i++) {
+        r[i] = 0.0;
+    }
+
+    r[15] = 1.0;
+
+    for (i = 0; i < 3; i++) {
+        r[i * 4 + (i + 1) % 3] = u[(i + 2) % 3] * s;
+        r[i * 4 + (i + 2) % 3] = -u[(i + 1) % 3] * s;
+    }
+
+    for (i = 0; i < 3; i++) {
+        for (j = 0; j < 3; j++) {
+            r[i * 4 + j] += c1 * u[i] * u[j] + (i == j ? c : 0.0f);
+        }
+    }
+}
+
+/*
+ * Simulates gluPerspectiveMatrix
+ */
+static void
+perspective_matrix(float fovy, float aspect, float znear, float zfar, float *r)
+{
+    int i;
+    float f;
+
+    f = 1.0f/SDL_tanf(fovy * 0.5f);
+
+    for (i = 0; i < 16; i++) {
+        r[i] = 0.0;
+    }
+
+    r[0] = f / aspect;
+    r[5] = f;
+    r[10] = (znear + zfar) / (znear - zfar);
+    r[11] = -1.0f;
+    r[14] = (2.0f * znear * zfar) / (znear - zfar);
+    r[15] = 0.0f;
+}
+
+/*
+ * Multiplies lhs by rhs and writes out to r. All matrices are 4x4 and column
+ * major. In-place multiplication is supported.
+ */
+static void
+multiply_matrix(float *lhs, float *rhs, float *r)
+{
+    int i, j, k;
+    float tmp[16];
+
+    for (i = 0; i < 4; i++) {
+        for (j = 0; j < 4; j++) {
+            tmp[j * 4 + i] = 0.0;
+
+            for (k = 0; k < 4; k++) {
+                tmp[j * 4 + i] += lhs[k * 4 + i] * rhs[j * 4 + k];
+            }
+        }
+    }
+
+    for (i = 0; i < 16; i++) {
+        r[i] = tmp[i];
+    }
+}
+
+typedef struct VertexData
+{
+    float x, y, z; /* 3D data. Vertex range -0.5..0.5 in all axes. Z -0.5 is near, 0.5 is far. */
+    float red, green, blue;  /* intensity 0 to 1 (alpha is always 1). */
+} VertexData;
+
+static const VertexData vertex_data[] = {
+    /* Front face. */
+    /* Bottom left */
+    { -0.5,  0.5, -0.5, 1.0, 0.0, 0.0 }, /* red */
+    {  0.5, -0.5, -0.5, 0.0, 0.0, 1.0 }, /* blue */
+    { -0.5, -0.5, -0.5, 0.0, 1.0, 0.0 }, /* green */
+
+    /* Top right */
+    { -0.5, 0.5, -0.5, 1.0, 0.0, 0.0 }, /* red */
+    { 0.5,  0.5, -0.5, 1.0, 1.0, 0.0 }, /* yellow */
+    { 0.5, -0.5, -0.5, 0.0, 0.0, 1.0 }, /* blue */
+
+    /* Left face */
+    /* Bottom left */
+    { -0.5,  0.5,  0.5, 1.0, 1.0, 1.0 }, /* white */
+    { -0.5, -0.5, -0.5, 0.0, 1.0, 0.0 }, /* green */
+    { -0.5, -0.5,  0.5, 0.0, 1.0, 1.0 }, /* cyan */
+
+    /* Top right */
+    { -0.5,  0.5,  0.5, 1.0, 1.0, 1.0 }, /* white */
+    { -0.5,  0.5, -0.5, 1.0, 0.0, 0.0 }, /* red */
+    { -0.5, -0.5, -0.5, 0.0, 1.0, 0.0 }, /* green */
+
+    /* Top face */
+    /* Bottom left */
+    { -0.5, 0.5,  0.5, 1.0, 1.0, 1.0 }, /* white */
+    {  0.5, 0.5, -0.5, 1.0, 1.0, 0.0 }, /* yellow */
+    { -0.5, 0.5, -0.5, 1.0, 0.0, 0.0 }, /* red */
+
+    /* Top right */
+    { -0.5, 0.5,  0.5, 1.0, 1.0, 1.0 }, /* white */
+    {  0.5, 0.5,  0.5, 0.0, 0.0, 0.0 }, /* black */
+    {  0.5, 0.5, -0.5, 1.0, 1.0, 0.0 }, /* yellow */
+
+    /* Right face */
+    /* Bottom left */
+    { 0.5,  0.5, -0.5, 1.0, 1.0, 0.0 }, /* yellow */
+    { 0.5, -0.5,  0.5, 1.0, 0.0, 1.0 }, /* magenta */
+    { 0.5, -0.5, -0.5, 0.0, 0.0, 1.0 }, /* blue */
+
+    /* Top right */
+    { 0.5,  0.5, -0.5, 1.0, 1.0, 0.0 }, /* yellow */
+    { 0.5,  0.5,  0.5, 0.0, 0.0, 0.0 }, /* black */
+    { 0.5, -0.5,  0.5, 1.0, 0.0, 1.0 }, /* magenta */
+
+    /* Back face */
+    /* Bottom left */
+    {  0.5,  0.5, 0.5, 0.0, 0.0, 0.0 }, /* black */
+    { -0.5, -0.5, 0.5, 0.0, 1.0, 1.0 }, /* cyan */
+    {  0.5, -0.5, 0.5, 1.0, 0.0, 1.0 }, /* magenta */
+
+    /* Top right */
+    {  0.5,  0.5,  0.5, 0.0, 0.0, 0.0 }, /* black */
+    { -0.5,  0.5,  0.5, 1.0, 1.0, 1.0 }, /* white */
+    { -0.5, -0.5,  0.5, 0.0, 1.0, 1.0 }, /* cyan */
+
+    /* Bottom face */
+    /* Bottom left */
+    { -0.5, -0.5, -0.5, 0.0, 1.0, 0.0 }, /* green */
+    {  0.5, -0.5,  0.5, 1.0, 0.0, 1.0 }, /* magenta */
+    { -0.5, -0.5,  0.5, 0.0, 1.0, 1.0 }, /* cyan */
+
+    /* Top right */
+    { -0.5, -0.5, -0.5, 0.0, 1.0, 0.0 }, /* green */
+    {  0.5, -0.5, -0.5, 0.0, 0.0, 1.0 }, /* blue */
+    {  0.5, -0.5,  0.5, 1.0, 0.0, 1.0 } /* magenta */
+};
+
+static SDL_GpuTexture*
+CreateDepthTexture(Uint32 drawablew, Uint32 drawableh)
+{
+    SDL_GpuTextureCreateInfo depthtex_createinfo;
+    SDL_GpuTexture *result;
+
+    depthtex_createinfo.type = SDL_GPU_TEXTURETYPE_2D;
+    depthtex_createinfo.format = SDL_GPU_TEXTUREFORMAT_D16_UNORM;
+    depthtex_createinfo.width = drawablew;
+    depthtex_createinfo.height = drawableh;
+    depthtex_createinfo.layerCountOrDepth = 1;
+    depthtex_createinfo.levelCount = 1;
+    depthtex_createinfo.sampleCount = render_state.sample_count;
+    depthtex_createinfo.usageFlags = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET_BIT;
+    depthtex_createinfo.props = 0;
+
+    result = SDL_CreateGpuTexture(gpu_device, &depthtex_createinfo);
+    CHECK_CREATE(result, "Depth Texture")
+
+    return result;
+}
+
+static SDL_GpuTexture*
+CreateMSAATexture(Uint32 drawablew, Uint32 drawableh)
+{
+    SDL_GpuTextureCreateInfo msaatex_createinfo;
+    SDL_GpuTexture *result;
+
+    if (render_state.sample_count == SDL_GPU_SAMPLECOUNT_1) {
+        return NULL;
+    }
+
+    msaatex_createinfo.type = SDL_GPU_TEXTURETYPE_2D;
+    msaatex_createinfo.format = SDL_GetGpuSwapchainTextureFormat(gpu_device, state->windows[0]);
+    msaatex_createinfo.width = drawablew;
+    msaatex_createinfo.height = drawableh;
+    msaatex_createinfo.layerCountOrDepth = 1;
+    msaatex_createinfo.levelCount = 1;
+    msaatex_createinfo.sampleCount = render_state.sample_count;
+    msaatex_createinfo.usageFlags = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET_BIT | SDL_GPU_TEXTUREUSAGE_SAMPLER_BIT;
+    msaatex_createinfo.props = 0;
+
+    result = SDL_CreateGpuTexture(gpu_device, &msaatex_createinfo);
+    CHECK_CREATE(result, "MSAA Texture")
+
+    return result;
+}
+
+static void
+Render(SDL_Window *window, const int windownum)
+{
+    WindowState *winstate = &window_states[windownum];
+    SDL_GpuTexture *swapchain;
+    SDL_GpuColorAttachmentInfo color_attachment;
+    SDL_GpuDepthStencilAttachmentInfo depth_attachment;
+    float matrix_rotate[16], matrix_modelview[16], matrix_perspective[16], matrix_final[16];
+    Uint32 drawablew, drawableh;
+    SDL_GpuCommandBuffer *cmd;
+    SDL_GpuRenderPass *pass;
+    SDL_GpuBufferBinding vertex_binding;
+    SDL_GpuBlitRegion src_region;
+    SDL_GpuBlitRegion dst_region;
+
+    /* Acquire the swapchain texture */
+
+    cmd = SDL_AcquireGpuCommandBuffer(gpu_device);
+    swapchain = SDL_AcquireGpuSwapchainTexture(cmd, state->windows[windownum], &drawablew, &drawableh);
+
+    if (!swapchain) {
+        /* No swapchain was acquired, probably too many frames in flight */
+        SDL_SubmitGpu(cmd);
+        return;
+    }
+
+    /*
+    * Do some rotation with Euler angles. It is not a fixed axis as
+    * quaterions would be, but the effect is cool.
+    */
+    rotate_matrix((float)winstate->angle_x, 1.0f, 0.0f, 0.0f, matrix_modelview);
+    rotate_matrix((float)winstate->angle_y, 0.0f, 1.0f, 0.0f, matrix_rotate);
+
+    multiply_matrix(matrix_rotate, matrix_modelview, matrix_modelview);
+
+    rotate_matrix((float)winstate->angle_z, 0.0f, 1.0f, 0.0f, matrix_rotate);
+
+    multiply_matrix(matrix_rotate, matrix_modelview, matrix_modelview);
+
+    /* Pull the camera back from the cube */
+    matrix_modelview[14] -= 2.5f;
+
+    perspective_matrix(45.0f, (float)drawablew/drawableh, 0.01f, 100.0f, matrix_perspective);
+    multiply_matrix(matrix_perspective, matrix_modelview, (float*) &matrix_final);
+
+    winstate->angle_x += 3;
+    winstate->angle_y += 2;
+    winstate->angle_z += 1;
+
+    if(winstate->angle_x >= 360) winstate->angle_x -= 360;
+    if(winstate->angle_x < 0) winstate->angle_x += 360;
+    if(winstate->angle_y >= 360) winstate->angle_y -= 360;
+    if(winstate->angle_y < 0) winstate->angle_y += 360;
+    if(winstate->angle_z >= 360) winstate->angle_z -= 360;
+    if(winstate->angle_z < 0) winstate->angle_z += 360;
+
+    /* Resize the depth buffer if the window size changed */
+
+    if (winstate->prev_drawablew != drawablew || winstate->prev_drawableh != drawableh) {
+        SDL_ReleaseGpuTexture(gpu_device, winstate->tex_depth);
+        SDL_ReleaseGpuTexture(gpu_device, winstate->tex_msaa);
+        winstate->tex_depth = CreateDepthTexture(drawablew, drawableh);
+        winstate->tex_msaa = CreateMSAATexture(drawablew, drawableh);
+    }
+    winstate->prev_drawablew = drawablew;
+    winstate->prev_drawableh = drawableh;
+
+    /* Set up the pass */
+
+    SDL_zero(color_attachment);
+    color_attachment.clearColor.a = 1.0f;
+    color_attachment.loadOp = SDL_GPU_LOADOP_CLEAR;
+    color_attachment.storeOp = SDL_GPU_STOREOP_STORE;
+    color_attachment.texture = winstate->tex_msaa ? winstate->tex_msaa : swapchain;
+
+    SDL_zero(depth_attachment);
+    depth_attachment.depthStencilClearValue.depth = 1.0f;
+    depth_attachment.loadOp = SDL_GPU_LOADOP_CLEAR;
+    depth_attachment.storeOp = SDL_GPU_STOREOP_DONT_CARE;
+    depth_attachment.texture = winstate->tex_depth;
+    depth_attachment.cycle = SDL_TRUE;
+
+    /* Set up the bindings */
+
+    vertex_binding.buffer = render_state.buf_vertex;
+    vertex_binding.offset = 0;
+
+    /* Draw the cube! */
+
+    SDL_PushGpuVertexUniformData(cmd, 0, matrix_final, sizeof(matrix_final));
+
+    pass = SDL_BeginGpuRenderPass(cmd, &color_attachment, 1, &depth_attachment);
+    SDL_BindGpuGraphicsPipeline(pass, render_state.pipeline);
+    SDL_BindGpuVertexBuffers(pass, 0, &vertex_binding, 1);
+    SDL_DrawGpuPrimitives(pass, 36, 1, 0, 0);
+    SDL_EndGpuRenderPass(pass);
+
+    /* Blit MSAA to swapchain, if needed */
+    if (render_state.sample_count > SDL_GPU_SAMPLECOUNT_1) {
+        SDL_zero(src_region);
+        src_region.texture = winstate->tex_msaa;
+        src_region.w = drawablew;
+        src_region.h = drawableh;
+
+        dst_region = src_region;
+        dst_region.texture = swapchain;
+
+        SDL_BlitGpu(cmd, &src_region, &dst_region, SDL_FLIP_NONE, SDL_GPU_FILTER_LINEAR, SDL_FALSE);
+    }
+
+    /* Submit the command buffer! */
+    SDL_SubmitGpu(cmd);
+
+    ++frames;
+}
+
+static SDL_GpuShader*
+load_shader(SDL_bool is_vertex)
+{
+    SDL_GpuShaderCreateInfo createinfo;
+    createinfo.samplerCount = 0;
+    createinfo.storageBufferCount = 0;
+    createinfo.storageTextureCount = 0;
+    createinfo.uniformBufferCount = is_vertex ? 1 : 0;
+    createinfo.props = 0;
+
+    SDL_GpuDriver backend = SDL_GetGpuDriver(gpu_device);
+    if (backend == SDL_GPU_DRIVER_D3D11) {
+        createinfo.format = SDL_GPU_SHADERFORMAT_DXBC;
+        createinfo.code = is_vertex ? D3D11_CubeVert : D3D11_CubeFrag;
+        createinfo.codeSize = is_vertex ? SDL_arraysize(D3D11_CubeVert) : SDL_arraysize(D3D11_CubeFrag);
+        createinfo.entryPointName = is_vertex ? "VSMain" : "PSMain";
+    } else if (backend == SDL_GPU_DRIVER_D3D12) {
+        createinfo.format = SDL_GPU_SHADERFORMAT_DXIL;
+        createinfo.code = is_vertex ? D3D12_CubeVert : D3D12_CubeFrag;
+        createinfo.codeSize = is_vertex ? SDL_arraysize(D3D12_CubeVert) : SDL_arraysize(D3D12_CubeFrag);
+        createinfo.entryPointName = is_vertex ? "VSMain" : "PSMain";
+    } else if (backend == SDL_GPU_DRIVER_METAL) {
+        createinfo.format = SDL_GPU_SHADERFORMAT_METALLIB;
+        createinfo.code = is_vertex ? cube_vert_metallib : cube_frag_metallib;
+        createinfo.codeSize = is_vertex ? cube_vert_metallib_len : cube_frag_metallib_len;
+        createinfo.entryPointName = is_vertex ? "vs_main" : "fs_main";
+    } else {
+        createinfo.format = SDL_GPU_SHADERFORMAT_SPIRV;
+        createinfo.code = is_vertex ? cube_vert_spv : cube_frag_spv;
+        createinfo.codeSize = is_vertex ? cube_vert_spv_len : cube_frag_spv_len;
+        createinfo.entryPointName = "main";
+    }
+
+    createinfo.stage = is_vertex ? SDL_GPU_SHADERSTAGE_VERTEX : SDL_GPU_SHADERSTAGE_FRAGMENT;
+    return SDL_CreateGpuShader(gpu_device, &createinfo);
+}
+
+static void
+init_render_state(int msaa)
+{
+    SDL_GpuCommandBuffer *cmd;
+    SDL_GpuTransferBuffer *buf_transfer;
+    void *map;
+    SDL_GpuTransferBufferLocation buf_location;
+    SDL_GpuBufferRegion dst_region;
+    SDL_GpuCopyPass *copy_pass;
+    SDL_GpuBufferCreateInfo buffer_desc;
+    SDL_GpuTransferBufferCreateInfo transfer_buffer_desc;
+    SDL_GpuGraphicsPipelineCreateInfo pipelinedesc;
+    SDL_GpuColorAttachmentDescription color_attachment_desc;
+    Uint32 drawablew, drawableh;
+    SDL_GpuVertexAttribute vertex_attributes[2];
+    SDL_GpuVertexBinding vertex_binding;
+    SDL_GpuShader *vertex_shader;
+    SDL_GpuShader *fragment_shader;
+    int i;
+
+    gpu_device = SDL_CreateGpuDevice(
+        TESTGPU_SUPPORTED_FORMATS,
+        1,
+        0,
+        NULL
+    );
+    CHECK_CREATE(gpu_device, "GPU device");
+
+    /* Claim the windows */
+
+    for (i = 0; i < state->num_windows; i++) {
+        SDL_ClaimGpuWindow(
+            gpu_device,
+            state->windows[i]
+        );
+    }
+
+    /* Create shaders */
+
+    vertex_shader = load_shader(SDL_TRUE);
+    CHECK_CREATE(vertex_shader, "Vertex Shader")
+    fragment_shader = load_shader(SDL_FALSE);
+    CHECK_CREATE(fragment_shader, "Fragment Shader")
+
+    /* Create buffers */
+
+    buffer_desc.usageFlags = SDL_GPU_BUFFERUSAGE_VERTEX_BIT;
+    buffer_desc.sizeInBytes = sizeof(vertex_data);
+    buffer_desc.props = 0;
+    render_state.buf_vertex = SDL_CreateGpuBuffer(
+        gpu_device,
+        &buffer_desc
+    );
+    CHECK_CREATE(render_state.buf_vertex, "Static vertex buffer")
+
+    SDL_SetGpuBufferName(gpu_device, render_state.buf_vertex, "космонавт");
+
+    transfer_buffer_desc.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
+    transfer_buffer_desc.sizeInBytes = sizeof(vertex_data);
+    transfer_buffer_desc.props = 0;
+    buf_transfer = SDL_CreateGpuTransferBuffer(
+        gpu_device,
+        &transfer_buffer_desc
+    );
+    CHECK_CREATE(buf_transfer, "Vertex transfer buffer")
+
+    /* We just need to upload the static data once. */
+    map = SDL_MapGpuTransferBuffer(gpu_device, buf_transfer, SDL_FALSE);
+    SDL_memcpy(map, vertex_data, sizeof(vertex_data));
+    SDL_UnmapGpuTransferBuffer(gpu_device, buf_transfer);
+
+    cmd = SDL_AcquireGpuCommandBuffer(gpu_device);
+    copy_pass = SDL_BeginGpuCopyPass(cmd);
+    buf_location.transferBuffer = buf_transfer;
+    buf_location.offset = 0;
+    dst_region.buffer = render_state.buf_vertex;
+    dst_region.offset = 0;
+    dst_region.size = sizeof(vertex_data);
+    SDL_UploadToGpuBuffer(copy_pass, &buf_location, &dst_region, SDL_FALSE);
+    SDL_EndGpuCopyPass(copy_pass);
+    SDL_SubmitGpu(cmd);
+
+    SDL_ReleaseGpuTransferBuffer(gpu_device, buf_transfer);
+
+    /* Determine which sample count to use */
+    render_state.sample_count = SDL_GPU_SAMPLECOUNT_1;
+    if (msaa && SDL_SupportsGpuSampleCount(
+        gpu_device,
+        SDL_GetGpuSwapchainTextureFormat(gpu_device, state->windows[0]),
+        SDL_GPU_SAMPLECOUNT_4)) {
+        render_state.sample_count = SDL_GPU_SAMPLECOUNT_4;
+    }
+
+    /* Set up the graphics pipeline */
+
+    SDL_zero(pipelinedesc);
+
+    color_attachment_desc.format = SDL_GetGpuSwapchainTextureFormat(gpu_device, state->windows[0]);
+
+    color_attachment_desc.blendState.blendEnable = 0;
+    color_attachment_desc.blendState.alphaBlendOp = SDL_GPU_BLENDOP_ADD;
+    color_attachment_desc.blendState.colorBlendOp = SDL_GPU_BLENDOP_ADD;
+    color_attachment_desc.blendState.colorWriteMask = 0xF;
+    color_attachment_desc.blendState.srcAlphaBlendFactor = SDL_GPU_BLENDFACTOR_ONE;
+    color_attachment_desc.blendState.dstAlphaBlendFactor = SDL_GPU_BLENDFACTOR_ZERO;
+    color_attachment_desc.blendState.srcColorBlendFactor = SDL_GPU_BLENDFACTOR_ONE;
+    color_attachment_desc.blendState.dstColorBlendFactor = SDL_GPU_BLENDFACTOR_ZERO;
+
+    pipelinedesc.attachmentInfo.colorAttachmentCount = 1;
+    pipelinedesc.attachmentInfo.colorAttachmentDescriptions = &color_attachment_desc;
+    pipelinedesc.attachmentInfo.depthStencilFormat = SDL_GPU_TEXTUREFORMAT_D16_UNORM;
+    pipelinedesc.attachmentInfo.hasDepthStencilAttachment = SDL_TRUE;
+
+    pipelinedesc.depthStencilState.depthTestEnable = 1;
+    pipelinedesc.depthStencilState.depthWriteEnable = 1;
+    pipelinedesc.depthStencilState.compareOp = SDL_GPU_COMPAREOP_LESS_OR_EQUAL;
+
+    pipelinedesc.multisampleState.sampleCount = render_state.sample_count;
+    pipelinedesc.multisampleState.sampleMask = 0xF;
+
+    pipelinedesc.primitiveType = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST;
+
+    pipelinedesc.vertexShader = vertex_shader;
+    pipelinedesc.fragmentShader = fragment_shader;
+
+    vertex_binding.binding = 0;
+    vertex_binding.inputRate = SDL_GPU_VERTEXINPUTRATE_VERTEX;
+    vertex_binding.instanceStepRate = 0;
+    vertex_binding.stride = sizeof(VertexData);
+
+    vertex_attributes[0].binding = 0;
+    vertex_attributes[0].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3;
+    vertex_attributes[0].location = 0;
+    vertex_attributes[0].offset = 0;
+
+    vertex_attributes[1].binding = 0;
+    vertex_attributes[1].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3;
+    vertex_attributes[1].location = 1;
+    vertex_attributes[1].offset = sizeof(float) * 3;
+
+    pipelinedesc.vertexInputState.vertexBindingCount = 1;
+    pipelinedesc.vertexInputState.vertexBindings = &vertex_binding;
+    pipelinedesc.vertexInputState.vertexAttributeCount = 2;
+    pipelinedesc.vertexInputState.vertexAttributes = (SDL_GpuVertexAttribute*) &vertex_attributes;
+
+    pipelinedesc.props = 0;
+
+    render_state.pipeline = SDL_CreateGpuGraphicsPipeline(gpu_device, &pipelinedesc);
+    CHECK_CREATE(render_state.pipeline, "Render Pipeline")
+
+    /* These are reference-counted; once the pipeline is created, you don't need to keep these. */
+    SDL_ReleaseGpuShader(gpu_device, vertex_shader);
+    SDL_ReleaseGpuShader(gpu_device, fragment_shader);
+
+    /* Set up per-window state */
+
+    window_states = (WindowState *) SDL_calloc(state->num_windows, sizeof (WindowState));
+    if (!window_states) {
+        SDL_Log("Out of memory!\n");
+        quit(2);
+    }
+
+    for (i = 0; i < state->num_windows; i++) {
+        WindowState *winstate = &window_states[i];
+
+        /* create a depth texture for the window */
+        SDL_GetWindowSizeInPixels(state->windows[i], (int*) &drawablew, (int*) &drawableh);
+        winstate->tex_depth = CreateDepthTexture(drawablew, drawableh);
+        winstate->tex_msaa = CreateMSAATexture(drawablew, drawableh);
+
+        /* make each window different */
+        winstate->angle_x = (i * 10) % 360;
+        winstate->angle_y = (i * 20) % 360;
+        winstate->angle_z = (i * 30) % 360;
+    }
+}
+
+static int done = 0;
+
+void loop()
+{
+    SDL_Event event;
+    int i;
+
+    /* Check for events */
+    while (SDL_PollEvent(&event) && !done) {
+        SDLTest_CommonEvent(state, &event, &done);
+    }
+    if (!done) {
+        for (i = 0; i < state->num_windows; ++i) {
+            Render(state->windows[i], i);
+        }
+    }
+#ifdef __EMSCRIPTEN__
+    else {
+        emscripten_cancel_main_loop();
+    }
+#endif
+}
+
+int
+main(int argc, char *argv[])
+{
+    int msaa;
+    int i;
+    const SDL_DisplayMode *mode;
+    Uint64 then, now;
+
+    /* Initialize params */
+    msaa = 0;
+
+    /* Initialize test framework */
+    state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
+    if (!state) {
+        return 1;
+    }
+    for (i = 1; i < argc;) {
+        int consumed;
+
+        consumed = SDLTest_CommonArg(state, i);
+        if (consumed == 0) {
+            if (SDL_strcasecmp(argv[i], "--msaa") == 0) {
+                ++msaa;
+                consumed = 1;
+            } else {
+                consumed = -1;
+            }
+        }
+        if (consumed < 0) {
+            static const char *options[] = { "[--msaa]", NULL };
+            SDLTest_CommonLogUsage(state, argv[0], options);
+            quit(1);
+        }
+        i += consumed;
+    }
+
+    state->skip_renderer = 1;
+    state->window_flags |= SDL_WINDOW_RESIZABLE;
+
+    if (!SDLTest_CommonInit(state)) {
+        quit(2);
+        return 0;
+    }
+
+    mode = SDL_GetCurrentDisplayMode(SDL_GetDisplayForWindow(state->windows[0]));
+    SDL_Log("Screen bpp: %d\n", SDL_BITSPERPIXEL(mode->format));
+
+    init_render_state(msaa);
+
+    /* Main render loop */
+    frames = 0;
+    then = SDL_GetTicks();
+    done = 0;
+
+#ifdef __EMSCRIPTEN__
+    emscripten_set_main_loop(loop, 0, 1);
+#else
+    while (!done) {
+        loop();
+    }
+#endif
+
+    /* Print out some timing information */
+    now = SDL_GetTicks();
+    if (now > then) {
+        SDL_Log("%2.2f frames per second\n",
+               ((double) frames * 1000) / (now - then));
+    }
+#if !defined(__ANDROID__)
+    quit(0);
+#endif
+    return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */