vkd3d-utils: Implement D3DDisassemble().

Very loosely based on Wine's d3dcompiler_43.
This commit is contained in:
Henri Verbeet 2024-01-25 19:40:39 +01:00 committed by Alexandre Julliard
parent 4fd4ecc020
commit 8c6f5b847b
Notes: Alexandre Julliard 2024-01-29 22:53:26 +01:00
Approved-by: Giovanni Mascellani (@giomasce)
Approved-by: Alexandre Julliard (@julliard)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/610
6 changed files with 176 additions and 0 deletions

View File

@ -89,6 +89,10 @@ const char *debugstr_w(const WCHAR *wstr, size_t wchar_size);
#define TRACE_ON() (vkd3d_dbg_get_level() == VKD3D_DBG_LEVEL_TRACE)
#endif
#ifndef WARN_ON
#define WARN_ON() (vkd3d_dbg_get_level() >= VKD3D_DBG_LEVEL_WARN)
#endif
#define FIXME_ONCE VKD3D_DBG_LOG_ONCE(FIXME, WARN)
#define VKD3D_DEBUG_ENV_NAME(name) const char *const vkd3d_dbg_env_name = name

View File

@ -79,6 +79,7 @@ HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filen
const void *secondary_data, SIZE_T secondary_data_size, ID3DBlob **shader,
ID3DBlob **error_messages);
HRESULT WINAPI D3DCreateBlob(SIZE_T size, ID3DBlob **blob);
HRESULT WINAPI D3DDisassemble(const void *data, SIZE_T data_size, UINT flags, const char *comments, ID3DBlob **blob);
HRESULT WINAPI D3DGetBlobPart(const void *data, SIZE_T data_size, D3D_BLOB_PART part, UINT flags, ID3DBlob **blob);
HRESULT WINAPI D3DGetDebugInfo(const void *data, SIZE_T data_size, ID3DBlob **blob);
HRESULT WINAPI D3DGetInputAndOutputSignatureBlob(const void *data, SIZE_T data_size, ID3DBlob **blob);
@ -89,5 +90,8 @@ HRESULT WINAPI D3DPreprocess(const void *data, SIZE_T size, const char *filename
HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection);
HRESULT WINAPI D3DStripShader(const void *data, SIZE_T data_size, UINT flags, ID3DBlob **blob);
typedef HRESULT (WINAPI *pD3DDisassemble)(const void *data, SIZE_T data_size,
UINT flags, const char *comments, ID3DBlob **blob);
#endif /* __D3DCOMPILER_H__ */
#endif /* __VKD3D_D3DCOMPILER_H */

View File

@ -117,6 +117,8 @@ VKD3D_UTILS_API HRESULT WINAPI D3DGetOutputSignatureBlob(const void *data, SIZE_
VKD3D_UTILS_API HRESULT WINAPI D3DStripShader(const void *data, SIZE_T data_size, UINT flags, ID3DBlob **blob);
/** \since 1.11 */
VKD3D_UTILS_API HRESULT WINAPI D3DDisassemble(const void *data,
SIZE_T data_size, UINT flags, const char *comments, ID3DBlob **blob);
VKD3D_UTILS_API HRESULT WINAPI D3DReflect(const void *data, SIZE_T data_size, REFIID iid, void **reflection);
#ifdef __cplusplus

View File

@ -11,6 +11,7 @@ global:
D3DCompile;
D3DCompile2;
D3DCreateBlob;
D3DDisassemble;
D3DGetBlobPart;
D3DGetDebugInfo;
D3DGetInputAndOutputSignatureBlob;

View File

@ -928,3 +928,75 @@ void vkd3d_utils_set_log_callback(PFN_vkd3d_log callback)
vkd3d_set_log_callback(callback);
vkd3d_dbg_set_log_callback(callback);
}
HRESULT WINAPI D3DDisassemble(const void *data, SIZE_T data_size,
UINT flags, const char *comments, ID3DBlob **blob)
{
enum vkd3d_shader_source_type source_type;
struct vkd3d_shader_compile_info info;
struct vkd3d_shader_code output;
const char *p, *q, *end;
char *messages;
HRESULT hr;
int ret;
static const struct vkd3d_shader_compile_option options[] =
{
{VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_10},
};
TRACE("data %p, data_size %lu, flags %#x, comments %p, blob %p.\n",
data, data_size, flags, comments, blob);
if (flags)
FIXME("Ignoring flags %#x.\n", flags);
if (comments)
FIXME("Ignoring comments %s.\n", debugstr_a(comments));
if (!data_size)
return E_INVALIDARG;
if (data_size >= sizeof(uint32_t) && *(uint32_t *)data == TAG_DXBC)
source_type = VKD3D_SHADER_SOURCE_DXBC_TPF;
else
source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE;
info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO;
info.next = NULL;
info.source.code = data;
info.source.size = data_size;
info.source_type = source_type;
info.target_type = VKD3D_SHADER_TARGET_D3D_ASM;
info.options = options;
info.option_count = ARRAY_SIZE(options);
info.log_level = VKD3D_SHADER_LOG_INFO;
info.source_name = NULL;
ret = vkd3d_shader_compile(&info, &output, &messages);
if (messages && *messages && WARN_ON())
{
WARN("Compiler log:\n");
for (p = messages, end = p + strlen(p); p < end; p = q)
{
if (!(q = memchr(p, '\n', end - p)))
q = end;
else
++q;
WARN(" %.*s", (int)(q - p), p);
}
WARN("\n");
}
vkd3d_shader_free_messages(messages);
if (ret < 0)
{
WARN("Failed to disassemble shader, ret %d.\n", ret);
return hresult_from_vkd3d_result(ret);
}
if (FAILED(hr = vkd3d_blob_create((void *)output.code, output.size, blob)))
vkd3d_shader_free_shader_code(&output);
return hr;
}

