For React Native. React Native applications use HLSL shader linking extensively. Obviously, these two functions are not enough because they are just stubs. But I think it's good to get them in the tree so they don't get lost. Currently, React Native applications need to rely on the bundled native d3dcompiler.
-- v3: d3dcompiler_47: Implement D3DCreateFunctionLinkingGraph(). d3dcompiler_47: Implement D3DCreateLinker().
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/d3dcompiler_43/compiler.c | 6 -- dlls/d3dcompiler_43/linker.c | 125 +++++++++++++++++++++++++ dlls/d3dcompiler_43/tests/hlsl_d3d11.c | 20 ++++ dlls/d3dcompiler_47/Makefile.in | 1 + 4 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 dlls/d3dcompiler_43/linker.c
diff --git a/dlls/d3dcompiler_43/compiler.c b/dlls/d3dcompiler_43/compiler.c index 58f3e3a4358..f5c259191b4 100644 --- a/dlls/d3dcompiler_43/compiler.c +++ b/dlls/d3dcompiler_43/compiler.c @@ -489,12 +489,6 @@ end: return hr; }
-HRESULT WINAPI D3DCreateLinker(ID3D11Linker **linker) -{ - FIXME("linker %p stub!\n", linker); - return E_NOTIMPL; -} - HRESULT WINAPI D3DLoadModule(const void *data, SIZE_T size, ID3D11Module **module) { FIXME("data %p, size %Iu, module %p stub!\n", data, size, module); diff --git a/dlls/d3dcompiler_43/linker.c b/dlls/d3dcompiler_43/linker.c new file mode 100644 index 00000000000..685a5fb286a --- /dev/null +++ b/dlls/d3dcompiler_43/linker.c @@ -0,0 +1,125 @@ +/* + * Copyright 2025 Zhiyi Zhang for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#define COBJMACROS +#include "wine/debug.h" +#include "d3dcompiler_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(d3dcompiler); + +struct d3d11_linker +{ + ID3D11Linker ID3D11Linker_iface; + LONG refcount; +}; + +static inline struct d3d11_linker *impl_from_ID3D11Linker(ID3D11Linker *iface) +{ + return CONTAINING_RECORD(iface, struct d3d11_linker, ID3D11Linker_iface); +} + +static HRESULT WINAPI d3d11_linker_QueryInterface(ID3D11Linker *iface, REFIID riid, void **object) +{ + struct d3d11_linker *linker = impl_from_ID3D11Linker(iface); + + TRACE("linker %p, riid %s, object %p.\n", linker, debugstr_guid(riid), object); + + if (IsEqualGUID(riid, &IID_ID3D11Linker) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IUnknown_AddRef(iface); + *object = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + *object = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d11_linker_AddRef(ID3D11Linker *iface) +{ + struct d3d11_linker *linker = impl_from_ID3D11Linker(iface); + ULONG refcount = InterlockedIncrement(&linker->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI d3d11_linker_Release(ID3D11Linker *iface) +{ + struct d3d11_linker *linker = impl_from_ID3D11Linker(iface); + ULONG refcount = InterlockedDecrement(&linker->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + free(linker); + + return refcount; +} + +static HRESULT WINAPI d3d11_linker_Link(ID3D11Linker *iface, ID3D11ModuleInstance *instance, + LPCSTR instance_name, LPCSTR target_name, UINT flags, ID3DBlob **shader, ID3DBlob **error) +{ + FIXME("iface %p, instance %p, instance_name %s, target_name %s, flags %#x, shader %p, error %p stub!\n", + iface, instance, wine_dbgstr_a(instance_name), wine_dbgstr_a(target_name), flags, shader, error); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d11_linker_UseLibrary(ID3D11Linker *iface, ID3D11ModuleInstance *instance) +{ + FIXME("iface %p, instance %p stub!\n", iface, instance); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d11_linker_AddClipPlaneFromCBuffer(ID3D11Linker *iface, UINT buffer_slot, + UINT buffer_entry) +{ + FIXME("iface %p, buffer_slot %u, buffer_entry %u stub!\n", iface, buffer_slot, buffer_entry); + return E_NOTIMPL; +} + +static const struct ID3D11LinkerVtbl d3d11_linker_vtbl = +{ + d3d11_linker_QueryInterface, + d3d11_linker_AddRef, + d3d11_linker_Release, + d3d11_linker_Link, + d3d11_linker_UseLibrary, + d3d11_linker_AddClipPlaneFromCBuffer, +}; + +HRESULT WINAPI D3DCreateLinker(ID3D11Linker **linker) +{ + struct d3d11_linker *object; + + TRACE("linker %p.\n", linker); + + if (!linker) + return E_INVALIDARG; + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + object->ID3D11Linker_iface.lpVtbl = &d3d11_linker_vtbl; + object->refcount = 1; + + *linker = &object->ID3D11Linker_iface; + return S_OK; +} diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d11.c b/dlls/d3dcompiler_43/tests/hlsl_d3d11.c index 5f58e6f3d1c..8f1ce3af37d 100644 --- a/dlls/d3dcompiler_43/tests/hlsl_d3d11.c +++ b/dlls/d3dcompiler_43/tests/hlsl_d3d11.c @@ -1164,12 +1164,32 @@ static void test_semantic_reflection(void) } }
+#if D3D_COMPILER_VERSION >= 47 + +static void test_D3DCreateLinker(void) +{ + ID3D11Linker *linker; + HRESULT hr; + + hr = D3DCreateLinker(NULL); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + + hr = D3DCreateLinker(&linker); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + linker->lpVtbl->Release(linker); +} + +#endif /* D3D_COMPILER_VERSION >= 47 */ + START_TEST(hlsl_d3d11) { HMODULE mod;
test_reflection(); test_semantic_reflection(); +#if D3D_COMPILER_VERSION >= 47 + test_D3DCreateLinker(); +#endif
if (!(mod = LoadLibraryA("d3d11.dll"))) { diff --git a/dlls/d3dcompiler_47/Makefile.in b/dlls/d3dcompiler_47/Makefile.in index a98ca7243c1..ab5da889126 100644 --- a/dlls/d3dcompiler_47/Makefile.in +++ b/dlls/d3dcompiler_47/Makefile.in @@ -14,6 +14,7 @@ SOURCES = \ blob.c \ bytecodewriter.c \ compiler.c \ + linker.c \ reflection.c \ utils.c \ version.rc
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/d3dcompiler_43/linker.c | 151 ++++++++++++++++++++++++ dlls/d3dcompiler_43/tests/hlsl_d3d11.c | 17 +++ dlls/d3dcompiler_47/d3dcompiler_47.spec | 2 +- include/d3dcompiler.h | 1 + 4 files changed, 170 insertions(+), 1 deletion(-)
diff --git a/dlls/d3dcompiler_43/linker.c b/dlls/d3dcompiler_43/linker.c index 685a5fb286a..ddc953b0017 100644 --- a/dlls/d3dcompiler_43/linker.c +++ b/dlls/d3dcompiler_43/linker.c @@ -21,6 +21,157 @@
WINE_DEFAULT_DEBUG_CHANNEL(d3dcompiler);
+struct d3d11_function_linking_graph +{ + ID3D11FunctionLinkingGraph ID3D11FunctionLinkingGraph_iface; + LONG refcount; +}; + +static inline struct d3d11_function_linking_graph *impl_from_ID3D11FunctionLinkingGraph(ID3D11FunctionLinkingGraph *iface) +{ + return CONTAINING_RECORD(iface, struct d3d11_function_linking_graph, ID3D11FunctionLinkingGraph_iface); +} + +static HRESULT WINAPI d3d11_function_linking_graph_QueryInterface(ID3D11FunctionLinkingGraph *iface, REFIID riid, void **object) +{ + struct d3d11_function_linking_graph *graph = impl_from_ID3D11FunctionLinkingGraph(iface); + + TRACE("graph %p, riid %s, object %p.\n", graph, debugstr_guid(riid), object); + + if (IsEqualGUID(riid, &IID_ID3D11FunctionLinkingGraph) + || IsEqualGUID(riid, &IID_IUnknown)) + { + IUnknown_AddRef(iface); + *object = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + *object = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI d3d11_function_linking_graph_AddRef(ID3D11FunctionLinkingGraph *iface) +{ + struct d3d11_function_linking_graph *graph = impl_from_ID3D11FunctionLinkingGraph(iface); + ULONG refcount = InterlockedIncrement(&graph->refcount); + + TRACE("%p increasing refcount to %lu.\n", iface, refcount); + + return refcount; +} + +static ULONG WINAPI d3d11_function_linking_graph_Release(ID3D11FunctionLinkingGraph *iface) +{ + struct d3d11_function_linking_graph *graph = impl_from_ID3D11FunctionLinkingGraph(iface); + ULONG refcount = InterlockedDecrement(&graph->refcount); + + TRACE("%p decreasing refcount to %lu.\n", iface, refcount); + + if (!refcount) + free(graph); + + return refcount; +} + +static HRESULT WINAPI d3d11_function_linking_graph_CreateModuleInstance(ID3D11FunctionLinkingGraph *iface, + ID3D11ModuleInstance **instance, ID3DBlob **error) +{ + FIXME("iface %p, instance %p, error %p stub!\n", iface, instance, error); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d11_function_linking_graph_SetInputSignature(ID3D11FunctionLinkingGraph *iface, + const D3D11_PARAMETER_DESC *parameter_desc, UINT parameter_count, ID3D11LinkingNode **input_node) +{ + FIXME("iface %p, parameter_desc %p, parameter_count %u, input_node %p stub!\n", iface, + parameter_desc, parameter_count, input_node); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d11_function_linking_graph_SetOutputSignature(ID3D11FunctionLinkingGraph *iface, + const D3D11_PARAMETER_DESC *parameter_desc, UINT parameter_count, ID3D11LinkingNode **output_node) +{ + FIXME("iface %p, parameter_desc %p, parameter_count %u, output_node %p stub!\n", iface, + parameter_desc, parameter_count, output_node); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d11_function_linking_graph_CallFunction(ID3D11FunctionLinkingGraph *iface, + LPCSTR namespace, ID3D11Module *module, LPCSTR function_name, ID3D11LinkingNode **call_node) +{ + FIXME("iface %p, namespace %s, module %p, function_name %s, call_node %p stub!\n", iface, + wine_dbgstr_a(namespace), module, wine_dbgstr_a(function_name), call_node); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d11_function_linking_graph_PassValue(ID3D11FunctionLinkingGraph *iface, + ID3D11LinkingNode *src_node, INT src_parameter_index, ID3D11LinkingNode *dst_node, + INT dst_parameter_index) +{ + FIXME("iface %p, src_node %p, src_parameter_index %d, dst_node %p, dst_parameter_index %d stub!\n", + iface, src_node, src_parameter_index, dst_node, dst_parameter_index); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d11_function_linking_graph_PassValueWithSwizzle(ID3D11FunctionLinkingGraph *iface, + ID3D11LinkingNode *src_node, INT src_parameter_index, LPCSTR src_swizzle, + ID3D11LinkingNode *dst_node, INT dst_parameter_index, LPCSTR dst_swizzle) +{ + FIXME("iface %p, src_node %p, src_parameter_index %d, src_swizzle %s, dst_node %p, " + "dst_parameter_index %d, dst_swizzle %s stub!\n", iface, src_node, src_parameter_index, + wine_dbgstr_a(src_swizzle), dst_node, dst_parameter_index, wine_dbgstr_a(dst_swizzle)); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d11_function_linking_graph_GetLastError(ID3D11FunctionLinkingGraph *iface, + ID3DBlob **error) +{ + FIXME("iface %p, error %p stub!\n", iface, error); + return E_NOTIMPL; +} + +static HRESULT WINAPI d3d11_function_linking_graph_GenerateHlsl(ID3D11FunctionLinkingGraph *iface, + UINT flags, ID3DBlob **buffer) +{ + FIXME("iface %p, flags %#x, buffer %p stub!\n", iface, flags, buffer); + return E_NOTIMPL; +} + +static const struct ID3D11FunctionLinkingGraphVtbl d3d11_function_linking_graph_vtbl = +{ + d3d11_function_linking_graph_QueryInterface, + d3d11_function_linking_graph_AddRef, + d3d11_function_linking_graph_Release, + d3d11_function_linking_graph_CreateModuleInstance, + d3d11_function_linking_graph_SetInputSignature, + d3d11_function_linking_graph_SetOutputSignature, + d3d11_function_linking_graph_CallFunction, + d3d11_function_linking_graph_PassValue, + d3d11_function_linking_graph_PassValueWithSwizzle, + d3d11_function_linking_graph_GetLastError, + d3d11_function_linking_graph_GenerateHlsl, +}; + +HRESULT WINAPI D3DCreateFunctionLinkingGraph(UINT flags, ID3D11FunctionLinkingGraph **graph) +{ + struct d3d11_function_linking_graph *object; + + TRACE("flags %#x, graph %p.\n", flags, graph); + + if (flags != 0 || !graph) + return E_INVALIDARG; + + if (!(object = calloc(1, sizeof(*object)))) + return E_OUTOFMEMORY; + + object->ID3D11FunctionLinkingGraph_iface.lpVtbl = &d3d11_function_linking_graph_vtbl; + object->refcount = 1; + + *graph = &object->ID3D11FunctionLinkingGraph_iface; + return S_OK; +} + struct d3d11_linker { ID3D11Linker ID3D11Linker_iface; diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d11.c b/dlls/d3dcompiler_43/tests/hlsl_d3d11.c index 8f1ce3af37d..087bcc22da2 100644 --- a/dlls/d3dcompiler_43/tests/hlsl_d3d11.c +++ b/dlls/d3dcompiler_43/tests/hlsl_d3d11.c @@ -1179,6 +1179,22 @@ static void test_D3DCreateLinker(void) linker->lpVtbl->Release(linker); }
+static void test_D3DCreateFunctionLinkingGraph(void) +{ + ID3D11FunctionLinkingGraph *graph; + HRESULT hr; + + hr = D3DCreateFunctionLinkingGraph(0, NULL); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + + hr = D3DCreateFunctionLinkingGraph(1, &graph); + ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr); + + hr = D3DCreateFunctionLinkingGraph(0, &graph); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + graph->lpVtbl->Release(graph); +} + #endif /* D3D_COMPILER_VERSION >= 47 */
START_TEST(hlsl_d3d11) @@ -1189,6 +1205,7 @@ START_TEST(hlsl_d3d11) test_semantic_reflection(); #if D3D_COMPILER_VERSION >= 47 test_D3DCreateLinker(); + test_D3DCreateFunctionLinkingGraph(); #endif
if (!(mod = LoadLibraryA("d3d11.dll"))) diff --git a/dlls/d3dcompiler_47/d3dcompiler_47.spec b/dlls/d3dcompiler_47/d3dcompiler_47.spec index 3ed049e6ab8..333dde2979c 100644 --- a/dlls/d3dcompiler_47/d3dcompiler_47.spec +++ b/dlls/d3dcompiler_47/d3dcompiler_47.spec @@ -4,7 +4,7 @@ @ stdcall D3DCompileFromFile(wstr ptr ptr str str long long ptr ptr) @ stub D3DCompressShaders @ stdcall D3DCreateBlob(long ptr) -@ stub D3DCreateFunctionLinkingGraph +@ stdcall D3DCreateFunctionLinkingGraph(long ptr) @ stdcall D3DCreateLinker(ptr) @ stub D3DDecompressShaders @ stdcall D3DDisassemble(ptr long long ptr ptr) diff --git a/include/d3dcompiler.h b/include/d3dcompiler.h index 87821a9031a..14e599081d8 100644 --- a/include/d3dcompiler.h +++ b/include/d3dcompiler.h @@ -153,6 +153,7 @@ typedef HRESULT (WINAPI *pD3DPreprocess)(const void *data, SIZE_T size, const ch const D3D_SHADER_MACRO *defines, ID3DInclude *include, ID3DBlob **shader, ID3DBlob **error_messages);
+HRESULT WINAPI D3DCreateFunctionLinkingGraph(UINT flags, ID3D11FunctionLinkingGraph **graph); HRESULT WINAPI D3DCreateLinker(ID3D11Linker **linker); HRESULT WINAPI D3DLoadModule(const void *data, SIZE_T size, ID3D11Module **module);
On Thu Jun 12 15:02:52 2025 +0000, Matteo Bruni wrote:
Thanks, I like this a lot! I'm attaching a little fixup for the first patch. [0001-fixup-d3dcompiler_47-Implement-D3DCreateLinker.txt](/uploads/6dd6f1f6a0d4772aef19de152844ad81/0001-fixup-d3dcompiler_47-Implement-D3DCreateLinker.txt)
Thanks for the fixup.
This merge request was approved by Matteo Bruni.