Skip to content

Commit b3703f9

Browse files
D3D11: enabled OpenXR support
1 parent ed41511 commit b3703f9

File tree

4 files changed

+108
-32
lines changed

4 files changed

+108
-32
lines changed

Graphics/GraphicsEngineD3D11/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ PRIVATE
135135
PUBLIC
136136
Diligent-GraphicsEngineD3D11Interface
137137
)
138+
if(DILIGENT_USE_OPENXR)
139+
target_link_libraries(Diligent-GraphicsEngineD3D11-static PRIVATE OpenXR::headers)
140+
target_compile_definitions(Diligent-GraphicsEngineD3D11-static PRIVATE DILIGENT_USE_OPENXR=1)
141+
endif()
138142

139143
target_link_libraries(Diligent-GraphicsEngineD3D11-shared
140144
PRIVATE

Graphics/GraphicsEngineD3D11/src/EngineFactoryD3D11.cpp

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
#include "EngineFactoryD3DBase.hpp"
4545
#include "DearchiverD3D11Impl.hpp"
4646

47+
#if DILIGENT_USE_OPENXR
48+
# define XR_USE_GRAPHICS_API_D3D11
49+
# include <openxr/openxr_platform.h>
50+
#endif
51+
4752
namespace Diligent
4853
{
4954

@@ -64,6 +69,41 @@ bool CheckAdapterD3D11Compatibility(IDXGIAdapter1* pDXGIAdapter, D3D_FEATURE_LEV
6469
return SUCCEEDED(hr);
6570
}
6671

72+
#if DILIGENT_USE_OPENXR
73+
void GetOpenXRAdapterRequirements(const OpenXRAttribs& XR, LUID& AdapterLUID, D3D_FEATURE_LEVEL& d3dFeatureLevel) noexcept(false)
74+
{
75+
if (XR.Instance == 0)
76+
return;
77+
78+
if (XR.GetInstanceProcAddr == nullptr)
79+
LOG_ERROR_AND_THROW("xrGetInstanceProcAddr must not be null");
80+
81+
XrInstance xrInstance = XR_NULL_HANDLE;
82+
static_assert(sizeof(xrInstance) == sizeof(XR.Instance), "XrInstance size mismatch");
83+
memcpy(&xrInstance, &XR.Instance, sizeof(xrInstance));
84+
85+
XrSystemId xrSystemId = XR_NULL_SYSTEM_ID;
86+
static_assert(sizeof(xrSystemId) == sizeof(XR.SystemId), "XrSystemId size mismatch");
87+
memcpy(&xrSystemId, &XR.SystemId, sizeof(XrSystemId));
88+
89+
PFN_xrGetInstanceProcAddr xrGetInstanceProcAddr = reinterpret_cast<PFN_xrGetInstanceProcAddr>(XR.GetInstanceProcAddr);
90+
PFN_xrGetD3D11GraphicsRequirementsKHR xrGetD3D11GraphicsRequirementsKHR = nullptr;
91+
if (XR_FAILED(xrGetInstanceProcAddr(xrInstance, "xrGetD3D11GraphicsRequirementsKHR", reinterpret_cast<PFN_xrVoidFunction*>(&xrGetD3D11GraphicsRequirementsKHR))))
92+
{
93+
LOG_ERROR_AND_THROW("Failed to get xrGetD3D11GraphicsRequirementsKHR. Make sure that XR_KHR_D3D11_enable extension is enabled.");
94+
}
95+
96+
XrGraphicsRequirementsD3D11KHR xrGraphicsRequirementsD3D11KHR{XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR};
97+
if (XR_FAILED(xrGetD3D11GraphicsRequirementsKHR(xrInstance, xrSystemId, &xrGraphicsRequirementsD3D11KHR)))
98+
{
99+
LOG_ERROR_AND_THROW("Failed to get D3D11 graphics requirements");
100+
}
101+
102+
AdapterLUID = xrGraphicsRequirementsD3D11KHR.adapterLuid;
103+
d3dFeatureLevel = (std::max)(d3dFeatureLevel, xrGraphicsRequirementsD3D11KHR.minFeatureLevel);
104+
}
105+
#endif
106+
67107
/// Engine factory for D3D11 implementation
68108
class EngineFactoryD3D11Impl : public EngineFactoryD3DBase<IEngineFactoryD3D11, RENDER_DEVICE_TYPE_D3D11>
69109
{
@@ -208,15 +248,31 @@ void EngineFactoryD3D11Impl::CreateDeviceAndContextsD3D11(const EngineD3D11Creat
208248
}
209249
#endif
210250

251+
LUID AdapterLUID{};
252+
D3D_FEATURE_LEVEL d3dFeatureLevel = GetD3DFeatureLevel((std::max)(EngineCI.GraphicsAPIVersion, Version{10, 0}));
253+
Uint32 AdapterId = EngineCI.AdapterId;
254+
#if DILIGENT_USE_OPENXR
255+
if (EngineCI.pXRAttribs != nullptr && EngineCI.pXRAttribs->Instance != 0)
256+
{
257+
GetOpenXRAdapterRequirements(*EngineCI.pXRAttribs, AdapterLUID, d3dFeatureLevel);
258+
if (AdapterId != DEFAULT_ADAPTER_ID)
259+
{
260+
LOG_WARNING_MESSAGE("AdapterId is ignored when OpenXR is used as the suitable adapter is selected by OpenXR runtime");
261+
}
262+
// There should be only one adapter
263+
AdapterId = 0;
264+
}
265+
#endif
266+
211267
CComPtr<IDXGIAdapter1> SpecificAdapter;
212-
if (EngineCI.AdapterId != DEFAULT_ADAPTER_ID)
268+
if (AdapterId != DEFAULT_ADAPTER_ID)
213269
{
214-
auto Adapters = FindCompatibleAdapters(EngineCI.GraphicsAPIVersion);
215-
if (EngineCI.AdapterId < Adapters.size())
216-
SpecificAdapter = Adapters[EngineCI.AdapterId];
270+
auto Adapters = FindCompatibleAdapters(d3dFeatureLevel, AdapterLUID);
271+
if (AdapterId < Adapters.size())
272+
SpecificAdapter = Adapters[AdapterId];
217273
else
218274
{
219-
LOG_ERROR_AND_THROW(EngineCI.AdapterId, " is not a valid hardware adapter id. Total number of compatible adapters available on this system: ", Adapters.size());
275+
LOG_ERROR_AND_THROW(AdapterId, " is not a valid hardware adapter id. Total number of compatible adapters available on this system: ", Adapters.size());
220276
}
221277
}
222278

Graphics/GraphicsEngineD3DBase/include/EngineFactoryD3DBase.hpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ namespace Diligent
3939
bool CheckAdapterD3D11Compatibility(IDXGIAdapter1* pDXGIAdapter, D3D_FEATURE_LEVEL FeatureLevel);
4040
bool CheckAdapterD3D12Compatibility(IDXGIAdapter1* pDXGIAdapter, D3D_FEATURE_LEVEL FeatureLevel);
4141

42+
inline bool operator==(const LUID& Lhs, const LUID& Rhs)
43+
{
44+
return Lhs.HighPart == Rhs.HighPart && Lhs.LowPart == Rhs.LowPart;
45+
}
46+
inline bool operator!=(const LUID& Lhs, const LUID& Rhs)
47+
{
48+
return !(Lhs == Rhs);
49+
}
50+
4251
template <typename BaseInterface, RENDER_DEVICE_TYPE DevType>
4352
class EngineFactoryD3DBase : public EngineFactoryBase<BaseInterface>
4453
{
@@ -142,7 +151,7 @@ class EngineFactoryD3DBase : public EngineFactoryBase<BaseInterface>
142151
}
143152

144153

145-
std::vector<CComPtr<IDXGIAdapter1>> FindCompatibleAdapters(Version MinVersion) const
154+
std::vector<CComPtr<IDXGIAdapter1>> FindCompatibleAdapters(D3D_FEATURE_LEVEL d3dFeatureLevel, LUID AdapterLUID = {}) const
146155
{
147156
std::vector<CComPtr<IDXGIAdapter1>> DXGIAdapters;
148157

@@ -154,12 +163,13 @@ class EngineFactoryD3DBase : public EngineFactoryBase<BaseInterface>
154163
}
155164

156165
CComPtr<IDXGIAdapter1> pDXIAdapter;
157-
158-
const auto d3dFeatureLevel = GetD3DFeatureLevel(MinVersion);
159166
for (UINT adapter = 0; pFactory->EnumAdapters1(adapter, &pDXIAdapter) != DXGI_ERROR_NOT_FOUND; ++adapter, pDXIAdapter.Release())
160167
{
161168
DXGI_ADAPTER_DESC1 AdapterDesc;
162169
pDXIAdapter->GetDesc1(&AdapterDesc);
170+
if (AdapterLUID != LUID{} && AdapterDesc.AdapterLuid != AdapterLUID)
171+
continue;
172+
163173
bool IsCompatibleAdapter = CheckAdapterCompatibility<DevType>(pDXIAdapter, d3dFeatureLevel);
164174
if (IsCompatibleAdapter)
165175
{
@@ -170,6 +180,10 @@ class EngineFactoryD3DBase : public EngineFactoryBase<BaseInterface>
170180
return DXGIAdapters;
171181
}
172182

183+
std::vector<CComPtr<IDXGIAdapter1>> FindCompatibleAdapters(Version MinVersion) const
184+
{
185+
return FindCompatibleAdapters(GetD3DFeatureLevel(MinVersion));
186+
}
173187

174188
virtual GraphicsAdapterInfo GetGraphicsAdapterInfo(void* pd3Device,
175189
IDXGIAdapter1* pDXIAdapter) const

Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -176,37 +176,39 @@ static uint32_t GetRequiredOpenXRVulkanVersion(uint32_t VulkanV
176176
PFN_xrGetInstanceProcAddr xrGetInstanceProcAddr) noexcept(false)
177177
{
178178
PFN_xrGetVulkanGraphicsRequirements2KHR xrGetVulkanGraphicsRequirements2KHR = nullptr;
179-
if (XR_SUCCEEDED(xrGetInstanceProcAddr(xrInstance, "xrGetVulkanGraphicsRequirements2KHR", reinterpret_cast<PFN_xrVoidFunction*>(&xrGetVulkanGraphicsRequirements2KHR))))
179+
if (XR_FAILED(xrGetInstanceProcAddr(xrInstance, "xrGetVulkanGraphicsRequirements2KHR", reinterpret_cast<PFN_xrVoidFunction*>(&xrGetVulkanGraphicsRequirements2KHR))))
180180
{
181-
VERIFY_EXPR(xrGetVulkanGraphicsRequirements2KHR != nullptr);
181+
LOG_ERROR_AND_THROW("Failed to get xrGetVulkanGraphicsRequirements2KHR function. Make sure that XR_KHR_vulkan_enable2 extension is enabled.");
182+
}
182183

183-
XrGraphicsRequirementsVulkan2KHR xrVulkan2Req{XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR};
184-
if (XR_SUCCEEDED(xrGetVulkanGraphicsRequirements2KHR(xrInstance, xrSystemId, &xrVulkan2Req)))
185-
{
186-
auto XrVersionToVkVersion = [](XrVersion XrVersion) {
187-
return VK_MAKE_API_VERSION(0, XR_VERSION_MAJOR(XrVersion), XR_VERSION_MINOR(XrVersion), 0);
188-
};
184+
VERIFY_EXPR(xrGetVulkanGraphicsRequirements2KHR != nullptr);
189185

190-
uint32_t MinVkVersion = XrVersionToVkVersion(xrVulkan2Req.minApiVersionSupported);
191-
if (VulkanVersion < MinVkVersion)
192-
{
193-
LOG_ERROR_AND_THROW("OpenXR requires Vulkan version ", VK_API_VERSION_MAJOR(MinVkVersion), '.', VK_API_VERSION_MINOR(MinVkVersion),
194-
", but this device only supports Vulkan ", VK_API_VERSION_MAJOR(VulkanVersion), '.', VK_API_VERSION_MINOR(VulkanVersion));
195-
}
196-
uint32_t MaxVkVersion = VK_MAKE_API_VERSION(0, XR_VERSION_MAJOR(xrVulkan2Req.maxApiVersionSupported), XR_VERSION_MINOR(xrVulkan2Req.maxApiVersionSupported), 0);
197-
if (MaxVkVersion < VulkanVersion)
198-
{
199-
LOG_INFO_MESSAGE("This device supports Vulkan ", VK_API_VERSION_MAJOR(VulkanVersion), '.', VK_API_VERSION_MINOR(VulkanVersion),
200-
", but OpenXR was only tested with Vulkan up to ", VK_API_VERSION_MAJOR(MaxVkVersion), '.', VK_API_VERSION_MINOR(MaxVkVersion),
201-
". Proceeding with Vulkan ", VK_API_VERSION_MAJOR(MaxVkVersion), '.', VK_API_VERSION_MINOR(MaxVkVersion), '.');
202-
VulkanVersion = MaxVkVersion;
203-
}
186+
XrGraphicsRequirementsVulkan2KHR xrVulkan2Req{XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR};
187+
if (XR_SUCCEEDED(xrGetVulkanGraphicsRequirements2KHR(xrInstance, xrSystemId, &xrVulkan2Req)))
188+
{
189+
auto XrVersionToVkVersion = [](XrVersion XrVersion) {
190+
return VK_MAKE_API_VERSION(0, XR_VERSION_MAJOR(XrVersion), XR_VERSION_MINOR(XrVersion), 0);
191+
};
192+
193+
uint32_t MinVkVersion = XrVersionToVkVersion(xrVulkan2Req.minApiVersionSupported);
194+
if (VulkanVersion < MinVkVersion)
195+
{
196+
LOG_ERROR_AND_THROW("OpenXR requires Vulkan version ", VK_API_VERSION_MAJOR(MinVkVersion), '.', VK_API_VERSION_MINOR(MinVkVersion),
197+
", but this device only supports Vulkan ", VK_API_VERSION_MAJOR(VulkanVersion), '.', VK_API_VERSION_MINOR(VulkanVersion));
204198
}
205-
else
199+
uint32_t MaxVkVersion = VK_MAKE_API_VERSION(0, XR_VERSION_MAJOR(xrVulkan2Req.maxApiVersionSupported), XR_VERSION_MINOR(xrVulkan2Req.maxApiVersionSupported), 0);
200+
if (MaxVkVersion < VulkanVersion)
206201
{
207-
LOG_WARNING_MESSAGE("Failed to get Vulkan requirements from OpenXR. Proceeding without checking Vulkan instance version requirements.");
202+
LOG_INFO_MESSAGE("This device supports Vulkan ", VK_API_VERSION_MAJOR(VulkanVersion), '.', VK_API_VERSION_MINOR(VulkanVersion),
203+
", but OpenXR was only tested with Vulkan up to ", VK_API_VERSION_MAJOR(MaxVkVersion), '.', VK_API_VERSION_MINOR(MaxVkVersion),
204+
". Proceeding with Vulkan ", VK_API_VERSION_MAJOR(MaxVkVersion), '.', VK_API_VERSION_MINOR(MaxVkVersion), '.');
205+
VulkanVersion = MaxVkVersion;
208206
}
209207
}
208+
else
209+
{
210+
LOG_WARNING_MESSAGE("Failed to get Vulkan requirements from OpenXR. Proceeding without checking Vulkan instance version requirements.");
211+
}
210212

211213
return VulkanVersion;
212214
}

0 commit comments

Comments
 (0)