[PATCH 1/2] d3dcompiler: Implement d3dcompiler_shader_reflection_GetThreadGroupSize().
Paul Gofman
pgofman at codeweavers.com
Tue Mar 8 04:56:42 CST 2022
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
dlls/d3dcompiler_43/reflection.c | 87 ++++++++++++++++++++++++--
dlls/d3dcompiler_43/tests/reflection.c | 57 +++++++++++++++++
2 files changed, 140 insertions(+), 4 deletions(-)
diff --git a/dlls/d3dcompiler_43/reflection.c b/dlls/d3dcompiler_43/reflection.c
index 91cc20cdded..1080b4dc6c8 100644
--- a/dlls/d3dcompiler_43/reflection.c
+++ b/dlls/d3dcompiler_43/reflection.c
@@ -50,6 +50,8 @@ 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
+#define D3DCOMPILER_SHADER_TYPE_CS 0x5
struct d3dcompiler_shader_signature
{
@@ -158,6 +160,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 +712,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 +1771,78 @@ 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)
{
+ DWORD 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(DWORD) != 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("Read invalid length %u, remaining %u.\n", len, size);
+ return E_FAIL;
+ }
+ if (opcode == SM5_OP_DCL_THREAD_GROUP)
+ {
+ TRACE("Found dcl_thread_group.\n");
+ 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];
+ }
+ size -= len;
+ u_ptr += len;
+ }
return S_OK;
}
@@ -1972,7 +2052,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..9781f91ab2b 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,14 @@ static void test_reflection_desc_ps(void)
ok(!desc.Stream, "(%u): got unexpected Stream %u.\n", i, desc.Stream);
}
+#if D3D_COMPILER_VERSION
+ size_total = ref11->lpVtbl->GetThreadGroupSize(ref11, &size_x, &size_y, &size_z);
+ ok(!size_x, "Got unexpected size %u.\n", size_x);
+ ok(!size_y, "Got unexpected size %u.\n", size_y);
+ ok(!size_z, "Got unexpected size %u.\n", size_z);
+ ok(!size_total, "Got unexpected size %u.\n", size_total);
+#endif
+
count = ref11->lpVtbl->Release(ref11);
ok(!count, "Got unexpected count %lu.\n", count);
}
@@ -1186,6 +1195,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, "Got 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, "Got unexpected size %u.\n", size_x);
+ ok(size_y == 8, "Got unexpected size %u.\n", size_y);
+ ok(size_z == 4, "Got unexpected size %u.\n", size_z);
+ ok(size_total == size_x * size_y *size_z, "Got 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 +2206,7 @@ START_TEST(reflection)
#if D3D_COMPILER_VERSION
test_reflection_references();
test_reflection_interfaces();
+ test_reflection_cs();
#else
test_d3d10_interfaces();
#endif
--
2.35.1
More information about the wine-devel
mailing list