From 2a4a8a5cf34e9697a976a8272a1c93e5660cbea6 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 10 Feb 2020 18:26:31 +0330 Subject: [PATCH] d3d9: Return a stub interface from Direct3DShaderValidatorCreate9(). Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46735 Signed-off-by: Zebediah Figura Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/d3d9/d3d9_main.c | 126 +++++++++++++++++++++++++++++++++++---- dlls/d3d9/tests/device.c | 66 ++++++++++++++++++++ 2 files changed, 182 insertions(+), 10 deletions(-) diff --git a/dlls/d3d9/d3d9_main.c b/dlls/d3d9/d3d9_main.c index 21df2a34cd2..75e627dd765 100644 --- a/dlls/d3d9/d3d9_main.c +++ b/dlls/d3d9/d3d9_main.c @@ -75,18 +75,124 @@ HRESULT WINAPI DECLSPEC_HOTPATCH Direct3DCreate9Ex(UINT sdk_version, IDirect3D9E return D3D_OK; } -/******************************************************************* - * Direct3DShaderValidatorCreate9 (D3D9.@) +/* The callback is called on any error encountered during validation, including + * improper IDirect3DShaderValidator9 method calls. + * - "file" and "line" are passed through directly from Instruction(). "line" + * is provably 32-bit, as 64-bit values passed to Instruction() will be + * truncated. + * - "arg3" has been observed to be at least 0, 2, and 6. The integer size is + * not known. + * - "message_id" is a numeric error code. fxc.exe adds 5000 before printing + * it. The integer size is not known. + * - "context" is passed through directly from Begin(). * - * No documentation available for this function. - * SDK only says it is internal and shouldn't be used. - */ -void* WINAPI Direct3DShaderValidatorCreate9(void) -{ - static int once; + * Improper calls to IDirect3DShaderValidator9 methods, or other errors not + * generated by specific Instruction() calls, yield NULL as the file, and + * either 0 or -1 as the line. + * + * The callback return type is not known, but programs (fxc.exe, The Sims 2) + * seem to consistently return 0. + * + * The interface and method names below are derived from the messages that + * native d3d9 prints on said improper method calls. + * + * Calls to Begin(), Instruction(), End() have been observed to return S_OK and + * E_FAIL. E_FAIL is not always returned if an error message is handed to the + * callback. */ - if (!once++) FIXME("stub\n"); - return NULL; +typedef HRESULT (WINAPI *shader_validator_cb)(const char *file, int line, + DWORD_PTR arg3, DWORD_PTR message_id, const char *message, void *context); + +typedef struct IDirect3DShaderValidator9 IDirect3DShaderValidator9; + +struct IDirect3DShaderValidator9Vtbl +{ + HRESULT (WINAPI *QueryInterface)(IDirect3DShaderValidator9 *iface, REFIID iid, void **out); + ULONG (WINAPI *AddRef)(IDirect3DShaderValidator9 *iface); + ULONG (WINAPI *Release)(IDirect3DShaderValidator9 *iface); + HRESULT (WINAPI *Begin)(IDirect3DShaderValidator9 *iface, + shader_validator_cb callback, void *context, DWORD_PTR arg3); + HRESULT (WINAPI *Instruction)(IDirect3DShaderValidator9 *iface, + const char *file, int line, const DWORD *tokens, DWORD token_count); + HRESULT (WINAPI *End)(IDirect3DShaderValidator9 *iface); +}; + +struct IDirect3DShaderValidator9 +{ + const struct IDirect3DShaderValidator9Vtbl *vtbl; +}; + +static HRESULT WINAPI shader_validator_QueryInterface(IDirect3DShaderValidator9 *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + + return E_NOINTERFACE; +} + +static ULONG WINAPI shader_validator_AddRef(IDirect3DShaderValidator9 *iface) +{ + TRACE("iface %p.\n", iface); + + return 2; +} + +static ULONG WINAPI shader_validator_Release(IDirect3DShaderValidator9 *iface) +{ + TRACE("iface %p.\n", iface); + + return 1; +} + +/* The size and type of the third argument is not known. The Sims 2 passes 0; + * fxc.exe passes 1. */ +static HRESULT WINAPI shader_validator_Begin(IDirect3DShaderValidator9 *iface, + shader_validator_cb callback, void *context, DWORD_PTR arg3) +{ + FIXME("iface %p, callback %p, context %p, arg3 %#Ix, stub!\n", iface, callback, context, arg3); + + return S_OK; +} + +/* - "file" and "line" are passed directly through to the callback. + * - "tokens" comprises a single instruction; the caller must determine its + * length. + * - "token_count" is in DWORDs. */ +static HRESULT WINAPI shader_validator_Instruction(IDirect3DShaderValidator9 *iface, + const char *file, int line, const DWORD *tokens, DWORD token_count) +{ + FIXME("iface %p, file %s, line %u, tokens %p, token_count %u, stub!\n", + iface, debugstr_a(file), line, tokens, token_count); + + return S_OK; +} + +static HRESULT WINAPI shader_validator_End(IDirect3DShaderValidator9 *iface) +{ + FIXME("iface %p, stub!\n", iface); + + return S_OK; +} + +static const struct IDirect3DShaderValidator9Vtbl shader_validator_vtbl = +{ + shader_validator_QueryInterface, + shader_validator_AddRef, + shader_validator_Release, + shader_validator_Begin, + shader_validator_Instruction, + shader_validator_End, +}; + +static IDirect3DShaderValidator9 shader_validator = {&shader_validator_vtbl}; + +IDirect3DShaderValidator9 * WINAPI Direct3DShaderValidatorCreate9(void) +{ + TRACE("Returning validator %p.\n", &shader_validator); + + return &shader_validator; } /*********************************************************************** diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 156cb188f05..8c1ebc1719c 100644 --- a/dlls/d3d9/tests/device.c +++ b/dlls/d3d9/tests/device.c @@ -53,6 +53,8 @@ struct device_desc static DEVMODEW registry_mode; +static void *(WINAPI *Direct3DShaderValidatorCreate9)(void); + static const DWORD simple_vs[] = { 0xfffe0101, /* vs_1_1 */ @@ -13447,8 +13449,69 @@ static void test_multi_adapter(void) IDirect3D9_Release(d3d); } +typedef HRESULT (WINAPI *shader_validator_cb)(const char *file, int line, + DWORD_PTR arg3, DWORD_PTR message_id, const char *message, void *context); + +typedef struct IDirect3DShaderValidator9 IDirect3DShaderValidator9; + +struct IDirect3DShaderValidator9Vtbl +{ + HRESULT (WINAPI *QueryInterface)(IDirect3DShaderValidator9 *iface, REFIID iid, void **out); + ULONG (WINAPI *AddRef)(IDirect3DShaderValidator9 *iface); + ULONG (WINAPI *Release)(IDirect3DShaderValidator9 *iface); + HRESULT (WINAPI *Begin)(IDirect3DShaderValidator9 *iface, + shader_validator_cb callback, void *context, DWORD_PTR arg3); + HRESULT (WINAPI *Instruction)(IDirect3DShaderValidator9 *iface, + const char *file, int line, const DWORD *tokens, DWORD token_count); + HRESULT (WINAPI *End)(IDirect3DShaderValidator9 *iface); +}; + +struct IDirect3DShaderValidator9 +{ + const struct IDirect3DShaderValidator9Vtbl *vtbl; +}; + +HRESULT WINAPI test_shader_validator_cb(const char *file, int line, DWORD_PTR arg3, + DWORD_PTR message_id, const char *message, void *context) +{ + ok(0, "Unexpected call.\n"); + return S_OK; +} + +static void test_shader_validator(void) +{ + IDirect3DShaderValidator9 *validator; + ULONG refcount; + HRESULT hr; + + validator = Direct3DShaderValidatorCreate9(); + + hr = validator->vtbl->Begin(validator, test_shader_validator_cb, NULL, 0); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = validator->vtbl->Instruction(validator, NULL, 0, &simple_vs[0], 1); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = validator->vtbl->Instruction(validator, NULL, 0, &simple_vs[1], 3); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = validator->vtbl->Instruction(validator, NULL, 0, &simple_vs[4], 4); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = validator->vtbl->Instruction(validator, NULL, 0, &simple_vs[8], 4); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = validator->vtbl->Instruction(validator, NULL, 0, &simple_vs[12], 4); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = validator->vtbl->Instruction(validator, NULL, 0, &simple_vs[16], 4); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = validator->vtbl->Instruction(validator, NULL, 0, &simple_vs[20], 1); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = validator->vtbl->End(validator); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + + refcount = validator->vtbl->Release(validator); + todo_wine ok(!refcount, "Validator has %u references left.\n", refcount); +} + START_TEST(device) { + HMODULE d3d9_handle = GetModuleHandleA("d3d9.dll"); WNDCLASSA wc = {0}; IDirect3D9 *d3d9; DEVMODEW current_mode; @@ -13476,6 +13539,8 @@ START_TEST(device) wc.lpszClassName = "d3d9_test_wc"; RegisterClassA(&wc); + Direct3DShaderValidatorCreate9 = (void *)GetProcAddress(d3d9_handle, "Direct3DShaderValidatorCreate9"); + test_get_set_vertex_declaration(); test_get_declaration(); test_fvf_decl_conversion(); @@ -13575,6 +13640,7 @@ START_TEST(device) test_vertex_buffer_read_write(); test_get_display_mode(); test_multi_adapter(); + test_shader_validator(); UnregisterClassA("d3d9_test_wc", GetModuleHandleA(NULL)); }