From f551f6353eaf4efe9b7f26d48822b96ebb0706a0 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Mon, 4 Mar 2019 22:38:04 -0800 Subject: Updated D3D11, D3D12, and Vk EngineFactory headers & structures --- Graphics/GraphicsEngineD3D12/CMakeLists.txt | 4 +- .../include/DeviceContextD3D12Impl.h | 12 +- .../include/RenderDeviceD3D12Impl.h | 16 +- .../interface/EngineFactoryD3D12.h | 133 +++++++ .../interface/RenderDeviceFactoryD3D12.h | 133 ------- Graphics/GraphicsEngineD3D12/readme.md | 2 +- .../src/DeviceContextD3D12Impl.cpp | 20 +- .../GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp | 438 +++++++++++++++++++++ .../src/RenderDeviceD3D12Impl.cpp | 30 +- .../src/RenderDeviceFactoryD3D12.cpp | 438 --------------------- .../src/ShaderResourceLayoutD3D12.cpp | 2 +- 11 files changed, 614 insertions(+), 614 deletions(-) create mode 100644 Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h delete mode 100644 Graphics/GraphicsEngineD3D12/interface/RenderDeviceFactoryD3D12.h create mode 100644 Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp delete mode 100644 Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp (limited to 'Graphics/GraphicsEngineD3D12') diff --git a/Graphics/GraphicsEngineD3D12/CMakeLists.txt b/Graphics/GraphicsEngineD3D12/CMakeLists.txt index d9505bd0..a5fac952 100644 --- a/Graphics/GraphicsEngineD3D12/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3D12/CMakeLists.txt @@ -40,10 +40,10 @@ set(INTERFACE interface/BufferViewD3D12.h interface/CommandQueueD3D12.h interface/DeviceContextD3D12.h + interface/EngineFactoryD3D12.h interface/FenceD3D12.h interface/PipelineStateD3D12.h interface/RenderDeviceD3D12.h - interface/RenderDeviceFactoryD3D12.h interface/SamplerD3D12.h interface/ShaderD3D12.h interface/ShaderResourceBindingD3D12.h @@ -64,11 +64,11 @@ set(SRC src/DescriptorHeap.cpp src/DeviceContextD3D12Impl.cpp src/D3D12DynamicHeap.cpp + src/EngineFactoryD3D12.cpp src/FenceD3D12Impl.cpp src/GenerateMips.cpp src/PipelineStateD3D12Impl.cpp src/RenderDeviceD3D12Impl.cpp - src/RenderDeviceFactoryD3D12.cpp src/RootSignature.cpp src/SamplerD3D12Impl.cpp src/ShaderD3D12Impl.cpp diff --git a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h index 438014e3..d22784dd 100644 --- a/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/DeviceContextD3D12Impl.h @@ -52,12 +52,12 @@ class DeviceContextD3D12Impl final : public DeviceContextNextGenBase< DeviceCont public: using TDeviceContextBase = DeviceContextNextGenBase< DeviceContextBase >; - DeviceContextD3D12Impl(IReferenceCounters* pRefCounters, - class RenderDeviceD3D12Impl* pDevice, - bool bIsDeferred, - const EngineD3D12Attribs& Attribs, - Uint32 ContextId, - Uint32 CommandQueueId); + DeviceContextD3D12Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D12Impl* pDevice, + bool bIsDeferred, + const EngineD3D12CreateInfo& EngineCI, + Uint32 ContextId, + Uint32 CommandQueueId); ~DeviceContextD3D12Impl(); virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override final; diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h index f9e4d3aa..376e32d1 100644 --- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h +++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h @@ -45,13 +45,13 @@ class RenderDeviceD3D12Impl final : public RenderDeviceNextGenBase< RenderDevice public: using TRenderDeviceBase = RenderDeviceNextGenBase< RenderDeviceD3DBase, ICommandQueueD3D12 >; - RenderDeviceD3D12Impl( IReferenceCounters* pRefCounters, - IMemoryAllocator& RawMemAllocator, - const EngineD3D12Attribs& CreationAttribs, - ID3D12Device* pD3D12Device, - size_t CommandQueueCount, - ICommandQueueD3D12** ppCmdQueues, - Uint32 NumDeferredContexts ); + RenderDeviceD3D12Impl( IReferenceCounters* pRefCounters, + IMemoryAllocator& RawMemAllocator, + const EngineD3D12CreateInfo& EngineCI, + ID3D12Device* pD3D12Device, + size_t CommandQueueCount, + ICommandQueueD3D12** ppCmdQueues, + Uint32 NumDeferredContexts ); ~RenderDeviceD3D12Impl(); virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override final; @@ -108,7 +108,7 @@ private: CComPtr m_pd3d12Device; - EngineD3D12Attribs m_EngineAttribs; + EngineD3D12CreateInfo m_EngineAttribs; CPUDescriptorHeap m_CPUDescriptorHeaps[D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES]; GPUDescriptorHeap m_GPUDescriptorHeaps[2]; // D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV == 0 diff --git a/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h b/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h new file mode 100644 index 00000000..7ac6e9e0 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h @@ -0,0 +1,133 @@ +/* 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * 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 + +/// \file +/// Declaration of functions that initialize Direct3D12-based engine implementation + +#include + +#include "../../GraphicsEngine/interface/RenderDevice.h" +#include "../../GraphicsEngine/interface/DeviceContext.h" +#include "../../GraphicsEngine/interface/SwapChain.h" + +#if PLATFORM_UNIVERSAL_WINDOWS && defined(ENGINE_DLL) +# include "../../../Common/interface/StringTools.h" +#endif + +namespace Diligent +{ + +class IEngineFactoryD3D12 +{ +public: + virtual void CreateDeviceAndContextsD3D12(const EngineD3D12CreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts) = 0; + + virtual void AttachToD3D12Device(void* pd3d12NativeDevice, + size_t CommandQueueCount, + class ICommandQueueD3D12** ppCommandQueues, + const EngineD3D12CreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts) = 0; + + virtual void CreateSwapChainD3D12( IRenderDevice* pDevice, + IDeviceContext* pImmediateContext, + const SwapChainDesc& SwapChainDesc, + const FullScreenModeDesc& FSDesc, + void* pNativeWndHandle, + ISwapChain** ppSwapChain ) = 0; + + virtual void EnumerateHardwareAdapters(Uint32& NumAdapters, + HardwareAdapterAttribs* Adapters) = 0; + + virtual void EnumerateDisplayModes(Uint32 AdapterId, + Uint32 OutputId, + TEXTURE_FORMAT Format, + Uint32& NumDisplayModes, + DisplayModeAttribs* DisplayModes) = 0; + +}; + + +#if ENGINE_DLL + + typedef IEngineFactoryD3D12* (*GetEngineFactoryD3D12Type)(); + + static bool LoadGraphicsEngineD3D12(GetEngineFactoryD3D12Type &GetFactoryFunc) + { + GetFactoryFunc = nullptr; + std::string LibName = "GraphicsEngineD3D12_"; + +#if _WIN64 + LibName += "64"; +#else + LibName += "32"; +#endif + +#ifdef _DEBUG + LibName += "d"; +#else + LibName += "r"; +#endif + + LibName += ".dll"; +#if PLATFORM_WIN32 + auto hModule = LoadLibraryA(LibName.c_str()); +#elif PLATFORM_UNIVERSAL_WINDOWS + auto hModule = LoadPackagedLibrary(WidenString(LibName).c_str(), 0); +#else +# error Unexpected platform +#endif + + if( hModule == NULL ) + { + std::stringstream ss; + ss << "Failed to load " << LibName << " library.\n"; + OutputDebugStringA(ss.str().c_str()); + return false; + } + + GetFactoryFunc = reinterpret_cast( GetProcAddress(hModule, "GetEngineFactoryD3D12") ); + if( GetFactoryFunc == NULL ) + { + std::stringstream ss; + ss << "Failed to load GetEngineFactoryD3D12() from " << LibName << " library.\n"; + OutputDebugStringA(ss.str().c_str()); + FreeLibrary( hModule ); + return false; + } + + return true; + } +#else + + IEngineFactoryD3D12* GetEngineFactoryD3D12(); + +#endif + +} diff --git a/Graphics/GraphicsEngineD3D12/interface/RenderDeviceFactoryD3D12.h b/Graphics/GraphicsEngineD3D12/interface/RenderDeviceFactoryD3D12.h deleted file mode 100644 index 80e6f580..00000000 --- a/Graphics/GraphicsEngineD3D12/interface/RenderDeviceFactoryD3D12.h +++ /dev/null @@ -1,133 +0,0 @@ -/* 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 - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. - * - * 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 - -/// \file -/// Declaration of functions that initialize Direct3D12-based engine implementation - -#include - -#include "../../GraphicsEngine/interface/RenderDevice.h" -#include "../../GraphicsEngine/interface/DeviceContext.h" -#include "../../GraphicsEngine/interface/SwapChain.h" - -#if PLATFORM_UNIVERSAL_WINDOWS && defined(ENGINE_DLL) -# include "../../../Common/interface/StringTools.h" -#endif - -namespace Diligent -{ - -class IEngineFactoryD3D12 -{ -public: - virtual void CreateDeviceAndContextsD3D12( const EngineD3D12Attribs& CreationAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts) = 0; - - virtual void AttachToD3D12Device(void* pd3d12NativeDevice, - size_t CommandQueueCount, - class ICommandQueueD3D12** ppCommandQueues, - const EngineD3D12Attribs& EngineAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts) = 0; - - virtual void CreateSwapChainD3D12( IRenderDevice* pDevice, - IDeviceContext* pImmediateContext, - const SwapChainDesc& SwapChainDesc, - const FullScreenModeDesc& FSDesc, - void* pNativeWndHandle, - ISwapChain** ppSwapChain ) = 0; - - virtual void EnumerateHardwareAdapters(Uint32& NumAdapters, - HardwareAdapterAttribs* Adapters) = 0; - - virtual void EnumerateDisplayModes(Uint32 AdapterId, - Uint32 OutputId, - TEXTURE_FORMAT Format, - Uint32& NumDisplayModes, - DisplayModeAttribs* DisplayModes) = 0; - -}; - - -#if ENGINE_DLL - - typedef IEngineFactoryD3D12* (*GetEngineFactoryD3D12Type)(); - - static bool LoadGraphicsEngineD3D12(GetEngineFactoryD3D12Type &GetFactoryFunc) - { - GetFactoryFunc = nullptr; - std::string LibName = "GraphicsEngineD3D12_"; - -#if _WIN64 - LibName += "64"; -#else - LibName += "32"; -#endif - -#ifdef _DEBUG - LibName += "d"; -#else - LibName += "r"; -#endif - - LibName += ".dll"; -#if PLATFORM_WIN32 - auto hModule = LoadLibraryA(LibName.c_str()); -#elif PLATFORM_UNIVERSAL_WINDOWS - auto hModule = LoadPackagedLibrary(WidenString(LibName).c_str(), 0); -#else -# error Unexpected platform -#endif - - if( hModule == NULL ) - { - std::stringstream ss; - ss << "Failed to load " << LibName << " library.\n"; - OutputDebugStringA(ss.str().c_str()); - return false; - } - - GetFactoryFunc = reinterpret_cast( GetProcAddress(hModule, "GetEngineFactoryD3D12") ); - if( GetFactoryFunc == NULL ) - { - std::stringstream ss; - ss << "Failed to load GetEngineFactoryD3D12() from " << LibName << " library.\n"; - OutputDebugStringA(ss.str().c_str()); - FreeLibrary( hModule ); - return false; - } - - return true; - } -#else - - IEngineFactoryD3D12* GetEngineFactoryD3D12(); - -#endif - -} diff --git a/Graphics/GraphicsEngineD3D12/readme.md b/Graphics/GraphicsEngineD3D12/readme.md index 3827a4f0..85ad141b 100644 --- a/Graphics/GraphicsEngineD3D12/readme.md +++ b/Graphics/GraphicsEngineD3D12/readme.md @@ -8,7 +8,7 @@ Implementation of Direct3D12 back-end The following code snippet shows how to initialize Diligent Engine in D3D12 mode. ```cpp -#include "RenderDeviceFactoryD3D12.h" +#include "EngineFactoryD3D12.h" using namespace Diligent; // ... diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 7e8eeeed..a1d9db3f 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -51,39 +51,39 @@ namespace Diligent return ss.str(); } - DeviceContextD3D12Impl::DeviceContextD3D12Impl( IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pDeviceD3D12Impl, - bool bIsDeferred, - const EngineD3D12Attribs& Attribs, - Uint32 ContextId, - Uint32 CommandQueueId) : + DeviceContextD3D12Impl::DeviceContextD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDeviceD3D12Impl, + bool bIsDeferred, + const EngineD3D12CreateInfo& EngineCI, + Uint32 ContextId, + Uint32 CommandQueueId) : TDeviceContextBase { pRefCounters, pDeviceD3D12Impl, ContextId, CommandQueueId, - bIsDeferred ? std::numeric_limits::max() : Attribs.NumCommandsToFlushCmdList, + bIsDeferred ? std::numeric_limits::max() : EngineCI.NumCommandsToFlushCmdList, bIsDeferred }, m_DynamicHeap { pDeviceD3D12Impl->GetDynamicMemoryManager(), GetContextObjectName("Dynamic heap", bIsDeferred, ContextId), - Attribs.DynamicHeapPageSize + EngineCI.DynamicHeapPageSize }, m_DynamicGPUDescriptorAllocator { { GetRawAllocator(), pDeviceD3D12Impl->GetGPUDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV), - Attribs.DynamicDescriptorAllocationChunkSize[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV], + EngineCI.DynamicDescriptorAllocationChunkSize[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV], GetContextObjectName("CBV_SRV_UAV dynamic descriptor allocator", bIsDeferred, ContextId) }, { GetRawAllocator(), pDeviceD3D12Impl->GetGPUDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER), - Attribs.DynamicDescriptorAllocationChunkSize[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER], + EngineCI.DynamicDescriptorAllocationChunkSize[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER], GetContextObjectName("SAMPLER dynamic descriptor allocator", bIsDeferred, ContextId) } }, diff --git a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp new file mode 100644 index 00000000..18a69020 --- /dev/null +++ b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp @@ -0,0 +1,438 @@ +/* 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 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * 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. + */ + +/// \file +/// Routines that initialize D3D12-based engine implementation + +#include "pch.h" +#include +#include "EngineFactoryD3D12.h" +#include "RenderDeviceD3D12Impl.h" +#include "DeviceContextD3D12Impl.h" +#include "SwapChainD3D12Impl.h" +#include "D3D12TypeConversions.h" +#include "EngineFactoryD3DBase.h" +#include "StringTools.h" +#include "EngineMemory.h" +#include "CommandQueueD3D12Impl.h" +#include +#include + +namespace Diligent +{ + +/// Engine factory for D3D12 implementation +class EngineFactoryD3D12Impl : public EngineFactoryD3DBase +{ +public: + static EngineFactoryD3D12Impl* GetInstance() + { + static EngineFactoryD3D12Impl TheFactory; + return &TheFactory; + } + + void CreateDeviceAndContextsD3D12(const EngineD3D12CreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts)override final; + + void AttachToD3D12Device(void* pd3d12NativeDevice, + size_t CommandQueueCount, + ICommandQueueD3D12** ppCommandQueues, + const EngineD3D12CreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts)override final; + + void CreateSwapChainD3D12( IRenderDevice* pDevice, + IDeviceContext* pImmediateContext, + const SwapChainDesc& SwapChainDesc, + const FullScreenModeDesc& FSDesc, + void* pNativeWndHandle, + ISwapChain** ppSwapChain )override final; +}; + +void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter) +{ + CComPtr adapter; + *ppAdapter = nullptr; + + for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, &adapter); ++adapterIndex) + { + DXGI_ADAPTER_DESC1 desc; + adapter->GetDesc1(&desc); + + if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) + { + // Skip software devices + continue; + } + + // Check to see if the adapter supports Direct3D 12, but don't create the + // actual device yet. + if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) + { + break; + } + } + + *ppAdapter = adapter.Detach(); +} + +/// Creates render device and device contexts for Direct3D12-based engine implementation + +/// \param [in] EngineCI - Engine creation attributes. +/// \param [out] ppDevice - Address of the memory location where pointer to +/// the created device will be written +/// \param [out] ppContexts - Address of the memory location where pointers to +/// the contexts will be written. The new immediate +/// context goes at position 0. If NumDeferredContexts > 0, +/// pointers to the deferred contexts are written afterwards. +/// \param [in] NumDeferredContexts - Number of deferred contexts. If non-zero number +/// of deferred contexts is requested, pointers to the +/// contexts are written to ppContexts array starting +/// at position 1 +void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12(const EngineD3D12CreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts) +{ + if (EngineCI.DebugMessageCallback != nullptr) + SetDebugMessageCallback(EngineCI.DebugMessageCallback); + + VERIFY( ppDevice && ppContexts, "Null pointer provided" ); + if( !ppDevice || !ppContexts ) + return; + + for(Uint32 Type=D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; Type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++Type) + { + auto CPUHeapAllocSize = EngineCI.CPUDescriptorHeapAllocationSize[Type]; + Uint32 MaxSize = 1 << 20; + if( CPUHeapAllocSize > 1 << 20 ) + { + LOG_ERROR( "CPU Heap allocation size is too large (", CPUHeapAllocSize, "). Max allowed size is ", MaxSize ); + return; + } + + if( (CPUHeapAllocSize % 16) != 0 ) + { + LOG_ERROR( "CPU Heap allocation size (", CPUHeapAllocSize, ") is expected to be multiple of 16" ); + return; + } + } + + *ppDevice = nullptr; + memset(ppContexts, 0, sizeof(*ppContexts) * (1+NumDeferredContexts)); + + RefCntAutoPtr pCmdQueueD3D12; + CComPtr d3d12Device; + try + { +#if defined(_DEBUG) + // Enable the D3D12 debug layer. + { + CComPtr debugController; + if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(debugController), reinterpret_cast(static_cast(&debugController)) ))) + { + debugController->EnableDebugLayer(); + } + } +#endif + + CComPtr factory; + HRESULT hr = CreateDXGIFactory1(__uuidof(factory), reinterpret_cast(static_cast(&factory)) ); + CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI factory"); + + CComPtr hardwareAdapter; + if(EngineCI.AdapterId == EngineD3D12CreateInfo::DefaultAdapterId) + { + GetHardwareAdapter(factory, &hardwareAdapter); + if(hardwareAdapter == nullptr) + LOG_ERROR_AND_THROW("No suitable hardware adapter found"); + } + else + { + auto Adapters = FindCompatibleAdapters(); + if(EngineCI.AdapterId < Adapters.size()) + hardwareAdapter = Adapters[EngineCI.AdapterId]; + else + { + LOG_ERROR_AND_THROW(EngineCI.AdapterId, " is not a valid hardware adapter id. Total number of compatible adapters available on this system: ", Adapters.size()); + } + } + + { + DXGI_ADAPTER_DESC1 desc; + hardwareAdapter->GetDesc1(&desc); + LOG_INFO_MESSAGE("D3D12-capabale hardware found: ", NarrowString(desc.Description), " (", desc.DedicatedVideoMemory >> 20, " MB)"); + } + + hr = D3D12CreateDevice(hardwareAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(d3d12Device), reinterpret_cast(static_cast(&d3d12Device)) ); + if( FAILED(hr)) + { + LOG_WARNING_MESSAGE("Failed to create hardware device. Attempting to create WARP device"); + + CComPtr warpAdapter; + hr = factory->EnumWarpAdapter( __uuidof(warpAdapter), reinterpret_cast(static_cast(&warpAdapter)) ); + CHECK_D3D_RESULT_THROW(hr, "Failed to enum warp adapter"); + + hr = D3D12CreateDevice( warpAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(d3d12Device), reinterpret_cast(static_cast(&d3d12Device)) ); + CHECK_D3D_RESULT_THROW(hr, "Failed to crate warp device"); + } + +#if _DEBUG + { + CComPtr pInfoQueue; + hr = d3d12Device->QueryInterface(__uuidof(pInfoQueue), reinterpret_cast(static_cast(&pInfoQueue))); + if( SUCCEEDED(hr) ) + { + // Suppress whole categories of messages + //D3D12_MESSAGE_CATEGORY Categories[] = {}; + + // Suppress messages based on their severity level + D3D12_MESSAGE_SEVERITY Severities[] = + { + D3D12_MESSAGE_SEVERITY_INFO + }; + + // Suppress individual messages by their ID + //D3D12_MESSAGE_ID DenyIds[] = {}; + + D3D12_INFO_QUEUE_FILTER NewFilter = {}; + //NewFilter.DenyList.NumCategories = _countof(Categories); + //NewFilter.DenyList.pCategoryList = Categories; + NewFilter.DenyList.NumSeverities = _countof(Severities); + NewFilter.DenyList.pSeverityList = Severities; + //NewFilter.DenyList.NumIDs = _countof(DenyIds); + //NewFilter.DenyList.pIDList = DenyIds; + + hr = pInfoQueue->PushStorageFilter(&NewFilter); + VERIFY(SUCCEEDED(hr), "Failed to push storage filter"); + } + } +#endif + +#ifndef RELEASE + // Prevent the GPU from overclocking or underclocking to get consistent timings + //d3d12Device->SetStablePowerState(TRUE); +#endif + + // Describe and create the command queue. + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + + CComPtr pd3d12CmdQueue; + hr = d3d12Device->CreateCommandQueue(&queueDesc, __uuidof(pd3d12CmdQueue), reinterpret_cast(static_cast(&pd3d12CmdQueue))); + CHECK_D3D_RESULT_THROW(hr, "Failed to create command queue"); + hr = pd3d12CmdQueue->SetName(L"Main Command Queue"); + VERIFY_EXPR(SUCCEEDED(hr)); + + CComPtr pd3d12Fence; + hr = d3d12Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(pd3d12Fence), reinterpret_cast(static_cast(&pd3d12Fence))); + CHECK_D3D_RESULT_THROW(hr, "Failed to create main command queue fence"); + d3d12Device->SetName(L"Main Command Queue fence"); + + auto &RawMemAllocator = GetRawAllocator(); + pCmdQueueD3D12 = NEW_RC_OBJ(RawMemAllocator, "CommandQueueD3D12 instance", CommandQueueD3D12Impl)(pd3d12CmdQueue, pd3d12Fence); + } + catch( const std::runtime_error & ) + { + LOG_ERROR( "Failed to initialize D3D12 resources" ); + return; + } + + std::array CmdQueues = {pCmdQueueD3D12}; + AttachToD3D12Device(d3d12Device, CmdQueues.size(), CmdQueues.data(), EngineCI, ppDevice, ppContexts, NumDeferredContexts); +} + + +/// Attaches to existing D3D12 device + +/// \param [in] pd3d12NativeDevice - pointer to native D3D12 device +/// \param [in] CommandQueueCount - Number of command queues +/// \param [in] ppCommandQueues - pointer to the array of command queues +/// \param [in] EngineCI - Engine creation attributes. +/// \param [out] ppDevice - Address of the memory location where pointer to +/// the created device will be written +/// \param [out] ppContexts - Address of the memory location where pointers to +/// the contexts will be written. Pointer to the immediate +/// context goes at position 0. If NumDeferredContexts > 0, +/// pointers to the deferred contexts go afterwards. +/// \param [in] NumDeferredContexts - Number of deferred contexts. If non-zero number +/// of deferred contexts is requested, pointers to the +/// contexts are written to ppContexts array starting +/// at position 1 +void EngineFactoryD3D12Impl::AttachToD3D12Device(void* pd3d12NativeDevice, + size_t CommandQueueCount, + ICommandQueueD3D12** ppCommandQueues, + const EngineD3D12CreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts) +{ + if (EngineCI.DebugMessageCallback != nullptr) + SetDebugMessageCallback(EngineCI.DebugMessageCallback); + + VERIFY( pd3d12NativeDevice && ppCommandQueues && ppDevice && ppContexts, "Null pointer provided" ); + if( !pd3d12NativeDevice || !ppCommandQueues || !ppDevice || !ppContexts ) + return; + + *ppDevice = nullptr; + memset(ppContexts, 0, sizeof(*ppContexts) * (1+NumDeferredContexts)); + + try + { + SetRawAllocator(EngineCI.pRawMemAllocator); + auto &RawMemAllocator = GetRawAllocator(); + auto d3d12Device = reinterpret_cast(pd3d12NativeDevice); + RenderDeviceD3D12Impl *pRenderDeviceD3D12( NEW_RC_OBJ(RawMemAllocator, "RenderDeviceD3D12Impl instance", RenderDeviceD3D12Impl)(RawMemAllocator, EngineCI, d3d12Device, CommandQueueCount, ppCommandQueues, NumDeferredContexts ) ); + pRenderDeviceD3D12->QueryInterface(IID_RenderDevice, reinterpret_cast(ppDevice) ); + + RefCntAutoPtr pImmediateCtxD3D12( NEW_RC_OBJ(RawMemAllocator, "DeviceContextD3D12Impl instance", DeviceContextD3D12Impl)(pRenderDeviceD3D12, false, EngineCI, 0, 0) ); + // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceD3D12 will + // keep a weak reference to the context + pImmediateCtxD3D12->QueryInterface(IID_DeviceContext, reinterpret_cast(ppContexts) ); + pRenderDeviceD3D12->SetImmediateContext(pImmediateCtxD3D12); + + for (Uint32 DeferredCtx = 0; DeferredCtx < NumDeferredContexts; ++DeferredCtx) + { + RefCntAutoPtr pDeferredCtxD3D12( NEW_RC_OBJ(RawMemAllocator, "DeviceContextD3D12Impl instance", DeviceContextD3D12Impl)(pRenderDeviceD3D12, true, EngineCI, 1+DeferredCtx, 0) ); + // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceD3D12 will + // keep a weak reference to the context + pDeferredCtxD3D12->QueryInterface(IID_DeviceContext, reinterpret_cast(ppContexts + 1 + DeferredCtx) ); + pRenderDeviceD3D12->SetDeferredContext(DeferredCtx, pDeferredCtxD3D12); + } + } + catch( const std::runtime_error & ) + { + if( *ppDevice ) + { + (*ppDevice)->Release(); + *ppDevice = nullptr; + } + for(Uint32 ctx=0; ctx < 1 + NumDeferredContexts; ++ctx) + { + if( ppContexts[ctx] != nullptr ) + { + ppContexts[ctx]->Release(); + ppContexts[ctx] = nullptr; + } + } + + LOG_ERROR( "Failed to create device and contexts" ); + } +} + +/// Creates a swap chain for Direct3D12-based engine implementation + +/// \param [in] pDevice - Pointer to the render device +/// \param [in] pImmediateContext - Pointer to the immediate device context +/// \param [in] SCDesc - Swap chain description +/// \param [in] FSDesc - Fullscreen mode description +/// \param [in] pNativeWndHandle - Platform-specific native handle of the window +/// the swap chain will be associated with: +/// * On Win32 platform, this should be window handle (HWND) +/// * On Universal Windows Platform, this should be reference to the +/// core window (Windows::UI::Core::CoreWindow) +/// +/// \param [out] ppSwapChain - Address of the memory location where pointer to the new +/// swap chain will be written +void EngineFactoryD3D12Impl::CreateSwapChainD3D12(IRenderDevice* pDevice, + IDeviceContext* pImmediateContext, + const SwapChainDesc& SCDesc, + const FullScreenModeDesc& FSDesc, + void* pNativeWndHandle, + ISwapChain** ppSwapChain ) +{ + VERIFY( ppSwapChain, "Null pointer provided" ); + if( !ppSwapChain ) + return; + + *ppSwapChain = nullptr; + + try + { + auto *pDeviceD3D12 = ValidatedCast( pDevice ); + auto *pDeviceContextD3D12 = ValidatedCast(pImmediateContext); + auto &RawMemAllocator = GetRawAllocator(); + auto *pSwapChainD3D12 = NEW_RC_OBJ(RawMemAllocator, "SwapChainD3D12Impl instance", SwapChainD3D12Impl)(SCDesc, FSDesc, pDeviceD3D12, pDeviceContextD3D12, pNativeWndHandle); + pSwapChainD3D12->QueryInterface( IID_SwapChain, reinterpret_cast(ppSwapChain) ); + + pDeviceContextD3D12->SetSwapChain(pSwapChainD3D12); + // Bind default render target + pDeviceContextD3D12->SetRenderTargets( 0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION ); + // Set default viewport + pDeviceContextD3D12->SetViewports( 1, nullptr, 0, 0 ); + + auto NumDeferredCtx = pDeviceD3D12->GetNumDeferredContexts(); + for (size_t ctx = 0; ctx < NumDeferredCtx; ++ctx) + { + if (auto pDeferredCtx = pDeviceD3D12->GetDeferredContext(ctx)) + { + auto* pDeferredCtxD3D12 = pDeferredCtx.RawPtr(); + pDeferredCtxD3D12->SetSwapChain(pSwapChainD3D12); + // We cannot bind default render target here because + // there is no guarantee that deferred context will be used + // in this frame. It is an error to bind + // RTV of an inactive buffer in the swap chain + } + } + } + catch( const std::runtime_error& ) + { + if( *ppSwapChain ) + { + (*ppSwapChain)->Release(); + *ppSwapChain = nullptr; + } + + LOG_ERROR( "Failed to create the swap chain" ); + } +} + + +#ifdef DOXYGEN +/// Loads Direct3D12-based engine implementation and exports factory functions +/// \param [out] GetFactoryFunc - Pointer to the function that returns factory for D3D12 engine implementation. +/// See EngineFactoryD3D12Impl. +/// \remarks Depending on the configuration and platform, the function loads different dll: +/// Platform\\Configuration | Debug | Release +/// --------------------------|-------------------------------|---------------------------- +/// x86 | GraphicsEngineD3D12_32d.dll | GraphicsEngineD3D12_32r.dll +/// x64 | GraphicsEngineD3D12_64d.dll | GraphicsEngineD3D12_64r.dll +/// +void LoadGraphicsEngineD3D12(GetEngineFactoryD3D12Type& GetFactoryFunc) +{ + // This function is only required because DoxyGen refuses to generate documentation for a static function when SHOW_FILES==NO + #error This function must never be compiled; +} +#endif + + +IEngineFactoryD3D12* GetEngineFactoryD3D12() +{ + return EngineFactoryD3D12Impl::GetInstance(); +} + +} diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index 4640daad..54396583 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -37,13 +37,13 @@ namespace Diligent { -RenderDeviceD3D12Impl :: RenderDeviceD3D12Impl(IReferenceCounters* pRefCounters, - IMemoryAllocator& RawMemAllocator, - const EngineD3D12Attribs& CreationAttribs, - ID3D12Device* pd3d12Device, - size_t CommandQueueCount, - ICommandQueueD3D12** ppCmdQueues, - Uint32 NumDeferredContexts) : +RenderDeviceD3D12Impl :: RenderDeviceD3D12Impl(IReferenceCounters* pRefCounters, + IMemoryAllocator& RawMemAllocator, + const EngineD3D12CreateInfo& EngineCI, + ID3D12Device* pd3d12Device, + size_t CommandQueueCount, + ICommandQueueD3D12** ppCmdQueues, + Uint32 NumDeferredContexts) : TRenderDeviceBase { pRefCounters, @@ -62,22 +62,22 @@ RenderDeviceD3D12Impl :: RenderDeviceD3D12Impl(IReferenceCounters* pRef sizeof(FenceD3D12Impl) }, m_pd3d12Device (pd3d12Device), - m_EngineAttribs (CreationAttribs), + m_EngineAttribs (EngineCI), m_CmdListManager(*this), m_CPUDescriptorHeaps { - {RawMemAllocator, *this, CreationAttribs.CPUDescriptorHeapAllocationSize[0], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE}, - {RawMemAllocator, *this, CreationAttribs.CPUDescriptorHeapAllocationSize[1], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE}, - {RawMemAllocator, *this, CreationAttribs.CPUDescriptorHeapAllocationSize[2], D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE}, - {RawMemAllocator, *this, CreationAttribs.CPUDescriptorHeapAllocationSize[3], D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE} + {RawMemAllocator, *this, EngineCI.CPUDescriptorHeapAllocationSize[0], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE}, + {RawMemAllocator, *this, EngineCI.CPUDescriptorHeapAllocationSize[1], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE}, + {RawMemAllocator, *this, EngineCI.CPUDescriptorHeapAllocationSize[2], D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE}, + {RawMemAllocator, *this, EngineCI.CPUDescriptorHeapAllocationSize[3], D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE} }, m_GPUDescriptorHeaps { - {RawMemAllocator, *this, CreationAttribs.GPUDescriptorHeapSize[0], CreationAttribs.GPUDescriptorHeapDynamicSize[0], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE}, - {RawMemAllocator, *this, CreationAttribs.GPUDescriptorHeapSize[1], CreationAttribs.GPUDescriptorHeapDynamicSize[1], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE} + {RawMemAllocator, *this, EngineCI.GPUDescriptorHeapSize[0], EngineCI.GPUDescriptorHeapDynamicSize[0], D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE}, + {RawMemAllocator, *this, EngineCI.GPUDescriptorHeapSize[1], EngineCI.GPUDescriptorHeapDynamicSize[1], D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE} }, m_ContextPool(STD_ALLOCATOR_RAW_MEM(PooledCommandContext, GetRawAllocator(), "Allocator for vector")), - m_DynamicMemoryManager(GetRawAllocator(), *this, CreationAttribs.NumDynamicHeapPagesToReserve, CreationAttribs.DynamicHeapPageSize), + m_DynamicMemoryManager(GetRawAllocator(), *this, EngineCI.NumDynamicHeapPagesToReserve, EngineCI.DynamicHeapPageSize), m_MipsGenerator(pd3d12Device) { m_DeviceCaps.DevType = DeviceType::D3D12; diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp deleted file mode 100644 index 3096ea9e..00000000 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceFactoryD3D12.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/* 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 - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. - * - * 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. - */ - -/// \file -/// Routines that initialize D3D12-based engine implementation - -#include "pch.h" -#include -#include "RenderDeviceFactoryD3D12.h" -#include "RenderDeviceD3D12Impl.h" -#include "DeviceContextD3D12Impl.h" -#include "SwapChainD3D12Impl.h" -#include "D3D12TypeConversions.h" -#include "EngineFactoryD3DBase.h" -#include "StringTools.h" -#include "EngineMemory.h" -#include "CommandQueueD3D12Impl.h" -#include -#include - -namespace Diligent -{ - -/// Engine factory for D3D12 implementation -class EngineFactoryD3D12Impl : public EngineFactoryD3DBase -{ -public: - static EngineFactoryD3D12Impl* GetInstance() - { - static EngineFactoryD3D12Impl TheFactory; - return &TheFactory; - } - - void CreateDeviceAndContextsD3D12( const EngineD3D12Attribs& CreationAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts)override final; - - void AttachToD3D12Device(void* pd3d12NativeDevice, - size_t CommandQueueCount, - ICommandQueueD3D12** ppCommandQueues, - const EngineD3D12Attribs& EngineAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts)override final; - - void CreateSwapChainD3D12( IRenderDevice* pDevice, - IDeviceContext* pImmediateContext, - const SwapChainDesc& SwapChainDesc, - const FullScreenModeDesc& FSDesc, - void* pNativeWndHandle, - ISwapChain** ppSwapChain )override final; -}; - -void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter) -{ - CComPtr adapter; - *ppAdapter = nullptr; - - for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != pFactory->EnumAdapters1(adapterIndex, &adapter); ++adapterIndex) - { - DXGI_ADAPTER_DESC1 desc; - adapter->GetDesc1(&desc); - - if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) - { - // Skip software devices - continue; - } - - // Check to see if the adapter supports Direct3D 12, but don't create the - // actual device yet. - if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) - { - break; - } - } - - *ppAdapter = adapter.Detach(); -} - -/// Creates render device and device contexts for Direct3D12-based engine implementation - -/// \param [in] CreationAttribs - Engine creation attributes. -/// \param [out] ppDevice - Address of the memory location where pointer to -/// the created device will be written -/// \param [out] ppContexts - Address of the memory location where pointers to -/// the contexts will be written. The new immediate -/// context goes at position 0. If NumDeferredContexts > 0, -/// pointers to the deferred contexts are written afterwards. -/// \param [in] NumDeferredContexts - Number of deferred contexts. If non-zero number -/// of deferred contexts is requested, pointers to the -/// contexts are written to ppContexts array starting -/// at position 1 -void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12( const EngineD3D12Attribs& CreationAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts) -{ - if (CreationAttribs.DebugMessageCallback != nullptr) - SetDebugMessageCallback(CreationAttribs.DebugMessageCallback); - - VERIFY( ppDevice && ppContexts, "Null pointer provided" ); - if( !ppDevice || !ppContexts ) - return; - - for(Uint32 Type=D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; Type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++Type) - { - auto CPUHeapAllocSize = CreationAttribs.CPUDescriptorHeapAllocationSize[Type]; - Uint32 MaxSize = 1 << 20; - if( CPUHeapAllocSize > 1 << 20 ) - { - LOG_ERROR( "CPU Heap allocation size is too large (", CPUHeapAllocSize, "). Max allowed size is ", MaxSize ); - return; - } - - if( (CPUHeapAllocSize % 16) != 0 ) - { - LOG_ERROR( "CPU Heap allocation size (", CPUHeapAllocSize, ") is expected to be multiple of 16" ); - return; - } - } - - *ppDevice = nullptr; - memset(ppContexts, 0, sizeof(*ppContexts) * (1+NumDeferredContexts)); - - RefCntAutoPtr pCmdQueueD3D12; - CComPtr d3d12Device; - try - { -#if defined(_DEBUG) - // Enable the D3D12 debug layer. - { - CComPtr debugController; - if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(debugController), reinterpret_cast(static_cast(&debugController)) ))) - { - debugController->EnableDebugLayer(); - } - } -#endif - - CComPtr factory; - HRESULT hr = CreateDXGIFactory1(__uuidof(factory), reinterpret_cast(static_cast(&factory)) ); - CHECK_D3D_RESULT_THROW(hr, "Failed to create DXGI factory"); - - CComPtr hardwareAdapter; - if(CreationAttribs.AdapterId == EngineD3D12Attribs::DefaultAdapterId) - { - GetHardwareAdapter(factory, &hardwareAdapter); - if(hardwareAdapter == nullptr) - LOG_ERROR_AND_THROW("No suitable hardware adapter found"); - } - else - { - auto Adapters = FindCompatibleAdapters(); - if(CreationAttribs.AdapterId < Adapters.size()) - hardwareAdapter = Adapters[CreationAttribs.AdapterId]; - else - { - LOG_ERROR_AND_THROW(CreationAttribs.AdapterId, " is not a valid hardware adapter id. Total number of compatible adapters available on this system: ", Adapters.size()); - } - } - - { - DXGI_ADAPTER_DESC1 desc; - hardwareAdapter->GetDesc1(&desc); - LOG_INFO_MESSAGE("D3D12-capabale hardware found: ", NarrowString(desc.Description), " (", desc.DedicatedVideoMemory >> 20, " MB)"); - } - - hr = D3D12CreateDevice(hardwareAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(d3d12Device), reinterpret_cast(static_cast(&d3d12Device)) ); - if( FAILED(hr)) - { - LOG_WARNING_MESSAGE("Failed to create hardware device. Attempting to create WARP device"); - - CComPtr warpAdapter; - hr = factory->EnumWarpAdapter( __uuidof(warpAdapter), reinterpret_cast(static_cast(&warpAdapter)) ); - CHECK_D3D_RESULT_THROW(hr, "Failed to enum warp adapter"); - - hr = D3D12CreateDevice( warpAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(d3d12Device), reinterpret_cast(static_cast(&d3d12Device)) ); - CHECK_D3D_RESULT_THROW(hr, "Failed to crate warp device"); - } - -#if _DEBUG - { - CComPtr pInfoQueue; - hr = d3d12Device->QueryInterface(__uuidof(pInfoQueue), reinterpret_cast(static_cast(&pInfoQueue))); - if( SUCCEEDED(hr) ) - { - // Suppress whole categories of messages - //D3D12_MESSAGE_CATEGORY Categories[] = {}; - - // Suppress messages based on their severity level - D3D12_MESSAGE_SEVERITY Severities[] = - { - D3D12_MESSAGE_SEVERITY_INFO - }; - - // Suppress individual messages by their ID - //D3D12_MESSAGE_ID DenyIds[] = {}; - - D3D12_INFO_QUEUE_FILTER NewFilter = {}; - //NewFilter.DenyList.NumCategories = _countof(Categories); - //NewFilter.DenyList.pCategoryList = Categories; - NewFilter.DenyList.NumSeverities = _countof(Severities); - NewFilter.DenyList.pSeverityList = Severities; - //NewFilter.DenyList.NumIDs = _countof(DenyIds); - //NewFilter.DenyList.pIDList = DenyIds; - - hr = pInfoQueue->PushStorageFilter(&NewFilter); - VERIFY(SUCCEEDED(hr), "Failed to push storage filter"); - } - } -#endif - -#ifndef RELEASE - // Prevent the GPU from overclocking or underclocking to get consistent timings - //d3d12Device->SetStablePowerState(TRUE); -#endif - - // Describe and create the command queue. - D3D12_COMMAND_QUEUE_DESC queueDesc = {}; - queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; - queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; - - CComPtr pd3d12CmdQueue; - hr = d3d12Device->CreateCommandQueue(&queueDesc, __uuidof(pd3d12CmdQueue), reinterpret_cast(static_cast(&pd3d12CmdQueue))); - CHECK_D3D_RESULT_THROW(hr, "Failed to create command queue"); - hr = pd3d12CmdQueue->SetName(L"Main Command Queue"); - VERIFY_EXPR(SUCCEEDED(hr)); - - CComPtr pd3d12Fence; - hr = d3d12Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(pd3d12Fence), reinterpret_cast(static_cast(&pd3d12Fence))); - CHECK_D3D_RESULT_THROW(hr, "Failed to create main command queue fence"); - d3d12Device->SetName(L"Main Command Queue fence"); - - auto &RawMemAllocator = GetRawAllocator(); - pCmdQueueD3D12 = NEW_RC_OBJ(RawMemAllocator, "CommandQueueD3D12 instance", CommandQueueD3D12Impl)(pd3d12CmdQueue, pd3d12Fence); - } - catch( const std::runtime_error & ) - { - LOG_ERROR( "Failed to initialize D3D12 resources" ); - return; - } - - std::array CmdQueues = {pCmdQueueD3D12}; - AttachToD3D12Device(d3d12Device, CmdQueues.size(), CmdQueues.data(), CreationAttribs, ppDevice, ppContexts, NumDeferredContexts); -} - - -/// Attaches to existing D3D12 device - -/// \param [in] pd3d12NativeDevice - pointer to native D3D12 device -/// \param [in] CommandQueueCount - Number of command queues -/// \param [in] ppCommandQueues - pointer to the array of command queues -/// \param [in] EngineAttribs - Engine creation attributes. -/// \param [out] ppDevice - Address of the memory location where pointer to -/// the created device will be written -/// \param [out] ppContexts - Address of the memory location where pointers to -/// the contexts will be written. Pointer to the immediate -/// context goes at position 0. If NumDeferredContexts > 0, -/// pointers to the deferred contexts go afterwards. -/// \param [in] NumDeferredContexts - Number of deferred contexts. If non-zero number -/// of deferred contexts is requested, pointers to the -/// contexts are written to ppContexts array starting -/// at position 1 -void EngineFactoryD3D12Impl::AttachToD3D12Device(void* pd3d12NativeDevice, - size_t CommandQueueCount, - ICommandQueueD3D12** ppCommandQueues, - const EngineD3D12Attribs& EngineAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts) -{ - if (EngineAttribs.DebugMessageCallback != nullptr) - SetDebugMessageCallback(EngineAttribs.DebugMessageCallback); - - VERIFY( pd3d12NativeDevice && ppCommandQueues && ppDevice && ppContexts, "Null pointer provided" ); - if( !pd3d12NativeDevice || !ppCommandQueues || !ppDevice || !ppContexts ) - return; - - *ppDevice = nullptr; - memset(ppContexts, 0, sizeof(*ppContexts) * (1+NumDeferredContexts)); - - try - { - SetRawAllocator(EngineAttribs.pRawMemAllocator); - auto &RawMemAllocator = GetRawAllocator(); - auto d3d12Device = reinterpret_cast(pd3d12NativeDevice); - RenderDeviceD3D12Impl *pRenderDeviceD3D12( NEW_RC_OBJ(RawMemAllocator, "RenderDeviceD3D12Impl instance", RenderDeviceD3D12Impl)(RawMemAllocator, EngineAttribs, d3d12Device, CommandQueueCount, ppCommandQueues, NumDeferredContexts ) ); - pRenderDeviceD3D12->QueryInterface(IID_RenderDevice, reinterpret_cast(ppDevice) ); - - RefCntAutoPtr pImmediateCtxD3D12( NEW_RC_OBJ(RawMemAllocator, "DeviceContextD3D12Impl instance", DeviceContextD3D12Impl)(pRenderDeviceD3D12, false, EngineAttribs, 0, 0) ); - // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceD3D12 will - // keep a weak reference to the context - pImmediateCtxD3D12->QueryInterface(IID_DeviceContext, reinterpret_cast(ppContexts) ); - pRenderDeviceD3D12->SetImmediateContext(pImmediateCtxD3D12); - - for (Uint32 DeferredCtx = 0; DeferredCtx < NumDeferredContexts; ++DeferredCtx) - { - RefCntAutoPtr pDeferredCtxD3D12( NEW_RC_OBJ(RawMemAllocator, "DeviceContextD3D12Impl instance", DeviceContextD3D12Impl)(pRenderDeviceD3D12, true, EngineAttribs, 1+DeferredCtx, 0) ); - // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceD3D12 will - // keep a weak reference to the context - pDeferredCtxD3D12->QueryInterface(IID_DeviceContext, reinterpret_cast(ppContexts + 1 + DeferredCtx) ); - pRenderDeviceD3D12->SetDeferredContext(DeferredCtx, pDeferredCtxD3D12); - } - } - catch( const std::runtime_error & ) - { - if( *ppDevice ) - { - (*ppDevice)->Release(); - *ppDevice = nullptr; - } - for(Uint32 ctx=0; ctx < 1 + NumDeferredContexts; ++ctx) - { - if( ppContexts[ctx] != nullptr ) - { - ppContexts[ctx]->Release(); - ppContexts[ctx] = nullptr; - } - } - - LOG_ERROR( "Failed to create device and contexts" ); - } -} - -/// Creates a swap chain for Direct3D12-based engine implementation - -/// \param [in] pDevice - Pointer to the render device -/// \param [in] pImmediateContext - Pointer to the immediate device context -/// \param [in] SCDesc - Swap chain description -/// \param [in] FSDesc - Fullscreen mode description -/// \param [in] pNativeWndHandle - Platform-specific native handle of the window -/// the swap chain will be associated with: -/// * On Win32 platform, this should be window handle (HWND) -/// * On Universal Windows Platform, this should be reference to the -/// core window (Windows::UI::Core::CoreWindow) -/// -/// \param [out] ppSwapChain - Address of the memory location where pointer to the new -/// swap chain will be written -void EngineFactoryD3D12Impl::CreateSwapChainD3D12( IRenderDevice* pDevice, - IDeviceContext* pImmediateContext, - const SwapChainDesc& SCDesc, - const FullScreenModeDesc& FSDesc, - void* pNativeWndHandle, - ISwapChain** ppSwapChain ) -{ - VERIFY( ppSwapChain, "Null pointer provided" ); - if( !ppSwapChain ) - return; - - *ppSwapChain = nullptr; - - try - { - auto *pDeviceD3D12 = ValidatedCast( pDevice ); - auto *pDeviceContextD3D12 = ValidatedCast(pImmediateContext); - auto &RawMemAllocator = GetRawAllocator(); - auto *pSwapChainD3D12 = NEW_RC_OBJ(RawMemAllocator, "SwapChainD3D12Impl instance", SwapChainD3D12Impl)(SCDesc, FSDesc, pDeviceD3D12, pDeviceContextD3D12, pNativeWndHandle); - pSwapChainD3D12->QueryInterface( IID_SwapChain, reinterpret_cast(ppSwapChain) ); - - pDeviceContextD3D12->SetSwapChain(pSwapChainD3D12); - // Bind default render target - pDeviceContextD3D12->SetRenderTargets( 0, nullptr, nullptr, RESOURCE_STATE_TRANSITION_MODE_TRANSITION ); - // Set default viewport - pDeviceContextD3D12->SetViewports( 1, nullptr, 0, 0 ); - - auto NumDeferredCtx = pDeviceD3D12->GetNumDeferredContexts(); - for (size_t ctx = 0; ctx < NumDeferredCtx; ++ctx) - { - if (auto pDeferredCtx = pDeviceD3D12->GetDeferredContext(ctx)) - { - auto *pDeferredCtxD3D12 = pDeferredCtx.RawPtr(); - pDeferredCtxD3D12->SetSwapChain(pSwapChainD3D12); - // We cannot bind default render target here because - // there is no guarantee that deferred context will be used - // in this frame. It is an error to bind - // RTV of an inactive buffer in the swap chain - } - } - } - catch( const std::runtime_error & ) - { - if( *ppSwapChain ) - { - (*ppSwapChain)->Release(); - *ppSwapChain = nullptr; - } - - LOG_ERROR( "Failed to create the swap chain" ); - } -} - - -#ifdef DOXYGEN -/// Loads Direct3D12-based engine implementation and exports factory functions -/// \param [out] GetFactoryFunc - Pointer to the function that returns factory for D3D12 engine implementation. -/// See EngineFactoryD3D12Impl. -/// \remarks Depending on the configuration and platform, the function loads different dll: -/// Platform\\Configuration | Debug | Release -/// --------------------------|-------------------------------|---------------------------- -/// x86 | GraphicsEngineD3D12_32d.dll | GraphicsEngineD3D12_32r.dll -/// x64 | GraphicsEngineD3D12_64d.dll | GraphicsEngineD3D12_64r.dll -/// -void LoadGraphicsEngineD3D12(GetEngineFactoryD3D12Type &GetFactoryFunc) -{ - // This function is only required because DoxyGen refuses to generate documentation for a static function when SHOW_FILES==NO - #error This function must never be compiled; -} -#endif - - -IEngineFactoryD3D12* GetEngineFactoryD3D12() -{ - return EngineFactoryD3D12Impl::GetInstance(); -} - -} diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index de7458b6..393c1c3b 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -749,7 +749,7 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR // D3D12_DESCRIPTOR_RANGE_TYPE_CBV = 2 const auto& SrcRes = SrcCache.GetRootTable(RangeType).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); if( !SrcRes.pObject ) - LOG_ERROR_MESSAGE( "No resource assigned to static shader variable '", res.Attribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'." ); + LOG_ERROR_MESSAGE( "No resource is assigned to static shader variable '", res.Attribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'." ); // Destination resource is at the root index and offset defined by the resource layout auto& DstRes = DstCache.GetRootTable(res.RootIndex).GetResource(res.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); -- cgit v1.2.3