View File

@ -1514,6 +1514,98 @@ static void test_signature_reflection(void)
}
}
static void test_disassemble_shader(void)
{
ID3DBlob *blob;
int hr;
/* A Direct3D 8 vertex shader without dcl_ instructions. */
static const uint32_t vs_1_1[] =
{
0xfffe0101, /* vs_1_1 */
0x00000005, 0x800f0000, 0x90000000, 0xa0e40000, /* mul r0, v0.x, c0 */
0x00000004, 0x800f0000, 0x90550000, 0xa0e40001, 0x80e40000, /* mad r0, v0.y, c1, r0 */
0x00000004, 0x800f0000, 0x90aa0000, 0xa0e40002, 0x80e40000, /* mad r0, v0.z, c2, r0 */
0x00000004, 0xc00f0000, 0x90ff0000, 0xa0e40003, 0x80e40000, /* mad oPos, v0.w, c3, r0 */
0x0000ffff, /* end */
};
static const uint32_t vs_2_0[] =
{
0xfffe0200, /* vs_2_0 */
0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
0x0200001f, 0x80000003, 0x900f0001, /* dcl_normal v1 */
0x0200001f, 0x8001000a, 0x900f0002, /* dcl_color1 v2 */
0x0200001f, 0x80000005, 0x900f0003, /* dcl_texcoord0 v3 */
0x02000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
0x02000001, 0xd00f0001, 0x90e40002, /* mov oD1, v2 */
0x02000001, 0xe0070000, 0x90e40003, /* mov oT0.xyz, v3 */
0x02000001, 0xc00f0001, 0x90ff0002, /* mov oFog, v2.w */
0x02000001, 0xc00f0002, 0x90ff0001, /* mov oPts, v1.w */
0x0000ffff, /* end */
};
/* A shader model 3 vertex shader without dcl_ instructions. */
static const uint32_t vs_3_0[] =
{
0xfffe0300, /* vs_3_0 */
0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
0x0000ffff, /* end */
};
/* A "shader model 4" d3dbc vertex shader. */
static const uint32_t vs_4_0[] =
{
0xfffe0400, /* vs_4_0 */
0x02000001, 0xe00f0000, 0x90e40000, /* mov o0, v0 */
0x0000ffff, /* end */
};
/* An actual shader model 4 dxbc-tpf vertex shader. */
static const uint32_t vs_4_0_dxbc[] =
{
#if 0
float4 main(float4 position : POSITION) : SV_POSITION
{
return position;
}
#endif
0x43425844, 0xa7a2f22d, 0x83ff2560, 0xe61638bd, 0x87e3ce90, 0x00000001, 0x000000d8, 0x00000003,
0x0000002c, 0x00000060, 0x00000094, 0x4e475349, 0x0000002c, 0x00000001, 0x00000008, 0x00000020,
0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0xababab00,
0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000001, 0x00000003,
0x00000000, 0x0000000f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x52444853, 0x0000003c, 0x00010040,
0x0000000f, 0x0300005f, 0x001010f2, 0x00000000, 0x04000067, 0x001020f2, 0x00000000, 0x00000001,
0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e,
};
hr = D3DDisassemble(vs_1_1, 0, 0, NULL, &blob);
ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
hr = D3DDisassemble(vs_1_1, sizeof(vs_1_1), 0, NULL, &blob);
todo ok(hr == S_OK, "Got hr %#x.\n", hr);
if (SUCCEEDED(hr))
ID3D10Blob_Release(blob);
hr = D3DDisassemble(vs_2_0, sizeof(vs_2_0), 0, NULL, &blob);
ok(hr == S_OK, "Got hr %#x.\n", hr);
ID3D10Blob_Release(blob);
hr = D3DDisassemble(vs_3_0, sizeof(vs_3_0), 0, NULL, &blob);
todo ok(hr == S_OK, "Got hr %#x.\n", hr);
if (SUCCEEDED(hr))
ID3D10Blob_Release(blob);
hr = D3DDisassemble(vs_4_0, sizeof(vs_4_0), 0, NULL, &blob);
todo ok(hr == S_OK, "Got hr %#x.\n", hr);
if (SUCCEEDED(hr))
ID3D10Blob_Release(blob);
hr = D3DDisassemble(vs_4_0_dxbc, sizeof(vs_4_0_dxbc), 0, NULL, &blob);
ok(hr == S_OK, "Got hr %#x.\n", hr);
ID3D10Blob_Release(blob);
}
START_TEST(hlsl_d3d12)
{
parse_args(argc, argv);
@ -1525,4 +1617,5 @@ START_TEST(hlsl_d3d12)
run_test(test_create_blob);
run_test(test_get_blob_part);
run_test(test_signature_reflection);
run_test(test_disassemble_shader);
}