Ver Fonte

GPU: Binding validation and prevent null dereference if expected binding is missing (#13164)

Evan Hemsley há 1 mês atrás
pai
commit
fbba5b272a
5 ficheiros alterados com 588 adições e 337 exclusões
  1. 208 43
      src/gpu/SDL_gpu.c
  2. 50 3
      src/gpu/SDL_sysgpu.h
  3. 158 146
      src/gpu/d3d12/SDL_gpu_d3d12.c
  4. 61 73
      src/gpu/metal/SDL_gpu_metal.m
  5. 111 72
      src/gpu/vulkan/SDL_gpu_vulkan.c

+ 208 - 43
src/gpu/SDL_gpu.c

@@ -93,10 +93,10 @@
         }                                                                                                                   \
     }
 
-#define CHECK_GRAPHICS_PIPELINE_BOUND                                                       \
-    if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->graphics_pipeline_bound) { \
-        SDL_assert_release(!"Graphics pipeline not bound!");                                \
-        return;                                                                             \
+#define CHECK_GRAPHICS_PIPELINE_BOUND                                                   \
+    if (!((RenderPass *)render_pass)->graphics_pipeline) { \
+        SDL_assert_release(!"Graphics pipeline not bound!");                            \
+        return;                                                                         \
     }
 
 #define CHECK_COMPUTEPASS                                     \
@@ -106,7 +106,7 @@
     }
 
 #define CHECK_COMPUTE_PIPELINE_BOUND                                                        \
