[PATCH v2] d3d9: Return a stub interface from Direct3DShaderValidatorCreate9().
Zebediah Figura
z.figura12 at gmail.com
Sun Feb 9 10:17:03 CST 2020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46735
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/d3d9/d3d9_main.c | 111 +++++++++++++++++++++++++++++++++++++--
dlls/d3d9/tests/device.c | 64 ++++++++++++++++++++++
2 files changed, 171 insertions(+), 4 deletions(-)
diff --git a/dlls/d3d9/d3d9_main.c b/dlls/d3d9/d3d9_main.c
index 21df2a34cd2..5832841f7f8 100644
--- a/dlls/d3d9/d3d9_main.c
+++ b/dlls/d3d9/d3d9_main.c
@@ -75,18 +75,121 @@ 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.
+ *
+ * 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. */
+
+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..59dfb98483a 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));
}
--
2.25.0
More information about the wine-devel
mailing list