SDL_shadercross: Address HLSL storage resource edge cases

From 11fc1982bc917353554ab596bb40082114fc0482 Mon Sep 17 00:00:00 2001
From: Evan Hemsley <[EMAIL REDACTED]>
Date: Thu, 21 Nov 2024 10:48:32 -0800
Subject: [PATCH] Address HLSL storage resource edge cases

---
 src/SDL_shadercross.c | 46 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 40 insertions(+), 6 deletions(-)

diff --git a/src/SDL_shadercross.c b/src/SDL_shadercross.c
index 6045689..2e78fb2 100644
--- a/src/SDL_shadercross.c
+++ b/src/SDL_shadercross.c
@@ -1470,10 +1470,12 @@ bool SDL_ShaderCross_ReflectGraphicsSPIRV(
     spvc_context context = NULL;
     spvc_parsed_ir ir = NULL;
     spvc_compiler compiler = NULL;
-    size_t num_texture_samplers;
-    size_t num_storage_textures;
-    size_t num_storage_buffers;
-    size_t num_uniform_buffers;
+    size_t num_texture_samplers = 0;
+    size_t num_storage_textures = 0;
+    size_t num_storage_buffers = 0;
+    size_t num_uniform_buffers = 0;
+    size_t num_separate_samplers = 0; // HLSL edge case
+    size_t num_separate_images = 0; // HLSL edge case
 
     /* Create the SPIRV-Cross context */
     result = spvc_context_create(&context);
@@ -1526,12 +1528,13 @@ bool SDL_ShaderCross_ReflectGraphicsSPIRV(
             resources,
             SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS,
             (const spvc_reflected_resource **)&reflected_resources,
-            &num_texture_samplers);
+            &num_separate_samplers);
         if (result < 0) {
             SPVC_ERROR(spvc_resources_get_resource_list_for_type);
             spvc_context_destroy(context);
             return false;
         }
+        num_texture_samplers = num_separate_samplers;
     }
 
     // Storage textures
@@ -1546,6 +1549,20 @@ bool SDL_ShaderCross_ReflectGraphicsSPIRV(
         return false;
     }
 
+    // If source is HLSL, storage images might be marked as separate images
+    result = spvc_resources_get_resource_list_for_type(
+        resources,
+        SPVC_RESOURCE_TYPE_SEPARATE_IMAGE,
+        (const spvc_reflected_resource **)&reflected_resources,
+        &num_separate_images);
+    if (result < 0) {
+        SPVC_ERROR(spvc_resources_get_resource_list_for_type);
+        spvc_context_destroy(context);
+        return false;
+    }
+    // The number of storage textures is the number of separate images minus the number of samplers.
+    num_storage_textures += (num_separate_images - num_separate_samplers);
+
     // Storage buffers
     result = spvc_resources_get_resource_list_for_type(
         resources,
@@ -1597,6 +1614,8 @@ bool SDL_ShaderCross_ReflectComputeSPIRV(
 
     size_t num_storage_textures = 0;
     size_t num_storage_buffers = 0;
+    size_t num_separate_samplers = 0; // HLSL edge case
+    size_t num_separate_images = 0; // HLSL edge case
 
     /* Create the SPIRV-Cross context */
     result = spvc_context_create(&context);
@@ -1649,12 +1668,13 @@ bool SDL_ShaderCross_ReflectComputeSPIRV(
             resources,
             SPVC_RESOURCE_TYPE_SEPARATE_SAMPLERS,
             (const spvc_reflected_resource **)&reflected_resources,
-            &num_texture_samplers);
+            &num_separate_samplers);
         if (result < 0) {
             SPVC_ERROR(spvc_resources_get_resource_list_for_type);
             spvc_context_destroy(context);
             return false;
         }
+        num_texture_samplers = num_separate_samplers;
     }
 
     // Storage textures
@@ -1669,6 +1689,20 @@ bool SDL_ShaderCross_ReflectComputeSPIRV(
         return false;
     }
 
+    // If source is HLSL, readonly storage images might be marked as separate images
+    result = spvc_resources_get_resource_list_for_type(
+        resources,
+        SPVC_RESOURCE_TYPE_SEPARATE_IMAGE,
+        (const spvc_reflected_resource **)&reflected_resources,
+        &num_separate_images);
+    if (result < 0) {
+        SPVC_ERROR(spvc_resources_get_resource_list_for_type);
+        spvc_context_destroy(context);
+        return false;
+    }
+    // The number of storage textures is the number of separate images minus the number of samplers.
+    num_storage_textures += (num_separate_images - num_separate_samplers);
+
     for (size_t i = 0; i < num_storage_textures; i += 1) {
         if (!spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationDescriptorSet) || !spvc_compiler_has_decoration(compiler, reflected_resources[i].id, SpvDecorationBinding)) {
             SDL_SetError("%s", "Shader resources must have descriptor set and binding index!");