From c89031ec58bca5faffa92d3498230c5484175e57 Mon Sep 17 00:00:00 2001 From: Cedric Guillemet <1312968+CedricGuillemet@users.noreply.github.com> Date: Tue, 18 Jul 2023 10:21:36 +0200 Subject: [PATCH] openxr extensions deferred init (#1258) Co-authored-by: Gary Hsu --- .../xr/Source/OpenXR/SceneUnderstanding.cpp | 4 +- Dependencies/xr/Source/OpenXR/XR.cpp | 33 ++-- Dependencies/xr/Source/OpenXR/XrInput.cpp | 12 +- Dependencies/xr/Source/OpenXR/XrRegistry.h | 2 +- .../xr/Source/OpenXR/XrSupportedExtensions.h | 165 +++++++++++++----- 5 files changed, 149 insertions(+), 67 deletions(-) diff --git a/Dependencies/xr/Source/OpenXR/SceneUnderstanding.cpp b/Dependencies/xr/Source/OpenXR/SceneUnderstanding.cpp index 7f49f40a8..893e8261d 100644 --- a/Dependencies/xr/Source/OpenXR/SceneUnderstanding.cpp +++ b/Dependencies/xr/Source/OpenXR/SceneUnderstanding.cpp @@ -80,7 +80,7 @@ struct SceneUnderstanding::SceneUnderstanding::Impl void Initialize(const InitOptions& options) { - if (options.Extensions.SceneUnderstandingSupported) + if (options.Extensions.SceneUnderstandingSupported()) { m_updateInterval = static_cast(NANOSECONDS_IN_SECOND * options.UpdateIntervalInSeconds); @@ -215,7 +215,7 @@ struct SceneUnderstanding::SceneUnderstanding::Impl void Enable(const InitOptions& options) { - if (!options.Extensions.SceneUnderstandingSupported) + if (!options.Extensions.SceneUnderstandingSupported()) { return; } diff --git a/Dependencies/xr/Source/OpenXR/XR.cpp b/Dependencies/xr/Source/OpenXR/XR.cpp index ec840e8bf..f0f3ba874 100644 --- a/Dependencies/xr/Source/OpenXR/XR.cpp +++ b/Dependencies/xr/Source/OpenXR/XR.cpp @@ -35,13 +35,21 @@ namespace xr XrSessionContext::Impl() : Extensions(std::make_unique()) {} + void InitializeExtensions() + { + if (Instance.Get() == XR_NULL_HANDLE) + { + throw std::runtime_error{ "Attempted to initialize extensions when instance was null" }; + } + Extensions->Initialize(); + } + void PopulateExtensions() { if (Instance.Get() == XR_NULL_HANDLE) { throw std::runtime_error{ "Attempted to populate extensions when instance was null" }; } - Extensions->PopulateDispatchTable(Instance.Get()); } @@ -210,12 +218,13 @@ namespace xr // Phase one of initialization. Cannot fail without crashing. void InitializeXrInstanceAndExtensions() { + Context.ContextImpl->InitializeExtensions(); auto& extensions = Context.ContextImpl->Extensions; auto& instanceHandle = Context.ContextImpl->Instance; XrInstanceCreateInfo createInfo{ XR_TYPE_INSTANCE_CREATE_INFO }; - createInfo.enabledExtensionCount = static_cast(extensions->Names.size()); - createInfo.enabledExtensionNames = extensions->Names.data(); + createInfo.enabledExtensionCount = static_cast(extensions->Names().size()); + createInfo.enabledExtensionNames = extensions->Names().data(); createInfo.applicationInfo = { "", 1, "BabylonNative", 1, XR_CURRENT_API_VERSION }; strcpy_s(createInfo.applicationInfo.applicationName, ApplicationName.c_str()); XrCheck(xrCreateInstance(&createInfo, instanceHandle.Put())); @@ -344,7 +353,7 @@ namespace xr XrCheck(xrCreateSession(instance, &createInfo, sessionHandle.Put())); // Initialize scene space - if (extensions->UnboundedRefSpaceSupported) + if (extensions->UnboundedRefSpaceSupported()) { sceneSpaceType = XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT; } @@ -441,7 +450,7 @@ namespace xr const auto& apiExtensions = *HmdImpl.Context.Extensions(); const auto& sceneSpace = HmdImpl.Context.Space(); - if (!apiExtensions.SpatialAnchorSupported) + if (!apiExtensions.SpatialAnchorSupported()) { throw std::runtime_error("Spatial anchors are not supported for this device."); } @@ -578,7 +587,7 @@ namespace xr { XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT }; - if (HmdImpl.Context.Extensions()->SecondaryViewConfigurationSupported && + if (HmdImpl.Context.Extensions()->SecondaryViewConfigurationSupported() && viewConfigType == XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_FIRST_PERSON_OBSERVER_MSFT) { secondaryViewConfigCreateInfo.viewConfigurationType = viewConfigType; @@ -654,8 +663,8 @@ namespace xr XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT }; const auto& supportedSecondaryViewConfigTypes = HmdImpl.SupportedSecondaryViewConfigurationTypes; - if (HmdImpl.Context.Extensions()->SecondaryViewConfigurationSupported && - HmdImpl.Context.Extensions()->FirstPersonObserverSupported && + if (HmdImpl.Context.Extensions()->SecondaryViewConfigurationSupported() && + HmdImpl.Context.Extensions()->FirstPersonObserverSupported() && supportedSecondaryViewConfigTypes.size() > 0) { secondaryViewConfigSessionBeginInfo.viewConfigurationCount = static_cast(supportedSecondaryViewConfigTypes.size()); @@ -755,7 +764,7 @@ namespace xr assert(viewCountOutput == renderResource.DepthSwapchain.ArraySize); renderResource.ProjectionLayerViews.resize(viewCountOutput); - if (context.Extensions()->DepthExtensionSupported) + if (context.Extensions()->DepthExtensionSupported()) { renderResource.DepthInfoViews.resize(viewCountOutput); } @@ -983,7 +992,7 @@ namespace xr { const auto& context = sessionImpl.HmdImpl.Context; const auto& sceneSpace = context.Space(); - const auto depthSupported = context.Extensions()->DepthExtensionSupported; + const auto depthSupported = context.Extensions()->DepthExtensionSupported(); uint32_t totalViewCount = 0; uint32_t primaryViewCount; @@ -1085,7 +1094,7 @@ namespace xr const auto& supportedSecondaryViewConfigTypes = m_impl->sessionImpl.HmdImpl.SupportedSecondaryViewConfigurationTypes; std::vector activeSecondaryViewConfigLayerInfos; XrSecondaryViewConfigurationFrameEndInfoMSFT frameEndSecondaryViewConfigInfo{ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT }; - if (extensions->SecondaryViewConfigurationSupported && supportedSecondaryViewConfigTypes.size() > 0) + if (extensions->SecondaryViewConfigurationSupported() && supportedSecondaryViewConfigTypes.size() > 0) { activeSecondaryViewConfigLayerInfos.reserve(supportedSecondaryViewConfigTypes.size()); const auto& resourceMap = m_impl->sessionImpl.RenderResources.ResourceMap; @@ -1151,7 +1160,7 @@ namespace xr frameEndInfo.layerCount = 1; frameEndInfo.layers = &layersPtr; - if (extensions->SecondaryViewConfigurationSupported && + if (extensions->SecondaryViewConfigurationSupported() && activeSecondaryViewConfigLayerInfos.size() > 0) { for (size_t i = 0; i < activeSecondaryViewConfigLayerInfos.size(); i++) diff --git a/Dependencies/xr/Source/OpenXR/XrInput.cpp b/Dependencies/xr/Source/OpenXR/XrInput.cpp index 93671601b..9ac5d98a2 100644 --- a/Dependencies/xr/Source/OpenXR/XrInput.cpp +++ b/Dependencies/xr/Source/OpenXR/XrInput.cpp @@ -228,7 +228,7 @@ namespace xr SupportsEyeTracking = args.EyeGazeInteractionProps.supportsEyeGazeInteraction; // Initialize the hand resources - HandData.SupportsArticulatedHandTracking = args.HandTrackingInteractionProps.supportsHandTracking && args.Extensions.HandTrackingSupported; + HandData.SupportsArticulatedHandTracking = args.HandTrackingInteractionProps.supportsHandTracking && args.Extensions.HandTrackingSupported(); InitializeHandResources(args.Session, args.Extensions); m_destroyHandTrackers = [this, extensions = args.Extensions]() { @@ -348,7 +348,7 @@ namespace xr microsoftControllerBindings.push_back({ ActionResources.ControllerGetGripPoseAction }); XrCheck(xrStringToPath(instance, path.data(), µsoftControllerBindings.back().binding)); - if (extensions.HandInteractionSupported) + if (extensions.HandInteractionSupported()) { microsoftHandBindings.push_back({ ActionResources.ControllerGetGripPoseAction }); XrCheck(xrStringToPath(instance, path.data(), µsoftHandBindings.back().binding)); @@ -385,7 +385,7 @@ namespace xr microsoftControllerBindings.push_back({ ActionResources.ControllerGetAimPoseAction }); XrCheck(xrStringToPath(instance, path.data(), µsoftControllerBindings.back().binding)); - if (extensions.HandInteractionSupported) + if (extensions.HandInteractionSupported()) { microsoftHandBindings.push_back({ ActionResources.ControllerGetAimPoseAction }); XrCheck(xrStringToPath(instance, path.data(), µsoftHandBindings.back().binding)); @@ -512,7 +512,7 @@ namespace xr instance, idx); - if (extensions.HandInteractionSupported) + if (extensions.HandInteractionSupported()) { // Create action and suggested bindings specific to hands CreateControllerActionAndBinding( @@ -551,7 +551,7 @@ namespace xr microsoftControllerSuggestedBindings.countSuggestedBindings = (uint32_t)microsoftControllerBindings.size(); XrCheck(xrSuggestInteractionProfileBindings(instance, µsoftControllerSuggestedBindings)); - if (extensions.HandInteractionSupported) + if (extensions.HandInteractionSupported()) { // Provide Microsoft hand suggested binding to instance XrInteractionProfileSuggestedBinding microsoftHandSuggestedBindings{ XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING }; @@ -689,7 +689,7 @@ namespace xr else if (interactionProfilePath == actionResources.MicrosoftHandInteractionPath) { // Get hand interaction data - if (args.Extensions.HandInteractionSupported) + if (args.Extensions.HandInteractionSupported()) { const auto& controllerInfo = ControllerInfo; auto& gamepadObject = inputSource.GamepadObject; diff --git a/Dependencies/xr/Source/OpenXR/XrRegistry.h b/Dependencies/xr/Source/OpenXR/XrRegistry.h index 6a7648925..7ae5a8a38 100644 --- a/Dependencies/xr/Source/OpenXR/XrRegistry.h +++ b/Dependencies/xr/Source/OpenXR/XrRegistry.h @@ -25,7 +25,7 @@ namespace xr bool OPENXR_CONTEXT_INTERFACE_API IsSessionRunning() const override; XrResult OPENXR_CONTEXT_INTERFACE_API GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function) const override; - const std::unique_ptr& XrSessionContext::Extensions() const; + const std::unique_ptr& Extensions() const; const SceneUnderstanding& SceneUnderstanding() const; struct Impl; diff --git a/Dependencies/xr/Source/OpenXR/XrSupportedExtensions.h b/Dependencies/xr/Source/OpenXR/XrSupportedExtensions.h index 5e8664347..244e096c5 100644 --- a/Dependencies/xr/Source/OpenXR/XrSupportedExtensions.h +++ b/Dependencies/xr/Source/OpenXR/XrSupportedExtensions.h @@ -8,44 +8,13 @@ namespace xr struct XrSupportedExtensions : ExtensionDispatchTable { XrSupportedExtensions() - : Names{} + : m_names{} { - uint32_t extensionCount{}; - XrResult result{ xrEnumerateInstanceExtensionProperties(nullptr, 0, &extensionCount, nullptr) }; - if (result != XR_SUCCESS) - { - // Avoid failing if device doesn't support OpenXR - return; - } - - m_extensionProperties.resize(extensionCount, { XR_TYPE_EXTENSION_PROPERTIES }); - XrCheck(xrEnumerateInstanceExtensionProperties(nullptr, extensionCount, &extensionCount, m_extensionProperties.data())); - - // D3D11 extension is required, so check if it's supported. - for (const char* extensionName : REQUIRED_EXTENSIONS) - { - if (!TryEnableExtension(extensionName)) - { - throw std::runtime_error{ "Required extension not supported" }; - } - } - - // Additional optional extensions for enhanced functionality. Track whether enabled in m_optionalExtensions. - DepthExtensionSupported = TryEnableExtension(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME); - UnboundedRefSpaceSupported = TryEnableExtension(XR_MSFT_UNBOUNDED_REFERENCE_SPACE_EXTENSION_NAME); - SpatialAnchorSupported = TryEnableExtension(XR_MSFT_SPATIAL_ANCHOR_EXTENSION_NAME); - SpatialAnchorInteropSupported = TryEnableExtension(XR_MSFT_PERCEPTION_ANCHOR_INTEROP_EXTENSION_NAME); - SecondaryViewConfigurationSupported = TryEnableExtension(XR_MSFT_SECONDARY_VIEW_CONFIGURATION_EXTENSION_NAME); - FirstPersonObserverSupported = TryEnableExtension(XR_MSFT_FIRST_PERSON_OBSERVER_EXTENSION_NAME); - HandInteractionSupported = TryEnableExtension(XR_MSFT_HAND_INTERACTION_EXTENSION_NAME); - HandTrackingSupported = TryEnableExtension(XR_EXT_HAND_TRACKING_EXTENSION_NAME); - SceneUnderstandingSupported = TryEnableExtension(XR_MSFT_SCENE_UNDERSTANDING_EXTENSION_NAME); - SceneUnderstandingSerializationSupported = TryEnableExtension(XR_MSFT_SCENE_UNDERSTANDING_SERIALIZATION_EXTENSION_NAME); - EyeTrackingSupported = TryEnableExtension(XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME); } bool TryEnableExtension(const char* extensionName) { + assert(m_initialized); if (m_supportedExtensionNames.count(extensionName) > 0) { return true; @@ -55,7 +24,7 @@ namespace xr { if (strcmp(extensionProperty.extensionName, extensionName) == 0) { - Names.push_back(extensionName); + m_names.push_back(extensionName); m_supportedExtensionNames.insert(extensionName); return true; } @@ -65,25 +34,129 @@ namespace xr bool IsExtensionSupported(const std::string& extensionName) const { + assert(m_initialized); return m_supportedExtensionNames.count(extensionName) > 0; } - std::vector Names{}; - bool DepthExtensionSupported{ false }; - bool UnboundedRefSpaceSupported{ false }; - bool SpatialAnchorSupported{ false }; - bool SpatialAnchorInteropSupported{ false }; - bool SecondaryViewConfigurationSupported{ false }; - bool FirstPersonObserverSupported{ false }; - bool HandInteractionSupported{ false }; - bool HandTrackingSupported{ false }; - bool SceneUnderstandingSupported{ false }; - bool SceneUnderstandingSerializationSupported{ false }; - bool EyeTrackingSupported{ false }; + bool DepthExtensionSupported() const + { + assert(m_initialized); + return m_depthExtensionSupported; + } + bool UnboundedRefSpaceSupported() const + { + assert(m_initialized); + return m_unboundedRefSpaceSupported; + } + bool SpatialAnchorSupported() const + { + assert(m_initialized); + return m_spatialAnchorSupported; + } + bool SpatialAnchorInteropSupported() const + { + assert(m_initialized); + return m_spatialAnchorInteropSupported; + } + bool SecondaryViewConfigurationSupported() const + { + assert(m_initialized); + return m_secondaryViewConfigurationSupported; + } + bool FirstPersonObserverSupported() const + { + assert(m_initialized); + return m_firstPersonObserverSupported; + } + bool HandInteractionSupported() const + { + assert(m_initialized); + return m_handInteractionSupported; + } + bool HandTrackingSupported() const + { + assert(m_initialized); + return m_handTrackingSupported; + } + bool SceneUnderstandingSupported() const + { + assert(m_initialized); + return m_sceneUnderstandingSupported; + } + bool SceneUnderstandingSerializationSupported() const + { + assert(m_initialized); + return m_sceneUnderstandingSerializationSupported; + } + bool EyeTrackingSupported() const + { + assert(m_initialized); + return m_eyeTrackingSupported; + } + + void Initialize() + { + if (m_initialized) + { + return; + } + m_initialized = true; + uint32_t extensionCount{}; + XrResult result{ xrEnumerateInstanceExtensionProperties(nullptr, 0, &extensionCount, nullptr) }; + if (result != XR_SUCCESS) + { + // Avoid failing if device doesn't support OpenXR + return; + } + m_extensionProperties.resize(extensionCount, { XR_TYPE_EXTENSION_PROPERTIES }); + XrCheck(xrEnumerateInstanceExtensionProperties(nullptr, extensionCount, &extensionCount, m_extensionProperties.data())); + + // D3D11 extension is required, so check if it's supported. + for (const char* extensionName : REQUIRED_EXTENSIONS) + { + if (!TryEnableExtension(extensionName)) + { + throw std::runtime_error{ "Required extension not supported" }; + } + } + + // Additional optional extensions for enhanced functionality. Track whether enabled in m_optionalExtensions. + m_depthExtensionSupported = TryEnableExtension(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME); + m_unboundedRefSpaceSupported = TryEnableExtension(XR_MSFT_UNBOUNDED_REFERENCE_SPACE_EXTENSION_NAME); + m_spatialAnchorSupported = TryEnableExtension(XR_MSFT_SPATIAL_ANCHOR_EXTENSION_NAME); + m_spatialAnchorInteropSupported = TryEnableExtension(XR_MSFT_PERCEPTION_ANCHOR_INTEROP_EXTENSION_NAME); + m_secondaryViewConfigurationSupported = TryEnableExtension(XR_MSFT_SECONDARY_VIEW_CONFIGURATION_EXTENSION_NAME); + m_firstPersonObserverSupported = TryEnableExtension(XR_MSFT_FIRST_PERSON_OBSERVER_EXTENSION_NAME); + m_handInteractionSupported = TryEnableExtension(XR_MSFT_HAND_INTERACTION_EXTENSION_NAME); + m_handTrackingSupported = TryEnableExtension(XR_EXT_HAND_TRACKING_EXTENSION_NAME); + m_sceneUnderstandingSupported = TryEnableExtension(XR_MSFT_SCENE_UNDERSTANDING_EXTENSION_NAME); + m_sceneUnderstandingSerializationSupported = TryEnableExtension(XR_MSFT_SCENE_UNDERSTANDING_SERIALIZATION_EXTENSION_NAME); + m_eyeTrackingSupported = TryEnableExtension(XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME); + } + const std::vector& Names() const + { + assert(m_initialized); + return m_names; + } private: + std::vector m_names{}; std::vector m_extensionProperties{}; std::unordered_set m_supportedExtensionNames{}; + + bool m_depthExtensionSupported{ false }; + bool m_unboundedRefSpaceSupported{ false }; + bool m_spatialAnchorSupported{ false }; + bool m_spatialAnchorInteropSupported{ false }; + bool m_secondaryViewConfigurationSupported{ false }; + bool m_firstPersonObserverSupported{ false }; + bool m_handInteractionSupported{ false }; + bool m_handTrackingSupported{ false }; + bool m_sceneUnderstandingSupported{ false }; + bool m_sceneUnderstandingSerializationSupported{ false }; + bool m_eyeTrackingSupported{ false }; + + bool m_initialized{ false }; }; } #endif \ No newline at end of file