d3dcompiler: Implement d3dcompiler_shader_reflection_GetThreadGroupSize().

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Matteo Bruni <mbruni@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2022-03-23 13:58:15 +01:00 committed by Alexandre Julliard
parent 273ab6c774
commit 47b9c450c6
2 changed files with 148 additions and 4 deletions

View file

@ -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;

View file

@ -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