From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com Signed-off-by: Matteo Bruni mbruni@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
From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2: Rebase.
dlls/d3dcompiler_43/reflection.c | 4 ++-- dlls/d3dcompiler_43/tests/reflection.c | 1 - 2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dcompiler_43/reflection.c b/dlls/d3dcompiler_43/reflection.c index 787d0388f93..096efc91bd4 100644 --- a/dlls/d3dcompiler_43/reflection.c +++ b/dlls/d3dcompiler_43/reflection.c @@ -1507,9 +1507,9 @@ static HRESULT d3dcompiler_parse_rdef(struct d3dcompiler_shader_reflection *r, c TRACE("Target: %#x.\n", r->target);
target_version = r->target & D3DCOMPILER_SHADER_TARGET_VERSION_MASK; - #if D3D_COMPILER_VERSION < 47 - if (target_version >= 0x501) + if (target_version >= 0x501 && (!D3D_COMPILER_VERSION || ((r->target & D3DCOMPILER_SHADER_TARGET_SHADERTYPE_MASK) + >> D3DCOMPILER_SHADER_TARGET_SHADERTYPE_SHIFT) != 0x4353 /* CS */)) { WARN("Target version %#x is not supported in d3dcompiler %u.\n", target_version, D3D_COMPILER_VERSION); return E_INVALIDARG; diff --git a/dlls/d3dcompiler_43/tests/reflection.c b/dlls/d3dcompiler_43/tests/reflection.c index e4261ad0d79..bfd79d04618 100644 --- a/dlls/d3dcompiler_43/tests/reflection.c +++ b/dlls/d3dcompiler_43/tests/reflection.c @@ -1231,7 +1231,6 @@ static void test_reflection_cs(void) 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;
Signed-off-by: Matteo Bruni mbruni@codeweavers.com ---
From an idea by Paul Gofman.
dlls/d3dcompiler_43/reflection.c | 11 ++++++-- dlls/d3dcompiler_43/tests/reflection.c | 39 ++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/dlls/d3dcompiler_43/reflection.c b/dlls/d3dcompiler_43/reflection.c index 096efc91bd4..0fa0dc16839 100644 --- a/dlls/d3dcompiler_43/reflection.c +++ b/dlls/d3dcompiler_43/reflection.c @@ -52,6 +52,8 @@ enum D3DCOMPILER_SIGNATURE_ELEMENT_SIZE #define D3DCOMPILER_SHADER_TARGET_SHADERTYPE_MASK 0xffff0000 #define D3DCOMPILER_SHADER_TARGET_SHADERTYPE_SHIFT 16
+#define D3DCOMPILER_SHDR_SHADER_TYPE_CS 0x4353 + enum d3dcompiler_shader_type { D3DCOMPILER_SHADER_TYPE_CS = 5, @@ -1487,6 +1489,9 @@ static HRESULT d3dcompiler_parse_rdef(struct d3dcompiler_shader_reflection *r, c size_t size = data_size >> 2; uint32_t target_version; const char *ptr = data; +#if D3D_COMPILER_VERSION < 47 + uint32_t shader_type; +#endif HRESULT hr;
TRACE("Size %Iu.\n", size); @@ -1508,8 +1513,10 @@ static HRESULT d3dcompiler_parse_rdef(struct d3dcompiler_shader_reflection *r, c
target_version = r->target & D3DCOMPILER_SHADER_TARGET_VERSION_MASK; #if D3D_COMPILER_VERSION < 47 - if (target_version >= 0x501 && (!D3D_COMPILER_VERSION || ((r->target & D3DCOMPILER_SHADER_TARGET_SHADERTYPE_MASK) - >> D3DCOMPILER_SHADER_TARGET_SHADERTYPE_SHIFT) != 0x4353 /* CS */)) + shader_type = (r->target & D3DCOMPILER_SHADER_TARGET_SHADERTYPE_MASK) + >> D3DCOMPILER_SHADER_TARGET_SHADERTYPE_SHIFT; + if ((target_version >= 0x501 && shader_type != D3DCOMPILER_SHDR_SHADER_TYPE_CS) + || (!D3D_COMPILER_VERSION && shader_type == D3DCOMPILER_SHDR_SHADER_TYPE_CS)) { WARN("Target version %#x is not supported in d3dcompiler %u.\n", target_version, D3D_COMPILER_VERSION); return E_INVALIDARG; diff --git a/dlls/d3dcompiler_43/tests/reflection.c b/dlls/d3dcompiler_43/tests/reflection.c index bfd79d04618..70f3a51683a 100644 --- a/dlls/d3dcompiler_43/tests/reflection.c +++ b/dlls/d3dcompiler_43/tests/reflection.c @@ -1198,9 +1198,32 @@ 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_4_0 /Fo + */ +#if 0 + [numthreads(16, 8, 4)] + void main( uint3 DTid : SV_DispatchThreadID ) + { + } +#endif + static const DWORD test_blob_cs_4_0[] = + { + 0x43425844, 0x698a31ca, 0x8c6eee35, 0x2377107a, 0xe1e69066, 0x00000001, 0x00000150, 0x00000005, + 0x00000034, 0x0000008c, 0x0000009c, 0x000000ac, 0x000000d4, 0x46454452, 0x00000050, 0x00000000, + 0x00000000, 0x00000000, 0x0000001c, 0x43530400, 0x00000100, 0x0000001c, 0x7263694d, 0x666f736f, + 0x52282074, 0x4c482029, 0x53204c53, 0x65646168, 0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e, + 0x2e323539, 0x31313133, 0xababab00, 0x4e475349, 0x00000008, 0x00000000, 0x00000008, 0x4e47534f, + 0x00000008, 0x00000000, 0x00000008, 0x58454853, 0x00000020, 0x00050040, 0x00000008, 0x0100086a, + 0x0400009b, 0x00000010, 0x00000008, 0x00000004, 0x0100003e, 0x54415453, 0x00000074, 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, + }; + /* * fxc.exe /T cs_5_1 /Fo */ @@ -1228,10 +1251,17 @@ static void test_reflection_cs(void) }; UINT size_x, size_y, size_z, size_total; ID3D11ShaderReflection *ref11; - HRESULT hr; + HRESULT hr, expected; + + expected = D3D_COMPILER_VERSION ? S_OK : E_INVALIDARG; + hr = call_reflect(test_blob_cs_4_0, test_blob_cs_4_0[6], &IID_ID3D11ShaderReflection, (void **)&ref11); + ok(hr == expected, "Unexpected hr %#lx.\n", hr); + + if (SUCCEEDED(hr)) + ref11->lpVtbl->Release(ref11);
hr = call_reflect(test_blob, test_blob[6], &IID_ID3D11ShaderReflection, (void **)&ref11); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == expected, "Unexpected hr %#lx.\n", hr); if (FAILED(hr)) return; size_total = ref11->lpVtbl->GetThreadGroupSize(ref11, &size_x, &size_y, &size_z); @@ -1242,7 +1272,6 @@ static void test_reflection_cs(void)
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) @@ -2208,10 +2237,10 @@ START_TEST(reflection) #if D3D_COMPILER_VERSION test_reflection_references(); test_reflection_interfaces(); - test_reflection_cs(); #else test_d3d10_interfaces(); #endif + test_reflection_cs(); test_reflection_desc_vs(); test_reflection_desc_ps(); test_reflection_desc_ps_output();