The open source OpenXR runtime
1// Copyright 2022, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Misc D3D11 helper routines.
6 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
7 * @ingroup aux_d3d
8 */
9
10#include "d3d_d3d11_helpers.hpp"
11
12#include "util/u_logging.h"
13
14#include <dxgi1_6.h>
15#include <wil/com.h>
16#include <wil/result.h>
17
18#include <vector>
19
20namespace xrt::auxiliary::d3d {
21template <typename T>
22static wil::com_ptr<T>
23try_create_dxgi_factory()
24{
25
26 wil::com_ptr<T> factory;
27 LOG_IF_FAILED(CreateDXGIFactory1(__uuidof(T), factory.put_void()));
28
29 return factory;
30}
31
32wil::com_ptr<IDXGIAdapter>
33getAdapterByIndex(uint16_t index, u_logging_level log_level)
34{
35
36 wil::com_ptr<IDXGIAdapter> ret;
37 auto factory6 = try_create_dxgi_factory<IDXGIFactory6>();
38 if (factory6 != nullptr) {
39 U_LOG_IFL_I(log_level, "Using IDXGIFactory6::EnumAdapterByGpuPreference to select adapter to use.");
40 LOG_IF_FAILED(factory6->EnumAdapterByGpuPreference(index, DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE,
41 __uuidof(IDXGIAdapter), ret.put_void()));
42 if (ret) {
43 return ret;
44 }
45 // Otherwise fall through to the other factory
46 }
47
48 auto factory = try_create_dxgi_factory<IDXGIFactory>();
49 if (factory != nullptr) {
50 U_LOG_IFL_I(log_level,
51 "IDXGIFactory6 unavailable, using IDXGIFactory::EnumAdapters to select adapter to use.");
52 LOG_IF_FAILED(factory->EnumAdapters(index, ret.put()));
53 return ret;
54 }
55 return ret;
56}
57
58wil::com_ptr<IDXGIAdapter>
59getAdapterByLUID(const xrt_luid_t &luid, u_logging_level log_level)
60{
61 LUID realLuid = reinterpret_cast<const LUID &>(luid);
62 wil::com_ptr<IDXGIAdapter> ret;
63 auto factory4 = try_create_dxgi_factory<IDXGIFactory4>();
64 if (factory4 != nullptr) {
65 U_LOG_IFL_I(log_level, "Using IDXGIFactory4::EnumAdapterByLuid to select adapter to use.");
66 LOG_IF_FAILED(factory4->EnumAdapterByLuid(realLuid, __uuidof(IDXGIAdapter), ret.put_void()));
67 if (ret) {
68 return ret;
69 }
70 // Otherwise fall through to the other factory
71 }
72
73 // This basically is manual implementation of EnumAdapterByLuid
74 auto factory1 = try_create_dxgi_factory<IDXGIFactory1>();
75 if (factory1 != nullptr) {
76 U_LOG_IFL_I(log_level,
77 "IDXGIFactory6 unavailable, using IDXGIFactory1::EnumAdapters1 to select adapter to use.");
78 for (unsigned int i = 0;; ++i) {
79
80 wil::com_ptr<IDXGIAdapter1> adapter;
81 if (!SUCCEEDED(factory1->EnumAdapters1(i, adapter.put()))) {
82 U_LOG_IFL_W(log_level,
83 "Ran out of adapters using IDXGIFactory1::EnumAdapters1 before finding a "
84 "matching LUID.");
85 break;
86 }
87 DXGI_ADAPTER_DESC1 desc{};
88 if (!SUCCEEDED(adapter->GetDesc1(&desc))) {
89 continue;
90 }
91 if (realLuid.HighPart == desc.AdapterLuid.HighPart &&
92 realLuid.LowPart == desc.AdapterLuid.LowPart) {
93 ret = adapter;
94 break;
95 }
96 }
97 }
98 return ret;
99}
100} // namespace xrt::auxiliary::d3d