summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2020-01-08 18:09:08 +0000
committerassiduous <assiduous@diligentgraphics.com>2020-01-08 18:09:08 +0000
commit61cb28a4c3a538f6d43098f045bdc07611652604 (patch)
tree0f7c4e61112a55de4f3deb817696b91d2a000c1f /Graphics/GraphicsEngineD3D12
parentUpdated factory functions to not throw exceptions, but return; fixed API vers... (diff)
downloadDiligentCore-61cb28a4c3a538f6d43098f045bdc07611652604.tar.gz
DiligentCore-61cb28a4c3a538f6d43098f045bdc07611652604.zip
Implemented manual loading of d3d12.dll (closed https://github.com/DiligentGraphics/DiligentCore/issues/113)
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/CMakeLists.txt15
-rw-r--r--Graphics/GraphicsEngineD3D12/include/D3D12Loader.h57
-rw-r--r--Graphics/GraphicsEngineD3D12/include/pch.h6
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h16
-rw-r--r--Graphics/GraphicsEngineD3D12/src/D3D12Loader.cpp88
-rw-r--r--Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp102
6 files changed, 281 insertions, 3 deletions
diff --git a/Graphics/GraphicsEngineD3D12/CMakeLists.txt b/Graphics/GraphicsEngineD3D12/CMakeLists.txt
index 8a59dd4d..a8b744e8 100644
--- a/Graphics/GraphicsEngineD3D12/CMakeLists.txt
+++ b/Graphics/GraphicsEngineD3D12/CMakeLists.txt
@@ -87,6 +87,14 @@ set(SRC
src/TextureViewD3D12Impl.cpp
)
+if(PLATFORM_WIN32)
+ list(APPEND INCLUDE include/D3D12Loader.h)
+ list(APPEND SRC src/D3D12Loader.cpp)
+ set(USE_D3D12_LOADER 1)
+else()
+ set(USE_D3D12_LOADER 0)
+endif()
+
set(SHADERS
shaders/GenerateMips/GenerateMipsGammaCS.hlsl
shaders/GenerateMips/GenerateMipsGammaOddCS.hlsl
@@ -143,12 +151,17 @@ PRIVATE
Diligent-GraphicsEngineNextGenBase
Diligent-TargetPlatform
dxgi.lib
- D3D12.lib
d3dcompiler.lib
PUBLIC
Diligent-GraphicsEngineD3D12Interface
)
+target_compile_definitions(Diligent-GraphicsEngineD3D12-static PRIVATE USE_D3D12_LOADER=${USE_D3D12_LOADER})
+if(NOT ${USE_D3D12_LOADER})
+ # Link with d3d12.lib if we don't use d3d12 loader
+ target_link_libraries(Diligent-GraphicsEngineD3D12-static PRIVATE d3d12.lib)
+endif()
+
target_link_libraries(Diligent-GraphicsEngineD3D12-shared
PRIVATE
Diligent-BuildSettings
diff --git a/Graphics/GraphicsEngineD3D12/include/D3D12Loader.h b/Graphics/GraphicsEngineD3D12/include/D3D12Loader.h
new file mode 100644
index 00000000..8e5b346d
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/include/D3D12Loader.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <d3d12.h>
+
+namespace Diligent
+{
+
+using D3D12CreateDeviceProcType = HRESULT(WINAPI*)(
+ _In_opt_ IUnknown* pAdapter,
+ D3D_FEATURE_LEVEL MinimumFeatureLevel,
+ _In_ REFIID riid,
+ _COM_Outptr_opt_ void** ppDevice);
+
+using D3D12GetDebugInterfaceProcType = HRESULT(WINAPI*)(
+ _In_ REFIID riid,
+ _COM_Outptr_opt_ void** ppvDebug);
+
+using D3D12SerializeRootSignatureProcType = HRESULT(WINAPI*)(
+ _In_ const D3D12_ROOT_SIGNATURE_DESC* pRootSignature,
+ _In_ D3D_ROOT_SIGNATURE_VERSION Version,
+ _Out_ ID3DBlob** ppBlob,
+ _Always_(_Outptr_opt_result_maybenull_) ID3DBlob** ppErrorBlob);
+
+extern D3D12CreateDeviceProcType D3D12CreateDevice;
+extern D3D12GetDebugInterfaceProcType D3D12GetDebugInterface;
+extern D3D12SerializeRootSignatureProcType D3D12SerializeRootSignature;
+
+HMODULE LoadD3D12Dll(const char* DLLPath = "d3d12.dll");
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/include/pch.h b/Graphics/GraphicsEngineD3D12/include/pch.h
index 0434de4d..101ffbdf 100644
--- a/Graphics/GraphicsEngineD3D12/include/pch.h
+++ b/Graphics/GraphicsEngineD3D12/include/pch.h
@@ -54,3 +54,9 @@
#include "RenderDeviceBase.h"
#include "ValidatedCast.h"
#include <atlcomcli.h>
+
+#if USE_D3D12_LOADER
+// On Win32 we manually load d3d12.dll and get entry points,
+// but UWP does not support that, so we link with d3d12.lib
+# include "D3D12Loader.h"
+#endif
diff --git a/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h b/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h
index 5f64976a..01bf3bae 100644
--- a/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h
+++ b/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h
@@ -52,6 +52,18 @@ static const INTERFACE_ID IID_EngineFactoryD3D12 =
class IEngineFactoryD3D12 : public IEngineFactory
{
public:
+ /// Loads D3D12 DLL and entry points.
+
+ /// \param [in] DllName - D3D12 dll name.
+ /// \return true if the library and entry points are loaded sucessfully and false otherwise.
+ ///
+ /// \remarks IEngineFactoryD3D12::CreateDeviceAndContextsD3D12() and
+ /// IEngineFactoryD3D12::AttachToD3D12Device() functions will automatically
+ /// load the DLL if it has not be loaded already.
+ ///
+ /// This method has no effect on UWP.
+ virtual bool LoadD3D12(const char* DllName = "d3d12.dll") = 0;
+
/// Creates a render device and device contexts for Direct3D12-based engine implementation.
/// \param [in] EngineCI - Engine creation info.
@@ -121,6 +133,8 @@ public:
/// \param [out] Adapters - Pointer to the array conataining adapter information. If
/// null is provided, the number of available adapters is written to
/// NumAdapters
+ ///
+ /// \note D3D12 must be loaded before this method can be called, see IEngineFactoryD3D12::LoadD3D12.
virtual void EnumerateAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel,
Uint32& NumAdapters,
AdapterAttribs* Adapters) = 0;
@@ -138,6 +152,8 @@ public:
/// this value should contain the maximum number of elements
/// to be written to DisplayModes array. It is overwritten with
/// the actual number of display modes written.
+ ///
+ /// \note D3D12 must be loaded before this method can be called, see IEngineFactoryD3D12::LoadD3D12.
virtual void EnumerateDisplayModes(DIRECT3D_FEATURE_LEVEL MinFeatureLevel,
Uint32 AdapterId,
Uint32 OutputId,
diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12Loader.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12Loader.cpp
new file mode 100644
index 00000000..f4f56281
--- /dev/null
+++ b/Graphics/GraphicsEngineD3D12/src/D3D12Loader.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+
+#include "D3D12Loader.h"
+#include "Errors.h"
+
+#ifndef NOMINMAX
+# define NOMINMAX
+#endif
+#include <Windows.h>
+
+namespace Diligent
+{
+
+D3D12CreateDeviceProcType D3D12CreateDevice;
+D3D12GetDebugInterfaceProcType D3D12GetDebugInterface;
+D3D12SerializeRootSignatureProcType D3D12SerializeRootSignature;
+
+HMODULE LoadD3D12Dll(const char* DLLPath)
+{
+#if PLATFORM_WIN32
+ auto hModule = LoadLibraryA(DLLPath);
+
+ if (hModule == NULL)
+ {
+ return NULL;
+ }
+
+ bool bAllEntriesLoaded = true;
+# define LOAD_D3D12_ENTRY_POINT(Func) \
+ do \
+ { \
+ Func = (Func##ProcType)GetProcAddress(hModule, #Func); \
+ if (Func == NULL) \
+ { \
+ bAllEntriesLoaded = false; \
+ LOG_ERROR_MESSAGE("Failed to loader '" #Func "' function from '", DLLPath, "' dll"); \
+ } \
+ } while (false)
+#elif PLATFORM_UNIVERSAL_WINDOWS
+ HMODULE hModule = (HMODULE)-1;
+# define LOAD_D3D12_ENTRY_POINT(Func) Func = ::Func
+#else
+# error Unexpected platform
+#endif
+
+ LOAD_D3D12_ENTRY_POINT(D3D12CreateDevice);
+ LOAD_D3D12_ENTRY_POINT(D3D12GetDebugInterface);
+ LOAD_D3D12_ENTRY_POINT(D3D12SerializeRootSignature);
+#undef LOAD_D3D12_ENTRY_POINT
+
+#if PLATFORM_WIN32
+ if (!bAllEntriesLoaded)
+ {
+ FreeLibrary(hModule);
+ return NULL;
+ }
+#endif
+
+ return hModule;
+}
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp
index 379b2ea8..904fed65 100644
--- a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp
@@ -29,7 +29,10 @@
/// Routines that initialize D3D12-based engine implementation
#include "pch.h"
+
#include <array>
+#include <string>
+
#include "EngineFactoryD3D12.h"
#include "RenderDeviceD3D12Impl.h"
#include "DeviceContextD3D12Impl.h"
@@ -39,6 +42,10 @@
#include "StringTools.h"
#include "EngineMemory.h"
#include "CommandQueueD3D12Impl.h"
+
+#ifndef NOMINMAX
+# define NOMINMAX
+#endif
#include <Windows.h>
#include <dxgi1_4.h>
@@ -61,6 +68,8 @@ public:
TBase{IID_EngineFactoryD3D12}
{}
+ bool LoadD3D12(const char* DllName) override final;
+
void CreateDeviceAndContextsD3D12(const EngineD3D12CreateInfo& EngineCI,
IRenderDevice** ppDevice,
IDeviceContext** ppContexts) override final;
@@ -78,8 +87,54 @@ public:
const FullScreenModeDesc& FSDesc,
void* pNativeWndHandle,
ISwapChain** ppSwapChain) override final;
+
+ virtual void EnumerateAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel,
+ Uint32& NumAdapters,
+ AdapterAttribs* Adapters) override final;
+
+ virtual void EnumerateDisplayModes(DIRECT3D_FEATURE_LEVEL MinFeatureLevel,
+ Uint32 AdapterId,
+ Uint32 OutputId,
+ TEXTURE_FORMAT Format,
+ Uint32& NumDisplayModes,
+ DisplayModeAttribs* DisplayModes) override final;
+
+
+private:
+#if USE_D3D12_LOADER
+ HMODULE m_hD3D12Dll = NULL;
+ std::string m_DllName;
+#endif
};
+bool EngineFactoryD3D12Impl::LoadD3D12(const char* DllName)
+{
+#if USE_D3D12_LOADER
+ if (m_hD3D12Dll == NULL)
+ {
+ m_hD3D12Dll = LoadD3D12Dll(DllName);
+ if (m_hD3D12Dll == NULL)
+ {
+ LOG_ERROR_MESSAGE("Failed to load Direct3D12 DLL (", DllName, "). Check that the system supports Direct3D12 and that the dll is present on the system.");
+ return false;
+ }
+
+ if (m_DllName.empty())
+ m_DllName = DllName;
+ else
+ {
+ if (StrCmpNoCase(m_DllName.c_str(), DllName) != 0)
+ {
+ LOG_WARNING_MESSAGE("D3D12 DLL has already been loaded as '", m_DllName,
+ "'. New name '", DllName, "' will be ignored.");
+ }
+ }
+ }
+#endif
+
+ return true;
+}
+
static void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter, D3D_FEATURE_LEVEL FeatureLevel)
{
CComPtr<IDXGIAdapter1> adapter;
@@ -115,7 +170,13 @@ void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12(const EngineD3D12Creat
SetDebugMessageCallback(EngineCI.DebugMessageCallback);
if (EngineCI.APIVersion != DILIGENT_API_VERSION)
- LOG_ERROR_AND_THROW("Diligent Engine runtime (", EngineCI.APIVersion, ") is not compatible with the client API version (", DILIGENT_API_VERSION, ")");
+ {
+ LOG_ERROR_MESSAGE("Diligent Engine runtime (", DILIGENT_API_VERSION, ") is not compatible with the client API version (", EngineCI.APIVersion, ")");
+ return;
+ }
+
+ if (!LoadD3D12(EngineCI.D3D12DllName))
+ return;
VERIFY(ppDevice && ppContexts, "Null pointer provided");
if (!ppDevice || !ppContexts)
@@ -322,7 +383,13 @@ void EngineFactoryD3D12Impl::AttachToD3D12Device(void* pd
SetDebugMessageCallback(EngineCI.DebugMessageCallback);
if (EngineCI.APIVersion != DILIGENT_API_VERSION)
- LOG_ERROR_AND_THROW("Diligent Engine runtime (", EngineCI.APIVersion, ") is not compatible with the client API version (", DILIGENT_API_VERSION, ")");
+ {
+ LOG_ERROR_MESSAGE("Diligent Engine runtime (", DILIGENT_API_VERSION, ") is not compatible with the client API version (", EngineCI.APIVersion, ")");
+ return;
+ }
+
+ if (!LoadD3D12(EngineCI.D3D12DllName))
+ return;
VERIFY(pd3d12NativeDevice && ppCommandQueues && ppDevice && ppContexts, "Null pointer provided");
if (!pd3d12NativeDevice || !ppCommandQueues || !ppDevice || !ppContexts)
@@ -410,6 +477,37 @@ void EngineFactoryD3D12Impl::CreateSwapChainD3D12(IRenderDevice* pDev
}
}
+void EngineFactoryD3D12Impl::EnumerateAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel,
+ Uint32& NumAdapters,
+ AdapterAttribs* Adapters)
+{
+#if USE_D3D12_LOADER
+ if (m_hD3D12Dll == NULL)
+ {
+ LOG_ERROR_MESSAGE("D3D12 has not been loaded. Please use IEngineFactoryD3D12::LoadD3D12() to load the library and entry points.");
+ return;
+ }
+#endif
+ TBase::EnumerateAdapters(MinFeatureLevel, NumAdapters, Adapters);
+}
+
+void EngineFactoryD3D12Impl::EnumerateDisplayModes(DIRECT3D_FEATURE_LEVEL MinFeatureLevel,
+ Uint32 AdapterId,
+ Uint32 OutputId,
+ TEXTURE_FORMAT Format,
+ Uint32& NumDisplayModes,
+ DisplayModeAttribs* DisplayModes)
+{
+#if USE_D3D12_LOADER
+ if (m_hD3D12Dll == NULL)
+ {
+ LOG_ERROR_MESSAGE("D3D12 has not been loaded. Please use IEngineFactoryD3D12::LoadD3D12() to load the library and entry points.");
+ return;
+ }
+#endif
+ TBase::EnumerateDisplayModes(MinFeatureLevel, AdapterId, OutputId, Format, NumDisplayModes, DisplayModes);
+}
+
#ifdef DOXYGEN
/// Loads Direct3D12-based engine implementation and exports factory functions