Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Windows] Make D3D12 loading dynamic to support pre-Windows 10 versions. #88496

Merged
merged 1 commit into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions drivers/d3d12/rendering_context_driver_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,28 @@ RenderingContextDriverD3D12::RenderingContextDriverD3D12() {
}

RenderingContextDriverD3D12::~RenderingContextDriverD3D12() {
if (lib_d3d12) {
FreeLibrary(lib_d3d12);
}
if (lib_dxgi) {
FreeLibrary(lib_dxgi);
}
}

Error RenderingContextDriverD3D12::_init_device_factory() {
uint32_t agility_sdk_version = GLOBAL_GET("rendering/rendering_device/d3d12/agility_sdk_version");
String agility_sdk_path = String(".\\") + Engine::get_singleton()->get_architecture_name();

lib_d3d12 = LoadLibraryW(L"D3D12.dll");
ERR_FAIL_NULL_V(lib_d3d12, ERR_CANT_CREATE);

lib_dxgi = LoadLibraryW(L"DXGI.dll");
ERR_FAIL_NULL_V(lib_dxgi, ERR_CANT_CREATE);

// Note: symbol is not available in MinGW import library.
PFN_D3D12_GET_INTERFACE d3d_D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)GetProcAddress(LoadLibraryW(L"D3D12.dll"), "D3D12GetInterface");
if (d3d_D3D12GetInterface == nullptr) {
// FIXME: Is it intended for this to silently return when it fails to find the symbol?
return OK;
PFN_D3D12_GET_INTERFACE d3d_D3D12GetInterface = (PFN_D3D12_GET_INTERFACE)(void *)GetProcAddress(lib_d3d12, "D3D12GetInterface");
if (!d3d_D3D12GetInterface) {
return OK; // Fallback to the system loader.
}

ID3D12SDKConfiguration *sdk_config = nullptr;
Expand All @@ -109,26 +120,35 @@ Error RenderingContextDriverD3D12::_init_device_factory() {
}
sdk_config->Release();
}

return OK;
}

Error RenderingContextDriverD3D12::_initialize_debug_layers() {
ComPtr<ID3D12Debug> debug_controller;
HRESULT res;

if (device_factory) {
res = device_factory->GetConfigurationInterface(CLSID_D3D12DebugGodot, IID_PPV_ARGS(&debug_controller));
} else {
res = D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller));
PFN_D3D12_GET_DEBUG_INTERFACE d3d_D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)(void *)GetProcAddress(lib_d3d12, "D3D12GetDebugInterface");
ERR_FAIL_NULL_V(d3d_D3D12GetDebugInterface, ERR_CANT_CREATE);

res = d3d_D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller));
}

ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_QUERY_FAILED);
debug_controller->EnableDebugLayer();
return OK;
}

