SDL: GPU: Cube Arrays (#10800)

From 66489f91bb4fb1189365052b710e7f38f053340f Mon Sep 17 00:00:00 2001
From: Evan Hemsley <[EMAIL REDACTED]>
Date: Thu, 12 Sep 2024 13:41:46 -0700
Subject: [PATCH] GPU: Cube Arrays (#10800)

---------

Co-authored-by: Caleb Cornett <caleb.cornett@outlook.com>
---
 include/SDL3/SDL_gpu.h            |     9 +-
 src/gpu/SDL_gpu.c                 |    29 +-
 src/gpu/SDL_sysgpu.h              |     2 +
 src/gpu/d3d11/D3D11_Blit.h        |   395 +-
 src/gpu/d3d11/SDL_gpu_d3d11.c     |    58 +-
 src/gpu/d3d11/compile_shaders.bat |     5 +-
 src/gpu/d3d12/D3D12_Blit.h        |  3898 +++++----
 src/gpu/d3d12/SDL_gpu_d3d12.c     |    47 +-
 src/gpu/d3d12/compile_shaders.bat |     5 +-
 src/gpu/d3dcommon/D3D_Blit.hlsl   |    30 +-
 src/gpu/metal/Metal_Blit.h        | 12853 ++++++++++++++++------------
 src/gpu/metal/Metal_Blit.metal    |    29 +-
 src/gpu/metal/SDL_gpu_metal.m     |    39 +-
 src/gpu/metal/compile_shaders.sh  |    12 +-
 src/gpu/vulkan/SDL_gpu_vulkan.c   |     7 +-
 15 files changed, 10391 insertions(+), 7027 deletions(-)

diff --git a/include/SDL3/SDL_gpu.h b/include/SDL3/SDL_gpu.h
index 0729842cb18e9..9bf2ad313bfd1 100644
--- a/include/SDL3/SDL_gpu.h
+++ b/include/SDL3/SDL_gpu.h
@@ -484,10 +484,11 @@ typedef Uint32 SDL_GPUTextureUsageFlags;
  */
 typedef enum SDL_GPUTextureType
 {
-    SDL_GPU_TEXTURETYPE_2D,        /**< The texture is a 2-dimensional image. */
-    SDL_GPU_TEXTURETYPE_2D_ARRAY,  /**< The texture is a 2-dimensional array image. */
-    SDL_GPU_TEXTURETYPE_3D,        /**< The texture is a 3-dimensional image. */
-    SDL_GPU_TEXTURETYPE_CUBE       /**< The texture is a cube image. */
+    SDL_GPU_TEXTURETYPE_2D,         /**< The texture is a 2-dimensional image. */
+    SDL_GPU_TEXTURETYPE_2D_ARRAY,   /**< The texture is a 2-dimensional array image. */
+    SDL_GPU_TEXTURETYPE_3D,         /**< The texture is a 3-dimensional image. */
+    SDL_GPU_TEXTURETYPE_CUBE,       /**< The texture is a cube image. */
+	SDL_GPU_TEXTURETYPE_CUBE_ARRAY  /**< The texture is a cube array image. */
 } SDL_GPUTextureType;
 
 /**
diff --git a/src/gpu/SDL_gpu.c b/src/gpu/SDL_gpu.c
index 398344b3640d5..6d33cf36835f3 100644
--- a/src/gpu/SDL_gpu.c
+++ b/src/gpu/SDL_gpu.c
@@ -177,6 +177,7 @@ SDL_GPUGraphicsPipeline *SDL_GPU_FetchBlitPipeline(
     SDL_GPUShader *blit_from_2d_array_shader,
     SDL_GPUShader *blit_from_3d_shader,
     SDL_GPUShader *blit_from_cube_shader,
+    SDL_GPUShader *blit_from_cube_array_shader,
     BlitPipelineCacheEntry **blit_pipelines,
     Uint32 *blit_pipeline_count,
     Uint32 *blit_pipeline_capacity)
@@ -211,7 +212,9 @@ SDL_GPUGraphicsPipeline *SDL_GPU_FetchBlitPipeline(
     blit_pipeline_create_info.vertex_shader = blit_vertex_shader;
     if (source_texture_type == SDL_GPU_TEXTURETYPE_CUBE) {
         blit_pipeline_create_info.fragment_shader = blit_from_cube_shader;
-    } else if (source_texture_type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
+    } else if (source_texture_type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
+        blit_pipeline_create_info.fragment_shader = blit_from_cube_array_shader;
+    }  else if (source_texture_type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
         blit_pipeline_create_info.fragment_shader = blit_from_2d_array_shader;
     } else if (source_texture_type == SDL_GPU_TEXTURETYPE_3D) {
         blit_pipeline_create_info.fragment_shader = blit_from_3d_shader;
@@ -259,6 +262,7 @@ void SDL_GPU_BlitCommon(
     SDL_GPUShader *blit_from_2d_array_shader,
     SDL_GPUShader *blit_from_3d_shader,
     SDL_GPUShader *blit_from_cube_shader,
+    SDL_GPUShader *blit_from_cube_array_shader,
     BlitPipelineCacheEntry **blit_pipelines,
     Uint32 *blit_pipeline_count,
     Uint32 *blit_pipeline_capacity)
@@ -283,6 +287,7 @@ void SDL_GPU_BlitCommon(
         blit_from_2d_array_shader,
         blit_from_3d_shader,
         blit_from_cube_shader,
+        blit_from_cube_array_shader,
         blit_pipelines,
         blit_pipeline_count,
         blit_pipeline_capacity);
@@ -818,6 +823,28 @@ SDL_GPUTexture *SDL_CreateGPUTexture(
                 SDL_assert_release(!"For cube textures: the format is unsupported for the given usage");
                 failed = true;
             }
+        } else if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
+            // Cubemap array validation
+            if (createinfo->width != createinfo->height) {
+                SDL_assert_release(!"For cube array textures: width and height must be identical");
+                failed = true;
+            }
+            if (createinfo->width > MAX_2D_DIMENSION || createinfo->height > MAX_2D_DIMENSION) {
+                SDL_assert_release(!"For cube array textures: width and height must be <= 16384");
+                failed = true;
+            }
+            if (createinfo->layer_count_or_depth % 6 != 0) {
+                SDL_assert_release(!"For cube array textures: layer_count_or_depth must be a multiple of 6");
+                failed = true;
+            }
+            if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) {
+                SDL_assert_release(!"For cube array textures: sample_count must be SDL_GPU_SAMPLECOUNT_1");
+                failed = true;
+            }
+            if (!SDL_GPUTextureSupportsFormat(device, createinfo->format, SDL_GPU_TEXTURETYPE_CUBE_ARRAY, createinfo->usage)) {
+                SDL_assert_release(!"For cube array textures: the format is unsupported for the given usage");
+                failed = true;
+            }
         } else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) {
             // 3D Texture Validation
             if (createinfo->width > MAX_3D_DIMENSION || createinfo->height > MAX_3D_DIMENSION || createinfo->layer_count_or_depth > MAX_3D_DIMENSION) {
diff --git a/src/gpu/SDL_sysgpu.h b/src/gpu/SDL_sysgpu.h
index 260f36346c42b..fb295f4592560 100644
--- a/src/gpu/SDL_sysgpu.h
+++ b/src/gpu/SDL_sysgpu.h
@@ -262,6 +262,7 @@ SDL_GPUGraphicsPipeline *SDL_GPU_FetchBlitPipeline(
     SDL_GPUShader *blitFrom2DArrayShader,
     SDL_GPUShader *blitFrom3DShader,
     SDL_GPUShader *blitFromCubeShader,
+    SDL_GPUShader *blitFromCubeArrayShader,
     BlitPipelineCacheEntry **blitPipelines,
     Uint32 *blitPipelineCount,
     Uint32 *blitPipelineCapacity);
@@ -276,6 +277,7 @@ void SDL_GPU_BlitCommon(
     SDL_GPUShader *blitFrom2DArrayShader,
     SDL_GPUShader *blitFrom3DShader,
     SDL_GPUShader *blitFromCubeShader,
+    SDL_GPUShader *blitFromCubeArrayShader,
     BlitPipelineCacheEntry **blitPipelines,
     Uint32 *blitPipelineCount,
     Uint32 *blitPipelineCapacity);
diff --git a/src/gpu/d3d11/D3D11_Blit.h b/src/gpu/d3d11/D3D11_Blit.h
index 2394dccf485d5..58800af6da3fa 100644
--- a/src/gpu/d3d11/D3D11_Blit.h
+++ b/src/gpu/d3d11/D3D11_Blit.h
@@ -1014,10 +1014,10 @@ switch r1.x
   break 
   case l(2)
   mul r0.xz, r0.xxzx, l(1.000000, 0.000000, -1.000000, 0.000000)
-  mov r0.y, l(-1.000000)
+  mov r0.y, l(1.000000)
   break 
   case l(3)
-  mov r0.y, l(1.000000)
+  mov r0.y, l(-1.000000)
   break 
   case l(4)
   mul r0.xy, r0.xzxx, l(1.000000, -1.000000, 0.000000, 0.000000)
@@ -1039,10 +1039,10 @@ ret
 
 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, 
+     68,  88,  66,  67,  10, 119, 
+    223,  12, 113, 233, 111,  65, 
+     57, 156,   6,  26, 212, 111, 
+     79,  35,   1,   0,   0,   0, 
     176,   6,   0,   0,   5,   0, 
       0,   0,  52,   0,   0,   0, 
     156,   2,   0,   0, 244,   2, 
@@ -1248,13 +1248,13 @@ const BYTE g_BlitFromCube[] =
      54,   0,   0,   5,  34,   0, 
      16,   0,   0,   0,   0,   0, 
       1,  64,   0,   0,   0,   0, 
-    128, 191,   2,   0,   0,   1, 
+    128,  63,   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, 
+    128, 191,   2,   0,   0,   1, 
       6,   0,   0,   3,   1,  64, 
       0,   0,   4,   0,   0,   0, 
      56,   0,   0,  10,  50,   0, 
@@ -1326,3 +1326,382 @@ const BYTE g_BlitFromCube[] =
       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 
+// SourceTextureCubeArray            texture  float4   cubearray             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_texturecubearray (float,float,float,float) t0
+dcl_input_ps linear v0.xy
+dcl_output o0.xyzw
+dcl_temps 3
+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
+udiv r1.x, r2.x, r1.x, l(6)
+switch r2.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 
+endswitch 
+utof r0.w, r1.x
+utof r1.x, cb0[1].x
+sample_l_indexable(texturecubearray)(float,float,float,float) o0.xyzw, r0.xyzw, t0.xyzw, s0, r1.x
+ret 
+// Approximately 34 instruction slots used
+#endif
+
+const BYTE g_BlitFromCubeArray[] =
+{
+     68,  88,  66,  67,  59, 147, 
+    203,  21,  33, 208, 116, 167, 
+     11, 254, 103,  46, 206, 206, 
+    176,  66,   1,   0,   0,   0, 
+    196,   6,   0,   0,   5,   0, 
+      0,   0,  52,   0,   0,   0, 
+    160,   2,   0,   0, 248,   2, 
+      0,   0,  44,   3,   0,   0, 
+     40,   6,   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,  10,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     13,   0,   0,   0, 193,   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,  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, 193,   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, 
+    244,   2,   0,   0,  80,   0, 
+      0,   0, 189,   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,  80,   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,   3,   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,  78,   0, 
+      0,   9,  18,   0,  16,   0, 
+      1,   0,   0,   0,  18,   0, 
+     16,   0,   2,   0,   0,   0, 
+     10,   0,  16,   0,   1,   0, 
+      0,   0,   1,  64,   0,   0, 
+      6,   0,   0,   0,  76,   0, 
+      0,   3,  10,   0,  16,   0, 
+      2,   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,  63, 
+      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, 191, 
+      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,  23,   0,   0,   1, 
+     86,   0,   0,   5, 130,   0, 
+     16,   0,   0,   0,   0,   0, 
+     10,   0,  16,   0,   1,   0, 
+      0,   0,  86,   0,   0,   6, 
+     18,   0,  16,   0,   1,   0, 
+      0,   0,  10, 128,  32,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  72,   0,   0, 141, 
+    130,   2,   0, 128,  67,  85, 
+     21,   0, 242,  32,  16,   0, 
+      0,   0,   0,   0,  70,  14, 
+     16,   0,   0,   0,   0,   0, 
+     70, 126,  16,   0,   0,   0, 
+      0,   0,   0,  96,  16,   0, 
+      0,   0,   0,   0,  10,   0, 
+     16,   0,   1,   0,   0,   0, 
+     62,   0,   0,   1,  83,  84, 
+     65,  84, 148,   0,   0,   0, 
+     34,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,   7,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   7,   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,   7,   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
+};
diff --git a/src/gpu/d3d11/SDL_gpu_d3d11.c b/src/gpu/d3d11/SDL_gpu_d3d11.c
index 519dd44789fc7..39e1f3e8f9af0 100644
--- a/src/gpu/d3d11/SDL_gpu_d3d11.c
+++ b/src/gpu/d3d11/SDL_gpu_d3d11.c
@@ -92,17 +92,19 @@ static const GUID D3D_IID_DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, { 0x87,
 
 // 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
+#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
+#define g_BlitFromCubeArray D3D11_BlitFromCubeArray
 #include "D3D11_Blit.h"
 #undef g_FullscreenVert
 #undef g_BlitFrom2D
 #undef g_BlitFrom2DArray
 #undef g_BlitFrom3D
 #undef g_BlitFromCube
+#undef g_BlitFromCubeArray
 
 // Macros
 
@@ -740,7 +742,7 @@ struct D3D11Renderer
     SDL_iconv_t iconv;
 
     // Blit
-    BlitPipelineCacheEntry blitPipelines[4];
+    BlitPipelineCacheEntry blitPipelines[5];
     SDL_GPUSampler *blitNearestSampler;
     SDL_GPUSampler *blitLinearSampler;
 
@@ -1940,7 +1942,7 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
         desc2D.SampleDesc.Quality = 0;
         desc2D.Usage = isStaging ? D3D11_USAGE_STAGING : D3D11_USAGE_DEFAULT;
 
-        if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+        if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
             desc2D.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
         }
         if (isMippable) {
@@ -1963,6 +1965,12 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
                 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
                 srvDesc.TextureCube.MipLevels = desc2D.MipLevels;
                 srvDesc.TextureCube.MostDetailedMip = 0;
+            } else if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
+                srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY;
+                srvDesc.TextureCubeArray.MipLevels = desc2D.MipLevels;
+                srvDesc.TextureCubeArray.MostDetailedMip = 0;
+                srvDesc.TextureCubeArray.First2DArrayFace = 0;
+                srvDesc.TextureCubeArray.NumCubes = layerCount / 6;
             } else if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) {
                 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
                 srvDesc.Texture2DArray.MipLevels = desc2D.MipLevels;
@@ -2136,7 +2144,7 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
 
                     rtvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format];
 
-                    if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+                    if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
                         rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
                         rtvDesc.Texture2DArray.MipSlice = levelIndex;
                         rtvDesc.Texture2DArray.FirstArraySlice = layerIndex;
@@ -2164,7 +2172,7 @@ static D3D11Texture *D3D11_INTERNAL_CreateTexture(
                 D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
                 uavDesc.Format = format;
 
-                if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE) {
+                if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) {
                     uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
                     uavDesc.Texture2DArray.MipSlice = levelIndex;
                     uavDesc.Texture2DArray.FirstArraySlice = layerIndex;
@@ -4316,6 +4324,7 @@ static void D3D11_Blit(
         NULL,
         NULL,
         NULL,
+        NULL,
         &blitPipelines,
         NULL,
         NULL);
@@ -5821,6 +5830,9 @@ static bool D3D11_SupportsTextureFormat(
     if (type == SDL_GPU_TEXTURETYPE_CUBE && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE)) {
         return false;
     }
+    if (type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE)) {
+        return false;
+    }
 
     // Are the usage flags supported?
     if ((usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) && !(formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) {
@@ -5952,6 +5964,7 @@ static void D3D11_INTERNAL_InitBlitPipelines(
     SDL_GPUShader *blitFrom2DArrayPixelShader;
     SDL_GPUShader *blitFrom3DPixelShader;
     SDL_GPUShader *blitFromCubePixelShader;
+    SDL_GPUShader *blitFromCubeArrayPixelShader;
     SDL_GPUGraphicsPipelineCreateInfo blitPipelineCreateInfo;
     SDL_GPUGraphicsPipeline *blitPipeline;
     SDL_GPUSamplerCreateInfo samplerCreateInfo;
@@ -6024,6 +6037,18 @@ static void D3D11_INTERNAL_InitBlitPipelines(
         SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCube pixel shader!");
     }
 
+    // BlitFromCubeArray pixel shader
+    shaderCreateInfo.code = (Uint8 *)D3D11_BlitFromCubeArray;
+    shaderCreateInfo.code_size = sizeof(D3D11_BlitFromCubeArray);
+
+    blitFromCubeArrayPixelShader = D3D11_CreateShader(
+        (SDL_GPURenderer *)renderer,
+        &shaderCreateInfo);
+
+    if (blitFromCubeArrayPixelShader == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCubeArray pixel shader!");
+    }
+
     // BlitFrom2D pipeline
     SDL_zero(blitPipelineCreateInfo);
 
@@ -6098,6 +6123,20 @@ static void D3D11_INTERNAL_InitBlitPipelines(
     renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].type = SDL_GPU_TEXTURETYPE_CUBE;
     renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].format = SDL_GPU_TEXTUREFORMAT_INVALID;
 
+    // BlitFromCubeArrayPipeline
+    blitPipelineCreateInfo.fragment_shader = blitFromCubeArrayPixelShader;
+    blitPipeline = D3D11_CreateGraphicsPipeline(
+        (SDL_GPURenderer *)renderer,
+        &blitPipelineCreateInfo);
+
+    if (blitPipeline == NULL) {
+        SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFromCubeArray pipeline!");
+    }
+
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE_ARRAY].pipeline = blitPipeline;
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE_ARRAY].type = SDL_GPU_TEXTURETYPE_CUBE_ARRAY;
+    renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE_ARRAY].format = SDL_GPU_TEXTUREFORMAT_INVALID;
+
     // Create samplers
     samplerCreateInfo.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
     samplerCreateInfo.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
@@ -6137,6 +6176,7 @@ static void D3D11_INTERNAL_InitBlitPipelines(
     D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFrom2DArrayPixelShader);
     D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFrom3DPixelShader);
     D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFromCubePixelShader);
+    D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFromCubeArrayPixelShader);
 }
 
 static void D3D11_INTERNAL_DestroyBlitPipelines(
diff --git a/src/gpu/d3d11/compile_shaders.bat b/src/gpu/d3d11/compile_shaders.bat
index 4880b85f7a7b3..56eadcc2554d3 100644
--- a/src/gpu/d3d11/compile_shaders.bat
+++ b/src/gpu/d3d11/compile_shaders.bat
@@ -3,5 +3,6 @@ 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
+fxc /T ps_5_0 /E BlitFromCubeArray /Fh D3D11_BlitFromCubeArray.h ..\d3dcommon\D3D_Blit.hlsl
+copy /b D3D11_FullscreenVert.h+D3D11_BlitFrom2D.h+D3D11_BlitFrom2DArray.h+D3D11_BlitFrom3D.h+D3D11_BlitFromCube.h+D3D11_BlitFromCubeArray.h D3D11_Blit.h
+del D3D11_FullscreenVert.h D3D11_BlitFrom2D.h D3D11_BlitFrom2DArray.h D3D11_BlitFrom3D.h D3D11_BlitFromCube.h D3D11_BlitFromCubeArray.h
diff --git a/src/gpu/d3d12/D3D12_Blit.h b/src/gpu/d3d12/D3D12_Blit.h
index e83c957b93717..d8cfbaf6c6be9 100644
--- a/src/gpu/d3d12/D3D12_Blit.h
+++ b/src/gpu/d3d12/D3D12_Blit.h
@@ -119,43 +119,176 @@ attributes #1 = { nounwind }
 #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, 

(Patch may be truncated, please check the link at the top of this post.)