[PATCH v2 1/3] d3dcompiler: Implement d3dcompiler_shader_reflection_GetThreadGroupSize().

Matteo Bruni mbruni at codeweavers.com
Wed Mar 23 07:58:15 CDT 2022


From: Paul Gofman <pgofman at codeweavers.com>

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
v2: Make a few small tweaks, mostly stylistic.

 dlls/d3dcompiler_43/reflection.c       | 92 ++++++++++++++++++++++++--
 dlls/d3dcompiler_43/tests/reflection.c | 60 +++++++++++++++++
 2 files changed, 148 insertions(+), 4 deletions(-)

diff --git a/dlls/d3dcompiler_43/reflection.c b/dlls/d3dcompiler_43/reflection.c
index 91cc20cdded..787d0388f93 100644
--- a/dlls/d3dcompiler_43/reflection.c
+++ b/dlls/d3dcompiler_43/reflection.c
@@ -50,6 +50,12 @@ enum D3DCOMPILER_SIGNATURE_ELEMENT_SIZE
 
 #define D3DCOMPILER_SHADER_TARGET_VERSION_MASK 0xffff
 #define D3DCOMPILER_SHADER_TARGET_SHADERTYPE_MASK 0xffff0000
+#define D3DCOMPILER_SHADER_TARGET_SHADERTYPE_SHIFT 16
+
+enum d3dcompiler_shader_type
+{
+    D3DCOMPILER_SHADER_TYPE_CS = 5,
+};
 
 struct d3dcompiler_shader_signature
 {
@@ -158,6 +164,9 @@ struct d3dcompiler_shader_reflection
     D3D_TESSELLATOR_OUTPUT_PRIMITIVE hs_output_primitive;
     D3D_TESSELLATOR_PARTITIONING hs_partitioning;
     D3D_TESSELLATOR_DOMAIN tessellator_domain;
+    UINT thread_group_size_x;
+    UINT thread_group_size_y;
+    UINT thread_group_size_z;
 
     struct d3dcompiler_shader_signature *isgn;
     struct d3dcompiler_shader_signature *osgn;
@@ -707,9 +716,21 @@ static HRESULT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetMinFeatureLeve
 static UINT STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetThreadGroupSize(
         ID3D11ShaderReflection *iface, UINT *sizex, UINT *sizey, UINT *sizez)
 {
-    FIXME("iface %p, sizex %p, sizey %p, sizez %p stub!\n", iface, sizex, sizey, sizez);
+    struct d3dcompiler_shader_reflection *reflection = impl_from_ID3D11ShaderReflection(iface);
 
-    return 0;
+    TRACE("iface %p, sizex %p, sizey %p, sizez %p.\n", iface, sizex, sizey, sizez);
+
+    if (!sizex || !sizey || !sizez)
+    {
+        WARN("Invalid argument specified.\n");
+        return E_INVALIDARG;
+    }
+
+    *sizex = reflection->thread_group_size_x;
+    *sizey = reflection->thread_group_size_y;
+    *sizez = reflection->thread_group_size_z;
+
+    return *sizex * *sizey * *sizez;
 }
 
 static UINT64 STDMETHODCALLTYPE d3dcompiler_shader_reflection_GetRequiresFlags(
@@ -1754,15 +1775,79 @@ static HRESULT d3dcompiler_parse_signature(struct d3dcompiler_shader_signature *
     return S_OK;
 }
 
+#define SM4_OPCODE_MASK                 0xff
+#define SM4_INSTRUCTION_LENGTH_SHIFT    24
+#define SM4_INSTRUCTION_LENGTH_MASK     (0x1fu << SM4_INSTRUCTION_LENGTH_SHIFT)
+
+enum sm4_opcode
+{
+    SM5_OP_DCL_THREAD_GROUP                 = 0x9b,
+};
+
 static HRESULT d3dcompiler_parse_shdr(struct d3dcompiler_shader_reflection *r, const char *data, size_t data_size)
 {
+    uint32_t opcode_token, opcode;
+    uint32_t size, shader_type;
     const char *ptr = data;
+    const uint32_t *u_ptr;
+    unsigned int len;
 
     r->version = read_u32(&ptr);
     TRACE("Shader version: %u\n", r->version);
 
-    /* todo: Check if anything else is needed from the shdr or shex blob. */
+    shader_type = (r->version & D3DCOMPILER_SHADER_TARGET_SHADERTYPE_MASK)
+            >> D3DCOMPILER_SHADER_TARGET_SHADERTYPE_SHIFT;
 
+    if (shader_type != D3DCOMPILER_SHADER_TYPE_CS)
+    {
+        /* TODO: Check if anything else is needed from the SHDR or SHEX blob. */
+        return S_OK;
+    }
+
+    size = read_u32(&ptr);
+    TRACE("size %u.\n", size);
+    if (size * sizeof(uint32_t) != data_size || size < 2)
+    {
+        WARN("Invalid size %u.\n", size);
+        return E_FAIL;
+    }
+    size -= 2;
+    u_ptr = (uint32_t *)ptr;
+    while (size)
+    {
+        opcode_token = *u_ptr;
+        opcode = opcode_token & SM4_OPCODE_MASK;
+        len = (opcode_token & SM4_INSTRUCTION_LENGTH_MASK) >> SM4_INSTRUCTION_LENGTH_SHIFT;
+        if (!len)
+        {
+            if (size < 2)
+            {
+                WARN("End of byte-code, failed to read length token.\n");
+                return E_FAIL;
+            }
+            len = u_ptr[1];
+        }
+        if (!len || size < len)
+        {
+            WARN("Invalid instruction length %u, size %u.\n", len, size);
+            return E_FAIL;
+        }
+        if (opcode == SM5_OP_DCL_THREAD_GROUP)
+        {
+            if (len != 4)
+            {
+                WARN("Invalid dcl_thread_group opcode length %u.\n", len);
+                return E_FAIL;
+            }
+            r->thread_group_size_x = u_ptr[1];
+            r->thread_group_size_y = u_ptr[2];
+            r->thread_group_size_z = u_ptr[3];
+            TRACE("Found dcl_thread_group %u, %u, %u.\n",
+                    r->thread_group_size_x, r->thread_group_size_y, r->thread_group_size_z);
+        }
+        size -= len;
+        u_ptr += len;
+    }
     return S_OK;
 }
 
@@ -1972,7 +2057,6 @@ HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID riid, void
     }
 
     *reflector = object;
-
     TRACE("Created ID3D11ShaderReflection %p\n", object);
 
     return S_OK;
diff --git a/dlls/d3dcompiler_43/tests/reflection.c b/dlls/d3dcompiler_43/tests/reflection.c
index f2b7f094de6..e4261ad0d79 100644
--- a/dlls/d3dcompiler_43/tests/reflection.c
+++ b/dlls/d3dcompiler_43/tests/reflection.c
@@ -777,6 +777,7 @@ static void test_reflection_desc_ps(void)
     D3D_NAME expected;
     unsigned int i;
 #if D3D_COMPILER_VERSION
+    UINT size_x, size_y, size_z, size_total;
     UINT ret;
 #endif
 
@@ -920,6 +921,17 @@ static void test_reflection_desc_ps(void)
             ok(!desc.Stream, "(%u): got unexpected Stream %u.\n", i, desc.Stream);
     }
 
