From 2e7d5bb429b5fa9ad9c15e69ca7d952827420a52 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Mon, 18 Mar 2024 11:43:23 -0700 Subject: [PATCH] Add the SDL_GPU API Project Lead: Evan Hemsley Co-designer, Metal Port, Console Ports: Co-authored-by: Caleb Cornett Production, QA, Debug: Co-authored-by: Ethan Lee SDL_Render Driver, Bugfixes: Co-authored-by: Andrei Alexeyev Additional D3D12 Programming, Bugfixes: Co-authored-by: Bart van der Werf Bugfixes and Feedback: Co-authored-by: Zakary Strange Co-authored-by: meyraud705 Co-authored-by: Joshua T. Fisher Co-authored-by: Topi Ritala Co-authored-by: David Gow Original API Proposal: Co-authored-by: Ryan C. Gordon --- .gitignore | 2 + Android.mk | 2 + CMakeLists.txt | 39 + VisualC-GDK/SDL/SDL.vcxproj | 15 + VisualC-GDK/SDL/SDL.vcxproj.filters | 6 + VisualC-WinRT/SDL-UWP.vcxproj | 4 + VisualC/SDL/SDL.vcxproj | 7 + VisualC/SDL/SDL.vcxproj.filters | 22 + include/SDL3/SDL.h | 1 + include/SDL3/SDL_gpu.h | 2512 ++++ include/SDL3/SDL_hints.h | 163 +- include/SDL3/SDL_log.h | 7 +- include/build_config/SDL_build_config.h.cmake | 7 + .../build_config/SDL_build_config_android.h | 2 + include/build_config/SDL_build_config_macos.h | 4 + .../build_config/SDL_build_config_windows.h | 6 + .../build_config/SDL_build_config_wingdk.h | 6 + include/build_config/SDL_build_config_xbox.h | 4 + src/SDL_log.c | 2 + src/core/SDL_core_unsupported.c | 10 + src/dynapi/SDL_dynapi.sym | 81 + src/dynapi/SDL_dynapi_overrides.h | 81 + src/dynapi/SDL_dynapi_procs.h | 81 + src/gpu/SDL_gpu.c | 2400 ++++ src/gpu/SDL_sysgpu.h | 779 + src/gpu/d3d11/D3D11_Blit.h | 1328 ++ src/gpu/d3d11/SDL_gpu_d3d11.c | 6135 ++++++++ src/gpu/d3d11/compile_shaders.bat | 7 + src/gpu/d3d12/D3D12_Blit.h | 2665 ++++ src/gpu/d3d12/SDL_gpu_d3d12.c | 8255 +++++++++++ src/gpu/d3d12/compile_shaders.bat | 17 + src/gpu/d3d12/compile_shaders_xbox.bat | 13 + src/gpu/d3dcommon/D3D_Blit.hlsl | 91 + src/gpu/metal/Metal_Blit.h | 7969 +++++++++++ src/gpu/metal/Metal_Blit.metal | 85 + src/gpu/metal/SDL_gpu_metal.m | 3984 ++++++ src/gpu/metal/compile_shaders.sh | 68 + src/gpu/vulkan/SDL_gpu_vulkan.c | 11797 ++++++++++++++++ src/gpu/vulkan/SDL_gpu_vulkan_vkfuncs.h | 176 + src/render/SDL_d3dmath.h | 2 +- src/render/SDL_render.c | 5 +- src/render/SDL_sysrender.h | 1 + src/render/sdlgpu/SDL_gpu_util.h | 74 + src/render/sdlgpu/SDL_pipeline_gpu.c | 223 + src/render/sdlgpu/SDL_pipeline_gpu.h | 49 + src/render/sdlgpu/SDL_render_gpu.c | 1303 ++ src/render/sdlgpu/SDL_shaders_gpu.c | 241 + src/render/sdlgpu/SDL_shaders_gpu.h | 63 + src/render/sdlgpu/shaders/.gitattributes | 1 + src/render/sdlgpu/shaders/.gitignore | 3 + src/render/sdlgpu/shaders/build-shaders.sh | 85 + src/render/sdlgpu/shaders/color.frag | 9 + src/render/sdlgpu/shaders/color.frag.metal.h | 28 + .../sdlgpu/shaders/color.frag.sm50.dxbc.h | 85 + .../sdlgpu/shaders/color.frag.sm60.dxil.h | 340 + src/render/sdlgpu/shaders/color.frag.spv.h | 29 + src/render/sdlgpu/shaders/dxbc50.h | 6 + src/render/sdlgpu/shaders/dxil60.h | 6 + src/render/sdlgpu/shaders/linepoint.vert | 17 + .../sdlgpu/shaders/linepoint.vert.metal.h | 51 + .../sdlgpu/shaders/linepoint.vert.sm50.dxbc.h | 172 + .../sdlgpu/shaders/linepoint.vert.sm60.dxil.h | 496 + .../sdlgpu/shaders/linepoint.vert.spv.h | 93 + src/render/sdlgpu/shaders/metal.h | 6 + src/render/sdlgpu/shaders/spir-v.h | 6 + src/render/sdlgpu/shaders/texture_rgb.frag | 12 + .../sdlgpu/shaders/texture_rgb.frag.metal.h | 41 + .../shaders/texture_rgb.frag.sm50.dxbc.h | 123 + .../shaders/texture_rgb.frag.sm60.dxil.h | 465 + .../sdlgpu/shaders/texture_rgb.frag.spv.h | 59 + src/render/sdlgpu/shaders/texture_rgba.frag | 12 + .../sdlgpu/shaders/texture_rgba.frag.metal.h | 40 + .../shaders/texture_rgba.frag.sm50.dxbc.h | 120 + .../shaders/texture_rgba.frag.sm60.dxil.h | 467 + .../sdlgpu/shaders/texture_rgba.frag.spv.h | 50 + src/render/sdlgpu/shaders/tri_color.vert | 17 + .../sdlgpu/shaders/tri_color.vert.metal.h | 48 + .../sdlgpu/shaders/tri_color.vert.sm50.dxbc.h | 178 + .../sdlgpu/shaders/tri_color.vert.sm60.dxil.h | 515 + .../sdlgpu/shaders/tri_color.vert.spv.h | 89 + src/render/sdlgpu/shaders/tri_texture.vert | 20 + .../sdlgpu/shaders/tri_texture.vert.metal.h | 56 + .../shaders/tri_texture.vert.sm50.dxbc.h | 195 + .../shaders/tri_texture.vert.sm60.dxil.h | 558 + .../sdlgpu/shaders/tri_texture.vert.spv.h | 106 + src/video/directx/SDL_d3d12.h | 11 + test/CMakeLists.txt | 1 + test/testgpu/build-shaders.sh | 103 + test/testgpu/cube.glsl | 31 + test/testgpu/cube.hlsl | 35 + test/testgpu/cube.metal | 38 + test/testgpu/testgpu_dxbc.h | 333 + test/testgpu/testgpu_dxil.h | 876 ++ test/testgpu/testgpu_metallib.h | 2584 ++++ test/testgpu/testgpu_spirv.h | 150 + test/testgpu_spinning_cube.c | 724 + 96 files changed, 60218 insertions(+), 66 deletions(-) create mode 100644 include/SDL3/SDL_gpu.h create mode 100644 src/gpu/SDL_gpu.c create mode 100644 src/gpu/SDL_sysgpu.h create mode 100644 src/gpu/d3d11/D3D11_Blit.h create mode 100644 src/gpu/d3d11/SDL_gpu_d3d11.c create mode 100644 src/gpu/d3d11/compile_shaders.bat create mode 100644 src/gpu/d3d12/D3D12_Blit.h create mode 100644 src/gpu/d3d12/SDL_gpu_d3d12.c create mode 100644 src/gpu/d3d12/compile_shaders.bat create mode 100644 src/gpu/d3d12/compile_shaders_xbox.bat create mode 100644 src/gpu/d3dcommon/D3D_Blit.hlsl create mode 100644 src/gpu/metal/Metal_Blit.h create mode 100644 src/gpu/metal/Metal_Blit.metal create mode 100644 src/gpu/metal/SDL_gpu_metal.m create mode 100755 src/gpu/metal/compile_shaders.sh create mode 100644 src/gpu/vulkan/SDL_gpu_vulkan.c create mode 100644 src/gpu/vulkan/SDL_gpu_vulkan_vkfuncs.h create mode 100644 src/render/sdlgpu/SDL_gpu_util.h create mode 100644 src/render/sdlgpu/SDL_pipeline_gpu.c create mode 100644 src/render/sdlgpu/SDL_pipeline_gpu.h create mode 100644 src/render/sdlgpu/SDL_render_gpu.c create mode 100644 src/render/sdlgpu/SDL_shaders_gpu.c create mode 100644 src/render/sdlgpu/SDL_shaders_gpu.h create mode 100644 src/render/sdlgpu/shaders/.gitattributes create mode 100644 src/render/sdlgpu/shaders/.gitignore create mode 100755 src/render/sdlgpu/shaders/build-shaders.sh create mode 100644 src/render/sdlgpu/shaders/color.frag create mode 100644 src/render/sdlgpu/shaders/color.frag.metal.h create mode 100644 src/render/sdlgpu/shaders/color.frag.sm50.dxbc.h create mode 100644 src/render/sdlgpu/shaders/color.frag.sm60.dxil.h create mode 100644 src/render/sdlgpu/shaders/color.frag.spv.h create mode 100644 src/render/sdlgpu/shaders/dxbc50.h create mode 100644 src/render/sdlgpu/shaders/dxil60.h create mode 100644 src/render/sdlgpu/shaders/linepoint.vert create mode 100644 src/render/sdlgpu/shaders/linepoint.vert.metal.h create mode 100644 src/render/sdlgpu/shaders/linepoint.vert.sm50.dxbc.h create mode 100644 src/render/sdlgpu/shaders/linepoint.vert.sm60.dxil.h create mode 100644 src/render/sdlgpu/shaders/linepoint.vert.spv.h create mode 100644 src/render/sdlgpu/shaders/metal.h create mode 100644 src/render/sdlgpu/shaders/spir-v.h create mode 100644 src/render/sdlgpu/shaders/texture_rgb.frag create mode 100644 src/render/sdlgpu/shaders/texture_rgb.frag.metal.h create mode 100644 src/render/sdlgpu/shaders/texture_rgb.frag.sm50.dxbc.h create mode 100644 src/render/sdlgpu/shaders/texture_rgb.frag.sm60.dxil.h create mode 100644 src/render/sdlgpu/shaders/texture_rgb.frag.spv.h create mode 100644 src/render/sdlgpu/shaders/texture_rgba.frag create mode 100644 src/render/sdlgpu/shaders/texture_rgba.frag.metal.h create mode 100644 src/render/sdlgpu/shaders/texture_rgba.frag.sm50.dxbc.h create mode 100644 src/render/sdlgpu/shaders/texture_rgba.frag.sm60.dxil.h create mode 100644 src/render/sdlgpu/shaders/texture_rgba.frag.spv.h create mode 100644 src/render/sdlgpu/shaders/tri_color.vert create mode 100644 src/render/sdlgpu/shaders/tri_color.vert.metal.h create mode 100644 src/render/sdlgpu/shaders/tri_color.vert.sm50.dxbc.h create mode 100644 src/render/sdlgpu/shaders/tri_color.vert.sm60.dxil.h create mode 100644 src/render/sdlgpu/shaders/tri_color.vert.spv.h create mode 100644 src/render/sdlgpu/shaders/tri_texture.vert create mode 100644 src/render/sdlgpu/shaders/tri_texture.vert.metal.h create mode 100644 src/render/sdlgpu/shaders/tri_texture.vert.sm50.dxbc.h create mode 100644 src/render/sdlgpu/shaders/tri_texture.vert.sm60.dxil.h create mode 100644 src/render/sdlgpu/shaders/tri_texture.vert.spv.h create mode 100755 test/testgpu/build-shaders.sh create mode 100644 test/testgpu/cube.glsl create mode 100644 test/testgpu/cube.hlsl create mode 100644 test/testgpu/cube.metal create mode 100644 test/testgpu/testgpu_dxbc.h create mode 100644 test/testgpu/testgpu_dxil.h create mode 100644 test/testgpu/testgpu_metallib.h create mode 100644 test/testgpu/testgpu_spirv.h create mode 100644 test/testgpu_spinning_cube.c diff --git a/.gitignore b/.gitignore index 5326a62c3..3c45e91b7 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 c26fc6721..31bc23bc4 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 414904b4a..d69831ae6 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 1ac0e2ec3..fa470003c 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 fbd091f59..61caf6d24 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 1c7b029a1..a71477150 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 657afb9f2..e1cbf90bf 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 57b5a527a..f7794e856 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 4e18f6382..c9633941d 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 000000000..3ac74d63c --- /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 d7bc37a04..bb83d6d2e 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 3c0e80f38..deda238c5 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 dceb68cd4..7300f777f 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 d6ae49abc..ddb158547 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 874b4d3be..cf6229e13 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 669d4e681..0a7a1b37d 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 3fd847c9d..49eb65c89 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 3ad30290d..750667142 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 c4be4483f..837a70f1c 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 3f39e54c7..e2753c1a1 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 f5d6cb303..513f314a6 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 7d6259dc8..d5d1a7371 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 acfdeffad..c44278d63 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 000000000..0bb35c193 --- /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 000000000..e31744712 --- /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 000000000..2394dccf4 --- /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 000000000..8d01331f1 --- /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 000000000..4880b85f7 --- /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 000000000..e83c957b9 --- /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 + ] + +;