Diligent Engine  v.2.4.g
EngineFactoryD3DBase.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2019-2021 Diligent Graphics LLC
3  * Copyright 2015-2019 Egor Yusov
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * In no event and under no legal theory, whether in tort (including negligence),
18  * contract, or otherwise, unless required by applicable law (such as deliberate
19  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
20  * liable for any damages, including any direct, indirect, special, incidental,
21  * or consequential damages of any character arising as a result of this License or
22  * out of the use or inability to use the software (including but not limited to damages
23  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
24  * all other commercial damages or losses), even if such Contributor has been advised
25  * of the possibility of such damages.
26  */
27 
28 #pragma once
29 
30 #include "DXGITypeConversions.hpp"
31 #include "EngineFactoryBase.hpp"
32 
35 
36 namespace Diligent
37 {
38 
39 template <typename BaseInterface, RENDER_DEVICE_TYPE DevType>
40 class EngineFactoryD3DBase : public EngineFactoryBase<BaseInterface>
41 {
42 public:
44 
45  EngineFactoryD3DBase(const INTERFACE_ID& FactoryIID) :
46  TEngineFactoryBase{FactoryIID}
47  {}
48 
49 
51  Uint32& NumAdapters,
52  GraphicsAdapterInfo* Adapters) override
53  {
54  auto DXGIAdapters = FindCompatibleAdapters(MinFeatureLevel);
55 
56  if (Adapters == nullptr)
57  NumAdapters = static_cast<Uint32>(DXGIAdapters.size());
58  else
59  {
60  NumAdapters = std::min(NumAdapters, static_cast<Uint32>(DXGIAdapters.size()));
61  for (Uint32 adapter = 0; adapter < NumAdapters; ++adapter)
62  {
63  IDXGIAdapter1* pDXIAdapter = DXGIAdapters[adapter];
64  DXGI_ADAPTER_DESC1 AdapterDesc;
65  pDXIAdapter->GetDesc1(&AdapterDesc);
66 
67  auto& Attribs = Adapters[adapter];
68 
69  Attribs = DXGI_ADAPTER_DESC_To_GraphicsAdapterInfo(AdapterDesc);
70 
71  Attribs.NumOutputs = 0;
72  CComPtr<IDXGIOutput> pOutput;
73  while (pDXIAdapter->EnumOutputs(Attribs.NumOutputs, &pOutput) != DXGI_ERROR_NOT_FOUND)
74  {
75  ++Attribs.NumOutputs;
76  pOutput.Release();
77  };
78  }
79  }
80  }
81 
82 
84  Uint32 AdapterId,
85  Uint32 OutputId,
86  TEXTURE_FORMAT Format,
87  Uint32& NumDisplayModes,
88  DisplayModeAttribs* DisplayModes) override
89  {
90  auto DXGIAdapters = FindCompatibleAdapters(MinFeatureLevel);
91  if (AdapterId >= DXGIAdapters.size())
92  {
93  LOG_ERROR("Incorrect adapter id ", AdapterId);
94  return;
95  }
96 
97  IDXGIAdapter1* pDXIAdapter = DXGIAdapters[AdapterId];
98 
99  DXGI_FORMAT DXIGFormat = TexFormatToDXGI_Format(Format);
100  CComPtr<IDXGIOutput> pOutput;
101  if (pDXIAdapter->EnumOutputs(OutputId, &pOutput) == DXGI_ERROR_NOT_FOUND)
102  {
103  DXGI_ADAPTER_DESC1 AdapterDesc;
104  pDXIAdapter->GetDesc1(&AdapterDesc);
105  char DescriptionMB[_countof(AdapterDesc.Description)];
106  WideCharToMultiByte(CP_ACP, 0, AdapterDesc.Description, -1, DescriptionMB, _countof(DescriptionMB), NULL, FALSE);
107  LOG_ERROR_MESSAGE("Failed to enumerate output ", OutputId, " of adapter ", AdapterId, " (", DescriptionMB, ')');
108  return;
109  }
110 
111  UINT numModes = 0;
112  // Get the number of elements
113  auto hr = pOutput->GetDisplayModeList(DXIGFormat, 0, &numModes, NULL);
114  if (DisplayModes != nullptr)
115  {
116  // Get the list
117  std::vector<DXGI_MODE_DESC> DXIDisplayModes(numModes);
118  hr = pOutput->GetDisplayModeList(DXIGFormat, 0, &numModes, DXIDisplayModes.data());
119  for (Uint32 m = 0; m < std::min(NumDisplayModes, numModes); ++m)
120  {
121  const auto& SrcMode = DXIDisplayModes[m];
122  auto& DstMode = DisplayModes[m];
123  DstMode.Width = SrcMode.Width;
124  DstMode.Height = SrcMode.Height;
125  DstMode.Format = DXGI_FormatToTexFormat(SrcMode.Format);
126  DstMode.RefreshRateNumerator = SrcMode.RefreshRate.Numerator;
127  DstMode.RefreshRateDenominator = SrcMode.RefreshRate.Denominator;
128  DstMode.Scaling = static_cast<SCALING_MODE>(SrcMode.Scaling);
129  DstMode.ScanlineOrder = static_cast<SCANLINE_ORDER>(SrcMode.ScanlineOrdering);
130  }
131  NumDisplayModes = std::min(NumDisplayModes, numModes);
132  }
133  else
134  {
135  NumDisplayModes = numModes;
136  }
137  }
138 
139 
140  std::vector<CComPtr<IDXGIAdapter1>> FindCompatibleAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel)
141  {
142  std::vector<CComPtr<IDXGIAdapter1>> DXGIAdapters;
143 
144  CComPtr<IDXGIFactory2> pFactory;
145  if (FAILED(CreateDXGIFactory1(__uuidof(IDXGIFactory2), (void**)&pFactory)))
146  {
147  LOG_ERROR_MESSAGE("Failed to create DXGI Factory");
148  return std::move(DXGIAdapters);
149  }
150 
151  CComPtr<IDXGIAdapter1> pDXIAdapter;
152 
153  auto d3dFeatureLevel = GetD3DFeatureLevel(MinFeatureLevel);
154  UINT adapter = 0;
155  for (; pFactory->EnumAdapters1(adapter, &pDXIAdapter) != DXGI_ERROR_NOT_FOUND; ++adapter, pDXIAdapter.Release())
156  {
157  DXGI_ADAPTER_DESC1 AdapterDesc;
158  pDXIAdapter->GetDesc1(&AdapterDesc);
159  bool IsCompatibleAdapter = CheckAdapterCompatibility<DevType>(pDXIAdapter, d3dFeatureLevel);
160  if (IsCompatibleAdapter)
161  {
162  DXGIAdapters.emplace_back(std::move(pDXIAdapter));
163  }
164  }
165 
166  return std::move(DXGIAdapters);
167  }
168 
169 
170 protected:
171  static D3D_FEATURE_LEVEL GetD3DFeatureLevel(DIRECT3D_FEATURE_LEVEL FeatureLevel)
172  {
173  switch (FeatureLevel)
174  {
175  case DIRECT3D_FEATURE_LEVEL_10_0: return D3D_FEATURE_LEVEL_10_0;
176  case DIRECT3D_FEATURE_LEVEL_10_1: return D3D_FEATURE_LEVEL_10_1;
177  case DIRECT3D_FEATURE_LEVEL_11_0: return D3D_FEATURE_LEVEL_11_0;
178  case DIRECT3D_FEATURE_LEVEL_11_1: return D3D_FEATURE_LEVEL_11_1;
179 #if defined(_WIN32_WINNT_WIN10) && (_WIN32_WINNT >= _WIN32_WINNT_WIN10)
180  case DIRECT3D_FEATURE_LEVEL_12_0: return D3D_FEATURE_LEVEL_12_0;
181  case DIRECT3D_FEATURE_LEVEL_12_1: return D3D_FEATURE_LEVEL_12_1;
182 #endif
183 
184  default:
185  UNEXPECTED("Unknown DIRECT3D_FEATURE_LEVEL ", static_cast<Uint32>(FeatureLevel));
186  return D3D_FEATURE_LEVEL_11_0;
187  }
188  }
189 
190 private:
191  template <RENDER_DEVICE_TYPE DevType>
192  bool CheckAdapterCompatibility(IDXGIAdapter1* pDXGIAdapter,
193  D3D_FEATURE_LEVEL FeatureLevels);
194 
195  template <>
196  bool CheckAdapterCompatibility<RENDER_DEVICE_TYPE_D3D11>(IDXGIAdapter1* pDXGIAdapter,
197  D3D_FEATURE_LEVEL FeatureLevel)
198  {
199  auto hr = D3D11CreateDevice(
200  nullptr,
201  D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device.
202  0,
203  0, // Flags.
204  &FeatureLevel, // Feature levels.
205  1, // Number of feature levels
206  D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
207  nullptr, // No need to keep the D3D device reference.
208  nullptr, // Feature level of the created adapter.
209  nullptr // No need to keep the D3D device context reference.
210  );
211  return SUCCEEDED(hr);
212  }
213 
214  template <>
215  bool CheckAdapterCompatibility<RENDER_DEVICE_TYPE_D3D12>(IDXGIAdapter1* pDXGIAdapter,
216  D3D_FEATURE_LEVEL FeatureLevel)
217  {
218  auto hr = D3D12CreateDevice(pDXGIAdapter, FeatureLevel, _uuidof(ID3D12Device), nullptr);
219  return SUCCEEDED(hr);
220  }
221 };
222 
223 } // namespace Diligent
Diligent::DIRECT3D_FEATURE_LEVEL_11_1
@ DIRECT3D_FEATURE_LEVEL_11_1
Feature level 11.1.
Definition: GraphicsTypes.h:2070
LOG_ERROR_MESSAGE
#define LOG_ERROR_MESSAGE(...)
Definition: Errors.hpp:122
Diligent::EngineFactoryD3DBase::EngineFactoryD3DBase
EngineFactoryD3DBase(const INTERFACE_ID &FactoryIID)
Definition: EngineFactoryD3DBase.hpp:45
Diligent::EngineFactoryD3DBase::EnumerateAdapters
virtual void EnumerateAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel, Uint32 &NumAdapters, GraphicsAdapterInfo *Adapters) override
Definition: EngineFactoryD3DBase.hpp:50
Diligent::EngineFactoryD3DBase::EnumerateDisplayModes
virtual void EnumerateDisplayModes(DIRECT3D_FEATURE_LEVEL MinFeatureLevel, Uint32 AdapterId, Uint32 OutputId, TEXTURE_FORMAT Format, Uint32 &NumDisplayModes, DisplayModeAttribs *DisplayModes) override
Definition: EngineFactoryD3DBase.hpp:83
UNEXPECTED
#define UNEXPECTED(...)
Definition: DebugUtilities.hpp:77
Diligent::SCANLINE_ORDER
SCANLINE_ORDER
Flags indicating the method the raster uses to create an image on a surface.
Definition: GraphicsTypes.h:1249
LOG_ERROR
#define LOG_ERROR(...)
Definition: Errors.hpp:76
Diligent::EngineFactoryD3DBase::GetD3DFeatureLevel
static D3D_FEATURE_LEVEL GetD3DFeatureLevel(DIRECT3D_FEATURE_LEVEL FeatureLevel)
Definition: EngineFactoryD3DBase.hpp:171
Diligent::D3D12CreateDevice
D3D12CreateDeviceProcType D3D12CreateDevice
Definition: D3D12Loader.cpp:40
Diligent::DIRECT3D_FEATURE_LEVEL_12_0
@ DIRECT3D_FEATURE_LEVEL_12_0
Feature level 12.0.
Definition: GraphicsTypes.h:2073
Diligent::INTERFACE_ID
Unique interface identifier.
Definition: InterfaceID.h:37
Diligent::DXGI_ADAPTER_DESC_To_GraphicsAdapterInfo
GraphicsAdapterInfo DXGI_ADAPTER_DESC_To_GraphicsAdapterInfo(const DXGI_ADAPTER_DESC1 &dxgiAdapterDesc)
Definition: DXGITypeConversions.cpp:457
EngineFactoryBase.hpp
std::min
Diligent::Vector2< T > min(const Diligent::Vector2< T > &Left, const Diligent::Vector2< T > &Right)
Definition: BasicMath.hpp:2289
Diligent::DisplayModeAttribs::Width
Uint32 Width
Display resolution width.
Definition: GraphicsTypes.h:1272
Diligent::DIRECT3D_FEATURE_LEVEL
DIRECT3D_FEATURE_LEVEL
Direct3D11/12 feature level.
Definition: GraphicsTypes.h:2058
Diligent::DisplayModeAttribs
Display mode attributes.
Definition: GraphicsTypes.h:1269
DILIGENT_CALL_TYPE
#define DILIGENT_CALL_TYPE
Definition: CommonDefinitions.h:45
Diligent::Uint32
uint32_t Uint32
32-bit unsigned integer
Definition: BasicTypes.h:51
Diligent::EngineFactoryD3DBase::FindCompatibleAdapters
std::vector< CComPtr< IDXGIAdapter1 > > FindCompatibleAdapters(DIRECT3D_FEATURE_LEVEL MinFeatureLevel)
Definition: EngineFactoryD3DBase.hpp:140
Diligent::DIRECT3D_FEATURE_LEVEL_11_0
@ DIRECT3D_FEATURE_LEVEL_11_0
Feature level 11.0.
Definition: GraphicsTypes.h:2067
Diligent::DIRECT3D_FEATURE_LEVEL_10_0
@ DIRECT3D_FEATURE_LEVEL_10_0
Feature level 10.0.
Definition: GraphicsTypes.h:2061
Diligent::EngineFactoryD3DBase
Definition: EngineFactoryD3DBase.hpp:40
Diligent::TEXTURE_FORMAT
TEXTURE_FORMAT
Texture formats.
Definition: GraphicsTypes.h:328
Diligent::GraphicsAdapterInfo
Graphics adapter properties.
Definition: GraphicsTypes.h:1782
Diligent::DIRECT3D_FEATURE_LEVEL_12_1
@ DIRECT3D_FEATURE_LEVEL_12_1
Feature level 12.1.
Definition: GraphicsTypes.h:2076
Diligent::TexFormatToDXGI_Format
DXGI_FORMAT TexFormatToDXGI_Format(TEXTURE_FORMAT TexFormat, Uint32 BindFlags=0)
Definition: DXGITypeConversions.cpp:276
Diligent::DIRECT3D_FEATURE_LEVEL_10_1
@ DIRECT3D_FEATURE_LEVEL_10_1
Feature level 10.1.
Definition: GraphicsTypes.h:2064
Diligent::DXGI_FormatToTexFormat
TEXTURE_FORMAT DXGI_FormatToTexFormat(DXGI_FORMAT DXGIFormat)
Definition: DXGITypeConversions.cpp:437
Diligent::SCALING_MODE
SCALING_MODE
Flags indicating how an image is stretched to fit a given monitor's resolution.
Definition: GraphicsTypes.h:1230
_countof
#define _countof(_Array)
Definition: AndroidPlatformDefinitions.h:38
Diligent
The library uses Direct3D-style math:
Definition: AdvancedMath.hpp:37
DXGITypeConversions.hpp
Diligent::EngineFactoryBase
Template class implementing base functionality of the engine factory.
Definition: EngineFactoryBase.hpp:48