Error RenderingContextDriverD3D12::_initialize_devices() {
const UINT dxgi_factory_flags = use_validation_layers() ? DXGI_CREATE_FACTORY_DEBUG : 0;
HRESULT res = CreateDXGIFactory2(dxgi_factory_flags, IID_PPV_ARGS(&dxgi_factory));

typedef HRESULT(WINAPI * PFN_DXGI_CREATE_DXGI_FACTORY2)(UINT, REFIID, void **);
PFN_DXGI_CREATE_DXGI_FACTORY2 dxgi_CreateDXGIFactory2 = (PFN_DXGI_CREATE_DXGI_FACTORY2)(void *)GetProcAddress(lib_dxgi, "CreateDXGIFactory2");
ERR_FAIL_NULL_V(dxgi_CreateDXGIFactory2, ERR_CANT_CREATE);

HRESULT res = dxgi_CreateDXGIFactory2(dxgi_factory_flags, IID_PPV_ARGS(&dxgi_factory));
ERR_FAIL_COND_V(!SUCCEEDED(res), ERR_CANT_CREATE);

// Enumerate all possible adapters.
Expand Down
3 changes: 3 additions & 0 deletions drivers/d3d12/rendering_context_driver_d3d12.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ class RenderingContextDriverD3D12 : public RenderingContextDriver {
bool needs_resize = false;
};

HMODULE lib_d3d12 = nullptr;
HMODULE lib_dxgi = nullptr;

IDXGIAdapter1 *create_adapter(uint32_t p_adapter_index) const;
ID3D12DeviceFactory *device_factory_get() const;
IDXGIFactory2 *dxgi_factory_get() const;
Expand Down
19 changes: 14 additions & 5 deletions drivers/d3d12/rendering_device_driver_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3201,7 +3201,7 @@ Vector<uint8_t> RenderingDeviceDriverD3D12::shader_compile_binary_from_spirv(Vec
root_sig_desc.Init_1_1(root_params.size(), root_params.ptr(), 0, nullptr, root_sig_flags);

ComPtr<ID3DBlob> error_blob;
HRESULT res = D3DX12SerializeVersionedRootSignature(&root_sig_desc, D3D_ROOT_SIGNATURE_VERSION_1_1, root_sig_blob.GetAddressOf(), error_blob.GetAddressOf());
HRESULT res = D3DX12SerializeVersionedRootSignature(context_driver->lib_d3d12, &root_sig_desc, D3D_ROOT_SIGNATURE_VERSION_1_1, root_sig_blob.GetAddressOf(), error_blob.GetAddressOf());
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), Vector<uint8_t>(),
"Serialization of root signature failed with error " + vformat("0x%08ux", (uint64_t)res) + " and the following message:\n" + String((char *)error_blob->GetBufferPointer(), error_blob->GetBufferSize()));

Expand Down Expand Up @@ -3462,7 +3462,10 @@ RDD::ShaderID RenderingDeviceDriverD3D12::shader_create_from_bytecode(const Vect

const uint8_t *root_sig_data_ptr = binptr + read_offset;

HRESULT res = D3D12CreateRootSignatureDeserializer(root_sig_data_ptr, binary_data.root_signature_len, IID_PPV_ARGS(shader_info_in.root_signature_deserializer.GetAddressOf()));
PFN_D3D12_CREATE_ROOT_SIGNATURE_DESERIALIZER d3d_D3D12CreateRootSignatureDeserializer = (PFN_D3D12_CREATE_ROOT_SIGNATURE_DESERIALIZER)(void *)GetProcAddress(context_driver->lib_d3d12, "D3D12CreateRootSignatureDeserializer");
ERR_FAIL_NULL_V(d3d_D3D12CreateRootSignatureDeserializer, ShaderID());

HRESULT res = d3d_D3D12CreateRootSignatureDeserializer(root_sig_data_ptr, binary_data.root_signature_len, IID_PPV_ARGS(shader_info_in.root_signature_deserializer.GetAddressOf()));
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ShaderID(), "D3D12CreateRootSignatureDeserializer failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");
read_offset += binary_data.root_signature_len;

Expand Down Expand Up @@ -5927,17 +5930,23 @@ Error RenderingDeviceDriverD3D12::_initialize_device() {
HRESULT res;

if (is_in_developer_mode()) {
typedef HRESULT(WINAPI * PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(_In_ UINT, _In_count_(NumFeatures) const IID *, _In_opt_count_(NumFeatures) void *, _In_opt_count_(NumFeatures) UINT *);
PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES d3d_D3D12EnableExperimentalFeatures = (PFN_D3D12_ENABLE_EXPERIMENTAL_FEATURES)(void *)GetProcAddress(context_driver->lib_d3d12, "D3D12EnableExperimentalFeatures");
ERR_FAIL_NULL_V(d3d_D3D12EnableExperimentalFeatures, ERR_CANT_CREATE);

UUID experimental_features[] = { D3D12ExperimentalShaderModels };
D3D12EnableExperimentalFeatures(1, experimental_features, nullptr, nullptr);
d3d_D3D12EnableExperimentalFeatures(1, experimental_features, nullptr, nullptr);
}

ID3D12DeviceFactory *device_factory = context_driver->device_factory_get();
if (device_factory != nullptr) {
res = device_factory->CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device.GetAddressOf()));
} else {
res = D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device.GetAddressOf()));
}
PFN_D3D12_CREATE_DEVICE d3d_D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)(void *)GetProcAddress(context_driver->lib_d3d12, "D3D12CreateDevice");
ERR_FAIL_NULL_V(d3d_D3D12CreateDevice, ERR_CANT_CREATE);

