summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineD3DBase
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-03-30 01:47:48 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-03-30 01:47:48 +0000
commitf3a224a1f19e9d67cb683a965d1fb88636eabf6c (patch)
treed534df76090785f2ef70eb9634d07aa0be0f52dc /Graphics/GraphicsEngineD3DBase
parentAdded shader name output when shader compilation fails (diff)
downloadDiligentCore-f3a224a1f19e9d67cb683a965d1fb88636eabf6c.tar.gz
DiligentCore-f3a224a1f19e9d67cb683a965d1fb88636eabf6c.zip
Implemented hardware adapter and display mode enumeration
Diffstat (limited to 'Graphics/GraphicsEngineD3DBase')
-rw-r--r--Graphics/GraphicsEngineD3DBase/CMakeLists.txt4
-rw-r--r--Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.h203
2 files changed, 207 insertions, 0 deletions
diff --git a/Graphics/GraphicsEngineD3DBase/CMakeLists.txt b/Graphics/GraphicsEngineD3DBase/CMakeLists.txt
index ee5066ba..cb683b09 100644
--- a/Graphics/GraphicsEngineD3DBase/CMakeLists.txt
+++ b/Graphics/GraphicsEngineD3DBase/CMakeLists.txt
@@ -8,6 +8,7 @@ set(INCLUDE
include/D3DTypeConversionImpl.h
include/D3DViewDescConversionImpl.h
include/DXGITypeConversions.h
+ include/EngineFactoryD3DBase.h
include/HLSLDefinitions.fxh
include/RenderDeviceD3DBase.h
include/ShaderD3DBase.h
@@ -58,6 +59,9 @@ PUBLIC
BuildSettings
GraphicsEngine
)
+if(D3D12_SUPPORTED)
+ target_link_libraries(GraphicsEngineD3DBase PRIVATE D3D12.lib)
+endif()
set_common_target_properties(GraphicsEngineD3DBase)
source_group("src" FILES ${SOURCE})
diff --git a/Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.h b/Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.h
new file mode 100644
index 00000000..3e91851a
--- /dev/null
+++ b/Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.h
@@ -0,0 +1,203 @@
+/* Copyright 2015-2018 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
+
+#include "DXGITypeConversions.h"
+
+/// \file
+/// Implementation of the Diligent::EngineFactoryD3DBase template class
+
+namespace Diligent
+{
+
+template<typename BaseInterface, DeviceType DevType>
+class EngineFactoryD3DBase : public BaseInterface
+{
+public:
+ /// Enumerates hardware adapters available on this machine
+
+ /// \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(Uint32 &NumAdapters,
+ HardwareAdapterAttribs *Adapters)override final
+ {
+ auto DXGIAdapters = FindCompatibleAdapters();
+
+ if (Adapters == nullptr)
+ NumAdapters = static_cast<Uint32>(DXGIAdapters.size());
+ else
+ {
+ NumAdapters = std::min(NumAdapters, static_cast<Uint32>(DXGIAdapters.size()));
+ for (Uint32 adapter = 0; adapter < NumAdapters; ++adapter)
+ {
+ IDXGIAdapter1 *pDXIAdapter = DXGIAdapters[adapter];
+ DXGI_ADAPTER_DESC1 AdapterDesc;
+ pDXIAdapter->GetDesc1(&AdapterDesc);
+
+ auto &Attribs = Adapters[adapter];
+ WideCharToMultiByte(CP_ACP, 0, AdapterDesc.Description, -1, Attribs.Description, _countof(Attribs.Description), NULL, FALSE);
+ Attribs.DedicatedVideoMemory = AdapterDesc.DedicatedVideoMemory;
+ Attribs.DedicatedSystemMemory = AdapterDesc.DedicatedSystemMemory;
+ Attribs.SharedSystemMemory = AdapterDesc.SharedSystemMemory;
+ Attribs.VendorId = AdapterDesc.VendorId;
+ Attribs.DeviceId = AdapterDesc.DeviceId;
+
+ Attribs.NumOutputs = 0;
+ CComPtr<IDXGIOutput> pOutput;
+ while (pDXIAdapter->EnumOutputs(Attribs.NumOutputs, &pOutput) != DXGI_ERROR_NOT_FOUND)
+ {
+ ++Attribs.NumOutputs;
+ pOutput.Release();
+ };
+ }
+ }
+ }
+
+ /// Enumerates available display modes for the specified output of the specified adapter
+
+ /// \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(Uint32 AdapterId,
+ Uint32 OutputId,
+ TEXTURE_FORMAT Format,
+ Uint32 &NumDisplayModes,
+ DisplayModeAttribs *DisplayModes)override final
+ {
+ auto DXGIAdapters = FindCompatibleAdapters();
+ if(AdapterId >= DXGIAdapters.size())
+ {
+ LOG_ERROR("Incorrect adapter id ", AdapterId);
+ return;
+ }
+
+ IDXGIAdapter1 *pDXIAdapter = DXGIAdapters[AdapterId];
+
+ DXGI_FORMAT DXIGFormat = TexFormatToDXGI_Format(Format);
+ CComPtr<IDXGIOutput> pOutput;
+ if (pDXIAdapter->EnumOutputs(OutputId, &pOutput) == DXGI_ERROR_NOT_FOUND)
+ {
+ DXGI_ADAPTER_DESC1 AdapterDesc;
+ pDXIAdapter->GetDesc1(&AdapterDesc);
+ char DescriptionMB[_countof(AdapterDesc.Description)];
+ WideCharToMultiByte(CP_ACP, 0, AdapterDesc.Description, -1, DescriptionMB, _countof(DescriptionMB), NULL, FALSE);
+ LOG_ERROR_MESSAGE("Failed to enumerate output ", OutputId, " for adapter ", AdapterId, " (", DescriptionMB, ')');
+ return;
+ }
+
+ UINT numModes = 0;
+ // Get the number of elements
+ auto hr = pOutput->GetDisplayModeList(DXIGFormat, 0, &numModes, NULL);
+ if (DisplayModes != nullptr)
+ {
+ // Get the list
+ std::vector<DXGI_MODE_DESC> DXIDisplayModes(numModes);
+ hr = pOutput->GetDisplayModeList(DXIGFormat, 0, &numModes, DXIDisplayModes.data());
+ for (Uint32 m = 0; m < std::min(NumDisplayModes, numModes); ++m)
+ {
+ const auto &SrcMode = DXIDisplayModes[m];
+ auto &DstMode = DisplayModes[m];
+ DstMode.Width = SrcMode.Width;
+ DstMode.Height = SrcMode.Height;
+ DstMode.Format = DXGI_FormatToTexFormat(SrcMode.Format);
+ DstMode.RefreshRate = static_cast<double>(SrcMode.RefreshRate.Numerator) / static_cast<double>(SrcMode.RefreshRate.Denominator);
+ DstMode.Scaling = static_cast<DisplayModeAttribs::SCALING>(SrcMode.Scaling);
+ DstMode.ScanlineOrder = static_cast<DisplayModeAttribs::SCANLINE_ORDER>(SrcMode.ScanlineOrdering);
+ }
+ NumDisplayModes = std::min(NumDisplayModes, numModes);
+ }
+ else
+ {
+ NumDisplayModes = numModes;
+ }
+ }
+
+private:
+
+ template<DeviceType DevType>
+ bool CheckAdapterCompatibility(IDXGIAdapter1 *pDXGIAdapter);
+
+ template<>
+ bool CheckAdapterCompatibility<DeviceType::D3D11>(IDXGIAdapter1 *pDXGIAdapter)
+ {
+ return true;
+ }
+
+ template<>
+ bool CheckAdapterCompatibility<DeviceType::D3D12>(IDXGIAdapter1 *pDXGIAdapter)
+ {
+ auto hr = D3D12CreateDevice(pDXGIAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr);
+ return SUCCEEDED(hr);
+ }
+
+ std::vector<CComPtr<IDXGIAdapter1>> FindCompatibleAdapters()
+ {
+ std::vector<CComPtr<IDXGIAdapter1>> DXGIAdapters;
+
+ CComPtr<IDXGIFactory2> pFactory;
+ if (FAILED(CreateDXGIFactory(__uuidof(IDXGIFactory2), (void**)&pFactory)))
+ {
+ LOG_ERROR_MESSAGE("Failed to create DXGI Factory");
+ return std::move(DXGIAdapters);
+ }
+
+ CComPtr<IDXGIAdapter1> pDXIAdapter;
+ UINT adapter = 0;
+ for (; pFactory->EnumAdapters1(adapter, &pDXIAdapter) != DXGI_ERROR_NOT_FOUND; ++adapter, pDXIAdapter.Release())
+ {
+ DXGI_ADAPTER_DESC1 AdapterDesc;
+ pDXIAdapter->GetDesc1(&AdapterDesc);
+ if (AdapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
+ {
+ // Skip software devices
+ continue;
+ }
+
+ bool IsCompatibleAdapter = CheckAdapterCompatibility<DevType>(pDXIAdapter);
+
+ if (IsCompatibleAdapter)
+ {
+ DXGIAdapters.emplace_back(std::move(pDXIAdapter));
+ }
+ }
+
+ return std::move(DXGIAdapters);
+ }
+};
+
+}