summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3D12
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2019-10-17 04:06:08 +0000
committerEgor Yusov <egor.yusov@gmail.com>2019-10-17 04:06:08 +0000
commitbc4a29a1fac0276e499bb37bb3c449ebdcacbe92 (patch)
tree50316f6b243300fdf9ef25afe1aad5d619ccfa08 /Graphics/GraphicsEngineD3D12
parentAdded option to install PDB files on Windows (closed https://github.com/Dilig... (diff)
downloadDiligentCore-bc4a29a1fac0276e499bb37bb3c449ebdcacbe92.tar.gz
DiligentCore-bc4a29a1fac0276e499bb37bb3c449ebdcacbe92.zip
A bunch of updates to specify minimum feature level for D3D11/D3D12 backends and to enable bindless mode (API version 240032)
Diffstat (limited to 'Graphics/GraphicsEngineD3D12')
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h2
-rw-r--r--Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h82
-rw-r--r--Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp78
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp46
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp27
5 files changed, 178 insertions, 57 deletions
diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
index 0756f454..b10ba472 100644
--- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
+++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.h
@@ -104,6 +104,8 @@ public:
const GenerateMipsHelper& GetMipsGenerator()const {return m_MipsGenerator;}
+ D3D_FEATURE_LEVEL GetD3DFeatureLevel()const;
+
private:
virtual void TestTextureFormat( TEXTURE_FORMAT TexFormat )override final;
void FreeCommandContext(PooledCommandContext&& Ctx);
diff --git a/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h b/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h
index 8b1022d1..5e9f9cba 100644
--- a/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h
+++ b/Graphics/GraphicsEngineD3D12/interface/EngineFactoryD3D12.h
@@ -44,13 +44,36 @@ namespace Diligent
static const INTERFACE_ID IID_EngineFactoryD3D12 =
{ 0x72bd38b0, 0x684a, 0x4889, { 0x9c, 0x68, 0xa, 0x80, 0xec, 0x80, 0x2d, 0xde } };
+/// Engine factory for Direct3D12 rendering backend
class IEngineFactoryD3D12 : public IEngineFactory
{
public:
+ /// Creates a render device and device contexts for Direct3D12-based engine implementation.
+
+ /// \param [in] EngineCI - Engine creation info.
+ /// \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. Immediate context goes at
+ /// position 0. If EngineCI.NumDeferredContexts > 0,
+ /// pointers to the deferred contexts are written afterwards.
virtual void CreateDeviceAndContextsD3D12(const EngineD3D12CreateInfo& EngineCI,
IRenderDevice** ppDevice,
IDeviceContext** ppContexts) = 0;
+
+ /// Attaches to existing Direct3D12 device.
+
+ /// \param [in] pd3d12NativeDevice - Pointer to the native Direct3D12 device.
+ /// \param [in] CommandQueueCount - Number of command queues.
+ /// \param [in] ppCommandQueues - Pointer to the array of command queues.
+ /// \param [in] EngineCI - Engine creation info.
+ /// \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. Immediate context goes at
+ /// position 0. If EngineCI.NumDeferredContexts > 0,
+ /// pointers to the deferred contexts are written afterwards.
virtual void AttachToD3D12Device(void* pd3d12NativeDevice,
size_t CommandQueueCount,
class ICommandQueueD3D12** ppCommandQueues,
@@ -58,6 +81,21 @@ public:
IRenderDevice** ppDevice,
IDeviceContext** ppContexts) = 0;
+
+ /// 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 the window handle (HWND)
+ /// * On Universal Windows Platform, this should be the 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
virtual void CreateSwapChainD3D12( IRenderDevice* pDevice,
IDeviceContext* pImmediateContext,
const SwapChainDesc& SwapChainDesc,
@@ -65,15 +103,43 @@ public:
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;
+ /// Enumerates hardware adapters available on this machine.
+
+ /// \param [in] MinFeatureLevel - Minimum required feature level.
+ /// \param [in,out] NumAdapters - Number of adapters. If Adapters is null, this value
+ /// will be overwritten with the number of adapters available
+ /// on this system. If Adapters is not null, this value should
+ /// contain maximum number of elements reserved in the array
+ /// pointed to by Adapters. In the latter case, this value
+ /// is overwritten with the actual number of elements written to
+ /// Adapters.
+ /// \param [out] Adapters - Pointer to the array conataining adapter information. If
+ /// null is provided, the number of available adapters is written to
+ /// NumAdapters
+ virtual void EnumerateHardwareAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel,
+ Uint32& NumAdapters,
+ HardwareAdapterAttribs* Adapters) = 0;
+
+
+ /// Enumerates available display modes for the specified output of the specified adapter.
+
+ /// \param [in] MinFeatureLevel - Minimum feature level of the adapter that was given to EnumerateHardwareAdapters().
+ /// \param [in] AdapterId - Id of the adapter enumerated by EnumerateHardwareAdapters().
+ /// \param [in] OutputId - Adapter output id.
+ /// \param [in] Format - Display mode format.
+ /// \param [in, out] NumDisplayModes - Number of display modes. If DisplayModes is null, this
+ /// value is overwritten with the number of display modes
+ /// available for this output. If DisplayModes is not null,
+ /// 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.
+ virtual void EnumerateDisplayModes(DIRECT3D_FEATURE_LEVEL MinFeatureLevel,
+ Uint32 AdapterId,
+ Uint32 OutputId,
+ TEXTURE_FORMAT Format,
+ Uint32& NumDisplayModes,
+ DisplayModeAttribs* DisplayModes) = 0;
};
diff --git a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp
index 6ccfc25e..0c91b8c9 100644
--- a/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/EngineFactoryD3D12.cpp
@@ -57,9 +57,9 @@ public:
TBase{IID_EngineFactoryD3D12}
{}
- void CreateDeviceAndContextsD3D12(const EngineD3D12CreateInfo& EngineCI,
- IRenderDevice** ppDevice,
- IDeviceContext** ppContexts)override final;
+ void CreateDeviceAndContextsD3D12(const EngineD3D12CreateInfo& EngineCI,
+ IRenderDevice** ppDevice,
+ IDeviceContext** ppContexts)override final;
void AttachToD3D12Device(void* pd3d12NativeDevice,
size_t CommandQueueCount,
@@ -76,7 +76,7 @@ public:
ISwapChain** ppSwapChain )override final;
};
-static void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter)
+static void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapter, D3D_FEATURE_LEVEL FeatureLevel)
{
CComPtr<IDXGIAdapter1> adapter;
*ppAdapter = nullptr;
@@ -94,7 +94,7 @@ static void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapte
// 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)))
+ if (SUCCEEDED(D3D12CreateDevice(adapter, FeatureLevel, _uuidof(ID3D12Device), nullptr)))
{
break;
}
@@ -103,17 +103,8 @@ static void GetHardwareAdapter(IDXGIFactory2* pFactory, IDXGIAdapter1** ppAdapte
*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. Immediate context goes at
-/// position 0. If EngineCI.NumDeferredContexts > 0,
-/// pointers to the deferred contexts are written afterwards.
-void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12(const EngineD3D12CreateInfo& EngineCI,
- IRenderDevice** ppDevice,
+void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12(const EngineD3D12CreateInfo& EngineCI,
+ IRenderDevice** ppDevice,
IDeviceContext** ppContexts)
{
if (EngineCI.DebugMessageCallback != nullptr)
@@ -123,7 +114,7 @@ void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12(const EngineD3D12Creat
if( !ppDevice || !ppContexts )
return;
- for(Uint32 Type=D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; Type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++Type)
+ 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;
@@ -165,13 +156,13 @@ void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12(const EngineD3D12Creat
CComPtr<IDXGIAdapter1> hardwareAdapter;
if(EngineCI.AdapterId == EngineD3D12CreateInfo::DefaultAdapterId)
{
- GetHardwareAdapter(factory, &hardwareAdapter);
+ GetHardwareAdapter(factory, &hardwareAdapter, GetD3DFeatureLevel(EngineCI.MinimumFeatureLevel));
if(hardwareAdapter == nullptr)
LOG_ERROR_AND_THROW("No suitable hardware adapter found");
}
else
{
- auto Adapters = FindCompatibleAdapters();
+ auto Adapters = FindCompatibleAdapters(EngineCI.MinimumFeatureLevel);
if(EngineCI.AdapterId < Adapters.size())
hardwareAdapter = Adapters[EngineCI.AdapterId];
else
@@ -186,7 +177,17 @@ void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12(const EngineD3D12Creat
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<void**>(static_cast<ID3D12Device**>(&d3d12Device)) );
+ constexpr auto MaxFeatureLevel = DIRECT3D_FEATURE_LEVEL_12_1;
+ for (auto FeatureLevel = MaxFeatureLevel; FeatureLevel >= EngineCI.MinimumFeatureLevel; FeatureLevel = static_cast<DIRECT3D_FEATURE_LEVEL>(Uint8{FeatureLevel}-1))
+ {
+ auto d3dFeatureLevel = GetD3DFeatureLevel(FeatureLevel);
+ hr = D3D12CreateDevice(hardwareAdapter, d3dFeatureLevel, __uuidof(d3d12Device), reinterpret_cast<void**>(static_cast<ID3D12Device**>(&d3d12Device)) );
+ if (SUCCEEDED(hr))
+ {
+ VERIFY_EXPR(d3d12Device);
+ break;
+ }
+ }
if( FAILED(hr))
{
LOG_WARNING_MESSAGE("Failed to create hardware device. Attempting to create WARP device");
@@ -195,7 +196,16 @@ void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12(const EngineD3D12Creat
hr = factory->EnumWarpAdapter( __uuidof(warpAdapter), reinterpret_cast<void**>(static_cast<IDXGIAdapter**>(&warpAdapter)) );
CHECK_D3D_RESULT_THROW(hr, "Failed to enum warp adapter");
- hr = D3D12CreateDevice( warpAdapter, D3D_FEATURE_LEVEL_11_0, __uuidof(d3d12Device), reinterpret_cast<void**>(static_cast<ID3D12Device**>(&d3d12Device)) );
+ for (auto FeatureLevel = MaxFeatureLevel; FeatureLevel >= EngineCI.MinimumFeatureLevel; FeatureLevel = static_cast<DIRECT3D_FEATURE_LEVEL>(Uint8{FeatureLevel}-1))
+ {
+ auto d3dFeatureLevel = GetD3DFeatureLevel(FeatureLevel);
+ hr = D3D12CreateDevice( warpAdapter, d3dFeatureLevel, __uuidof(d3d12Device), reinterpret_cast<void**>(static_cast<ID3D12Device**>(&d3d12Device)) );
+ if (SUCCEEDED(hr))
+ {
+ VERIFY_EXPR(d3d12Device);
+ break;
+ }
+ }
CHECK_D3D_RESULT_THROW(hr, "Failed to crate warp device");
}
@@ -277,18 +287,7 @@ void EngineFactoryD3D12Impl::CreateDeviceAndContextsD3D12(const EngineD3D12Creat
}
-/// 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. Immediate context goes at
-/// position 0. If EngineCI.NumDeferredContexts > 0,
-/// pointers to the deferred contexts are written afterwards.
void EngineFactoryD3D12Impl::AttachToD3D12Device(void* pd3d12NativeDevice,
size_t CommandQueueCount,
ICommandQueueD3D12** ppCommandQueues,
@@ -349,20 +348,7 @@ void EngineFactoryD3D12Impl::AttachToD3D12Device(void* pd
}
}
-/// 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,
diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
index 3100da7b..27f37dc0 100644
--- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
@@ -37,6 +37,24 @@
namespace Diligent
{
+D3D_FEATURE_LEVEL RenderDeviceD3D12Impl :: GetD3DFeatureLevel() const
+{
+ D3D_FEATURE_LEVEL FeatureLevels[] =
+ {
+ D3D_FEATURE_LEVEL_12_1,
+ D3D_FEATURE_LEVEL_12_0,
+ D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_1,
+ D3D_FEATURE_LEVEL_10_0
+ };
+ D3D12_FEATURE_DATA_FEATURE_LEVELS FeatureLevelsData = {};
+ FeatureLevelsData.pFeatureLevelsRequested = FeatureLevels;
+ FeatureLevelsData.NumFeatureLevels = _countof(FeatureLevels);
+ m_pd3d12Device->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS, &FeatureLevelsData, sizeof(FeatureLevelsData));
+ return FeatureLevelsData.MaxSupportedFeatureLevel;
+}
+
RenderDeviceD3D12Impl :: RenderDeviceD3D12Impl(IReferenceCounters* pRefCounters,
IMemoryAllocator& RawMemAllocator,
IEngineFactory* pEngineFactory,
@@ -85,8 +103,32 @@ RenderDeviceD3D12Impl :: RenderDeviceD3D12Impl(IReferenceCounters* pRe
m_MipsGenerator {pd3d12Device}
{
m_DeviceCaps.DevType = DeviceType::D3D12;
- m_DeviceCaps.MajorVersion = 12;
- m_DeviceCaps.MinorVersion = 0;
+ auto FeatureLevel = GetD3DFeatureLevel();
+ switch (FeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_12_0:
+ case D3D_FEATURE_LEVEL_12_1:
+ m_DeviceCaps.MajorVersion = 12;
+ m_DeviceCaps.MinorVersion = FeatureLevel == D3D_FEATURE_LEVEL_12_1 ? 1 : 0;
+ m_DeviceCaps.bBindlessSupported = true;
+ break;
+
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_11_1:
+ m_DeviceCaps.MajorVersion = 11;
+ m_DeviceCaps.MinorVersion = FeatureLevel == D3D_FEATURE_LEVEL_11_1 ? 1 : 0;
+ m_DeviceCaps.bBindlessSupported = FeatureLevel == D3D_FEATURE_LEVEL_11_1;
+ break;
+
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ m_DeviceCaps.MajorVersion = 10;
+ m_DeviceCaps.MinorVersion = FeatureLevel == D3D_FEATURE_LEVEL_10_1 ? 1 : 0;
+ break;
+
+ default:
+ UNEXPECTED("Unexpected D3D feature level");
+ }
m_DeviceCaps.bSeparableProgramSupported = True;
m_DeviceCaps.bMultithreadedResourceCreationSupported = True;
}
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp
index 509ef10b..c189bf3e 100644
--- a/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderD3D12Impl.cpp
@@ -32,6 +32,31 @@
namespace Diligent
{
+static const char* GetD3D12ShaderModel(RenderDeviceD3D12Impl* pDevice)
+{
+ auto d3dDeviceFeatureLevel = pDevice->GetD3DFeatureLevel();
+ switch(d3dDeviceFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_12_1:
+ case D3D_FEATURE_LEVEL_12_0:
+ case D3D_FEATURE_LEVEL_11_1:
+ return "5_1";
+
+ case D3D_FEATURE_LEVEL_11_0:
+ return "5_0";
+
+ case D3D_FEATURE_LEVEL_10_1:
+ return "4_1";
+
+ case D3D_FEATURE_LEVEL_10_0:
+ return "4_0";
+
+ default:
+ UNEXPECTED("Unexpected D3D feature level ", static_cast<Uint32>(d3dDeviceFeatureLevel));
+ return "4_0";
+ }
+}
+
ShaderD3D12Impl::ShaderD3D12Impl(IReferenceCounters* pRefCounters,
RenderDeviceD3D12Impl* pRenderDeviceD3D12,
const ShaderCreateInfo& ShaderCI) :
@@ -41,7 +66,7 @@ ShaderD3D12Impl::ShaderD3D12Impl(IReferenceCounters* pRefCounters,
pRenderDeviceD3D12,
ShaderCI.Desc
},
- ShaderD3DBase{ShaderCI}
+ ShaderD3DBase{ShaderCI, GetD3D12ShaderModel(pRenderDeviceD3D12)}
{
// Load shader resources
auto& Allocator = GetRawAllocator();