Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46735 Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/d3d9/d3d9_main.c | 107 +++++++++++++++++++++++++++++++++++++-- dlls/d3d9/tests/device.c | 64 +++++++++++++++++++++++ 2 files changed, 167 insertions(+), 4 deletions(-)
diff --git a/dlls/d3d9/d3d9_main.c b/dlls/d3d9/d3d9_main.c index 21df2a34cd2..a2e09ca1dfb 100644 --- a/dlls/d3d9/d3d9_main.c +++ b/dlls/d3d9/d3d9_main.c @@ -75,18 +75,117 @@ HRESULT WINAPI DECLSPEC_HOTPATCH Direct3DCreate9Ex(UINT sdk_version, IDirect3D9E return D3D_OK; }
+/* 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(). + * + * 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. */ + +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; + +typedef struct +{ + 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 *code, DWORD code_len); + HRESULT WINAPI (*End)(IDirect3DShaderValidator9 *iface); +} IDirect3DShaderValidator9Vtbl; + +struct IDirect3DShaderValidator9 +{ + const IDirect3DShaderValidator9Vtbl *vtbl; +}; + +static HRESULT WINAPI shader_validator_QueryInterface(IDirect3DShaderValidator9 *iface, REFIID iid, void **out) +{ + TRACE("iface %p, iid %p, out %p.\n", iface, 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. + * - "code" comprises a single instruction; the program must determine its + * length. + * - "code_len" is in DWORDs. */ +static HRESULT WINAPI shader_validator_Instruction(IDirect3DShaderValidator9 *iface, + const char *file, int line, const DWORD *code, DWORD code_len) +{ + FIXME("iface %p, file %s, line %u, code %p, code_len %u, stub!\n", iface, debugstr_a(file), line, code, code_len); + return S_OK; +} + +static HRESULT WINAPI shader_validator_End(IDirect3DShaderValidator9 *iface) +{ + FIXME("iface %p, stub!\n", iface); + return S_OK; +} + +static const 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}; + /******************************************************************* * Direct3DShaderValidatorCreate9 (D3D9.@) * * No documentation available for this function. * SDK only says it is internal and shouldn't be used. */ -void* WINAPI Direct3DShaderValidatorCreate9(void) +IDirect3DShaderValidator9 * WINAPI Direct3DShaderValidatorCreate9(void) { - static int once; + TRACE("Returning validator %p.\n", &shader_validator);
- if (!once++) FIXME("stub\n"); - return NULL; + return &shader_validator; }
/*********************************************************************** diff --git a/dlls/d3d9/tests/device.c b/dlls/d3d9/tests/device.c index 38b2dbcb3a3..6fbec0c2fd2 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 */ @@ -13434,8 +13436,67 @@ 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; + +typedef struct +{ + 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 *code, DWORD code_len); + HRESULT WINAPI (*End)(IDirect3DShaderValidator9 *iface); +} IDirect3DShaderValidator9Vtbl; + +struct IDirect3DShaderValidator9 +{ + const 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; @@ -13463,6 +13524,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(); @@ -13562,6 +13625,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)); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=64746
Your paranoid android.
=== w1064v1809 (32 bit report) ===
d3d9: device.c:1810: Test failed: The cursor handle is 00010003
Zebediah Figura z.figura12@gmail.com wrote:
+typedef struct +{
- 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 *code, DWORD code_len);
- HRESULT WINAPI (*End)(IDirect3DShaderValidator9 *iface);
+} IDirect3DShaderValidator9Vtbl;
WINAPI should be moved inside of brackets otherwise this won't compile with MSVC (here and in other places, confusingly this patch uses correct and incorrect styles).
On 2/9/20 4:39 AM, Dmitry Timoshkov wrote:
Zebediah Figura z.figura12@gmail.com wrote:
+typedef struct +{
- 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 *code, DWORD code_len);
- HRESULT WINAPI (*End)(IDirect3DShaderValidator9 *iface);
+} IDirect3DShaderValidator9Vtbl;
WINAPI should be moved inside of brackets otherwise this won't compile with MSVC (here and in other places, confusingly this patch uses correct and incorrect styles).
Thank you for catching that; it was an unintentional mistake.