-    if (!((CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER)->compute_pipeline_bound) { \
+    if (!((ComputePass *)compute_pass)->compute_pipeline) { \
         SDL_assert_release(!"Compute pipeline not bound!");                                 \
         return;                                                                             \
     }
@@ -174,12 +174,18 @@
 #define RENDERPASS_DEVICE \
     ((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->device
 
+#define RENDERPASS_BOUND_PIPELINE \
+    ((RenderPass *)render_pass)->graphics_pipeline
+
 #define COMPUTEPASS_COMMAND_BUFFER \
     ((Pass *)compute_pass)->command_buffer
 
 #define COMPUTEPASS_DEVICE \
     ((CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER)->device
 
+#define COMPUTEPASS_BOUND_PIPELINE \
+    ((ComputePass *)compute_pass)->compute_pipeline
+
 #define COPYPASS_COMMAND_BUFFER \
     ((Pass *)copy_pass)->command_buffer
 
@@ -511,6 +517,73 @@ void SDL_GPU_BlitCommon(
     SDL_EndGPURenderPass(render_pass);
 }
 
+static void SDL_GPU_CheckGraphicsBindings(SDL_GPURenderPass *render_pass)
+{
+    RenderPass *rp = (RenderPass *)render_pass;
+    GraphicsPipelineCommonHeader *pipeline = (GraphicsPipelineCommonHeader *)RENDERPASS_BOUND_PIPELINE;
+    for (Uint32 i = 0; i < pipeline->num_vertex_samplers; i += 1) {
+        if (!rp->vertex_sampler_bound[i]) {
+            SDL_assert_release(!"Missing vertex sampler binding!");
+        }
+    }
+    for (Uint32 i = 0; i < pipeline->num_vertex_storage_textures; i += 1) {
+        if (!rp->vertex_storage_texture_bound[i]) {
+            SDL_assert_release(!"Missing vertex storage texture binding!");
+        }
+    }
+    for (Uint32 i = 0; i < pipeline->num_vertex_storage_buffers; i += 1) {
+        if (!rp->vertex_storage_buffer_bound[i]) {
+            SDL_assert_release(!"Missing vertex storage buffer binding!");
+        }
+    }
+    for (Uint32 i = 0; i < pipeline->num_fragment_samplers; i += 1) {
+        if (!rp->fragment_sampler_bound[i]) {
+            SDL_assert_release(!"Missing fragment sampler binding!");
+        }
+    }
+    for (Uint32 i = 0; i < pipeline->num_fragment_storage_textures; i += 1) {
+        if (!rp->fragment_storage_texture_bound[i]) {
+            SDL_assert_release(!"Missing fragment storage texture binding!");
+        }
+    }
+    for (Uint32 i = 0; i < pipeline->num_fragment_storage_buffers; i += 1) {
+        if (!rp->fragment_storage_buffer_bound[i]) {
+            SDL_assert_release(!"Missing fragment storage buffer binding!");
+        }
+    }
+}
+
+static void SDL_GPU_CheckComputeBindings(SDL_GPUComputePass *compute_pass)
+{
+    ComputePass *cp = (ComputePass *)compute_pass;
+    ComputePipelineCommonHeader *pipeline = (ComputePipelineCommonHeader *)COMPUTEPASS_BOUND_PIPELINE;
+    for (Uint32 i = 0; i < pipeline->numSamplers; i += 1) {
+        if (!cp->sampler_bound[i]) {
+            SDL_assert_release(!"Missing compute sampler binding!");
+        }
+    }
+    for (Uint32 i = 0; i < pipeline->numReadonlyStorageTextures; i += 1) {
+        if (!cp->read_only_storage_texture_bound[i]) {
+            SDL_assert_release(!"Missing compute readonly storage texture binding!");
+        }
+    }
+    for (Uint32 i = 0; i < pipeline->numReadonlyStorageBuffers; i += 1) {
+        if (!cp->read_only_storage_buffer_bound[i]) {
+            SDL_assert_release(!"Missing compute readonly storage buffer binding!");
+        }
+    }
+    for (Uint32 i = 0; i < pipeline->numReadWriteStorageTextures; i += 1) {
+        if (!cp->read_write_storage_texture_bound[i]) {
+            SDL_assert_release(!"Missing compute read-write storage texture binding!");
+        }
+    }
+    for (Uint32 i = 0; i < pipeline->numReadWriteStorageBuffers; i += 1) {
+        if (!cp->read_write_storage_buffer_bound[i]) {
+            SDL_assert_release(!"Missing compute read-write storage buffer bbinding!");
+        }
+    }
+}
+
 // Driver Functions
 
 #ifndef SDL_GPU_DISABLED
@@ -1482,15 +1555,29 @@ SDL_GPUCommandBuffer *SDL_AcquireGPUCommandBuffer(
     commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
     commandBufferHeader->device = device;
     commandBufferHeader->render_pass.command_buffer = command_buffer;
-    commandBufferHeader->render_pass.in_progress = false;
-    commandBufferHeader->graphics_pipeline_bound = false;
     commandBufferHeader->compute_pass.command_buffer = command_buffer;
-    commandBufferHeader->compute_pass.in_progress = false;
-    commandBufferHeader->compute_pipeline_bound = false;
     commandBufferHeader->copy_pass.command_buffer = command_buffer;
-    commandBufferHeader->copy_pass.in_progress = false;
-    commandBufferHeader->swapchain_texture_acquired = false;
-    commandBufferHeader->submitted = false;
+
+    if (device->debug_mode) {
+        commandBufferHeader->render_pass.in_progress = false;
+        commandBufferHeader->render_pass.graphics_pipeline = NULL;
+        commandBufferHeader->compute_pass.in_progress = false;
+        commandBufferHeader->compute_pass.compute_pipeline = NULL;
+        commandBufferHeader->copy_pass.in_progress = false;
+        commandBufferHeader->swapchain_texture_acquired = false;
+        commandBufferHeader->submitted = false;
+        SDL_zeroa(commandBufferHeader->render_pass.vertex_sampler_bound);
+        SDL_zeroa(commandBufferHeader->render_pass.vertex_storage_texture_bound);
+        SDL_zeroa(commandBufferHeader->render_pass.vertex_storage_buffer_bound);
+        SDL_zeroa(commandBufferHeader->render_pass.fragment_sampler_bound);
+        SDL_zeroa(commandBufferHeader->render_pass.fragment_storage_texture_bound);
+        SDL_zeroa(commandBufferHeader->render_pass.fragment_storage_buffer_bound);
+        SDL_zeroa(commandBufferHeader->compute_pass.sampler_bound);
+        SDL_zeroa(commandBufferHeader->compute_pass.read_only_storage_texture_bound);
+        SDL_zeroa(commandBufferHeader->compute_pass.read_only_storage_buffer_bound);
+        SDL_zeroa(commandBufferHeader->compute_pass.read_write_storage_texture_bound);
+        SDL_zeroa(commandBufferHeader->compute_pass.read_write_storage_buffer_bound);
+    }
 
     return command_buffer;
 }
@@ -1681,14 +1768,18 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
         depth_stencil_target_info);
 
     commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
-    commandBufferHeader->render_pass.in_progress = true;
-    for (Uint32 i = 0; i < num_color_targets; i += 1) {
-        commandBufferHeader->render_pass.color_targets[i] = color_target_infos[i].texture;
-    }
-    commandBufferHeader->render_pass.num_color_targets = num_color_targets;
-    if (depth_stencil_target_info != NULL) {
-        commandBufferHeader->render_pass.depth_stencil_target = depth_stencil_target_info->texture;
+
+    if (COMMAND_BUFFER_DEVICE->debug_mode) {
+        commandBufferHeader->render_pass.in_progress = true;
+        for (Uint32 i = 0; i < num_color_targets; i += 1) {
+            commandBufferHeader->render_pass.color_targets[i] = color_target_infos[i].texture;
+        }
+        commandBufferHeader->render_pass.num_color_targets = num_color_targets;
+        if (depth_stencil_target_info != NULL) {
+            commandBufferHeader->render_pass.depth_stencil_target = depth_stencil_target_info->texture;
+        }
     }
+
     return (SDL_GPURenderPass *)&(commandBufferHeader->render_pass);
 }
 
@@ -1696,8 +1787,6 @@ void SDL_BindGPUGraphicsPipeline(
     SDL_GPURenderPass *render_pass,
     SDL_GPUGraphicsPipeline *graphics_pipeline)
 {
-    CommandBufferCommonHeader *commandBufferHeader;
-
     if (render_pass == NULL) {
         SDL_InvalidParamError("render_pass");
         return;
@@ -1711,8 +1800,10 @@ void SDL_BindGPUGraphicsPipeline(
         RENDERPASS_COMMAND_BUFFER,
         graphics_pipeline);
 
-    commandBufferHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
-    commandBufferHeader->graphics_pipeline_bound = true;
+
+    if (RENDERPASS_DEVICE->debug_mode) {
+        RENDERPASS_BOUND_PIPELINE = graphics_pipeline;
+    }
 }
 
 void SDL_SetGPUViewport(
@@ -1867,6 +1958,10 @@ void SDL_BindGPUVertexSamplers(
         {
             CHECK_SAMPLER_TEXTURES
         }
+
+        for (Uint32 i = 0; i < num_bindings; i += 1) {
+            ((RenderPass *)render_pass)->vertex_sampler_bound[first_slot + i] = true;
+        }
     }
 
     RENDERPASS_DEVICE->BindVertexSamplers(
@@ -1894,6 +1989,10 @@ void SDL_BindGPUVertexStorageTextures(
     if (RENDERPASS_DEVICE->debug_mode) {
         CHECK_RENDERPASS
         CHECK_STORAGE_TEXTURES
+
+        for (Uint32 i = 0; i < num_bindings; i += 1) {
+            ((RenderPass *)render_pass)->vertex_storage_texture_bound[first_slot + i] = true;
+        }
     }
 
     RENDERPASS_DEVICE->BindVertexStorageTextures(
@@ -1920,6 +2019,10 @@ void SDL_BindGPUVertexStorageBuffers(
 
     if (RENDERPASS_DEVICE->debug_mode) {
         CHECK_RENDERPASS
+
+        for (Uint32 i = 0; i < num_bindings; i += 1) {
+            ((RenderPass *)render_pass)->vertex_storage_buffer_bound[first_slot + i] = true;
+        }
     }
 
     RENDERPASS_DEVICE->BindVertexStorageBuffers(
@@ -1947,10 +2050,13 @@ void SDL_BindGPUFragmentSamplers(
     if (RENDERPASS_DEVICE->debug_mode) {
         CHECK_RENDERPASS
 
-        if (!((CommandBufferCommonHeader*)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation)
-        {
+        if (!((CommandBufferCommonHeader*)RENDERPASS_COMMAND_BUFFER)->ignore_render_pass_texture_validation) {
             CHECK_SAMPLER_TEXTURES
         }
+
+        for (Uint32 i = 0; i < num_bindings; i += 1) {
+            ((RenderPass *)render_pass)->fragment_sampler_bound[first_slot + i] = true;
+        }
     }
 
     RENDERPASS_DEVICE->BindFragmentSamplers(
@@ -1978,6 +2084,10 @@ void SDL_BindGPUFragmentStorageTextures(
     if (RENDERPASS_DEVICE->debug_mode) {
         CHECK_RENDERPASS
         CHECK_STORAGE_TEXTURES
+
+        for (Uint32 i = 0; i < num_bindings; i += 1) {
+            ((RenderPass *)render_pass)->fragment_storage_texture_bound[first_slot + i] = true;
+        }
     }
 
     RENDERPASS_DEVICE->BindFragmentStorageTextures(
@@ -2004,6 +2114,10 @@ void SDL_BindGPUFragmentStorageBuffers(
 
     if (RENDERPASS_DEVICE->debug_mode) {
         CHECK_RENDERPASS
+
+        for (Uint32 i = 0; i < num_bindings; i += 1) {
+            ((RenderPass *)render_pass)->fragment_storage_buffer_bound[first_slot + i] = true;
+        }
     }
 
     RENDERPASS_DEVICE->BindFragmentStorageBuffers(
@@ -2029,6 +2143,7 @@ void SDL_DrawGPUIndexedPrimitives(
     if (RENDERPASS_DEVICE->debug_mode) {
         CHECK_RENDERPASS
         CHECK_GRAPHICS_PIPELINE_BOUND
+        SDL_GPU_CheckGraphicsBindings(render_pass);
     }
 
     RENDERPASS_DEVICE->DrawIndexedPrimitives(
@@ -2055,6 +2170,7 @@ void SDL_DrawGPUPrimitives(
     if (RENDERPASS_DEVICE->debug_mode) {
         CHECK_RENDERPASS
         CHECK_GRAPHICS_PIPELINE_BOUND
+        SDL_GPU_CheckGraphicsBindings(render_pass);
     }
 
     RENDERPASS_DEVICE->DrawPrimitives(
@@ -2083,6 +2199,7 @@ void SDL_DrawGPUPrimitivesIndirect(
     if (RENDERPASS_DEVICE->debug_mode) {
         CHECK_RENDERPASS
         CHECK_GRAPHICS_PIPELINE_BOUND
+        SDL_GPU_CheckGraphicsBindings(render_pass);
     }
 
     RENDERPASS_DEVICE->DrawPrimitivesIndirect(
@@ -2110,6 +2227,7 @@ void SDL_DrawGPUIndexedPrimitivesIndirect(
     if (RENDERPASS_DEVICE->debug_mode) {
         CHECK_RENDERPASS
         CHECK_GRAPHICS_PIPELINE_BOUND
+        SDL_GPU_CheckGraphicsBindings(render_pass);
     }
 
     RENDERPASS_DEVICE->DrawIndexedPrimitivesIndirect(
@@ -2123,6 +2241,7 @@ void SDL_EndGPURenderPass(
     SDL_GPURenderPass *render_pass)
 {
     CommandBufferCommonHeader *commandBufferCommonHeader;
+    commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
 
     if (render_pass == NULL) {
         SDL_InvalidParamError("render_pass");
@@ -2136,15 +2255,22 @@ void SDL_EndGPURenderPass(
     RENDERPASS_DEVICE->EndRenderPass(
         RENDERPASS_COMMAND_BUFFER);
 
-    commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
-    commandBufferCommonHeader->render_pass.in_progress = false;
-    for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1)
-    {
-        commandBufferCommonHeader->render_pass.color_targets[i] = NULL;
+    if (RENDERPASS_DEVICE->debug_mode) {
+        commandBufferCommonHeader->render_pass.in_progress = false;
+        for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1)
+        {
+            commandBufferCommonHeader->render_pass.color_targets[i] = NULL;
+        }
+        commandBufferCommonHeader->render_pass.num_color_targets = 0;
+        commandBufferCommonHeader->render_pass.depth_stencil_target = NULL;
+        commandBufferCommonHeader->render_pass.graphics_pipeline = NULL;
+        SDL_zeroa(commandBufferCommonHeader->render_pass.vertex_sampler_bound);
+        SDL_zeroa(commandBufferCommonHeader->render_pass.vertex_storage_texture_bound);
+        SDL_zeroa(commandBufferCommonHeader->render_pass.vertex_storage_buffer_bound);
+        SDL_zeroa(commandBufferCommonHeader->render_pass.fragment_sampler_bound);
+        SDL_zeroa(commandBufferCommonHeader->render_pass.fragment_storage_texture_bound);
+        SDL_zeroa(commandBufferCommonHeader->render_pass.fragment_storage_buffer_bound);
     }
-    commandBufferCommonHeader->render_pass.num_color_targets = 0;
-    commandBufferCommonHeader->render_pass.depth_stencil_target = NULL;
-    commandBufferCommonHeader->graphics_pipeline_bound = false;
 }
 
 // Compute Pass
@@ -2211,7 +2337,19 @@ SDL_GPUComputePass *SDL_BeginGPUComputePass(
         num_storage_buffer_bindings);
 
     commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
-    commandBufferHeader->compute_pass.in_progress = true;
+
+    if (COMMAND_BUFFER_DEVICE->debug_mode) {
+        commandBufferHeader->compute_pass.in_progress = true;
+
+        for (Uint32 i = 0; i < num_storage_texture_bindings; i += 1) {
+            commandBufferHeader->compute_pass.read_write_storage_texture_bound[i] = true;
+        }
+
+        for (Uint32 i = 0; i < num_storage_buffer_bindings; i += 1) {
+            commandBufferHeader->compute_pass.read_write_storage_buffer_bound[i] = true;
+        }
+    }
+
     return (SDL_GPUComputePass *)&(commandBufferHeader->compute_pass);
 }
 
@@ -2219,8 +2357,6 @@ void SDL_BindGPUComputePipeline(
     SDL_GPUComputePass *compute_pass,
     SDL_GPUComputePipeline *compute_pipeline)
 {
-    CommandBufferCommonHeader *commandBufferHeader;
-
     if (compute_pass == NULL) {
         SDL_InvalidParamError("compute_pass");
         return;
@@ -2238,8 +2374,10 @@ void SDL_BindGPUComputePipeline(
         COMPUTEPASS_COMMAND_BUFFER,
         compute_pipeline);
 
-    commandBufferHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER;
-    commandBufferHeader->compute_pipeline_bound = true;
+
+    if (COMPUTEPASS_DEVICE->debug_mode) {
+        COMPUTEPASS_BOUND_PIPELINE = compute_pipeline;
+    }
 }
 
 void SDL_BindGPUComputeSamplers(
@@ -2259,6 +2397,10 @@ void SDL_BindGPUComputeSamplers(
 
     if (COMPUTEPASS_DEVICE->debug_mode) {
         CHECK_COMPUTEPASS
+
+        for (Uint32 i = 0; i < num_bindings; i += 1) {
+            ((ComputePass *)compute_pass)->sampler_bound[first_slot + i] = true;
+        }
     }
 
     COMPUTEPASS_DEVICE->BindComputeSamplers(
@@ -2285,6 +2427,10 @@ void SDL_BindGPUComputeStorageTextures(
 
     if (COMPUTEPASS_DEVICE->debug_mode) {
         CHECK_COMPUTEPASS
+
+        for (Uint32 i = 0; i < num_bindings; i += 1) {
+            ((ComputePass *)compute_pass)->read_only_storage_texture_bound[first_slot + i] = true;
+        }
     }
 
     COMPUTEPASS_DEVICE->BindComputeStorageTextures(
@@ -2311,6 +2457,10 @@ void SDL_BindGPUComputeStorageBuffers(
 
     if (COMPUTEPASS_DEVICE->debug_mode) {
         CHECK_COMPUTEPASS
+
+        for (Uint32 i = 0; i < num_bindings; i += 1) {
+            ((ComputePass *)compute_pass)->read_only_storage_buffer_bound[first_slot + i] = true;
+        }
     }
 
     COMPUTEPASS_DEVICE->BindComputeStorageBuffers(
@@ -2334,6 +2484,7 @@ void SDL_DispatchGPUCompute(
     if (COMPUTEPASS_DEVICE->debug_mode) {
         CHECK_COMPUTEPASS
         CHECK_COMPUTE_PIPELINE_BOUND
+        SDL_GPU_CheckComputeBindings(compute_pass);
     }
 
     COMPUTEPASS_DEVICE->DispatchCompute(
@@ -2356,6 +2507,7 @@ void SDL_DispatchGPUComputeIndirect(
     if (COMPUTEPASS_DEVICE->debug_mode) {
         CHECK_COMPUTEPASS
         CHECK_COMPUTE_PIPELINE_BOUND
+        SDL_GPU_CheckComputeBindings(compute_pass);
     }
 
     COMPUTEPASS_DEVICE->DispatchComputeIndirect(
@@ -2381,9 +2533,16 @@ void SDL_EndGPUComputePass(
     COMPUTEPASS_DEVICE->EndComputePass(
         COMPUTEPASS_COMMAND_BUFFER);
 
-    commandBufferCommonHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER;
-    commandBufferCommonHeader->compute_pass.in_progress = false;
-    commandBufferCommonHeader->compute_pipeline_bound = false;
+    if (COMPUTEPASS_DEVICE->debug_mode) {
+        commandBufferCommonHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER;
+        commandBufferCommonHeader->compute_pass.in_progress = false;
+        commandBufferCommonHeader->compute_pass.compute_pipeline = false;
+        SDL_zeroa(commandBufferCommonHeader->compute_pass.sampler_bound);
+        SDL_zeroa(commandBufferCommonHeader->compute_pass.read_only_storage_texture_bound);
+        SDL_zeroa(commandBufferCommonHeader->compute_pass.read_only_storage_buffer_bound);
+        SDL_zeroa(commandBufferCommonHeader->compute_pass.read_write_storage_texture_bound);
+        SDL_zeroa(commandBufferCommonHeader->compute_pass.read_write_storage_buffer_bound);
+    }
 }
 
 // TransferBuffer Data
@@ -2441,7 +2600,11 @@ SDL_GPUCopyPass *SDL_BeginGPUCopyPass(
         command_buffer);
 
     commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
-    commandBufferHeader->copy_pass.in_progress = true;
+
+    if (COMMAND_BUFFER_DEVICE->debug_mode) {
+        commandBufferHeader->copy_pass.in_progress = true;
+    }
+
     return (SDL_GPUCopyPass *)&(commandBufferHeader->copy_pass);
 }
 
@@ -2699,7 +2862,9 @@ void SDL_EndGPUCopyPass(
     COPYPASS_DEVICE->EndCopyPass(
         COPYPASS_COMMAND_BUFFER);
 
-    ((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->copy_pass.in_progress = false;
+    if (COPYPASS_DEVICE->debug_mode) {
+        ((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->copy_pass.in_progress = false;
+    }
 }
 
 void SDL_GenerateMipmapsForGPUTexture(

+ 50 - 3
src/gpu/SDL_sysgpu.h

@@ -47,6 +47,20 @@ typedef struct Pass
     bool in_progress;
 } Pass;
 
+typedef struct ComputePass
+{
+    SDL_GPUCommandBuffer *command_buffer;
+    bool in_progress;
+
+    SDL_GPUComputePipeline *compute_pipeline;
+
+    bool sampler_bound[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    bool read_only_storage_texture_bound[MAX_STORAGE_TEXTURES_PER_STAGE];
+    bool read_only_storage_buffer_bound[MAX_STORAGE_BUFFERS_PER_STAGE];
+    bool read_write_storage_texture_bound[MAX_COMPUTE_WRITE_TEXTURES];
+    bool read_write_storage_buffer_bound[MAX_COMPUTE_WRITE_BUFFERS];
+} ComputePass;
+
 typedef struct RenderPass
 {
     SDL_GPUCommandBuffer *command_buffer;
@@ -54,15 +68,25 @@ typedef struct RenderPass
     SDL_GPUTexture *color_targets[MAX_COLOR_TARGET_BINDINGS];
     Uint32 num_color_targets;
     SDL_GPUTexture *depth_stencil_target;
+
+    SDL_GPUGraphicsPipeline *graphics_pipeline;
+
+    bool vertex_sampler_bound[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    bool vertex_storage_texture_bound[MAX_STORAGE_TEXTURES_PER_STAGE];
+    bool vertex_storage_buffer_bound[MAX_STORAGE_BUFFERS_PER_STAGE];
+
+    bool fragment_sampler_bound[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    bool fragment_storage_texture_bound[MAX_STORAGE_TEXTURES_PER_STAGE];
+    bool fragment_storage_buffer_bound[MAX_STORAGE_BUFFERS_PER_STAGE];
 } RenderPass;
 
 typedef struct CommandBufferCommonHeader
 {
     SDL_GPUDevice *device;
+
     RenderPass render_pass;
-    bool graphics_pipeline_bound;
-    Pass compute_pass;
-    bool compute_pipeline_bound;
+    ComputePass compute_pass;
+
     Pass copy_pass;
     bool swapchain_texture_acquired;
     bool submitted;
@@ -75,6 +99,29 @@ typedef struct TextureCommonHeader
     SDL_GPUTextureCreateInfo info;
 } TextureCommonHeader;
 
+typedef struct GraphicsPipelineCommonHeader
+{
+    Uint32 num_vertex_samplers;
+    Uint32 num_vertex_storage_textures;
+    Uint32 num_vertex_storage_buffers;
+    Uint32 num_vertex_uniform_buffers;
+
+    Uint32 num_fragment_samplers;
+    Uint32 num_fragment_storage_textures;
+    Uint32 num_fragment_storage_buffers;
+    Uint32 num_fragment_uniform_buffers;
+} GraphicsPipelineCommonHeader;
+
+typedef struct ComputePipelineCommonHeader
+{
+    Uint32 numSamplers;
+    Uint32 numReadonlyStorageTextures;
+    Uint32 numReadonlyStorageBuffers;
+    Uint32 numReadWriteStorageTextures;
+    Uint32 numReadWriteStorageBuffers;
+    Uint32 numUniformBuffers;
+} ComputePipelineCommonHeader;
+
 typedef struct BlitFragmentUniforms
 {
     // texcoord space

+ 158 - 146
src/gpu/d3d12/SDL_gpu_d3d12.c

@@ -1004,26 +1004,38 @@ struct D3D12CommandBuffer
     Uint32 vertexBufferOffsets[MAX_VERTEX_BUFFERS];
     Uint32 vertexBufferCount;
 
-    D3D12Texture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
-    D3D12Sampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
-    D3D12Texture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
-    D3D12Buffer *vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE vertexSamplerTextureDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE vertexSamplerDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE vertexStorageTextureDescriptorHandles[MAX_STORAGE_TEXTURES_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE vertexStorageBufferDescriptorHandles[MAX_STORAGE_BUFFERS_PER_STAGE];
+
     D3D12UniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
 
-    D3D12Texture *fragmentSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
-    D3D12Sampler *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
-    D3D12Texture *fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
-    D3D12Buffer *fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE fragmentSamplerTextureDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE fragmentSamplerDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE fragmentStorageTextureDescriptorHandles[MAX_STORAGE_TEXTURES_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE fragmentStorageBufferDescriptorHandles[MAX_STORAGE_BUFFERS_PER_STAGE];
+
     D3D12UniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
 
-    D3D12Texture *computeSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
-    D3D12Sampler *computeSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE computeSamplerTextureDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE computeSamplerDescriptorHandles[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE computeReadOnlyStorageTextureDescriptorHandles[MAX_STORAGE_TEXTURES_PER_STAGE];
+    D3D12_CPU_DESCRIPTOR_HANDLE computeReadOnlyStorageBufferDescriptorHandles[MAX_STORAGE_BUFFERS_PER_STAGE];
+
+    // Track these separately because barriers can happen mid compute pass
     D3D12Texture *computeReadOnlyStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
     D3D12Buffer *computeReadOnlyStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+
+    D3D12_CPU_DESCRIPTOR_HANDLE computeReadWriteStorageTextureDescriptorHandles[MAX_COMPUTE_WRITE_TEXTURES];
+    D3D12_CPU_DESCRIPTOR_HANDLE computeReadWriteStorageBufferDescriptorHandles[MAX_COMPUTE_WRITE_BUFFERS];
+
+    // Track these separately because they are bound when the compute pass begins
     D3D12TextureSubresource *computeReadWriteStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
     Uint32 computeReadWriteStorageTextureSubresourceCount;
     D3D12Buffer *computeReadWriteStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
     Uint32 computeReadWriteStorageBufferCount;
+
     D3D12UniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
 
     // Resource tracking
@@ -1087,22 +1099,14 @@ typedef struct D3D12GraphicsRootSignature
 
 struct D3D12GraphicsPipeline
 {
+    GraphicsPipelineCommonHeader header;
+
     ID3D12PipelineState *pipelineState;
     D3D12GraphicsRootSignature *rootSignature;
     SDL_GPUPrimitiveType primitiveType;
 
     Uint32 vertexStrides[MAX_VERTEX_BUFFERS];
 
-    Uint32 vertexSamplerCount;
-    Uint32 vertexUniformBufferCount;
-    Uint32 vertexStorageBufferCount;
-    Uint32 vertexStorageTextureCount;
-
-    Uint32 fragmentSamplerCount;
-    Uint32 fragmentUniformBufferCount;
-    Uint32 fragmentStorageBufferCount;
-    Uint32 fragmentStorageTextureCount;
-
     SDL_AtomicInt referenceCount;
 };
 
@@ -1121,16 +1125,11 @@ typedef struct D3D12ComputeRootSignature
 
 struct D3D12ComputePipeline
 {
+    ComputePipelineCommonHeader header;
+
     ID3D12PipelineState *pipelineState;
     D3D12ComputeRootSignature *rootSignature;
 
-    Uint32 numSamplers;
-    Uint32 numReadOnlyStorageTextures;
-    Uint32 numReadOnlyStorageBuffers;
-    Uint32 numReadWriteStorageTextures;
-    Uint32 numReadWriteStorageBuffers;
-    Uint32 numUniformBuffers;
-
     SDL_AtomicInt referenceCount;
 };
 
@@ -2884,12 +2883,12 @@ static SDL_GPUComputePipeline *D3D12_CreateComputePipeline(
 
     computePipeline->pipelineState = pipelineState;
     computePipeline->rootSignature = rootSignature;
-    computePipeline->numSamplers = createinfo->num_samplers;
-    computePipeline->numReadOnlyStorageTextures = createinfo->num_readonly_storage_textures;
-    computePipeline->numReadOnlyStorageBuffers = createinfo->num_readonly_storage_buffers;
-    computePipeline->numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
-    computePipeline->numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
-    computePipeline->numUniformBuffers = createinfo->num_uniform_buffers;
+    computePipeline->header.numSamplers = createinfo->num_samplers;
+    computePipeline->header.numReadonlyStorageTextures = createinfo->num_readonly_storage_textures;
+    computePipeline->header.numReadonlyStorageBuffers = createinfo->num_readonly_storage_buffers;
+    computePipeline->header.numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
+    computePipeline->header.numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
+    computePipeline->header.numUniformBuffers = createinfo->num_uniform_buffers;
     SDL_SetAtomicInt(&computePipeline->referenceCount, 0);
 
     if (renderer->debug_mode && SDL_HasProperty(createinfo->props, SDL_PROP_GPU_COMPUTEPIPELINE_CREATE_NAME_STRING)) {
@@ -3170,15 +3169,15 @@ static SDL_GPUGraphicsPipeline *D3D12_CreateGraphicsPipeline(
 
     pipeline->primitiveType = createinfo->primitive_type;
 
-    pipeline->vertexSamplerCount = vertShader->num_samplers;
-    pipeline->vertexStorageTextureCount = vertShader->numStorageTextures;
-    pipeline->vertexStorageBufferCount = vertShader->numStorageBuffers;
-    pipeline->vertexUniformBufferCount = vertShader->numUniformBuffers;
+    pipeline->header.num_vertex_samplers = vertShader->num_samplers;
+    pipeline->header.num_vertex_storage_textures = vertShader->numStorageTextures;
+    pipeline->header.num_vertex_storage_buffers = vertShader->numStorageBuffers;
+    pipeline->header.num_vertex_uniform_buffers = vertShader->numUniformBuffers;
 
-    pipeline->fragmentSamplerCount = fragShader->num_samplers;
-    pipeline->fragmentStorageTextureCount = fragShader->numStorageTextures;
-    pipeline->fragmentStorageBufferCount = fragShader->numStorageBuffers;
-    pipeline->fragmentUniformBufferCount = fragShader->numUniformBuffers;
+    pipeline->header.num_fragment_samplers = fragShader->num_samplers;
+    pipeline->header.num_fragment_storage_textures = fragShader->numStorageTextures;
+    pipeline->header.num_fragment_storage_buffers = fragShader->numStorageBuffers;
+    pipeline->header.num_fragment_uniform_buffers = fragShader->numUniformBuffers;
 
     SDL_SetAtomicInt(&pipeline->referenceCount, 0);
 
@@ -4633,14 +4632,14 @@ static void D3D12_BindGraphicsPipeline(
         d3d12CommandBuffer->needFragmentUniformBufferBind[i] = true;
     }
 
-    for (i = 0; i < pipeline->vertexUniformBufferCount; i += 1) {
+    for (i = 0; i < pipeline->header.num_vertex_uniform_buffers; i += 1) {
         if (d3d12CommandBuffer->vertexUniformBuffers[i] == NULL) {
             d3d12CommandBuffer->vertexUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
                 d3d12CommandBuffer);
         }
     }
 
-    for (i = 0; i < pipeline->fragmentUniformBufferCount; i += 1) {
+    for (i = 0; i < pipeline->header.num_fragment_uniform_buffers; i += 1) {
         if (d3d12CommandBuffer->fragmentUniformBuffers[i] == NULL) {
             d3d12CommandBuffer->fragmentUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
                 d3d12CommandBuffer);
@@ -4707,21 +4706,21 @@ static void D3D12_BindVertexSamplers(
         D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
         D3D12Sampler *sampler = (D3D12Sampler *)textureSamplerBindings[i].sampler;
 
-        if (d3d12CommandBuffer->vertexSamplers[firstSlot + i] != sampler) {
+        if (d3d12CommandBuffer->vertexSamplerDescriptorHandles[firstSlot + i].ptr != sampler->handle.cpuHandle.ptr) {
             D3D12_INTERNAL_TrackSampler(
                 d3d12CommandBuffer,
                 sampler);
 
-            d3d12CommandBuffer->vertexSamplers[firstSlot + i] = sampler;
+            d3d12CommandBuffer->vertexSamplerDescriptorHandles[firstSlot + i] = sampler->handle.cpuHandle;
             d3d12CommandBuffer->needVertexSamplerBind = true;
         }
 
-        if (d3d12CommandBuffer->vertexSamplerTextures[firstSlot + i] != container->activeTexture) {
+        if (d3d12CommandBuffer->vertexSamplerTextureDescriptorHandles[firstSlot + i].ptr != container->activeTexture->srvHandle.cpuHandle.ptr) {
             D3D12_INTERNAL_TrackTexture(
                 d3d12CommandBuffer,
                 container->activeTexture);
 
-            d3d12CommandBuffer->vertexSamplerTextures[firstSlot + i] = container->activeTexture;
+            d3d12CommandBuffer->vertexSamplerTextureDescriptorHandles[firstSlot + i] = container->activeTexture->srvHandle.cpuHandle;
             d3d12CommandBuffer->needVertexSamplerBind = true;
         }
     }
@@ -4739,10 +4738,10 @@ static void D3D12_BindVertexStorageTextures(
         D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextures[i];
         D3D12Texture *texture = container->activeTexture;
 
-        if (d3d12CommandBuffer->vertexStorageTextures[firstSlot + i] != texture) {
+        if (d3d12CommandBuffer->vertexStorageTextureDescriptorHandles[firstSlot + i].ptr != texture->srvHandle.cpuHandle.ptr) {
             D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, texture);
 
-            d3d12CommandBuffer->vertexStorageTextures[firstSlot + i] = texture;
+            d3d12CommandBuffer->vertexStorageTextureDescriptorHandles[firstSlot + i] = texture->srvHandle.cpuHandle;
             d3d12CommandBuffer->needVertexStorageTextureBind = true;
         }
     }
@@ -4758,12 +4757,12 @@ static void D3D12_BindVertexStorageBuffers(
 
     for (Uint32 i = 0; i < numBindings; i += 1) {
         D3D12BufferContainer *container = (D3D12BufferContainer *)storageBuffers[i];
-        if (d3d12CommandBuffer->vertexStorageBuffers[firstSlot + i] != container->activeBuffer) {
+        if (d3d12CommandBuffer->vertexStorageBufferDescriptorHandles[firstSlot + i].ptr != container->activeBuffer->srvDescriptor.cpuHandle.ptr) {
             D3D12_INTERNAL_TrackBuffer(
                 d3d12CommandBuffer,
                 container->activeBuffer);
 
-            d3d12CommandBuffer->vertexStorageBuffers[firstSlot + i] = container->activeBuffer;
+            d3d12CommandBuffer->vertexStorageBufferDescriptorHandles[firstSlot + i] = container->activeBuffer->srvDescriptor.cpuHandle;
             d3d12CommandBuffer->needVertexStorageBufferBind = true;
         }
     }
@@ -4781,21 +4780,21 @@ static void D3D12_BindFragmentSamplers(
         D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
         D3D12Sampler *sampler = (D3D12Sampler *)textureSamplerBindings[i].sampler;
 
-        if (d3d12CommandBuffer->fragmentSamplers[firstSlot + i] != sampler) {
+        if (d3d12CommandBuffer->fragmentSamplerDescriptorHandles[firstSlot + i].ptr != sampler->handle.cpuHandle.ptr) {
             D3D12_INTERNAL_TrackSampler(
                 d3d12CommandBuffer,
                 sampler);
 
-            d3d12CommandBuffer->fragmentSamplers[firstSlot + i] = sampler;
+            d3d12CommandBuffer->fragmentSamplerDescriptorHandles[firstSlot + i] = sampler->handle.cpuHandle;
             d3d12CommandBuffer->needFragmentSamplerBind = true;
         }
 
-        if (d3d12CommandBuffer->fragmentSamplerTextures[firstSlot + i] != container->activeTexture) {
+        if (d3d12CommandBuffer->fragmentSamplerTextureDescriptorHandles[firstSlot + i].ptr != container->activeTexture->srvHandle.cpuHandle.ptr) {
             D3D12_INTERNAL_TrackTexture(
                 d3d12CommandBuffer,
                 container->activeTexture);
 
-            d3d12CommandBuffer->fragmentSamplerTextures[firstSlot + i] = container->activeTexture;
+            d3d12CommandBuffer->fragmentSamplerTextureDescriptorHandles[firstSlot + i] = container->activeTexture->srvHandle.cpuHandle;
             d3d12CommandBuffer->needFragmentSamplerBind = true;
         }
     }
@@ -4813,10 +4812,10 @@ static void D3D12_BindFragmentStorageTextures(
         D3D12TextureContainer *container = (D3D12TextureContainer *)storageTextures[i];
         D3D12Texture *texture = container->activeTexture;
 
-        if (d3d12CommandBuffer->fragmentStorageTextures[firstSlot + i] != texture) {
+        if (d3d12CommandBuffer->fragmentStorageTextureDescriptorHandles[firstSlot + i].ptr != texture->srvHandle.cpuHandle.ptr) {
             D3D12_INTERNAL_TrackTexture(d3d12CommandBuffer, texture);
 
-            d3d12CommandBuffer->fragmentStorageTextures[firstSlot + i] = texture;
+            d3d12CommandBuffer->fragmentStorageTextureDescriptorHandles[firstSlot + i] = texture->srvHandle.cpuHandle;
             d3d12CommandBuffer->needFragmentStorageTextureBind = true;
         }
     }
@@ -4833,12 +4832,12 @@ static void D3D12_BindFragmentStorageBuffers(
     for (Uint32 i = 0; i < numBindings; i += 1) {
         D3D12BufferContainer *container = (D3D12BufferContainer *)storageBuffers[i];
 
-        if (d3d12CommandBuffer->fragmentStorageBuffers[firstSlot + i] != container->activeBuffer) {
+        if (d3d12CommandBuffer->fragmentStorageBufferDescriptorHandles[firstSlot + i].ptr != container->activeBuffer->srvDescriptor.cpuHandle.ptr) {
             D3D12_INTERNAL_TrackBuffer(
                 d3d12CommandBuffer,
                 container->activeBuffer);
 
-            d3d12CommandBuffer->fragmentStorageBuffers[firstSlot + i] = container->activeBuffer;
+            d3d12CommandBuffer->fragmentStorageBufferDescriptorHandles[firstSlot + i] = container->activeBuffer->srvDescriptor.cpuHandle;
             d3d12CommandBuffer->needFragmentStorageBufferBind = true;
         }
     }
@@ -4919,15 +4918,19 @@ static void D3D12_INTERNAL_WriteGPUDescriptors(
     gpuBaseDescriptor->ptr = heap->descriptorHeapGPUStart.ptr + (heap->currentDescriptorIndex * heap->descriptorSize);
 
     for (Uint32 i = 0; i < resourceHandleCount; i += 1) {
-        ID3D12Device_CopyDescriptorsSimple(
-            commandBuffer->renderer->device,
-            1,
-            gpuHeapCpuHandle,
-            resourceDescriptorHandles[i],
-            heapType);
+        // This will crash the driver if it gets a null handle! Cool!
+        if (resourceDescriptorHandles[i].ptr != 0)
+        {
+            ID3D12Device_CopyDescriptorsSimple(
+                commandBuffer->renderer->device,
+                1,
+                gpuHeapCpuHandle,
+                resourceDescriptorHandles[i],
+                heapType);
 
-        heap->currentDescriptorIndex += 1;
-        gpuHeapCpuHandle.ptr += heap->descriptorSize;
+            heap->currentDescriptorIndex += 1;
+            gpuHeapCpuHandle.ptr += heap->descriptorSize;
+        }
     }
 }
 
@@ -4962,16 +4965,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
     }
 
     if (commandBuffer->needVertexSamplerBind) {
-        if (graphicsPipeline->vertexSamplerCount > 0) {
-            for (Uint32 i = 0; i < graphicsPipeline->vertexSamplerCount; i += 1) {
-                cpuHandles[i] = commandBuffer->vertexSamplers[i]->handle.cpuHandle;
+        if (graphicsPipeline->header.num_vertex_samplers > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->header.num_vertex_samplers; i += 1) {
+                cpuHandles[i] = commandBuffer->vertexSamplerDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
                 cpuHandles,
-                graphicsPipeline->vertexSamplerCount,
+                graphicsPipeline->header.num_vertex_samplers,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
@@ -4979,15 +4982,15 @@ static void D3D12_INTERNAL_BindGraphicsResources(
                 graphicsPipeline->rootSignature->vertexSamplerRootIndex,
                 gpuDescriptorHandle);
 
-            for (Uint32 i = 0; i < graphicsPipeline->vertexSamplerCount; i += 1) {
-                cpuHandles[i] = commandBuffer->vertexSamplerTextures[i]->srvHandle.cpuHandle;
+            for (Uint32 i = 0; i < graphicsPipeline->header.num_vertex_samplers; i += 1) {
+                cpuHandles[i] = commandBuffer->vertexSamplerTextureDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
                 cpuHandles,
-                graphicsPipeline->vertexSamplerCount,
+                graphicsPipeline->header.num_vertex_samplers,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
@@ -4999,16 +5002,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
     }
 
     if (commandBuffer->needVertexStorageTextureBind) {
-        if (graphicsPipeline->vertexStorageTextureCount > 0) {
-            for (Uint32 i = 0; i < graphicsPipeline->vertexStorageTextureCount; i += 1) {
-                cpuHandles[i] = commandBuffer->vertexStorageTextures[i]->srvHandle.cpuHandle;
+        if (graphicsPipeline->header.num_vertex_storage_textures > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->header.num_vertex_storage_textures; i += 1) {
+                cpuHandles[i] = commandBuffer->vertexStorageTextureDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
                 cpuHandles,
-                graphicsPipeline->vertexStorageTextureCount,
+                graphicsPipeline->header.num_vertex_storage_textures,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
@@ -5020,16 +5023,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
     }
 
     if (commandBuffer->needVertexStorageBufferBind) {
-        if (graphicsPipeline->vertexStorageBufferCount > 0) {
-            for (Uint32 i = 0; i < graphicsPipeline->vertexStorageBufferCount; i += 1) {
-                cpuHandles[i] = commandBuffer->vertexStorageBuffers[i]->srvDescriptor.cpuHandle;
+        if (graphicsPipeline->header.num_vertex_storage_buffers > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->header.num_vertex_storage_buffers; i += 1) {
+                cpuHandles[i] = commandBuffer->vertexStorageBufferDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
                 cpuHandles,
-                graphicsPipeline->vertexStorageBufferCount,
+                graphicsPipeline->header.num_vertex_storage_buffers,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
@@ -5042,7 +5045,7 @@ static void D3D12_INTERNAL_BindGraphicsResources(
 
     for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
         if (commandBuffer->needVertexUniformBufferBind[i]) {
-            if (graphicsPipeline->vertexUniformBufferCount > i) {
+            if (graphicsPipeline->header.num_vertex_uniform_buffers > i) {
                 ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(
                     commandBuffer->graphicsCommandList,
                     graphicsPipeline->rootSignature->vertexUniformBufferRootIndex[i],
@@ -5053,16 +5056,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
     }
 
     if (commandBuffer->needFragmentSamplerBind) {
-        if (graphicsPipeline->fragmentSamplerCount > 0) {
-            for (Uint32 i = 0; i < graphicsPipeline->fragmentSamplerCount; i += 1) {
-                cpuHandles[i] = commandBuffer->fragmentSamplers[i]->handle.cpuHandle;
+        if (graphicsPipeline->header.num_fragment_samplers > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->header.num_fragment_samplers; i += 1) {
+                cpuHandles[i] = commandBuffer->fragmentSamplerDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
                 cpuHandles,
-                graphicsPipeline->fragmentSamplerCount,
+                graphicsPipeline->header.num_fragment_samplers,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
@@ -5070,15 +5073,15 @@ static void D3D12_INTERNAL_BindGraphicsResources(
                 graphicsPipeline->rootSignature->fragmentSamplerRootIndex,
                 gpuDescriptorHandle);
 
-            for (Uint32 i = 0; i < graphicsPipeline->fragmentSamplerCount; i += 1) {
-                cpuHandles[i] = commandBuffer->fragmentSamplerTextures[i]->srvHandle.cpuHandle;
+            for (Uint32 i = 0; i < graphicsPipeline->header.num_fragment_samplers; i += 1) {
+                cpuHandles[i] = commandBuffer->fragmentSamplerTextureDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
                 cpuHandles,
-                graphicsPipeline->fragmentSamplerCount,
+                graphicsPipeline->header.num_fragment_samplers,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
@@ -5090,16 +5093,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
     }
 
     if (commandBuffer->needFragmentStorageTextureBind) {
-        if (graphicsPipeline->fragmentStorageTextureCount > 0) {
-            for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageTextureCount; i += 1) {
-                cpuHandles[i] = commandBuffer->fragmentStorageTextures[i]->srvHandle.cpuHandle;
+        if (graphicsPipeline->header.num_fragment_storage_textures > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->header.num_fragment_storage_textures; i += 1) {
+                cpuHandles[i] = commandBuffer->fragmentStorageTextureDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
                 cpuHandles,
-                graphicsPipeline->fragmentStorageTextureCount,
+                graphicsPipeline->header.num_fragment_storage_textures,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
@@ -5111,16 +5114,16 @@ static void D3D12_INTERNAL_BindGraphicsResources(
     }
 
     if (commandBuffer->needFragmentStorageBufferBind) {
-        if (graphicsPipeline->fragmentStorageBufferCount > 0) {
-            for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageBufferCount; i += 1) {
-                cpuHandles[i] = commandBuffer->fragmentStorageBuffers[i]->srvDescriptor.cpuHandle;
+        if (graphicsPipeline->header.num_fragment_storage_buffers > 0) {
+            for (Uint32 i = 0; i < graphicsPipeline->header.num_fragment_storage_buffers; i += 1) {
+                cpuHandles[i] = commandBuffer->fragmentStorageBufferDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
                 cpuHandles,
-                graphicsPipeline->fragmentStorageBufferCount,
+                graphicsPipeline->header.num_fragment_storage_buffers,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(
@@ -5133,7 +5136,7 @@ static void D3D12_INTERNAL_BindGraphicsResources(
 
     for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
         if (commandBuffer->needFragmentUniformBufferBind[i]) {
-            if (graphicsPipeline->fragmentUniformBufferCount > i) {
+            if (graphicsPipeline->header.num_fragment_uniform_buffers > i) {
                 ID3D12GraphicsCommandList_SetGraphicsRootConstantBufferView(
                     commandBuffer->graphicsCommandList,
                     graphicsPipeline->rootSignature->fragmentUniformBufferRootIndex[i],
@@ -5298,15 +5301,15 @@ static void D3D12_EndRenderPass(
     SDL_zeroa(d3d12CommandBuffer->vertexBufferOffsets);
     d3d12CommandBuffer->vertexBufferCount = 0;
 
-    SDL_zeroa(d3d12CommandBuffer->vertexSamplerTextures);
-    SDL_zeroa(d3d12CommandBuffer->vertexSamplers);
-    SDL_zeroa(d3d12CommandBuffer->vertexStorageTextures);
-    SDL_zeroa(d3d12CommandBuffer->vertexStorageBuffers);
+    SDL_zeroa(d3d12CommandBuffer->vertexSamplerTextureDescriptorHandles);
+    SDL_zeroa(d3d12CommandBuffer->vertexSamplerDescriptorHandles);
+    SDL_zeroa(d3d12CommandBuffer->vertexStorageTextureDescriptorHandles);
+    SDL_zeroa(d3d12CommandBuffer->vertexStorageBufferDescriptorHandles);
 
-    SDL_zeroa(d3d12CommandBuffer->fragmentSamplerTextures);
-    SDL_zeroa(d3d12CommandBuffer->fragmentSamplers);
-    SDL_zeroa(d3d12CommandBuffer->fragmentStorageTextures);
-    SDL_zeroa(d3d12CommandBuffer->fragmentStorageBuffers);
+    SDL_zeroa(d3d12CommandBuffer->fragmentSamplerTextureDescriptorHandles);
+    SDL_zeroa(d3d12CommandBuffer->fragmentSamplerDescriptorHandles);
+    SDL_zeroa(d3d12CommandBuffer->fragmentStorageTextureDescriptorHandles);
+    SDL_zeroa(d3d12CommandBuffer->fragmentStorageBufferDescriptorHandles);
 }
 
 // Compute Pass
@@ -5340,6 +5343,7 @@ static void D3D12_BeginComputePass(
                 D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
 
             d3d12CommandBuffer->computeReadWriteStorageTextureSubresources[i] = subresource;
+            d3d12CommandBuffer->computeReadWriteStorageTextureDescriptorHandles[i] = subresource->uavHandle.cpuHandle;
 
             D3D12_INTERNAL_TrackTexture(
                 d3d12CommandBuffer,
@@ -5358,6 +5362,7 @@ static void D3D12_BeginComputePass(
                 D3D12_RESOURCE_STATE_UNORDERED_ACCESS);
 
             d3d12CommandBuffer->computeReadWriteStorageBuffers[i] = buffer;
+            d3d12CommandBuffer->computeReadWriteStorageBufferDescriptorHandles[i] = buffer->uavDescriptor.cpuHandle;
 
             D3D12_INTERNAL_TrackBuffer(
                 d3d12CommandBuffer,
@@ -5399,7 +5404,7 @@ static void D3D12_BindComputePipeline(
         d3d12CommandBuffer->needComputeUniformBufferBind[i] = true;
     }
 
-    for (Uint32 i = 0; i < pipeline->numUniformBuffers; i += 1) {
+    for (Uint32 i = 0; i < pipeline->header.numUniformBuffers; i += 1) {
         if (d3d12CommandBuffer->computeUniformBuffers[i] == NULL) {
             d3d12CommandBuffer->computeUniformBuffers[i] = D3D12_INTERNAL_AcquireUniformBufferFromPool(
                 d3d12CommandBuffer);
@@ -5409,9 +5414,9 @@ static void D3D12_BindComputePipeline(
     D3D12_INTERNAL_TrackComputePipeline(d3d12CommandBuffer, pipeline);
 
     // Bind write-only resources after setting root signature
-    if (pipeline->numReadWriteStorageTextures > 0) {
-        for (Uint32 i = 0; i < pipeline->numReadWriteStorageTextures; i += 1) {
-            cpuHandles[i] = d3d12CommandBuffer->computeReadWriteStorageTextureSubresources[i]->uavHandle.cpuHandle;
+    if (pipeline->header.numReadWriteStorageTextures > 0) {
+        for (Uint32 i = 0; i < pipeline->header.numReadWriteStorageTextures; i += 1) {
+            cpuHandles[i] = d3d12CommandBuffer->computeReadWriteStorageTextureDescriptorHandles[i];
         }
 
         D3D12_INTERNAL_WriteGPUDescriptors(
@@ -5427,9 +5432,9 @@ static void D3D12_BindComputePipeline(
             gpuDescriptorHandle);
     }
 
-    if (pipeline->numReadWriteStorageBuffers > 0) {
-        for (Uint32 i = 0; i < pipeline->numReadWriteStorageBuffers; i += 1) {
-            cpuHandles[i] = d3d12CommandBuffer->computeReadWriteStorageBuffers[i]->uavDescriptor.cpuHandle;
+    if (pipeline->header.numReadWriteStorageBuffers > 0) {
+        for (Uint32 i = 0; i < pipeline->header.numReadWriteStorageBuffers; i += 1) {
+            cpuHandles[i] = d3d12CommandBuffer->computeReadWriteStorageBufferDescriptorHandles[i];
         }
 
         D3D12_INTERNAL_WriteGPUDescriptors(
@@ -5458,21 +5463,21 @@ static void D3D12_BindComputeSamplers(
         D3D12TextureContainer *container = (D3D12TextureContainer *)textureSamplerBindings[i].texture;
         D3D12Sampler *sampler = (D3D12Sampler *)textureSamplerBindings[i].sampler;
 
-        if (d3d12CommandBuffer->computeSamplers[firstSlot + i] != sampler) {
+        if (d3d12CommandBuffer->computeSamplerDescriptorHandles[firstSlot + i].ptr != sampler->handle.cpuHandle.ptr) {
             D3D12_INTERNAL_TrackSampler(
                 d3d12CommandBuffer,
                 (D3D12Sampler *)textureSamplerBindings[i].sampler);
 
-            d3d12CommandBuffer->computeSamplers[firstSlot + i] = (D3D12Sampler *)textureSamplerBindings[i].sampler;
+            d3d12CommandBuffer->computeSamplerDescriptorHandles[firstSlot + i] = sampler->handle.cpuHandle;
             d3d12CommandBuffer->needComputeSamplerBind = true;
         }
 
-        if (d3d12CommandBuffer->computeSamplerTextures[firstSlot + i] != container->activeTexture) {
+        if (d3d12CommandBuffer->computeSamplerTextureDescriptorHandles[firstSlot + i].ptr != container->activeTexture->srvHandle.cpuHandle.ptr) {
             D3D12_INTERNAL_TrackTexture(
                 d3d12CommandBuffer,
                 container->activeTexture);
 
-            d3d12CommandBuffer->computeSamplerTextures[firstSlot + i] = container->activeTexture;
+            d3d12CommandBuffer->computeSamplerTextureDescriptorHandles[firstSlot + i] = container->activeTexture->srvHandle.cpuHandle;
             d3d12CommandBuffer->needComputeSamplerBind = true;
         }
     }
@@ -5509,6 +5514,7 @@ static void D3D12_BindComputeStorageTextures(
                 container->activeTexture);
 
             d3d12CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i] = container->activeTexture;
+            d3d12CommandBuffer->computeReadOnlyStorageTextureDescriptorHandles[firstSlot + i] = container->activeTexture->srvHandle.cpuHandle;
             d3d12CommandBuffer->needComputeReadOnlyStorageTextureBind = true;
         }
     }
@@ -5546,6 +5552,7 @@ static void D3D12_BindComputeStorageBuffers(
                 buffer);
 
             d3d12CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i] = buffer;
+            d3d12CommandBuffer->computeReadOnlyStorageBufferDescriptorHandles[firstSlot + i] = buffer->srvDescriptor.cpuHandle;
             d3d12CommandBuffer->needComputeReadOnlyStorageBufferBind = true;
         }
     }
@@ -5581,16 +5588,16 @@ static void D3D12_INTERNAL_BindComputeResources(
     D3D12_GPU_DESCRIPTOR_HANDLE gpuDescriptorHandle;
 
     if (commandBuffer->needComputeSamplerBind) {
-        if (computePipeline->numSamplers > 0) {
-            for (Uint32 i = 0; i < computePipeline->numSamplers; i += 1) {
-                cpuHandles[i] = commandBuffer->computeSamplers[i]->handle.cpuHandle;
+        if (computePipeline->header.numSamplers > 0) {
+            for (Uint32 i = 0; i < computePipeline->header.numSamplers; i += 1) {
+                cpuHandles[i] = commandBuffer->computeSamplerDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER,
                 cpuHandles,
-                computePipeline->numSamplers,
+                computePipeline->header.numSamplers,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
@@ -5598,15 +5605,15 @@ static void D3D12_INTERNAL_BindComputeResources(
                 computePipeline->rootSignature->samplerRootIndex,
                 gpuDescriptorHandle);
 
-            for (Uint32 i = 0; i < computePipeline->numSamplers; i += 1) {
-                cpuHandles[i] = commandBuffer->computeSamplerTextures[i]->srvHandle.cpuHandle;
+            for (Uint32 i = 0; i < computePipeline->header.numSamplers; i += 1) {
+                cpuHandles[i] = commandBuffer->computeSamplerTextureDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
                 cpuHandles,
-                computePipeline->numSamplers,
+                computePipeline->header.numSamplers,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
@@ -5618,16 +5625,16 @@ static void D3D12_INTERNAL_BindComputeResources(
     }
 
     if (commandBuffer->needComputeReadOnlyStorageTextureBind) {
-        if (computePipeline->numReadOnlyStorageTextures > 0) {
-            for (Uint32 i = 0; i < computePipeline->numReadOnlyStorageTextures; i += 1) {
-                cpuHandles[i] = commandBuffer->computeReadOnlyStorageTextures[i]->srvHandle.cpuHandle;
+        if (computePipeline->header.numReadonlyStorageTextures > 0) {
+            for (Uint32 i = 0; i < computePipeline->header.numReadonlyStorageTextures; i += 1) {
+                cpuHandles[i] = commandBuffer->computeReadOnlyStorageTextureDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
                 cpuHandles,
-                computePipeline->numReadOnlyStorageTextures,
+                computePipeline->header.numReadonlyStorageTextures,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
@@ -5639,16 +5646,16 @@ static void D3D12_INTERNAL_BindComputeResources(
     }
 
     if (commandBuffer->needComputeReadOnlyStorageBufferBind) {
-        if (computePipeline->numReadOnlyStorageBuffers > 0) {
-            for (Uint32 i = 0; i < computePipeline->numReadOnlyStorageBuffers; i += 1) {
-                cpuHandles[i] = commandBuffer->computeReadOnlyStorageBuffers[i]->srvDescriptor.cpuHandle;
+        if (computePipeline->header.numReadonlyStorageBuffers > 0) {
+            for (Uint32 i = 0; i < computePipeline->header.numReadonlyStorageBuffers; i += 1) {
+                cpuHandles[i] = commandBuffer->computeReadOnlyStorageBufferDescriptorHandles[i];
             }
 
             D3D12_INTERNAL_WriteGPUDescriptors(
                 commandBuffer,
                 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
                 cpuHandles,
-                computePipeline->numReadOnlyStorageBuffers,
+                computePipeline->header.numReadonlyStorageBuffers,
                 &gpuDescriptorHandle);
 
             ID3D12GraphicsCommandList_SetComputeRootDescriptorTable(
@@ -5661,7 +5668,7 @@ static void D3D12_INTERNAL_BindComputeResources(
 
     for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
         if (commandBuffer->needComputeUniformBufferBind[i]) {
-            if (computePipeline->numUniformBuffers > i) {
+            if (computePipeline->header.numUniformBuffers > i) {
                 ID3D12GraphicsCommandList_SetComputeRootConstantBufferView(
                     commandBuffer->graphicsCommandList,
                     computePipeline->rootSignature->uniformBufferRootIndex[i],
@@ -5760,8 +5767,11 @@ static void D3D12_EndComputePass(
         }
     }
 
-    SDL_zeroa(d3d12CommandBuffer->computeSamplerTextures);
-    SDL_zeroa(d3d12CommandBuffer->computeSamplers);
+    SDL_zeroa(d3d12CommandBuffer->computeSamplerTextureDescriptorHandles);
+    SDL_zeroa(d3d12CommandBuffer->computeSamplerDescriptorHandles);
+
+    SDL_zeroa(d3d12CommandBuffer->computeReadWriteStorageTextureDescriptorHandles);
+    SDL_zeroa(d3d12CommandBuffer->computeReadWriteStorageBufferDescriptorHandles);
 
     d3d12CommandBuffer->currentComputePipeline = NULL;
 }
@@ -7351,20 +7361,22 @@ static SDL_GPUCommandBuffer *D3D12_AcquireCommandBuffer(
     SDL_zeroa(commandBuffer->vertexBufferOffsets);
     commandBuffer->vertexBufferCount = 0;
 
-    SDL_zeroa(commandBuffer->vertexSamplerTextures);
-    SDL_zeroa(commandBuffer->vertexSamplers);
-    SDL_zeroa(commandBuffer->vertexStorageTextures);
-    SDL_zeroa(commandBuffer->vertexStorageBuffers);
+    SDL_zeroa(commandBuffer->vertexSamplerTextureDescriptorHandles);
+    SDL_zeroa(commandBuffer->vertexSamplerDescriptorHandles);
+    SDL_zeroa(commandBuffer->vertexStorageTextureDescriptorHandles);
+    SDL_zeroa(commandBuffer->vertexStorageBufferDescriptorHandles);
     SDL_zeroa(commandBuffer->vertexUniformBuffers);
 
-    SDL_zeroa(commandBuffer->fragmentSamplerTextures);
-    SDL_zeroa(commandBuffer->fragmentSamplers);
-    SDL_zeroa(commandBuffer->fragmentStorageTextures);
-    SDL_zeroa(commandBuffer->fragmentStorageBuffers);
+    SDL_zeroa(commandBuffer->fragmentSamplerTextureDescriptorHandles);
+    SDL_zeroa(commandBuffer->fragmentSamplerDescriptorHandles);
+    SDL_zeroa(commandBuffer->fragmentStorageTextureDescriptorHandles);
+    SDL_zeroa(commandBuffer->fragmentStorageBufferDescriptorHandles);
     SDL_zeroa(commandBuffer->fragmentUniformBuffers);
 
-    SDL_zeroa(commandBuffer->computeSamplerTextures);
-    SDL_zeroa(commandBuffer->computeSamplers);
+    SDL_zeroa(commandBuffer->computeSamplerTextureDescriptorHandles);
+    SDL_zeroa(commandBuffer->computeSamplerDescriptorHandles);
+    SDL_zeroa(commandBuffer->computeReadOnlyStorageTextureDescriptorHandles);
+    SDL_zeroa(commandBuffer->computeReadOnlyStorageBufferDescriptorHandles);
     SDL_zeroa(commandBuffer->computeReadOnlyStorageTextures);
     SDL_zeroa(commandBuffer->computeReadOnlyStorageBuffers);
     SDL_zeroa(commandBuffer->computeReadWriteStorageTextureSubresources);

+ 61 - 73
src/gpu/metal/SDL_gpu_metal.m

@@ -476,33 +476,21 @@ typedef struct MetalShader
 
 typedef struct MetalGraphicsPipeline
 {
+    GraphicsPipelineCommonHeader header;
+
     id<MTLRenderPipelineState> handle;
 
     SDL_GPURasterizerState rasterizerState;
     SDL_GPUPrimitiveType primitiveType;
 
     id<MTLDepthStencilState> depth_stencil_state;
-
-    Uint32 vertexSamplerCount;
-    Uint32 vertexUniformBufferCount;
-    Uint32 vertexStorageBufferCount;
-    Uint32 vertexStorageTextureCount;
-
-    Uint32 fragmentSamplerCount;
-    Uint32 fragmentUniformBufferCount;
-    Uint32 fragmentStorageBufferCount;
-    Uint32 fragmentStorageTextureCount;
 } MetalGraphicsPipeline;
 
 typedef struct MetalComputePipeline
 {
+    ComputePipelineCommonHeader header;
+
     id<MTLComputePipelineState> handle;
-    Uint32 numSamplers;
-    Uint32 numReadonlyStorageTextures;
-    Uint32 numReadWriteStorageTextures;
-    Uint32 numReadonlyStorageBuffers;
-    Uint32 numReadWriteStorageBuffers;
-    Uint32 numUniformBuffers;
     Uint32 threadcountX;
     Uint32 threadcountY;
     Uint32 threadcountZ;
@@ -1085,12 +1073,12 @@ static SDL_GPUComputePipeline *METAL_CreateComputePipeline(
 
         pipeline = SDL_calloc(1, sizeof(MetalComputePipeline));
         pipeline->handle = handle;
-        pipeline->numSamplers = createinfo->num_samplers;
-        pipeline->numReadonlyStorageTextures = createinfo->num_readonly_storage_textures;
-        pipeline->numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
-        pipeline->numReadonlyStorageBuffers = createinfo->num_readonly_storage_buffers;
-        pipeline->numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
-        pipeline->numUniformBuffers = createinfo->num_uniform_buffers;
+        pipeline->header.numSamplers = createinfo->num_samplers;
+        pipeline->header.numReadonlyStorageTextures = createinfo->num_readonly_storage_textures;
+        pipeline->header.numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures;
+        pipeline->header.numReadonlyStorageBuffers = createinfo->num_readonly_storage_buffers;
+        pipeline->header.numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers;
+        pipeline->header.numUniformBuffers = createinfo->num_uniform_buffers;
         pipeline->threadcountX = createinfo->threadcount_x;
         pipeline->threadcountY = createinfo->threadcount_y;
         pipeline->threadcountZ = createinfo->threadcount_z;
@@ -1234,14 +1222,14 @@ static SDL_GPUGraphicsPipeline *METAL_CreateGraphicsPipeline(
         result->depth_stencil_state = depthStencilState;
         result->rasterizerState = createinfo->rasterizer_state;
         result->primitiveType = createinfo->primitive_type;
-        result->vertexSamplerCount = vertexShader->numSamplers;
-        result->vertexUniformBufferCount = vertexShader->numUniformBuffers;
-        result->vertexStorageBufferCount = vertexShader->numStorageBuffers;
-        result->vertexStorageTextureCount = vertexShader->numStorageTextures;
-        result->fragmentSamplerCount = fragmentShader->numSamplers;
-        result->fragmentUniformBufferCount = fragmentShader->numUniformBuffers;
-        result->fragmentStorageBufferCount = fragmentShader->numStorageBuffers;
-        result->fragmentStorageTextureCount = fragmentShader->numStorageTextures;
+        result->header.num_vertex_samplers = vertexShader->numSamplers;
+        result->header.num_vertex_uniform_buffers = vertexShader->numUniformBuffers;
+        result->header.num_vertex_storage_buffers = vertexShader->numStorageBuffers;
+        result->header.num_vertex_storage_textures = vertexShader->numStorageTextures;
+        result->header.num_fragment_samplers = fragmentShader->numSamplers;
+        result->header.num_fragment_uniform_buffers = fragmentShader->numUniformBuffers;
+        result->header.num_fragment_storage_buffers = fragmentShader->numStorageBuffers;
+        result->header.num_fragment_storage_textures = fragmentShader->numStorageTextures;
         return (SDL_GPUGraphicsPipeline *)result;
     }
 }
@@ -2439,14 +2427,14 @@ static void METAL_BindGraphicsPipeline(
             metalCommandBuffer->needFragmentUniformBufferBind[i] = true;
         }
 
-        for (i = 0; i < pipeline->vertexUniformBufferCount; i += 1) {
+        for (i = 0; i < pipeline->header.num_vertex_uniform_buffers; i += 1) {
             if (metalCommandBuffer->vertexUniformBuffers[i] == NULL) {
                 metalCommandBuffer->vertexUniformBuffers[i] = METAL_INTERNAL_AcquireUniformBufferFromPool(
                     metalCommandBuffer);
             }
         }
 
-        for (i = 0; i < pipeline->fragmentUniformBufferCount; i += 1) {
+        for (i = 0; i < pipeline->header.num_fragment_uniform_buffers; i += 1) {
             if (metalCommandBuffer->fragmentUniformBuffers[i] == NULL) {
                 metalCommandBuffer->fragmentUniformBuffers[i] = METAL_INTERNAL_AcquireUniformBufferFromPool(
                     metalCommandBuffer);
@@ -2677,11 +2665,11 @@ static void METAL_INTERNAL_BindGraphicsResources(
     // Vertex Samplers+Textures
 
     if (commandBuffer->needVertexSamplerBind) {
-        if (graphicsPipeline->vertexSamplerCount > 0) {
+        if (graphicsPipeline->header.num_vertex_samplers > 0) {
             [commandBuffer->renderEncoder setVertexSamplerStates:commandBuffer->vertexSamplers
-                                                       withRange:NSMakeRange(0, graphicsPipeline->vertexSamplerCount)];
+                                                       withRange:NSMakeRange(0, graphicsPipeline->header.num_vertex_samplers)];
             [commandBuffer->renderEncoder setVertexTextures:commandBuffer->vertexTextures
-                                                  withRange:NSMakeRange(0, graphicsPipeline->vertexSamplerCount)];
+                                                  withRange:NSMakeRange(0, graphicsPipeline->header.num_vertex_samplers)];
         }
         commandBuffer->needVertexSamplerBind = false;
     }
@@ -2689,10 +2677,10 @@ static void METAL_INTERNAL_BindGraphicsResources(
     // Vertex Storage Textures
 
     if (commandBuffer->needVertexStorageTextureBind) {
-        if (graphicsPipeline->vertexStorageTextureCount > 0) {
+        if (graphicsPipeline->header.num_vertex_storage_textures > 0) {
             [commandBuffer->renderEncoder setVertexTextures:commandBuffer->vertexStorageTextures
-                                                  withRange:NSMakeRange(graphicsPipeline->vertexSamplerCount,
-                                                                        graphicsPipeline->vertexStorageTextureCount)];
+                                                  withRange:NSMakeRange(graphicsPipeline->header.num_vertex_samplers,
+                                                                        graphicsPipeline->header.num_vertex_storage_textures)];
         }
         commandBuffer->needVertexStorageTextureBind = false;
     }
@@ -2700,20 +2688,20 @@ static void METAL_INTERNAL_BindGraphicsResources(
     // Vertex Storage Buffers
 
     if (commandBuffer->needVertexStorageBufferBind) {
-        if (graphicsPipeline->vertexStorageBufferCount > 0) {
+        if (graphicsPipeline->header.num_vertex_storage_buffers > 0) {
             [commandBuffer->renderEncoder setVertexBuffers:commandBuffer->vertexStorageBuffers
                                                    offsets:offsets
-                                                 withRange:NSMakeRange(graphicsPipeline->vertexUniformBufferCount,
-                                                                       graphicsPipeline->vertexStorageBufferCount)];
+                                                 withRange:NSMakeRange(graphicsPipeline->header.num_vertex_uniform_buffers,
+                                                                       graphicsPipeline->header.num_vertex_storage_buffers)];
         }
         commandBuffer->needVertexStorageBufferBind = false;
     }
 
     // Vertex Uniform Buffers
 
-    for (Uint32 i = 0; i < graphicsPipeline->vertexUniformBufferCount; i += 1) {
+    for (Uint32 i = 0; i < graphicsPipeline->header.num_vertex_uniform_buffers; i += 1) {
         if (commandBuffer->needVertexUniformBufferBind[i]) {
-            if (graphicsPipeline->vertexUniformBufferCount > i) {
+            if (graphicsPipeline->header.num_vertex_uniform_buffers > i) {
                 [commandBuffer->renderEncoder
                     setVertexBuffer:commandBuffer->vertexUniformBuffers[i]->handle
                              offset:commandBuffer->vertexUniformBuffers[i]->drawOffset
@@ -2726,11 +2714,11 @@ static void METAL_INTERNAL_BindGraphicsResources(
     // Fragment Samplers+Textures
 
     if (commandBuffer->needFragmentSamplerBind) {
-        if (graphicsPipeline->fragmentSamplerCount > 0) {
+        if (graphicsPipeline->header.num_fragment_samplers > 0) {
             [commandBuffer->renderEncoder setFragmentSamplerStates:commandBuffer->fragmentSamplers
-                                                         withRange:NSMakeRange(0, graphicsPipeline->fragmentSamplerCount)];
+                                                         withRange:NSMakeRange(0, graphicsPipeline->header.num_fragment_samplers)];
             [commandBuffer->renderEncoder setFragmentTextures:commandBuffer->fragmentTextures
-                                                    withRange:NSMakeRange(0, graphicsPipeline->fragmentSamplerCount)];
+                                                    withRange:NSMakeRange(0, graphicsPipeline->header.num_fragment_samplers)];
         }
         commandBuffer->needFragmentSamplerBind = false;
     }
@@ -2738,10 +2726,10 @@ static void METAL_INTERNAL_BindGraphicsResources(
     // Fragment Storage Textures
 
     if (commandBuffer->needFragmentStorageTextureBind) {
-        if (graphicsPipeline->fragmentStorageTextureCount > 0) {
+        if (graphicsPipeline->header.num_fragment_storage_textures > 0) {
             [commandBuffer->renderEncoder setFragmentTextures:commandBuffer->fragmentStorageTextures
-                                                    withRange:NSMakeRange(graphicsPipeline->fragmentSamplerCount,
-                                                                          graphicsPipeline->fragmentStorageTextureCount)];
+                                                    withRange:NSMakeRange(graphicsPipeline->header.num_fragment_samplers,
+                                                                          graphicsPipeline->header.num_fragment_storage_textures)];
         }
         commandBuffer->needFragmentStorageTextureBind = false;
     }
@@ -2749,20 +2737,20 @@ static void METAL_INTERNAL_BindGraphicsResources(
     // Fragment Storage Buffers
 
     if (commandBuffer->needFragmentStorageBufferBind) {
-        if (graphicsPipeline->fragmentStorageBufferCount > 0) {
+        if (graphicsPipeline->header.num_fragment_storage_buffers > 0) {
             [commandBuffer->renderEncoder setFragmentBuffers:commandBuffer->fragmentStorageBuffers
                                                      offsets:offsets
-                                                   withRange:NSMakeRange(graphicsPipeline->fragmentUniformBufferCount,
-                                                                         graphicsPipeline->fragmentStorageBufferCount)];
+                                                   withRange:NSMakeRange(graphicsPipeline->header.num_fragment_uniform_buffers,
+                                                                         graphicsPipeline->header.num_fragment_storage_buffers)];
         }
         commandBuffer->needFragmentStorageBufferBind = false;
     }
 
     // Fragment Uniform Buffers
 
-    for (Uint32 i = 0; i < graphicsPipeline->fragmentUniformBufferCount; i += 1) {
+    for (Uint32 i = 0; i < graphicsPipeline->header.num_fragment_uniform_buffers; i += 1) {
         if (commandBuffer->needFragmentUniformBufferBind[i]) {
-            if (graphicsPipeline->fragmentUniformBufferCount > i) {
+            if (graphicsPipeline->header.num_fragment_uniform_buffers > i) {
                 [commandBuffer->renderEncoder
                     setFragmentBuffer:commandBuffer->fragmentUniformBuffers[i]->handle
                             offset:commandBuffer->fragmentUniformBuffers[i]->drawOffset
@@ -2781,38 +2769,38 @@ static void METAL_INTERNAL_BindComputeResources(
     NSUInteger offsets[MAX_STORAGE_BUFFERS_PER_STAGE] = { 0 };
 
     if (commandBuffer->needComputeSamplerBind) {
-        if (computePipeline->numSamplers > 0) {
+        if (computePipeline->header.numSamplers > 0) {
             [commandBuffer->computeEncoder setTextures:commandBuffer->computeSamplerTextures
-                                             withRange:NSMakeRange(0, computePipeline->numSamplers)];
+                                             withRange:NSMakeRange(0, computePipeline->header.numSamplers)];
             [commandBuffer->computeEncoder setSamplerStates:commandBuffer->computeSamplers
-                                                  withRange:NSMakeRange(0, computePipeline->numSamplers)];
+                                                  withRange:NSMakeRange(0, computePipeline->header.numSamplers)];
         }
         commandBuffer->needComputeSamplerBind = false;
     }
 
     if (commandBuffer->needComputeReadOnlyStorageTextureBind) {
-        if (computePipeline->numReadonlyStorageTextures > 0) {
+        if (computePipeline->header.numReadonlyStorageTextures > 0) {
             [commandBuffer->computeEncoder setTextures:commandBuffer->computeReadOnlyTextures
                                              withRange:NSMakeRange(
-                                                           computePipeline->numSamplers,
-                                                           computePipeline->numReadonlyStorageTextures)];
+                                                           computePipeline->header.numSamplers,
+                                                           computePipeline->header.numReadonlyStorageTextures)];
         }
         commandBuffer->needComputeReadOnlyStorageTextureBind = false;
     }
 
     if (commandBuffer->needComputeReadOnlyStorageBufferBind) {
-        if (computePipeline->numReadonlyStorageBuffers > 0) {
+        if (computePipeline->header.numReadonlyStorageBuffers > 0) {
             [commandBuffer->computeEncoder setBuffers:commandBuffer->computeReadOnlyBuffers
                                               offsets:offsets
-                                            withRange:NSMakeRange(computePipeline->numUniformBuffers,
-                                                                  computePipeline->numReadonlyStorageBuffers)];
+                                            withRange:NSMakeRange(computePipeline->header.numUniformBuffers,
+                                                                  computePipeline->header.numReadonlyStorageBuffers)];
         }
         commandBuffer->needComputeReadOnlyStorageBufferBind = false;
     }
 
     for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) {
         if (commandBuffer->needComputeUniformBufferBind[i]) {
-            if (computePipeline->numUniformBuffers > i) {
+            if (computePipeline->header.numUniformBuffers > i) {
                 [commandBuffer->computeEncoder
                     setBuffer:commandBuffer->computeUniformBuffers[i]->handle
                     offset:commandBuffer->computeUniformBuffers[i]->drawOffset
@@ -3160,7 +3148,7 @@ static void METAL_BindComputePipeline(
             metalCommandBuffer->needComputeUniformBufferBind[i] = true;
         }
 
-        for (Uint32 i = 0; i < pipeline->numUniformBuffers; i += 1) {
+        for (Uint32 i = 0; i < pipeline->header.numUniformBuffers; i += 1) {
             if (metalCommandBuffer->computeUniformBuffers[i] == NULL) {
                 metalCommandBuffer->computeUniformBuffers[i] = METAL_INTERNAL_AcquireUniformBufferFromPool(
                     metalCommandBuffer);
@@ -3168,22 +3156,22 @@ static void METAL_BindComputePipeline(
         }
 
         // Bind write-only resources
-        if (pipeline->numReadWriteStorageTextures > 0) {
+        if (pipeline->header.numReadWriteStorageTextures > 0) {
             [metalCommandBuffer->computeEncoder setTextures:metalCommandBuffer->computeReadWriteTextures
                                                   withRange:NSMakeRange(
-                                                        pipeline->numSamplers +
-                                                            pipeline->numReadonlyStorageTextures,
-                                                        pipeline->numReadWriteStorageTextures)];
+                                                        pipeline->header.numSamplers +
+                                                            pipeline->header.numReadonlyStorageTextures,
+                                                        pipeline->header.numReadWriteStorageTextures)];
         }
 
         NSUInteger offsets[MAX_COMPUTE_WRITE_BUFFERS] = { 0 };
-        if (pipeline->numReadWriteStorageBuffers > 0) {
+        if (pipeline->header.numReadWriteStorageBuffers > 0) {
             [metalCommandBuffer->computeEncoder setBuffers:metalCommandBuffer->computeReadWriteBuffers
                                                    offsets:offsets
                                                  withRange:NSMakeRange(
-                                                        pipeline->numUniformBuffers +
-                                                            pipeline->numReadonlyStorageBuffers,
-                                                        pipeline->numReadWriteStorageBuffers)];
+                                                        pipeline->header.numUniformBuffers +
+                                                            pipeline->header.numReadonlyStorageBuffers,
+                                                        pipeline->header.numReadWriteStorageBuffers)];
         }
     }
 }

+ 111 - 72
src/gpu/vulkan/SDL_gpu_vulkan.c

@@ -793,13 +793,13 @@ typedef struct DescriptorSetLayout
 typedef struct GraphicsPipelineResourceLayoutHashTableKey
 {
     Uint32 vertexSamplerCount;
-    Uint32 vertexStorageBufferCount;
     Uint32 vertexStorageTextureCount;
+    Uint32 vertexStorageBufferCount;
     Uint32 vertexUniformBufferCount;
 
     Uint32 fragmentSamplerCount;
-    Uint32 fragmentStorageBufferCount;
     Uint32 fragmentStorageTextureCount;
+    Uint32 fragmentStorageBufferCount;
     Uint32 fragmentUniformBufferCount;
 } GraphicsPipelineResourceLayoutHashTableKey;
 
@@ -817,18 +817,20 @@ typedef struct VulkanGraphicsPipelineResourceLayout
     DescriptorSetLayout *descriptorSetLayouts[4];
 
     Uint32 vertexSamplerCount;
-    Uint32 vertexStorageBufferCount;
     Uint32 vertexStorageTextureCount;
+    Uint32 vertexStorageBufferCount;
     Uint32 vertexUniformBufferCount;
 
     Uint32 fragmentSamplerCount;
-    Uint32 fragmentStorageBufferCount;
     Uint32 fragmentStorageTextureCount;
+    Uint32 fragmentStorageBufferCount;
     Uint32 fragmentUniformBufferCount;
 } VulkanGraphicsPipelineResourceLayout;
 
 typedef struct VulkanGraphicsPipeline
 {
+    GraphicsPipelineCommonHeader header;
+
     VkPipeline pipeline;
     SDL_GPUPrimitiveType primitiveType;
 
@@ -872,6 +874,8 @@ typedef struct VulkanComputePipelineResourceLayout
 
 typedef struct VulkanComputePipeline
 {
+    ComputePipelineCommonHeader header;
+
     VkShaderModule shaderModule;
     VkPipeline pipeline;
     VulkanComputePipelineResourceLayout *resourceLayout;
@@ -1009,25 +1013,33 @@ typedef struct VulkanCommandBuffer
     Uint32 vertexBufferCount;
     bool needVertexBufferBind;
 
-    VulkanTexture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
-    VulkanSampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
-    VulkanTexture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
-    VulkanBuffer *vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+    VkImageView vertexSamplerTextureViewBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    VkSampler vertexSamplerBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    VkImageView vertexStorageTextureViewBindings[MAX_STORAGE_TEXTURES_PER_STAGE];
+    VkBuffer vertexStorageBufferBindings[MAX_STORAGE_BUFFERS_PER_STAGE];
 
-    VulkanTexture *fragmentSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
-    VulkanSampler *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
-    VulkanTexture *fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
-    VulkanBuffer *fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
+    VkImageView fragmentSamplerTextureViewBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    VkSampler fragmentSamplerBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    VkImageView fragmentStorageTextureViewBindings[MAX_STORAGE_TEXTURES_PER_STAGE];
+    VkBuffer fragmentStorageBufferBindings[MAX_STORAGE_BUFFERS_PER_STAGE];
 
-    VulkanTextureSubresource *readWriteComputeStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
-    Uint32 readWriteComputeStorageTextureSubresourceCount;
-    VulkanBuffer *readWriteComputeStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
+    VkImageView computeSamplerTextureViewBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    VkSampler computeSamplerBindings[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    VkImageView readOnlyComputeStorageTextureViewBindings[MAX_STORAGE_TEXTURES_PER_STAGE];
+    VkBuffer readOnlyComputeStorageBufferBindings[MAX_STORAGE_BUFFERS_PER_STAGE];
 
-    VulkanTexture *computeSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE];
-    VulkanSampler *computeSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE];
+    // Track these separately because barriers can happen mid compute pass
     VulkanTexture *readOnlyComputeStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE];
     VulkanBuffer *readOnlyComputeStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE];
 
+    VkImageView readWriteComputeStorageTextureViewBindings[MAX_COMPUTE_WRITE_TEXTURES];
+    VkBuffer readWriteComputeStorageBufferBindings[MAX_COMPUTE_WRITE_BUFFERS];
+
+    // Track these separately because they are barriered when the compute pass begins
+    VulkanTextureSubresource *readWriteComputeStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES];
+    Uint32 readWriteComputeStorageTextureSubresourceCount;
+    VulkanBuffer *readWriteComputeStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS];
+
     // Uniform buffers
 
     VulkanUniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE];
@@ -5103,8 +5115,8 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
             currentWriteDescriptorSet->pTexelBufferView = NULL;
             currentWriteDescriptorSet->pBufferInfo = NULL;
 
-            imageInfos[imageInfoCount].sampler = commandBuffer->vertexSamplers[i]->sampler;
-            imageInfos[imageInfoCount].imageView = commandBuffer->vertexSamplerTextures[i]->fullView;
+            imageInfos[imageInfoCount].sampler = commandBuffer->vertexSamplerBindings[i];
+            imageInfos[imageInfoCount].imageView = commandBuffer->vertexSamplerTextureViewBindings[i];
             imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 
             currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
@@ -5127,7 +5139,7 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
             currentWriteDescriptorSet->pBufferInfo = NULL;
 
             imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
-            imageInfos[imageInfoCount].imageView = commandBuffer->vertexStorageTextures[i]->fullView;
+            imageInfos[imageInfoCount].imageView = commandBuffer->vertexStorageTextureViewBindings[i];
             imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
 
             currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
@@ -5149,7 +5161,7 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
             currentWriteDescriptorSet->pTexelBufferView = NULL;
             currentWriteDescriptorSet->pImageInfo = NULL;
 
-            bufferInfos[bufferInfoCount].buffer = commandBuffer->vertexStorageBuffers[i]->buffer;
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->vertexStorageBufferBindings[i];
             bufferInfos[bufferInfoCount].offset = 0;
             bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
 
@@ -5222,8 +5234,8 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
             currentWriteDescriptorSet->pTexelBufferView = NULL;
             currentWriteDescriptorSet->pBufferInfo = NULL;
 
-            imageInfos[imageInfoCount].sampler = commandBuffer->fragmentSamplers[i]->sampler;
-            imageInfos[imageInfoCount].imageView = commandBuffer->fragmentSamplerTextures[i]->fullView;
+            imageInfos[imageInfoCount].sampler = commandBuffer->fragmentSamplerBindings[i];
+            imageInfos[imageInfoCount].imageView = commandBuffer->fragmentSamplerTextureViewBindings[i];
             imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 
             currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
@@ -5246,7 +5258,7 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
             currentWriteDescriptorSet->pBufferInfo = NULL;
 
             imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
-            imageInfos[imageInfoCount].imageView = commandBuffer->fragmentStorageTextures[i]->fullView;
+            imageInfos[imageInfoCount].imageView = commandBuffer->fragmentStorageTextureViewBindings[i];
             imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
 
             currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
@@ -5268,7 +5280,7 @@ static void VULKAN_INTERNAL_BindGraphicsDescriptorSets(
             currentWriteDescriptorSet->pTexelBufferView = NULL;
             currentWriteDescriptorSet->pImageInfo = NULL;
 
-            bufferInfos[bufferInfoCount].buffer = commandBuffer->fragmentStorageBuffers[i]->buffer;
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->fragmentStorageBufferBindings[i];
             bufferInfos[bufferInfoCount].offset = 0;
             bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
 
@@ -6541,6 +6553,16 @@ static SDL_GPUGraphicsPipeline *VULKAN_CreateGraphicsPipeline(
             &nameInfo);
     }
 
+    // Put this data in the pipeline we can do validation in gpu.c
+    graphicsPipeline->header.num_vertex_samplers = graphicsPipeline->resourceLayout->vertexSamplerCount;
+    graphicsPipeline->header.num_vertex_storage_buffers = graphicsPipeline->resourceLayout->vertexStorageBufferCount;
+    graphicsPipeline->header.num_vertex_storage_textures = graphicsPipeline->resourceLayout->vertexStorageTextureCount;
+    graphicsPipeline->header.num_vertex_uniform_buffers = graphicsPipeline->resourceLayout->vertexUniformBufferCount;
+    graphicsPipeline->header.num_fragment_samplers = graphicsPipeline->resourceLayout->fragmentSamplerCount;
+    graphicsPipeline->header.num_fragment_storage_buffers = graphicsPipeline->resourceLayout->fragmentStorageBufferCount;
+    graphicsPipeline->header.num_fragment_storage_textures = graphicsPipeline->resourceLayout->fragmentStorageTextureCount;
+    graphicsPipeline->header.num_fragment_uniform_buffers = graphicsPipeline->resourceLayout->fragmentUniformBufferCount;
+
     return (SDL_GPUGraphicsPipeline *)graphicsPipeline;
 }
 
@@ -6658,6 +6680,14 @@ static SDL_GPUComputePipeline *VULKAN_CreateComputePipeline(
             &nameInfo);
     }
 
+    // Track these here for debug layer
+    vulkanComputePipeline->header.numSamplers = vulkanComputePipeline->resourceLayout->numSamplers;
+    vulkanComputePipeline->header.numReadonlyStorageTextures = vulkanComputePipeline->resourceLayout->numReadonlyStorageTextures;
+    vulkanComputePipeline->header.numReadonlyStorageBuffers = vulkanComputePipeline->resourceLayout->numReadonlyStorageBuffers;
+    vulkanComputePipeline->header.numReadWriteStorageTextures = vulkanComputePipeline->resourceLayout->numReadWriteStorageTextures;
+    vulkanComputePipeline->header.numReadWriteStorageBuffers = vulkanComputePipeline->resourceLayout->numReadWriteStorageBuffers;
+    vulkanComputePipeline->header.numUniformBuffers = vulkanComputePipeline->resourceLayout->numUniformBuffers;
+
     return (SDL_GPUComputePipeline *)vulkanComputePipeline;
 }
 
@@ -7458,21 +7488,21 @@ static void VULKAN_BindVertexSamplers(
         VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
         VulkanSampler *sampler = (VulkanSampler *)textureSamplerBindings[i].sampler;
 
-        if (vulkanCommandBuffer->vertexSamplers[firstSlot + i] != sampler) {
+        if (vulkanCommandBuffer->vertexSamplerBindings[firstSlot + i] != sampler->sampler) {
             VULKAN_INTERNAL_TrackSampler(
                 vulkanCommandBuffer,
                 (VulkanSampler *)textureSamplerBindings[i].sampler);
 
-            vulkanCommandBuffer->vertexSamplers[firstSlot + i] = (VulkanSampler *)textureSamplerBindings[i].sampler;
+            vulkanCommandBuffer->vertexSamplerBindings[firstSlot + i] = sampler->sampler;
             vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
         }
 
-        if (vulkanCommandBuffer->vertexSamplerTextures[firstSlot + i] != textureContainer->activeTexture) {
+        if (vulkanCommandBuffer->vertexSamplerTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
             VULKAN_INTERNAL_TrackTexture(
                 vulkanCommandBuffer,
                 textureContainer->activeTexture);
 
-            vulkanCommandBuffer->vertexSamplerTextures[firstSlot + i] = textureContainer->activeTexture;
+            vulkanCommandBuffer->vertexSamplerTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
             vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
         }
     }
@@ -7489,12 +7519,12 @@ static void VULKAN_BindVertexStorageTextures(
     for (Uint32 i = 0; i < numBindings; i += 1) {
         VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
 
-        if (vulkanCommandBuffer->vertexStorageTextures[firstSlot + i] != textureContainer->activeTexture) {
+        if (vulkanCommandBuffer->vertexStorageTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
             VULKAN_INTERNAL_TrackTexture(
                 vulkanCommandBuffer,
                 textureContainer->activeTexture);
 
-            vulkanCommandBuffer->vertexStorageTextures[firstSlot + i] = textureContainer->activeTexture;
+            vulkanCommandBuffer->vertexStorageTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
             vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
         }
     }
@@ -7511,12 +7541,12 @@ static void VULKAN_BindVertexStorageBuffers(
     for (Uint32 i = 0; i < numBindings; i += 1) {
         VulkanBufferContainer *bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
 
-        if (vulkanCommandBuffer->vertexStorageBuffers[firstSlot + i] != bufferContainer->activeBuffer) {
+        if (vulkanCommandBuffer->vertexStorageBufferBindings[firstSlot + i] != bufferContainer->activeBuffer->buffer) {
             VULKAN_INTERNAL_TrackBuffer(
                 vulkanCommandBuffer,
                 bufferContainer->activeBuffer);
 
-            vulkanCommandBuffer->vertexStorageBuffers[firstSlot + i] = bufferContainer->activeBuffer;
+            vulkanCommandBuffer->vertexStorageBufferBindings[firstSlot + i] = bufferContainer->activeBuffer->buffer;
             vulkanCommandBuffer->needNewVertexResourceDescriptorSet = true;
         }
     }
@@ -7534,21 +7564,21 @@ static void VULKAN_BindFragmentSamplers(
         VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
         VulkanSampler *sampler = (VulkanSampler *)textureSamplerBindings[i].sampler;
 
-        if (vulkanCommandBuffer->fragmentSamplers[firstSlot + i] != sampler) {
+        if (vulkanCommandBuffer->fragmentSamplerBindings[firstSlot + i] != sampler->sampler) {
             VULKAN_INTERNAL_TrackSampler(
                 vulkanCommandBuffer,
                 (VulkanSampler *)textureSamplerBindings[i].sampler);
 
-            vulkanCommandBuffer->fragmentSamplers[firstSlot + i] = (VulkanSampler *)textureSamplerBindings[i].sampler;
+            vulkanCommandBuffer->fragmentSamplerBindings[firstSlot + i] = sampler->sampler;
             vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
         }
 
-        if (vulkanCommandBuffer->fragmentSamplerTextures[firstSlot + i] != textureContainer->activeTexture) {
+        if (vulkanCommandBuffer->fragmentSamplerTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
             VULKAN_INTERNAL_TrackTexture(
                 vulkanCommandBuffer,
                 textureContainer->activeTexture);
 
-            vulkanCommandBuffer->fragmentSamplerTextures[firstSlot + i] = textureContainer->activeTexture;
+            vulkanCommandBuffer->fragmentSamplerTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
             vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
         }
     }
@@ -7565,12 +7595,12 @@ static void VULKAN_BindFragmentStorageTextures(
     for (Uint32 i = 0; i < numBindings; i += 1) {
         VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)storageTextures[i];
 
-        if (vulkanCommandBuffer->fragmentStorageTextures[firstSlot + i] != textureContainer->activeTexture) {
+        if (vulkanCommandBuffer->fragmentStorageTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
             VULKAN_INTERNAL_TrackTexture(
                 vulkanCommandBuffer,
                 textureContainer->activeTexture);
 
-            vulkanCommandBuffer->fragmentStorageTextures[firstSlot + i] = textureContainer->activeTexture;
+            vulkanCommandBuffer->fragmentStorageTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
             vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
         }
     }
@@ -7589,12 +7619,12 @@ static void VULKAN_BindFragmentStorageBuffers(
     for (i = 0; i < numBindings; i += 1) {
         bufferContainer = (VulkanBufferContainer *)storageBuffers[i];
 
-        if (vulkanCommandBuffer->fragmentStorageBuffers[firstSlot + i] != bufferContainer->activeBuffer) {
+        if (vulkanCommandBuffer->fragmentStorageBufferBindings[firstSlot + i] != bufferContainer->activeBuffer->buffer) {
             VULKAN_INTERNAL_TrackBuffer(
                 vulkanCommandBuffer,
                 bufferContainer->activeBuffer);
 
-            vulkanCommandBuffer->fragmentStorageBuffers[firstSlot + i] = bufferContainer->activeBuffer;
+            vulkanCommandBuffer->fragmentStorageBufferBindings[firstSlot + i] = bufferContainer->activeBuffer->buffer;
             vulkanCommandBuffer->needNewFragmentResourceDescriptorSet = true;
         }
     }
@@ -8107,15 +8137,15 @@ static void VULKAN_EndRenderPass(
     SDL_zeroa(vulkanCommandBuffer->vertexBufferOffsets);
     vulkanCommandBuffer->vertexBufferCount = 0;
 
-    SDL_zeroa(vulkanCommandBuffer->vertexSamplers);
-    SDL_zeroa(vulkanCommandBuffer->vertexSamplerTextures);
-    SDL_zeroa(vulkanCommandBuffer->vertexStorageTextures);
-    SDL_zeroa(vulkanCommandBuffer->vertexStorageBuffers);
+    SDL_zeroa(vulkanCommandBuffer->vertexSamplerBindings);
+    SDL_zeroa(vulkanCommandBuffer->vertexSamplerTextureViewBindings);
+    SDL_zeroa(vulkanCommandBuffer->vertexStorageTextureViewBindings);
+    SDL_zeroa(vulkanCommandBuffer->vertexStorageBufferBindings);
 
-    SDL_zeroa(vulkanCommandBuffer->fragmentSamplers);
-    SDL_zeroa(vulkanCommandBuffer->fragmentSamplerTextures);
-    SDL_zeroa(vulkanCommandBuffer->fragmentStorageTextures);
-    SDL_zeroa(vulkanCommandBuffer->fragmentStorageBuffers);
+    SDL_zeroa(vulkanCommandBuffer->fragmentSamplerBindings);
+    SDL_zeroa(vulkanCommandBuffer->fragmentSamplerTextureViewBindings);
+    SDL_zeroa(vulkanCommandBuffer->fragmentStorageTextureViewBindings);
+    SDL_zeroa(vulkanCommandBuffer->fragmentStorageBufferBindings);
 }
 
 static void VULKAN_BeginComputePass(
@@ -8145,6 +8175,7 @@ static void VULKAN_BeginComputePass(
             VULKAN_TEXTURE_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE);
 
         vulkanCommandBuffer->readWriteComputeStorageTextureSubresources[i] = subresource;
+        vulkanCommandBuffer->readWriteComputeStorageTextureViewBindings[i] = subresource->computeWriteView;
 
         VULKAN_INTERNAL_TrackTexture(
             vulkanCommandBuffer,
@@ -8161,6 +8192,7 @@ static void VULKAN_BeginComputePass(
             VULKAN_BUFFER_USAGE_MODE_COMPUTE_STORAGE_READ_WRITE);
 
         vulkanCommandBuffer->readWriteComputeStorageBuffers[i] = buffer;
+        vulkanCommandBuffer->readWriteComputeStorageBufferBindings[i] = buffer->buffer;
 
         VULKAN_INTERNAL_TrackBuffer(
             vulkanCommandBuffer,
@@ -8212,21 +8244,21 @@ static void VULKAN_BindComputeSamplers(
         VulkanTextureContainer *textureContainer = (VulkanTextureContainer *)textureSamplerBindings[i].texture;
         VulkanSampler *sampler = (VulkanSampler *)textureSamplerBindings[i].sampler;
 
-        if (vulkanCommandBuffer->computeSamplers[firstSlot + i] != sampler) {
+        if (vulkanCommandBuffer->computeSamplerBindings[firstSlot + i] != sampler->sampler) {
             VULKAN_INTERNAL_TrackSampler(
                 vulkanCommandBuffer,
                 sampler);
 
-            vulkanCommandBuffer->computeSamplers[firstSlot + i] = sampler;
+            vulkanCommandBuffer->computeSamplerBindings[firstSlot + i] = sampler->sampler;
             vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
         }
 
-        if (vulkanCommandBuffer->computeSamplerTextures[firstSlot + i] != textureContainer->activeTexture) {
+        if (vulkanCommandBuffer->computeSamplerTextureViewBindings[firstSlot + i] != textureContainer->activeTexture->fullView) {
             VULKAN_INTERNAL_TrackTexture(
                 vulkanCommandBuffer,
                 textureContainer->activeTexture);
 
-            vulkanCommandBuffer->computeSamplerTextures[firstSlot + i] = textureContainer->activeTexture;
+            vulkanCommandBuffer->computeSamplerTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
             vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
         }
     }
@@ -8267,6 +8299,7 @@ static void VULKAN_BindComputeStorageTextures(
                 textureContainer->activeTexture);
 
             vulkanCommandBuffer->readOnlyComputeStorageTextures[firstSlot + i] = textureContainer->activeTexture;
+            vulkanCommandBuffer->readOnlyComputeStorageTextureViewBindings[firstSlot + i] = textureContainer->activeTexture->fullView;
             vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
         }
     }
@@ -8306,6 +8339,7 @@ static void VULKAN_BindComputeStorageBuffers(
                 bufferContainer->activeBuffer);
 
             vulkanCommandBuffer->readOnlyComputeStorageBuffers[firstSlot + i] = bufferContainer->activeBuffer;
+            vulkanCommandBuffer->readOnlyComputeStorageBufferBindings[firstSlot + i] = bufferContainer->activeBuffer->buffer;
             vulkanCommandBuffer->needNewComputeReadOnlyDescriptorSet = true;
         }
     }
@@ -8380,8 +8414,8 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
             currentWriteDescriptorSet->pTexelBufferView = NULL;
             currentWriteDescriptorSet->pBufferInfo = NULL;
 
-            imageInfos[imageInfoCount].sampler = commandBuffer->computeSamplers[i]->sampler;
-            imageInfos[imageInfoCount].imageView = commandBuffer->computeSamplerTextures[i]->fullView;
+            imageInfos[imageInfoCount].sampler = commandBuffer->computeSamplerBindings[i];
+            imageInfos[imageInfoCount].imageView = commandBuffer->computeSamplerTextureViewBindings[i];
             imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 
             currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
@@ -8404,7 +8438,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
             currentWriteDescriptorSet->pBufferInfo = NULL;
 
             imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
-            imageInfos[imageInfoCount].imageView = commandBuffer->readOnlyComputeStorageTextures[i]->fullView;
+            imageInfos[imageInfoCount].imageView = commandBuffer->readOnlyComputeStorageTextureViewBindings[i];
             imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
 
             currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
@@ -8426,7 +8460,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
             currentWriteDescriptorSet->pTexelBufferView = NULL;
             currentWriteDescriptorSet->pImageInfo = NULL;
 
-            bufferInfos[bufferInfoCount].buffer = commandBuffer->readOnlyComputeStorageBuffers[i]->buffer;
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->readOnlyComputeStorageBufferBindings[i];
             bufferInfos[bufferInfoCount].offset = 0;
             bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
 
@@ -8461,7 +8495,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
             currentWriteDescriptorSet->pBufferInfo = NULL;
 
             imageInfos[imageInfoCount].sampler = VK_NULL_HANDLE;
-            imageInfos[imageInfoCount].imageView = commandBuffer->readWriteComputeStorageTextureSubresources[i]->computeWriteView;
+            imageInfos[imageInfoCount].imageView = commandBuffer->readWriteComputeStorageTextureViewBindings[i];
             imageInfos[imageInfoCount].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
 
             currentWriteDescriptorSet->pImageInfo = &imageInfos[imageInfoCount];
@@ -8483,7 +8517,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
             currentWriteDescriptorSet->pTexelBufferView = NULL;
             currentWriteDescriptorSet->pImageInfo = NULL;
 
-            bufferInfos[bufferInfoCount].buffer = commandBuffer->readWriteComputeStorageBuffers[i]->buffer;
+            bufferInfos[bufferInfoCount].buffer = commandBuffer->readWriteComputeStorageBufferBindings[i];
             bufferInfos[bufferInfoCount].offset = 0;
             bufferInfos[bufferInfoCount].range = VK_WHOLE_SIZE;
 
@@ -8650,9 +8684,12 @@ static void VULKAN_EndComputePass(
         }
     }
 
-    // we don't need a barrier because sampler state is always the default if sampler bit is set
-    SDL_zeroa(vulkanCommandBuffer->computeSamplerTextures);
-    SDL_zeroa(vulkanCommandBuffer->computeSamplers);
+    // we don't need a barrier for sampler resources because sampler state is always the default if sampler bit is set
+    SDL_zeroa(vulkanCommandBuffer->computeSamplerTextureViewBindings);
+    SDL_zeroa(vulkanCommandBuffer->computeSamplerBindings);
+
+    SDL_zeroa(vulkanCommandBuffer->readWriteComputeStorageTextureViewBindings);
+    SDL_zeroa(vulkanCommandBuffer->readWriteComputeStorageBufferBindings);
 
     vulkanCommandBuffer->currentComputePipeline = NULL;
 
@@ -9518,21 +9555,23 @@ static SDL_GPUCommandBuffer *VULKAN_AcquireCommandBuffer(
     SDL_zeroa(commandBuffer->vertexBufferOffsets);
     commandBuffer->vertexBufferCount = 0;
 
-    SDL_zeroa(commandBuffer->vertexSamplerTextures);
-    SDL_zeroa(commandBuffer->vertexSamplers);
-    SDL_zeroa(commandBuffer->vertexStorageTextures);
-    SDL_zeroa(commandBuffer->vertexStorageBuffers);
+    SDL_zeroa(commandBuffer->vertexSamplerTextureViewBindings);
+    SDL_zeroa(commandBuffer->vertexSamplerBindings);
+    SDL_zeroa(commandBuffer->vertexStorageTextureViewBindings);
+    SDL_zeroa(commandBuffer->vertexStorageBufferBindings);
 
-    SDL_zeroa(commandBuffer->fragmentSamplerTextures);
-    SDL_zeroa(commandBuffer->fragmentSamplers);
-    SDL_zeroa(commandBuffer->fragmentStorageTextures);
-    SDL_zeroa(commandBuffer->fragmentStorageBuffers);
+    SDL_zeroa(commandBuffer->fragmentSamplerTextureViewBindings);
+    SDL_zeroa(commandBuffer->fragmentSamplerBindings);
+    SDL_zeroa(commandBuffer->fragmentStorageTextureViewBindings);
+    SDL_zeroa(commandBuffer->fragmentStorageBufferBindings);
 
     SDL_zeroa(commandBuffer->readWriteComputeStorageTextureSubresources);
     commandBuffer->readWriteComputeStorageTextureSubresourceCount = 0;
     SDL_zeroa(commandBuffer->readWriteComputeStorageBuffers);
-    SDL_zeroa(commandBuffer->computeSamplerTextures);
-    SDL_zeroa(commandBuffer->computeSamplers);
+    SDL_zeroa(commandBuffer->computeSamplerTextureViewBindings);
+    SDL_zeroa(commandBuffer->computeSamplerBindings);
+    SDL_zeroa(commandBuffer->readOnlyComputeStorageTextureViewBindings);
+    SDL_zeroa(commandBuffer->readOnlyComputeStorageBufferBindings);
     SDL_zeroa(commandBuffer->readOnlyComputeStorageTextures);
     SDL_zeroa(commandBuffer->readOnlyComputeStorageBuffers);