diff --git a/.gitignore b/.gitignore
index 5326a62c39..3c45e91b75 100644
--- a/.gitignore
+++ b/.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
diff --git a/Android.mk b/Android.mk
index c26fc6721f..31bc23bc42 100644
--- a/Android.mk
+++ b/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) \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 414904b4a1..d69831ae64 100644
--- a/CMakeLists.txt
+++ b/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
diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj
index 1ac0e2ec30..fa470003ce 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj
+++ b/VisualC-GDK/SDL/SDL.vcxproj
@@ -166,6 +166,7 @@
$(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir)
+ $(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir)
Building shader blobs (Xbox Series)
@@ -200,6 +201,7 @@
$(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) one
+ $(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir) one
Building shader blobs (Xbox One)
@@ -266,6 +268,7 @@
$(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir)
+ $(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir)
Building shader blobs (Xbox Series)
@@ -301,6 +304,7 @@
$(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) one
+ $(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir) one
Building shader blobs (Xbox One)
@@ -330,6 +334,7 @@
+
@@ -424,6 +429,7 @@
+
@@ -865,6 +871,15 @@
+
+
+
+ CompileAsCpp
+ CompileAsCpp
+ CompileAsCpp
+ CompileAsCpp
+
+
diff --git a/VisualC-GDK/SDL/SDL.vcxproj.filters b/VisualC-GDK/SDL/SDL.vcxproj.filters
index fbd091f590..61caf6d249 100644
--- a/VisualC-GDK/SDL/SDL.vcxproj.filters
+++ b/VisualC-GDK/SDL/SDL.vcxproj.filters
@@ -57,6 +57,10 @@
+
+
+
+
@@ -249,6 +253,7 @@
+
@@ -341,6 +346,7 @@
filesystem
+
diff --git a/VisualC-WinRT/SDL-UWP.vcxproj b/VisualC-WinRT/SDL-UWP.vcxproj
index 1c7b029a1d..a714771500 100644
--- a/VisualC-WinRT/SDL-UWP.vcxproj
+++ b/VisualC-WinRT/SDL-UWP.vcxproj
@@ -125,6 +125,7 @@
+
@@ -343,6 +344,9 @@
+
+
+
diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj
index 657afb9f2e..e1cbf90bf5 100644
--- a/VisualC/SDL/SDL.vcxproj
+++ b/VisualC/SDL/SDL.vcxproj
@@ -254,6 +254,7 @@
+
@@ -348,6 +349,8 @@
+
+
@@ -408,6 +411,10 @@
+
+
+
+
diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters
index 57b5a527a7..f7794e8566 100644
--- a/VisualC/SDL/SDL.vcxproj.filters
+++ b/VisualC/SDL/SDL.vcxproj.filters
@@ -198,6 +198,8 @@
{0000d7fda065b13b0ca4ab262c380000}
+
+ {098fbef9-d8a0-4b3b-b57b-d157d395335d}
{00008dfdfa0190856fbf3c7db52d0000}
@@ -907,6 +909,14 @@
video\offscreen
+
+ API Headers
+
+
+ gpu
+
+
+ gpu
@@ -1562,6 +1572,18 @@
video\offscreen
+
+ gpu
+
+
+ gpu
+
+
+ gpu
+
+
+ gpu
+
diff --git a/include/SDL3/SDL.h b/include/SDL3/SDL.h
index 4e18f63822..c9633941dc 100644
--- a/include/SDL3/SDL.h
+++ b/include/SDL3/SDL.h
@@ -43,6 +43,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/include/SDL3/SDL_gpu.h b/include/SDL3/SDL_gpu.h
new file mode 100644
index 0000000000..3ac74d63ca
--- /dev/null
+++ b/include/SDL3/SDL_gpu.h
@@ -0,0 +1,2512 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2024 Sam Lantinga
+
+ 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
+
+#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 */
diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h
index d7bc37a041..bb83d6d2ed 100644
--- a/include/SDL3/SDL_hints.h
+++ b/include/SDL3/SDL_hints.h
@@ -39,8 +39,8 @@
#ifndef SDL_hints_h_
#define SDL_hints_h_
-#include
#include
+#include
#include
/* 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.
diff --git a/include/SDL3/SDL_log.h b/include/SDL3/SDL_log.h
index 3c0e80f38c..deda238c50 100644
--- a/include/SDL3/SDL_log.h
+++ b/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,
diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake
index dceb68cd43..7300f777f8 100644
--- a/include/build_config/SDL_build_config.h.cmake
+++ b/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@
diff --git a/include/build_config/SDL_build_config_android.h b/include/build_config/SDL_build_config_android.h
index d6ae49abc5..ddb1585479 100644
--- a/include/build_config/SDL_build_config_android.h
+++ b/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
diff --git a/include/build_config/SDL_build_config_macos.h b/include/build_config/SDL_build_config_macos.h
index 874b4d3be8..cf6229e130 100644
--- a/include/build_config/SDL_build_config_macos.h
+++ b/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
diff --git a/include/build_config/SDL_build_config_windows.h b/include/build_config/SDL_build_config_windows.h
index 669d4e6810..0a7a1b37dc 100644
--- a/include/build_config/SDL_build_config_windows.h
+++ b/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
diff --git a/include/build_config/SDL_build_config_wingdk.h b/include/build_config/SDL_build_config_wingdk.h
index 3fd847c9d1..49eb65c890 100644
--- a/include/build_config/SDL_build_config_wingdk.h
+++ b/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
diff --git a/include/build_config/SDL_build_config_xbox.h b/include/build_config/SDL_build_config_xbox.h
index 3ad30290dd..750667142e 100644
--- a/include/build_config/SDL_build_config_xbox.h
+++ b/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
diff --git a/src/SDL_log.c b/src/SDL_log.c
index c4be4483f9..837a70f1c6 100644
--- a/src/SDL_log.c
+++ b/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;
diff --git a/src/core/SDL_core_unsupported.c b/src/core/SDL_core_unsupported.c
index 3f39e54c7b..e2753c1a10 100644
--- a/src/core/SDL_core_unsupported.c
+++ b/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))
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index f5d6cb3032..513f314a6b 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/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: *;
};
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 7d6259dc8c..d5d1a73716 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/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
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index acfdeffad7..c44278d63c 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/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),)
diff --git a/src/gpu/SDL_gpu.c b/src/gpu/SDL_gpu.c
new file mode 100644
index 0000000000..0bb35c193c
--- /dev/null
+++ b/src/gpu/SDL_gpu.c
@@ -0,0 +1,2400 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2024 Sam Lantinga
+
+ 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);
+}
diff --git a/src/gpu/SDL_sysgpu.h b/src/gpu/SDL_sysgpu.h
new file mode 100644
index 0000000000..e317447120
--- /dev/null
+++ b/src/gpu/SDL_sysgpu.h
@@ -0,0 +1,779 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2024 Sam Lantinga
+
+ 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
diff --git a/src/gpu/d3d11/D3D11_Blit.h b/src/gpu/d3d11/D3D11_Blit.h
new file mode 100644
index 0000000000..2394dccf48
--- /dev/null
+++ b/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
+};
diff --git a/src/gpu/d3d11/SDL_gpu_d3d11.c b/src/gpu/d3d11/SDL_gpu_d3d11.c
new file mode 100644
index 0000000000..8d01331f1b
--- /dev/null
+++ b/src/gpu/d3d11/SDL_gpu_d3d11.c
@@ -0,0 +1,6135 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2024 Sam Lantinga
+
+ 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
+#include
+#include
+#include
+#include
+
+#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
diff --git a/src/gpu/d3d11/compile_shaders.bat b/src/gpu/d3d11/compile_shaders.bat
new file mode 100644
index 0000000000..4880b85f7a
--- /dev/null
+++ b/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
\ No newline at end of file
diff --git a/src/gpu/d3d12/D3D12_Blit.h b/src/gpu/d3d12/D3D12_Blit.h
new file mode 100644
index 0000000000..e83c957b93
--- /dev/null
+++ b/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 >" = type { <4 x float>, %"class.Texture2D >::mips_type" }
+%"class.Texture2D >::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 >"* 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 >" = type { <4 x float>, %"class.Texture2DArray >::mips_type" }
+%"class.Texture2DArray >::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 >"* 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 >" = type { <4 x float>, %"class.Texture3D >::mips_type" }
+%"class.Texture3D >::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 >"* 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 >" = 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
+ ]
+
+;