This series allows linking of our d3dx9.dll against d3dcompiler.lib from the Windows SDK. It presumably also fixes the d3dcompiler tests, although I didn't bother building them with Visual Studio so far.
And yes, I did check, that stringification macro works on MSVC.
-- v2: d3dcompiler: Make D3DAssemble a private export. d3dcompiler/tests: Load D3DAssemble via GetProcAddress. d3dx9: Load D3DAssemble via GetProcAddress.
From: Stefan Dösinger stefan@codeweavers.com
This allows linking our d3dx9.dll to Microsoft's d3dcompiler.lib implib. --- dlls/d3dx9_36/shader.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-)
diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c index 1aa75d64dc5..7d06090aa15 100644 --- a/dlls/d3dx9_36/shader.c +++ b/dlls/d3dx9_36/shader.c @@ -26,11 +26,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
-/* This function is not declared in the SDK headers yet. */ -HRESULT WINAPI D3DAssemble(const void *data, SIZE_T datasize, const char *filename, - const D3D_SHADER_MACRO *defines, ID3DInclude *include, UINT flags, - ID3DBlob **shader, ID3DBlob **error_messages); - static inline BOOL is_valid_bytecode(DWORD token) { return (token & 0xfffe0000) == 0xfffe0000; @@ -193,19 +188,41 @@ HRESULT WINAPI D3DXFindShaderComment(const DWORD *byte_code, DWORD fourcc, const return S_FALSE; }
+static BOOL WINAPI load_d3dassemble_once(INIT_ONCE *once, void *param, void **context) +{ + /* FIXME: This assumes that d3dcompiler.h and dlls/d3dcompiler_XX/Makefile.in stay + * in sync regarding which library creates the unnumbered d3dcompiler.lib implib. + * GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, D3DCompile) would + * be nice, but "D3DCompile" will point to the IAT stub, not d3dcompiler_xy.dll */ + HMODULE mod = GetModuleHandleW(D3DCOMPILER_DLL_W); + void **assemble = param; + + if (!mod) + ERR("%s not found - which d3dcompiler are we linked against?\n", D3DCOMPILER_DLL_A); + + *assemble = (void *)GetProcAddress(mod, "D3DAssemble"); + return TRUE; +} + HRESULT WINAPI D3DXAssembleShader(const char *data, UINT data_len, const D3DXMACRO *defines, ID3DXInclude *include, DWORD flags, ID3DXBuffer **shader, ID3DXBuffer **error_messages) { + static HRESULT (WINAPI *pD3DAssemble)(const void *data, SIZE_T datasize, const char *filename, + const D3D_SHADER_MACRO * defines, ID3DInclude * include, UINT flags, + ID3DBlob * *shader, ID3DBlob * *error_messages); + static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT; HRESULT hr;
TRACE("data %p, data_len %u, defines %p, include %p, flags %#lx, shader %p, error_messages %p.\n", data, data_len, defines, include, flags, shader, error_messages);
+ InitOnceExecuteOnce(&init_once, load_d3dassemble_once, &pD3DAssemble, NULL); + /* Forward to d3dcompiler: the parameter types aren't really different, the actual data types are equivalent */ - hr = D3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines, - (ID3DInclude *)include, flags, (ID3DBlob **)shader, - (ID3DBlob **)error_messages); + hr = pD3DAssemble(data, data_len, NULL, (D3D_SHADER_MACRO *)defines, + (ID3DInclude *)include, flags, (ID3DBlob **)shader, + (ID3DBlob **)error_messages);
if(hr == E_FAIL) hr = D3DXERR_INVALIDDATA; return hr;
From: Stefan Dösinger stefan@codeweavers.com
--- dlls/d3dcompiler_43/tests/asm.c | 23 +++++++++++++++-------- dlls/d3dcompiler_43/tests/hlsl_d3d9.c | 11 +++++++++-- 2 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/dlls/d3dcompiler_43/tests/asm.c b/dlls/d3dcompiler_43/tests/asm.c index 6c22eae66c8..b7ec199a2f2 100644 --- a/dlls/d3dcompiler_43/tests/asm.c +++ b/dlls/d3dcompiler_43/tests/asm.c @@ -27,7 +27,7 @@ perhaps with a different name? */ #define D3DXERR_INVALIDDATA 0x88760b59
-HRESULT WINAPI D3DAssemble(const void *data, SIZE_T datasize, const char *filename, +static HRESULT (WINAPI *pD3DAssemble)(const void *data, SIZE_T datasize, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, UINT flags, ID3DBlob **shader, ID3DBlob **error_messages);
@@ -57,7 +57,7 @@ static void exec_tests(const char *name, struct shader_test tests[], unsigned in for(i = 0; i < count; i++) { /* D3DAssemble sets messages to 0 if there aren't error messages */ messages = NULL; - hr = D3DAssemble(tests[i].text, strlen(tests[i].text), NULL, NULL, + hr = pD3DAssemble(tests[i].text, strlen(tests[i].text), NULL, NULL, NULL, D3DCOMPILE_SKIP_VALIDATION, &shader, &messages); ok(hr == S_OK, "Test %s, shader %u: D3DAssemble failed with error %#lx - %ld.\n", name, i, hr, hr & 0xffff); if(messages) { @@ -1431,7 +1431,7 @@ static void failure_test(void) { { shader = NULL; messages = NULL; - hr = D3DAssemble(tests[i], strlen(tests[i]), NULL, NULL, NULL, D3DCOMPILE_SKIP_VALIDATION, &shader, &messages); + hr = pD3DAssemble(tests[i], strlen(tests[i]), NULL, NULL, NULL, D3DCOMPILE_SKIP_VALIDATION, &shader, &messages); ok(hr == D3DXERR_INVALIDDATA, "Test %u: Got unexpected hr %#lx.\n", i, hr); if (messages) { @@ -1556,7 +1556,7 @@ static void assembleshader_test(void) { /* defines test */ shader = NULL; messages = NULL; - hr = D3DAssemble(test1, strlen(test1), NULL, defines, NULL, D3DCOMPILE_SKIP_VALIDATION, &shader, &messages); + hr = pD3DAssemble(test1, strlen(test1), NULL, defines, NULL, D3DCOMPILE_SKIP_VALIDATION, &shader, &messages); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); if (messages) { @@ -1567,14 +1567,14 @@ static void assembleshader_test(void) {
/* NULL messages test */ shader = NULL; - hr = D3DAssemble(test1, strlen(test1), NULL, defines, NULL, D3DCOMPILE_SKIP_VALIDATION, &shader, NULL); + hr = pD3DAssemble(test1, strlen(test1), NULL, defines, NULL, D3DCOMPILE_SKIP_VALIDATION, &shader, NULL); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); if (shader) ID3D10Blob_Release(shader);
/* NULL shader test */ messages = NULL; - hr = D3DAssemble(test1, strlen(test1), NULL, defines, NULL, D3DCOMPILE_SKIP_VALIDATION, NULL, &messages); + hr = pD3DAssemble(test1, strlen(test1), NULL, defines, NULL, D3DCOMPILE_SKIP_VALIDATION, NULL, &messages); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); if (messages) { @@ -1586,7 +1586,7 @@ static void assembleshader_test(void) { shader = NULL; messages = NULL; include.ID3DInclude_iface.lpVtbl = &D3DInclude_Vtbl; - hr = D3DAssemble(testshader, strlen(testshader), NULL, NULL, + hr = pD3DAssemble(testshader, strlen(testshader), NULL, NULL, &include.ID3DInclude_iface, D3DCOMPILE_SKIP_VALIDATION, &shader, &messages); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); if (messages) @@ -1599,7 +1599,7 @@ static void assembleshader_test(void) { /* NULL shader tests */ shader = NULL; messages = NULL; - hr = D3DAssemble(NULL, 0, NULL, NULL, NULL, D3DCOMPILE_SKIP_VALIDATION, &shader, &messages); + hr = pD3DAssemble(NULL, 0, NULL, NULL, NULL, D3DCOMPILE_SKIP_VALIDATION, &shader, &messages); ok(hr == D3DXERR_INVALIDDATA, "Got unexpected hr %#lx.\n", hr); if (messages) { @@ -1762,6 +1762,13 @@ static void test_disassemble_shader(void)
START_TEST(asm) { +#define XSTR(a) STR(a) +#define STR(a) #a + HMODULE d3dcompiler = GetModuleHandleA("d3dcompiler_" XSTR(D3D_COMPILER_VERSION)); + pD3DAssemble = (void *)GetProcAddress(d3dcompiler, "D3DAssemble"); +#undef STR +#undef XSTR + preproc_test(); ps_1_1_test(); vs_1_1_test(); diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c index 4fef301a721..506475008ba 100644 --- a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c +++ b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c @@ -26,7 +26,7 @@
#define D3DXERR_INVALIDDATA 0x88760b59
-HRESULT WINAPI D3DAssemble(const void *data, SIZE_T datasize, const char *filename, +static HRESULT (WINAPI *pD3DAssemble)(const void *data, SIZE_T datasize, const char *filename, const D3D_SHADER_MACRO *defines, ID3DInclude *include, UINT flags, ID3DBlob **shader, ID3DBlob **error_messages);
@@ -1499,7 +1499,7 @@ static HRESULT call_D3DAssemble(const char *source_name, ID3DInclude *include, I "#include "include\include3.h"\n" "mov oC0, c0";
- return D3DAssemble(ps_code, sizeof(ps_code), source_name, NULL, include, 0, blob, errors); + return pD3DAssemble(ps_code, sizeof(ps_code), source_name, NULL, include, 0, blob, errors); }
static HRESULT call_D3DCompile(const char *source_name, ID3DInclude *include, ID3D10Blob **blob, ID3D10Blob **errors) @@ -1770,6 +1770,13 @@ START_TEST(hlsl_d3d9) } pD3DXGetShaderConstantTable = (void *)GetProcAddress(mod, "D3DXGetShaderConstantTable");
+#define XSTR(a) STR(a) +#define STR(a) #a + mod = GetModuleHandleA("d3dcompiler_" XSTR(D3D_COMPILER_VERSION)); + pD3DAssemble = (void *)GetProcAddress(mod, "D3DAssemble"); +#undef STR +#undef XSTR + test_swizzle(); test_math(); test_conditionals();
From: Stefan Dösinger stefan@codeweavers.com
---
It is a private export in the Windows SDK d3dcompiler.lib import library.
Changes to files other than d3dcompiler_47.spec are academic because the import libraries they generate don't exist in the Windows SDK. --- dlls/d3dcompiler_41/d3dcompiler_41.spec | 2 +- dlls/d3dcompiler_42/d3dcompiler_42.spec | 2 +- dlls/d3dcompiler_43/d3dcompiler_43.spec | 2 +- dlls/d3dcompiler_46/d3dcompiler_46.spec | 2 +- dlls/d3dcompiler_47/d3dcompiler_47.spec | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/dlls/d3dcompiler_41/d3dcompiler_41.spec b/dlls/d3dcompiler_41/d3dcompiler_41.spec index e5127bc4ab9..604c7748cf3 100644 --- a/dlls/d3dcompiler_41/d3dcompiler_41.spec +++ b/dlls/d3dcompiler_41/d3dcompiler_41.spec @@ -1,4 +1,4 @@ -@ stdcall D3DAssemble(ptr long str ptr ptr long ptr ptr) +@ stdcall -private D3DAssemble(ptr long str ptr ptr long ptr ptr) @ stub DebugSetMute @ stdcall D3DCompile(ptr long str ptr ptr str str long long ptr ptr) @ stub D3DDisassemble10Effect(ptr long ptr) diff --git a/dlls/d3dcompiler_42/d3dcompiler_42.spec b/dlls/d3dcompiler_42/d3dcompiler_42.spec index e5127bc4ab9..604c7748cf3 100644 --- a/dlls/d3dcompiler_42/d3dcompiler_42.spec +++ b/dlls/d3dcompiler_42/d3dcompiler_42.spec @@ -1,4 +1,4 @@ -@ stdcall D3DAssemble(ptr long str ptr ptr long ptr ptr) +@ stdcall -private D3DAssemble(ptr long str ptr ptr long ptr ptr) @ stub DebugSetMute @ stdcall D3DCompile(ptr long str ptr ptr str str long long ptr ptr) @ stub D3DDisassemble10Effect(ptr long ptr) diff --git a/dlls/d3dcompiler_43/d3dcompiler_43.spec b/dlls/d3dcompiler_43/d3dcompiler_43.spec index ab6cfa04aff..7e2d0411b4e 100644 --- a/dlls/d3dcompiler_43/d3dcompiler_43.spec +++ b/dlls/d3dcompiler_43/d3dcompiler_43.spec @@ -1,4 +1,4 @@ -@ stdcall D3DAssemble(ptr long str ptr ptr long ptr ptr) +@ stdcall -private D3DAssemble(ptr long str ptr ptr long ptr ptr) @ stub DebugSetMute @ stdcall D3DCompile(ptr long str ptr ptr str str long long ptr ptr) @ stub D3DCompressShaders diff --git a/dlls/d3dcompiler_46/d3dcompiler_46.spec b/dlls/d3dcompiler_46/d3dcompiler_46.spec index b069779db06..d6742566502 100644 --- a/dlls/d3dcompiler_46/d3dcompiler_46.spec +++ b/dlls/d3dcompiler_46/d3dcompiler_46.spec @@ -1,4 +1,4 @@ -@ stdcall D3DAssemble(ptr long str ptr ptr long ptr ptr) +@ stdcall -private D3DAssemble(ptr long str ptr ptr long ptr ptr) @ stdcall D3DCompile(ptr long str ptr ptr str str long long ptr ptr) @ stdcall D3DCompile2(ptr long str ptr ptr str str long long long ptr long ptr ptr) @ stdcall D3DCompileFromFile(wstr ptr ptr str str long long ptr ptr) diff --git a/dlls/d3dcompiler_47/d3dcompiler_47.spec b/dlls/d3dcompiler_47/d3dcompiler_47.spec index 38ae8960dc5..ca132979565 100644 --- a/dlls/d3dcompiler_47/d3dcompiler_47.spec +++ b/dlls/d3dcompiler_47/d3dcompiler_47.spec @@ -1,4 +1,4 @@ -@ stdcall D3DAssemble(ptr long str ptr ptr long ptr ptr) +@ stdcall -private D3DAssemble(ptr long str ptr ptr long ptr ptr) @ stdcall D3DCompile(ptr long str ptr ptr str str long long ptr ptr) @ stdcall D3DCompile2(ptr long str ptr ptr str str long long long ptr long ptr ptr) @ stdcall D3DCompileFromFile(wstr ptr ptr str str long long ptr ptr)
Matteo Bruni (@Mystral) commented about dlls/d3dcompiler_43/tests/asm.c:
START_TEST(asm) { +#define XSTR(a) STR(a) +#define STR(a) #a
- HMODULE d3dcompiler = GetModuleHandleA("d3dcompiler_" XSTR(D3D_COMPILER_VERSION));
- pD3DAssemble = (void *)GetProcAddress(d3dcompiler, "D3DAssemble");
+#undef STR +#undef XSTR
I overlooked this the first time around. Why the double #define? Does MSVC not like it otherwise?
On Wed Apr 26 15:27:25 2023 +0000, Matteo Bruni wrote:
I overlooked this the first time around. Why the double #define? Does MSVC not like it otherwise?
I don't claim to understand it myself, but https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification.html
So afaiu the STR macro goes from STR(42) to "42", but STR(D3D_COMPILER_VERSION) gives "D3D_COMPILER_VERSION". So we need an extra macro to expand the D3D_COMPILER_VERSION macro - XSTR(D3D_COMPILER_VERSION) will give 47 (no string, just an int literal), then STR(47) gives us "47" as a string.
On Wed Apr 26 19:23:53 2023 +0000, Stefan Dösinger wrote:
I don't claim to understand it myself, but https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification.html So afaiu the STR macro goes from STR(42) to "42", but STR(D3D_COMPILER_VERSION) gives "D3D_COMPILER_VERSION". So we need an extra macro to expand the D3D_COMPILER_VERSION macro - XSTR(D3D_COMPILER_VERSION) will give 47 (no string, just an int literal), then STR(47) gives us "47" as a string.
Note that I could also sprintf(buffer, "d3dcompiler_%d", D3D_COMPILER_VERSION), but then I'd need an extra buffer and do something at runtime that the preprocessor can do for us.
On Wed Apr 26 19:25:46 2023 +0000, Stefan Dösinger wrote:
Note that I could also sprintf(buffer, "d3dcompiler_%d", D3D_COMPILER_VERSION), but then I'd need an extra buffer and do something at runtime that the preprocessor can do for us.
Ah indeed, I thought I tested with a single macro but I actually didn't and I can confirm the above.
This merge request was approved by Matteo Bruni.
Note that I could also sprintf(buffer, "d3dcompiler_%d", D3D_COMPILER_VERSION), but then I'd need an extra buffer and do something at runtime that the preprocessor can do for us.
If you have to explain the preprocessor magic, then avoiding it would be better. Doing extra work at runtime is obviously not an issue in a test.