res = d3d_D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(device.GetAddressOf()));
}
ERR_FAIL_COND_V_MSG(!SUCCEEDED(res), ERR_CANT_CREATE, "D3D12CreateDevice failed with error " + vformat("0x%08ux", (uint64_t)res) + ".");

if (context_driver->use_validation_layers()) {
Expand Down
12 changes: 10 additions & 2 deletions platform/windows/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,10 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
else:
print("Missing environment variable: WindowsSdkDir")

if int(env["target_win_version"], 16) < 0x0601:
print("`target_win_version` should be 0x0601 or higher (Windows 7).")
sys.exit(255)

env.AppendUnique(
CPPDEFINES=[
"WINDOWS_ENABLED",
Expand Down Expand Up @@ -485,7 +489,7 @@ def configure_msvc(env: "SConsEnvironment", vcvars_msvc_config):
sys.exit(255)

env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"])
LIBS += ["d3d12", "dxgi", "dxguid"]
LIBS += ["dxgi", "dxguid"]
LIBS += ["version"] # Mesa dependency.

# Needed for avoiding C1128.
Expand Down Expand Up @@ -650,6 +654,10 @@ def configure_mingw(env: "SConsEnvironment"):

## Compile flags

if int(env["target_win_version"], 16) < 0x0601:
print("`target_win_version` should be 0x0601 or higher (Windows 7).")
sys.exit(255)

if not env["use_llvm"]:
env.Append(CCFLAGS=["-mwindows"])

Expand Down Expand Up @@ -710,7 +718,7 @@ def configure_mingw(env: "SConsEnvironment"):
sys.exit(255)

env.AppendUnique(CPPDEFINES=["D3D12_ENABLED", "RD_ENABLED"])
env.Append(LIBS=["d3d12", "dxgi", "dxguid"])
env.Append(LIBS=["dxgi", "dxguid"])

# PIX
if not env["arch"] in ["x86_64", "arm64"] or env["pix_path"] == "" or not os.path.exists(env["pix_path"]):
Expand Down
2 changes: 2 additions & 0 deletions platform/windows/display_server_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ typedef UINT32 PEN_MASK;
#define POINTER_MESSAGE_FLAG_FIRSTBUTTON 0x00000010
#endif

#if WINVER < 0x0602
enum tagPOINTER_INPUT_TYPE {
PT_POINTER = 0x00000001,
PT_TOUCH = 0x00000002,
Expand Down Expand Up @@ -242,6 +243,7 @@ typedef struct tagPOINTER_PEN_INFO {
INT32 tiltX;
INT32 tiltY;
} POINTER_PEN_INFO;
#endif

#endif //POINTER_STRUCTURES

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,9 @@ struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE
// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when
// 1.1 is not supported.
inline HRESULT D3DX12SerializeVersionedRootSignature(
/* GODOT start */
_In_ HMODULE pLibD3D12,
/* GODOT end */
_In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,
D3D_ROOT_SIGNATURE_VERSION MaxVersion,
_Outptr_ ID3DBlob** ppBlob,
Expand All @@ -1006,13 +1009,22 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
*ppErrorBlob = nullptr;
}

/* GODOT start */
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d_D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeRootSignature");
if (d3d_D3D12SerializeRootSignature == nullptr) {
return E_INVALIDARG;
}
PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE d3d_D3D12SerializeVersionedRootSignature = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeVersionedRootSignature");
/* GODOT end */
switch (MaxVersion)
{
case D3D_ROOT_SIGNATURE_VERSION_1_0:
switch (pRootSignatureDesc->Version)
{
case D3D_ROOT_SIGNATURE_VERSION_1_0:
return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
/* GODOT start */
return d3d_D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
/* GODOT end */

case D3D_ROOT_SIGNATURE_VERSION_1_1:
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
Expand Down Expand Up @@ -1114,7 +1126,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
if (SUCCEEDED(hr))
{
const CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
/* GODOT start */
hr = d3d_D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
/* GODOT end */
}

if (pParameters)
Expand Down Expand Up @@ -1145,7 +1159,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
{
case D3D_ROOT_SIGNATURE_VERSION_1_0:
case D3D_ROOT_SIGNATURE_VERSION_1_1:
return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
/* GODOT start */
return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
/* GODOT end */

#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
case D3D_ROOT_SIGNATURE_VERSION_1_2:
Expand Down Expand Up @@ -1181,7 +1197,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
if (SUCCEEDED(hr))
{
const CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC desc(desc_1_1.NumParameters, desc_1_1.pParameters, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
hr = D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
/* GODOT start */
hr = d3d_D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
/* GODOT end */
}

if (pStaticSamplers)
Expand All @@ -1197,7 +1215,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
case D3D_ROOT_SIGNATURE_VERSION_1_2:
#endif
return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
/* GODOT start */
return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
/* GODOT end */
}

return E_INVALIDARG;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
diff --git a/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h b/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
index 572efed852..18efa7a0cb 100644
--- a/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
+++ b/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
@@ -996,6 +996,9 @@ struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE
// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when
// 1.1 is not supported.
inline HRESULT D3DX12SerializeVersionedRootSignature(
+/* GODOT start */
+ _In_ HMODULE pLibD3D12,
+/* GODOT end */
_In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,
D3D_ROOT_SIGNATURE_VERSION MaxVersion,
_Outptr_ ID3DBlob** ppBlob,
@@ -1006,13 +1009,22 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
*ppErrorBlob = nullptr;
}

+ /* GODOT start */
+ PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d_D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeRootSignature");
+ if (d3d_D3D12SerializeRootSignature == nullptr) {
+ return E_INVALIDARG;
+ }
+ PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE d3d_D3D12SerializeVersionedRootSignature = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeVersionedRootSignature");
+ /* GODOT end */
switch (MaxVersion)
{
case D3D_ROOT_SIGNATURE_VERSION_1_0:
switch (pRootSignatureDesc->Version)
{
case D3D_ROOT_SIGNATURE_VERSION_1_0:
- return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
+/* GODOT start */
+ return d3d_D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
+/* GODOT end */

case D3D_ROOT_SIGNATURE_VERSION_1_1:
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
@@ -1114,7 +1126,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
if (SUCCEEDED(hr))
{
const CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
- hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
+/* GODOT start */
+ hr = d3d_D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
+/* GODOT end */
}

if (pParameters)
@@ -1145,7 +1159,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
{
case D3D_ROOT_SIGNATURE_VERSION_1_0:
case D3D_ROOT_SIGNATURE_VERSION_1_1:
- return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
+/* GODOT start */
+ return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
+/* GODOT end */

#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
case D3D_ROOT_SIGNATURE_VERSION_1_2:
@@ -1181,7 +1197,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
if (SUCCEEDED(hr))
{
const CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC desc(desc_1_1.NumParameters, desc_1_1.pParameters, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
- hr = D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
+/* GODOT start */
+ hr = d3d_D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
+/* GODOT end */
}

if (pStaticSamplers)
@@ -1197,7 +1215,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
case D3D_ROOT_SIGNATURE_VERSION_1_2:
#endif
- return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
+/* GODOT start */
+ return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
+/* GODOT end */
}

return E_INVALIDARG;
Loading