diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-01-08 18:09:08 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-01-08 18:09:08 +0000 |
| commit | 61cb28a4c3a538f6d43098f045bdc07611652604 (patch) | |
| tree | 0f7c4e61112a55de4f3deb817696b91d2a000c1f /Graphics/GraphicsEngineD3D12 | |
| parent | Updated factory functions to not throw exceptions, but return; fixed API vers... (diff) | |
| download | DiligentCore-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.txt | 15 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D12/include/D3D12Loader.h | 57 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D12/include/pch.h | 6 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h | 16 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D12/src/D3D12Loader.cpp | 88 | ||||
| -rw-r--r-- | Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp | 102 |
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 |