+#if D3D_COMPILER_VERSION
+    size_x = 0xdeadbeef;
+    size_y = 0xdeadbeef;
+    size_z = 0xdeadbeef;
+    size_total = ref11->lpVtbl->GetThreadGroupSize(ref11, &size_x, &size_y, &size_z);
+    ok(!size_x, "Unexpected size %u.\n", size_x);
+    ok(!size_y, "Unexpected size %u.\n", size_y);
+    ok(!size_z, "Unexpected size %u.\n", size_z);
+    ok(!size_total, "Unexpected size %u.\n", size_total);
+#endif
+
     count = ref11->lpVtbl->Release(ref11);
     ok(!count, "Got unexpected count %lu.\n", count);
 }
@@ -1186,6 +1198,53 @@ static const D3D12_SHADER_INPUT_BIND_DESC test_reflection_bound_resources_result
     {"c2", D3D_SIT_CBUFFER, 1, 1, 0, 0, D3D_SRV_DIMENSION_UNKNOWN, 0, 0, 1},
 };
 
+#if D3D_COMPILER_VERSION
+static void test_reflection_cs(void)
+{
+    /*
+     * fxc.exe /T cs_5_1 /Fo
+     */
+#if 0
+    [numthreads(16, 8, 4)]
+    void main( uint3 DTid : SV_DispatchThreadID )
+    {
+    }
+#endif
+    static const DWORD test_blob[] =
+    {
+        0x43425844, 0x77a220d9, 0xfebd5b9c, 0x14a86e30, 0x57537394, 0x00000001, 0x00000184, 0x00000005,
+        0x00000034, 0x000000a0, 0x000000b0, 0x000000c0, 0x000000e8, 0x46454452, 0x00000064, 0x00000000,
+        0x00000000, 0x00000000, 0x0000003c, 0x43530501, 0x00000500, 0x0000003c, 0x25441313, 0x0000003c,
+        0x00000018, 0x00000028, 0x00000028, 0x00000024, 0x0000000c, 0x00000000, 0x7263694d, 0x666f736f,
+        0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x31207265, 0x00312e30,
+        0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, 0x00000008, 0x00000000, 0x00000008,
+        0x58454853, 0x00000020, 0x00050051, 0x00000008, 0x0100086a, 0x0400009b, 0x00000010, 0x00000008,
+        0x00000004, 0x0100003e, 0x54415453, 0x00000094, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
+        0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        0x00000000,
+    };
+    UINT size_x, size_y, size_z, size_total;
+    ID3D11ShaderReflection *ref11;
+    HRESULT hr;
+
+    hr = call_reflect(test_blob, test_blob[6], &IID_ID3D11ShaderReflection, (void **)&ref11);
+    todo_wine_if(D3D_COMPILER_VERSION < 47)
+    ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+    if (FAILED(hr))
+        return;
+    size_total = ref11->lpVtbl->GetThreadGroupSize(ref11, &size_x, &size_y, &size_z);
+    ok(size_x == 16, "Unexpected size %u.\n", size_x);
+    ok(size_y == 8, "Unexpected size %u.\n", size_y);
+    ok(size_z == 4, "Unexpected size %u.\n", size_z);
+    ok(size_total == size_x * size_y * size_z, "Unexpected size %u.\n", size_total);
+
+    ref11->lpVtbl->Release(ref11);
+}
+#endif
+
 static void test_reflection_bound_resources(const DWORD *blob, const D3D12_SHADER_INPUT_BIND_DESC *result,
         unsigned int result_count, unsigned int target_version)
 {
@@ -2150,6 +2209,7 @@ START_TEST(reflection)
 #if D3D_COMPILER_VERSION
     test_reflection_references();
     test_reflection_interfaces();
+    test_reflection_cs();
 #else
     test_d3d10_interfaces();
 #endif
-- 
2.34.1




More information about the wine-devel mailing list