17#include <QtQuick3DUtils/private/qssgassert_p.h>
18#include <QtQuick3D/private/qquick3dviewport_p.h>
20#include <QtQuick/qquickwindow.h>
21#include <QtQuick/qquickrendercontrol.h>
23#include <QtCore/qobject.h>
25#include <openxr/openxr_reflection.h>
27#ifdef XR_USE_GRAPHICS_API_VULKAN
31#ifdef XR_USE_GRAPHICS_API_D3D11
35#ifdef XR_USE_GRAPHICS_API_D3D12
39#ifdef XR_USE_GRAPHICS_API_OPENGL
43#ifdef XR_USE_PLATFORM_ANDROID
44# include <QtCore/qnativeinterface.h>
45# include <QtCore/QJniEnvironment>
46# include <QtCore/QJniObject>
47# ifdef XR_USE_GRAPHICS_API_OPENGL_ES
54 switch (referenceSpace) {
56 return XR_REFERENCE_SPACE_TYPE_LOCAL;
58 return XR_REFERENCE_SPACE_TYPE_STAGE;
60 return XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT;
62 return XR_REFERENCE_SPACE_TYPE_LOCAL;
68 switch (referenceSpace) {
69 case XR_REFERENCE_SPACE_TYPE_LOCAL:
71 case XR_REFERENCE_SPACE_TYPE_STAGE:
73 case XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT:
81#define ENUM_CASE_STR(name, val) case name: return #name;
82#define MAKE_TO_STRING_FUNC(enumType) \
83 static inline const char* to_string(enumType e) { \
85 XR_LIST_ENUM_##enumType(ENUM_CASE_STR) \
86 default: return "Unknown " #enumType; \
96static
bool isExtensionSupported(const
char *extensionName, const
QVector<XrExtensionProperties> &instanceExtensionProperties, uint32_t *extensionVersion =
nullptr)
98 for (
const auto &extensionProperty : instanceExtensionProperties) {
99 if (!strcmp(extensionName, extensionProperty.extensionName)) {
100 if (extensionVersion)
101 *extensionVersion = extensionProperty.extensionVersion;
108static bool isApiLayerSupported(
const char *layerName,
const QVector<XrApiLayerProperties> &apiLayerProperties)
110 for (
const auto &prop : apiLayerProperties) {
111 if (!strcmp(layerName, prop.layerName))
121#ifdef XR_EXT_debug_utils
122static XRAPI_ATTR XrBool32 XRAPI_CALL defaultDebugCallbackFunc(XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
123 XrDebugUtilsMessageTypeFlagsEXT messageType,
124 const XrDebugUtilsMessengerCallbackDataEXT *callbackData,
130 qDebug(
"xrDebug [QOpenXRManager %p] %s", self, callbackData->message);
138void QQuick3DXrManagerPrivate::setErrorString(XrResult
result,
const char *callName)
140 m_errorString = QObject::tr(
"%1 for runtime %2 %3 failed with %4.")
145 if (
result == XR_ERROR_FORM_FACTOR_UNAVAILABLE)
146 m_errorString += QObject::tr(
"\nThe OpenXR runtime has no connection to the headset; check if connection is active and functional.");
166void QQuick3DXrManagerPrivate::updateCameraHelper(
QQuick3DXrEyeCamera *
camera,
const XrCompositionLayerProjectionView &layerView)
168 camera->setLeftTangent(
qTan(layerView.fov.angleLeft));
169 camera->setRightTangent(
qTan(layerView.fov.angleRight));
170 camera->setUpTangent(
qTan(layerView.fov.angleUp));
171 camera->setDownTangent(
qTan(layerView.fov.angleDown));
174 layerView.pose.position.y,
175 layerView.pose.position.z) * 100.0f);
178 layerView.pose.orientation.x,
179 layerView.pose.orientation.y,
180 layerView.pose.orientation.z));
185void QQuick3DXrManagerPrivate::updateCameraNonMultiview(
int eye,
const XrCompositionLayerProjectionView &layerView)
194 updateCameraHelper(eyeCamera, layerView);
196 q->m_vrViewport->setCamera(eyeCamera);
200void QQuick3DXrManagerPrivate::updateCameraMultiview(
int projectionLayerViewStartIndex,
int count)
207 QVarLengthArray<QQuick3DCamera *, 4> cameras;
208 for (
int i = projectionLayerViewStartIndex;
i < projectionLayerViewStartIndex +
count; ++
i) {
211 updateCameraHelper(eyeCamera, m_projectionLayerViews[
i]);
212 cameras.append(eyeCamera);
214 vrViewport->setMultiViewCameras(cameras.data(), cameras.count());
219 bool supported =
false;
220 XrSystemPassthroughProperties2FB passthroughSystemProperties{};
221 passthroughSystemProperties.type = XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES2_FB;
223 XrSystemProperties systemProperties{};
224 systemProperties.type = XR_TYPE_SYSTEM_PROPERTIES;
225 systemProperties.next = &passthroughSystemProperties;
227 XrSystemGetInfo systemGetInfo{};
228 systemGetInfo.type = XR_TYPE_SYSTEM_GET_INFO;
229 systemGetInfo.formFactor = m_formFactor;
231 XrSystemId systemId = XR_NULL_SYSTEM_ID;
232 xrGetSystem(m_instance, &systemGetInfo, &systemId);
233 xrGetSystemProperties(m_instance, systemId, &systemProperties);
235 supported = (passthroughSystemProperties.capabilities & XR_PASSTHROUGH_CAPABILITY_BIT_FB) == XR_PASSTHROUGH_CAPABILITY_BIT_FB;
241 XrSystemPassthroughPropertiesFB oldPassthroughSystemProperties{};
242 oldPassthroughSystemProperties.type = XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB;
243 systemProperties.next = &oldPassthroughSystemProperties;
244 xrGetSystemProperties(m_instance, systemId, &systemProperties);
245 supported = oldPassthroughSystemProperties.supportsPassthrough;
260 return m_graphics && m_graphics->
rhi();
275 bool exitRenderLoop =
false;
276 bool requestrestart =
false;
277 pollEvents(&exitRenderLoop, &requestrestart);
280 emit q->sessionEnded();
282 if (m_sessionRunning && m_inputManager) {
288void QQuick3DXrManagerPrivate::destroySwapchain()
290 for (
const Swapchain &swapchain : m_swapchains)
291 xrDestroySwapchain(swapchain.
handle);
293 m_swapchains.clear();
294 m_swapchainImages.clear();
296 for (
const Swapchain &swapchain : m_depthSwapchains)
297 xrDestroySwapchain(swapchain.
handle);
299 m_depthSwapchains.clear();
300 m_depthSwapchainImages.clear();
305 Q_ASSERT(m_session != XR_NULL_HANDLE);
307 XrFrameWaitInfo frameWaitInfo{};
308 frameWaitInfo.type = XR_TYPE_FRAME_WAIT_INFO;
309 XrFrameState frameState{};
310 frameState.type = XR_TYPE_FRAME_STATE;
311 if (!checkXrResult(xrWaitFrame(m_session, &frameWaitInfo, &frameState))) {
316 XrFrameBeginInfo frameBeginInfo{};
317 frameBeginInfo.type = XR_TYPE_FRAME_BEGIN_INFO;
318 if (!checkXrResult(xrBeginFrame(m_session, &frameBeginInfo))) {
323 QVector<XrCompositionLayerBaseHeader*>
layers;
327 XrCompositionLayerPassthroughFB passthroughCompLayer{};
328 passthroughCompLayer.type = XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB;
329 if (m_enablePassthrough && m_passthroughSupported) {
330 if (m_passthroughLayer == XR_NULL_HANDLE)
331 createMetaQuestPassthroughLayer();
332 passthroughCompLayer.layerHandle = m_passthroughLayer;
333 passthroughCompLayer.flags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
334 passthroughCompLayer.space = XR_NULL_HANDLE;
335 layers.push_back(
reinterpret_cast<XrCompositionLayerBaseHeader*
>(&passthroughCompLayer));
338 XrCompositionLayerProjection
layer{};
339 layer.type = XR_TYPE_COMPOSITION_LAYER_PROJECTION;
340 layer.layerFlags = XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT;
341 layer.layerFlags |= XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT;
342 layer.layerFlags |= XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT;
344 if (frameState.shouldRender == XR_TRUE) {
345 if (renderLayer(frameState.predictedDisplayTime, frameState.predictedDisplayPeriod,
layer)) {
346 layers.push_back(
reinterpret_cast<XrCompositionLayerBaseHeader*
>(&
layer));
350 XrFrameEndInfo frameEndInfo{};
351 frameEndInfo.type = XR_TYPE_FRAME_END_INFO;
352 frameEndInfo.displayTime = frameState.predictedDisplayTime;
353 if (!m_enablePassthrough)
354 frameEndInfo.environmentBlendMode = m_environmentBlendMode;
356 frameEndInfo.environmentBlendMode = XR_ENVIRONMENT_BLEND_MODE_OPAQUE;
357 frameEndInfo.layerCount = (uint32_t)
layers.size();
358 frameEndInfo.layers =
layers.data();
359 if (!checkXrResult(xrEndFrame(m_session, &frameEndInfo)))
365 QSSG_ASSERT(rhi !=
nullptr && m_graphics !=
nullptr,
return false);
367#if QT_CONFIG(graphicsframecapture)
368 if (m_frameCapture) {
370 m_frameCapture->setCapturePrefix(
QLatin1String(
"quick3dxr"));
371 m_frameCapture->setRhi(rhi);
372 if (!m_frameCapture->isLoaded()) {
373 qWarning(
"Quick 3D XR: Frame capture was requested but QGraphicsFrameCapture is not initialized"
374 " (or has no backends enabled in the Qt build)");
376 qDebug(
"Quick 3D XR: Frame capture initialized");
382 return m_isGraphicsInitialized;
385bool QQuick3DXrManagerPrivate::initialize()
394#if QT_CONFIG(graphicsframecapture)
397 qWarning(
"Quick 3D XR: Frame capture was requested, but Qt is built without QGraphicsFrameCapture");
401#ifdef XR_USE_PLATFORM_ANDROID
403 PFN_xrInitializeLoaderKHR xrInitializeLoaderKHR;
404 xrGetInstanceProcAddr(
405 XR_NULL_HANDLE,
"xrInitializeLoaderKHR", (PFN_xrVoidFunction*)&xrInitializeLoaderKHR);
406 if (xrInitializeLoaderKHR != NULL) {
407 m_javaVM = QJniEnvironment::javaVM();
408 m_androidActivity = QNativeInterface::QAndroidApplication::context();
410 XrLoaderInitInfoAndroidKHR loaderInitializeInfoAndroid;
411 memset(&loaderInitializeInfoAndroid, 0,
sizeof(loaderInitializeInfoAndroid));
412 loaderInitializeInfoAndroid.type = XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR;
413 loaderInitializeInfoAndroid.next = NULL;
414 loaderInitializeInfoAndroid.applicationVM =
m_javaVM;
415 loaderInitializeInfoAndroid.applicationContext = m_androidActivity.object();
416 XrResult xrResult = xrInitializeLoaderKHR((XrLoaderInitInfoBaseHeaderKHR*)&loaderInitializeInfoAndroid);
417 if (xrResult != XR_SUCCESS) {
418 qWarning(
"Failed to initialize OpenXR Loader: %s", to_string(xrResult));
425 auto graphicsAPI = QQuickWindow::graphicsApi();
427 m_graphics =
nullptr;
428#ifdef XR_USE_GRAPHICS_API_VULKAN
432#ifdef XR_USE_GRAPHICS_API_D3D11
436#ifdef XR_USE_GRAPHICS_API_D3D12
440#ifdef XR_USE_GRAPHICS_API_OPENGL
444#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
450 qDebug() <<
"The Qt Quick Scenegraph is not using a supported RHI mode:" << graphicsAPI;
455 checkXrExtensions(
nullptr);
461 XrResult
result = createXrInstance();
462 if (
result != XR_SUCCESS) {
463 setErrorString(
result,
"xrCreateInstance");
465 m_graphics =
nullptr;
472 setupDebugMessenger();
475 result = initializeSystem();
476 if (
result != XR_SUCCESS) {
477 setErrorString(
result,
"xrGetSystem");
479 m_graphics =
nullptr;
484 if (!
q->setupGraphics()) {
485 m_errorString = QObject::tr(
"Failed to set up 3D API integration");
487 m_graphics =
nullptr;
492 XrSessionCreateInfo xrSessionInfo{};
493 xrSessionInfo.type = XR_TYPE_SESSION_CREATE_INFO;
494 xrSessionInfo.next = m_graphics->
handle();
495 xrSessionInfo.systemId = m_systemId;
497 result = xrCreateSession(m_instance, &xrSessionInfo, &m_session);
498 if (
result != XR_SUCCESS) {
499 setErrorString(
result,
"xrCreateSession");
501 m_graphics =
nullptr;
506 if (m_colorspaceExtensionSupported)
507 setupMetaQuestColorSpaces();
508 if (m_displayRefreshRateExtensionSupported)
509 setupMetaQuestRefreshRates();
510 if (m_spaceExtensionSupported)
511 m_spaceExtension->
initialize(m_instance, m_session);
513 checkReferenceSpaces();
520 if (!setupAppSpace())
522 if (!setupViewSpace())
525 if (!createSwapchains())
531void QQuick3DXrManagerPrivate::teardown()
533 if (m_inputManager) {
535 m_inputManager =
nullptr;
538 if (m_spaceExtension) {
540 m_spaceExtension =
nullptr;
543 if (m_passthroughLayer)
544 destroyMetaQuestPassthroughLayer();
545 if (m_passthroughFeature)
546 destroyMetaQuestPassthrough();
550 if (m_appSpace != XR_NULL_HANDLE) {
551 xrDestroySpace(m_appSpace);
554 if (m_viewSpace != XR_NULL_HANDLE)
555 xrDestroySpace(m_viewSpace);
557 xrDestroySession(m_session);
559#ifdef XR_EXT_debug_utils
560 if (m_debugMessenger) {
561 m_xrDestroyDebugUtilsMessengerEXT(m_debugMessenger);
562 m_debugMessenger = XR_NULL_HANDLE;
566 xrDestroyInstance(m_instance);
574void QQuick3DXrManagerPrivate::checkReferenceSpaces()
576 Q_ASSERT(m_session != XR_NULL_HANDLE);
579 if (!checkXrResult(xrEnumerateReferenceSpaces(m_session, 0, &spaceCount,
nullptr))) {
580 qWarning(
"Failed to enumerate reference spaces");
583 m_availableReferenceSpace.resize(spaceCount);
584 if (!checkXrResult(xrEnumerateReferenceSpaces(m_session, spaceCount, &spaceCount, m_availableReferenceSpace.data()))) {
585 qWarning(
"Failed to enumerate reference spaces");
589 qDebug(
"Available reference spaces: %d", spaceCount);
590 for (XrReferenceSpaceType space : m_availableReferenceSpace) {
591 qDebug(
" Name: %s", to_string(space));
595bool QQuick3DXrManagerPrivate::isReferenceSpaceAvailable(XrReferenceSpaceType
type)
597 return m_availableReferenceSpace.contains(
type);
600bool QQuick3DXrManagerPrivate::setupAppSpace()
604 Q_ASSERT(m_session != XR_NULL_HANDLE);
606 XrPosef identityPose;
607 identityPose.orientation.w = 1;
608 identityPose.orientation.x = 0;
609 identityPose.orientation.y = 0;
610 identityPose.orientation.z = 0;
611 identityPose.position.x = 0;
612 identityPose.position.y = 0;
613 identityPose.position.z = 0;
615 XrReferenceSpaceType newReferenceSpace;
616 XrSpace newAppSpace = XR_NULL_HANDLE;
617 m_isEmulatingLocalFloor =
false;
619 if (isReferenceSpaceAvailable(m_requestedReferenceSpace)) {
620 newReferenceSpace = m_requestedReferenceSpace;
621 }
else if (m_requestedReferenceSpace == XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT &&
622 isReferenceSpaceAvailable(XR_REFERENCE_SPACE_TYPE_STAGE)) {
623 m_isEmulatingLocalFloor =
true;
624 m_isFloorResetPending =
true;
625 newReferenceSpace = XR_REFERENCE_SPACE_TYPE_LOCAL;
627 qWarning(
"Requested reference space is not available");
628 newReferenceSpace = XR_REFERENCE_SPACE_TYPE_LOCAL;
632 qDebug(
"Creating new reference space for app space: %s", to_string(newReferenceSpace));
633 XrReferenceSpaceCreateInfo referenceSpaceCreateInfo{};
634 referenceSpaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
635 referenceSpaceCreateInfo.poseInReferenceSpace = identityPose;
636 referenceSpaceCreateInfo.referenceSpaceType = newReferenceSpace;
637 if (!checkXrResult(xrCreateReferenceSpace(m_session, &referenceSpaceCreateInfo, &newAppSpace))) {
638 qWarning(
"Failed to create app space");
643 xrDestroySpace(m_appSpace);
645 m_appSpace = newAppSpace;
646 m_referenceSpace = newReferenceSpace;
649 if (!m_isFloorResetPending)
650 emit q->referenceSpaceChanged();
656void QQuick3DXrManagerPrivate::updateAppSpace(XrTime predictedDisplayTime)
662 if (m_requestedReferenceSpace != m_referenceSpace && !m_isFloorResetPending) {
663 if (!setupAppSpace()) {
665 qWarning(
"Setting requested reference space failed");
666 m_requestedReferenceSpace = m_referenceSpace;
675 if (m_isFloorResetPending) {
676 if (!resetEmulatedFloorHeight(predictedDisplayTime)) {
678 m_requestedReferenceSpace = XR_REFERENCE_SPACE_TYPE_LOCAL;
679 emit q->referenceSpaceChanged();
686bool QQuick3DXrManagerPrivate::setupViewSpace()
688 Q_ASSERT(m_session != XR_NULL_HANDLE);
690 XrPosef identityPose;
691 identityPose.orientation.w = 1;
692 identityPose.orientation.x = 0;
693 identityPose.orientation.y = 0;
694 identityPose.orientation.z = 0;
695 identityPose.position.x = 0;
696 identityPose.position.y = 0;
697 identityPose.position.z = 0;
699 XrSpace newViewSpace = XR_NULL_HANDLE;
701 XrReferenceSpaceCreateInfo referenceSpaceCreateInfo{};
702 referenceSpaceCreateInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
703 referenceSpaceCreateInfo.poseInReferenceSpace = identityPose;
704 referenceSpaceCreateInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_VIEW;
705 if (!checkXrResult(xrCreateReferenceSpace(m_session, &referenceSpaceCreateInfo, &newViewSpace))) {
706 qWarning(
"Failed to create view space");
710 if (m_viewSpace != XR_NULL_HANDLE)
711 xrDestroySpace(m_viewSpace);
713 m_viewSpace = newViewSpace;
718bool QQuick3DXrManagerPrivate::resetEmulatedFloorHeight(XrTime predictedDisplayTime)
724 m_isFloorResetPending =
false;
726 XrPosef identityPose;
727 identityPose.orientation.w = 1;
728 identityPose.orientation.x = 0;
729 identityPose.orientation.y = 0;
730 identityPose.orientation.z = 0;
731 identityPose.position.x = 0;
732 identityPose.position.y = 0;
733 identityPose.position.z = 0;
735 XrSpace localSpace = XR_NULL_HANDLE;
736 XrSpace stageSpace = XR_NULL_HANDLE;
738 XrReferenceSpaceCreateInfo createInfo{};
739 createInfo.type = XR_TYPE_REFERENCE_SPACE_CREATE_INFO;
740 createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
741 createInfo.poseInReferenceSpace = identityPose;
743 if (!checkXrResult(xrCreateReferenceSpace(m_session, &createInfo, &localSpace))) {
744 qWarning(
"Failed to create local space (for emulated LOCAL_FLOOR space)");
748 createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_STAGE;
749 if (!checkXrResult(xrCreateReferenceSpace(m_session, &createInfo, &stageSpace))) {
750 qWarning(
"Failed to create stage space (for emulated LOCAL_FLOOR space)");
751 xrDestroySpace(localSpace);
755 XrSpaceLocation stageLocation{};
756 stageLocation.type = XR_TYPE_SPACE_LOCATION;
757 stageLocation.pose = identityPose;
759 if (!checkXrResult(xrLocateSpace(stageSpace, localSpace, predictedDisplayTime, &stageLocation))) {
760 qWarning(
"Failed to locate STAGE space in LOCAL space, in order to emulate LOCAL_FLOOR");
761 xrDestroySpace(localSpace);
762 xrDestroySpace(stageSpace);
766 xrDestroySpace(localSpace);
767 xrDestroySpace(stageSpace);
769 XrSpace newAppSpace = XR_NULL_HANDLE;
770 createInfo.referenceSpaceType = XR_REFERENCE_SPACE_TYPE_LOCAL;
771 createInfo.poseInReferenceSpace.position.y = stageLocation.pose.position.y;
772 if (!checkXrResult(xrCreateReferenceSpace(m_session, &createInfo, &newAppSpace))) {
773 qWarning(
"Failed to recreate emulated LOCAL_FLOOR play space with latest floor estimate");
777 xrDestroySpace(m_appSpace);
778 m_appSpace = newAppSpace;
779 m_referenceSpace = XR_REFERENCE_SPACE_TYPE_LOCAL_FLOOR_EXT;
780 emit q->referenceSpaceChanged();
785bool QQuick3DXrManagerPrivate::createSwapchains()
787 Q_ASSERT(m_session != XR_NULL_HANDLE);
791 XrSystemProperties systemProperties{};
792 systemProperties.type = XR_TYPE_SYSTEM_PROPERTIES;
794 XrSystemHandTrackingPropertiesEXT handTrackingSystemProperties{};
795 handTrackingSystemProperties.type = XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT;
796 systemProperties.next = &handTrackingSystemProperties;
798 if (!checkXrResult(xrGetSystemProperties(m_instance, m_systemId, &systemProperties))) {
799 qWarning(
"Failed to get OpenXR system properties");
802 qDebug(
"System Properties: Name=%s VendorId=%d", systemProperties.systemName, systemProperties.vendorId);
803 qDebug(
"System Graphics Properties: MaxWidth=%d MaxHeight=%d MaxLayers=%d",
804 systemProperties.graphicsProperties.maxSwapchainImageWidth,
805 systemProperties.graphicsProperties.maxSwapchainImageHeight,
806 systemProperties.graphicsProperties.maxLayerCount);
807 qDebug(
"System Tracking Properties: OrientationTracking=%s PositionTracking=%s",
808 systemProperties.trackingProperties.orientationTracking == XR_TRUE ?
"True" :
"False",
809 systemProperties.trackingProperties.positionTracking == XR_TRUE ?
"True" :
"False");
810 qDebug(
"System Hand Tracking Properties: handTracking=%s",
811 handTrackingSystemProperties.supportsHandTracking == XR_TRUE ?
"True" :
"False");
815 if (!checkXrResult(xrEnumerateViewConfigurationViews(m_instance,
822 qWarning(
"Failed to enumerate view configurations");
825 m_configViews.resize(viewCount, {XR_TYPE_VIEW_CONFIGURATION_VIEW,
nullptr, 0, 0, 0, 0, 0, 0});
826 if (!checkXrResult(xrEnumerateViewConfigurationViews(m_instance,
831 m_configViews.data())))
833 qWarning(
"Failed to enumerate view configurations");
836 m_views.resize(viewCount, {XR_TYPE_VIEW,
nullptr, {}, {}});
837 m_projectionLayerViews.resize(viewCount, {});
838 m_layerDepthInfos.resize(viewCount, {});
843 uint32_t swapchainFormatCount;
844 if (!checkXrResult(xrEnumerateSwapchainFormats(m_session, 0, &swapchainFormatCount,
nullptr))) {
845 qWarning(
"Failed to enumerate swapchain formats");
848 QVector<int64_t> swapchainFormats(swapchainFormatCount);
849 if (!checkXrResult(xrEnumerateSwapchainFormats(m_session,
850 swapchainFormats.size(),
851 &swapchainFormatCount,
852 swapchainFormats.data())))
854 qWarning(
"Failed to enumerate swapchain formats");
858 Q_ASSERT(swapchainFormatCount == swapchainFormats.size());
860 if (m_compositionLayerDepthSupported)
865 QString swapchainFormatsString;
866 for (int64_t
format : swapchainFormats) {
867 const bool selectedColor =
format == m_colorSwapchainFormat;
868 const bool selectedDepth =
format == m_depthSwapchainFormat;
869 swapchainFormatsString += u
" ";
871 swapchainFormatsString += u
"[";
872 else if (selectedDepth)
873 swapchainFormatsString += u
"<";
876 swapchainFormatsString += u
"]";
877 else if (selectedDepth)
878 swapchainFormatsString += u
">";
883 const XrViewConfigurationView &vp = m_configViews[0];
894 if (m_multiviewRendering) {
896 XrSwapchainCreateInfo swapchainCreateInfo{};
897 swapchainCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO;
898 swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT | XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT;
899 swapchainCreateInfo.format = m_colorSwapchainFormat;
900 swapchainCreateInfo.sampleCount = 1;
901 swapchainCreateInfo.width = vp.recommendedImageRectWidth;
902 swapchainCreateInfo.height = vp.recommendedImageRectHeight;
903 swapchainCreateInfo.faceCount = 1;
904 swapchainCreateInfo.arraySize = viewCount;
905 swapchainCreateInfo.mipCount = 1;
907 qDebug(
"Creating multiview swapchain for %u view(s) with dimensions Width=%d Height=%d SampleCount=%d Format=%llx",
909 vp.recommendedImageRectWidth,
910 vp.recommendedImageRectHeight,
912 static_cast<long long unsigned int>(m_colorSwapchainFormat));
915 swapchain.width = swapchainCreateInfo.width;
916 swapchain.height = swapchainCreateInfo.height;
917 swapchain.arraySize = swapchainCreateInfo.arraySize;
918 if (checkXrResult(xrCreateSwapchain(m_session, &swapchainCreateInfo, &swapchain.handle))) {
919 uint32_t imageCount = 0;
920 if (!checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, 0, &imageCount,
nullptr))) {
921 qWarning(
"Failed to enumerate swapchain images");
926 if (!checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, imageCount, &imageCount, swapchainImages[0]))) {
927 qWarning(
"Failed to enumerate swapchain images");
931 m_swapchains.append(swapchain);
932 m_swapchainImages.insert(swapchain.handle, swapchainImages);
934 qWarning(
"xrCreateSwapchain failed (multiview)");
942 if (m_compositionLayerDepthSupported && m_depthSwapchainFormat > 0) {
943 swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
944 swapchainCreateInfo.format = m_depthSwapchainFormat;
945 if (checkXrResult(xrCreateSwapchain(m_session, &swapchainCreateInfo, &swapchain.handle))) {
946 uint32_t imageCount = 0;
947 if (!checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, 0, &imageCount,
nullptr))) {
948 qWarning(
"Failed to enumerate depth swapchain images");
953 if (!checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, imageCount, &imageCount, swapchainImages[0]))) {
954 qWarning(
"Failed to enumerate depth swapchain images");
958 m_depthSwapchains.append(swapchain);
959 m_depthSwapchainImages.insert(swapchain.handle, swapchainImages);
961 qWarning(
"xrCreateSwapchain failed for depth swapchain (multiview)");
967 for (uint32_t
i = 0;
i < viewCount;
i++) {
968 qDebug(
"Creating swapchain for view %u with dimensions Width=%d Height=%d SampleCount=%d Format=%llx",
970 vp.recommendedImageRectWidth,
971 vp.recommendedImageRectHeight,
973 static_cast<long long unsigned int>(m_colorSwapchainFormat));
976 XrSwapchainCreateInfo swapchainCreateInfo{};
977 swapchainCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO;
978 swapchainCreateInfo.arraySize = 1;
979 swapchainCreateInfo.format = m_colorSwapchainFormat;
980 swapchainCreateInfo.width = vp.recommendedImageRectWidth;
981 swapchainCreateInfo.height = vp.recommendedImageRectHeight;
982 swapchainCreateInfo.mipCount = 1;
983 swapchainCreateInfo.faceCount = 1;
984 swapchainCreateInfo.sampleCount = 1;
985 swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT;
987 swapchain.width = swapchainCreateInfo.width;
988 swapchain.height = swapchainCreateInfo.height;
989 if (checkXrResult(xrCreateSwapchain(m_session, &swapchainCreateInfo, &swapchain.handle))) {
990 uint32_t imageCount = 0;
991 if (!checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, 0, &imageCount,
nullptr))) {
992 qWarning(
"Failed to enumerate swapchain images");
997 if (!checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, imageCount, &imageCount, swapchainImages[0]))) {
998 qWarning(
"Failed to enumerate swapchain images");
1002 m_swapchains.append(swapchain);
1003 m_swapchainImages.insert(swapchain.handle, swapchainImages);
1005 qWarning(
"xrCreateSwapchain failed (view %u)", viewCount);
1009 if (m_compositionLayerDepthSupported && m_depthSwapchainFormat > 0) {
1010 swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1011 swapchainCreateInfo.format = m_depthSwapchainFormat;
1012 if (checkXrResult(xrCreateSwapchain(m_session, &swapchainCreateInfo, &swapchain.handle))) {
1013 uint32_t imageCount = 0;
1014 if (!checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, 0, &imageCount,
nullptr))) {
1015 qWarning(
"Failed to enumerate depth swapchain images");
1020 if (!checkXrResult(xrEnumerateSwapchainImages(swapchain.handle, imageCount, &imageCount, swapchainImages[0]))) {
1021 qWarning(
"Failed to enumerate depth swapchain images");
1025 m_depthSwapchains.append(swapchain);
1026 m_depthSwapchainImages.insert(swapchain.handle, swapchainImages);
1028 qWarning(
"xrCreateSwapchain failed for depth swapchain (view %u)", viewCount);
1035 if (m_multiviewRendering) {
1036 if (m_swapchains.isEmpty())
1038 if (m_compositionLayerDepthSupported && m_depthSwapchains.isEmpty())
1041 if (m_swapchains.count() !=
qsizetype(viewCount))
1043 if (m_compositionLayerDepthSupported && m_depthSwapchains.count() !=
qsizetype(viewCount))
1048 for (uint32_t
i = 0;
i < viewCount; ++
i) {
1049 m_projectionLayerViews[
i].type = XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW;
1050 m_projectionLayerViews[
i].next =
nullptr;
1051 m_projectionLayerViews[
i].subImage.swapchain = m_swapchains[0].handle;
1052 m_projectionLayerViews[
i].subImage.imageArrayIndex =
i;
1053 m_projectionLayerViews[
i].subImage.imageRect.offset.x = 0;
1054 m_projectionLayerViews[
i].subImage.imageRect.offset.y = 0;
1055 m_projectionLayerViews[
i].subImage.imageRect.extent.width = vp.recommendedImageRectWidth;
1056 m_projectionLayerViews[
i].subImage.imageRect.extent.height = vp.recommendedImageRectHeight;
1058 m_layerDepthInfos[
i].type = XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR;
1059 m_layerDepthInfos[
i].next =
nullptr;
1060 m_layerDepthInfos[
i].subImage.swapchain = m_depthSwapchains[0].handle;
1061 m_layerDepthInfos[
i].subImage.imageArrayIndex =
i;
1062 m_layerDepthInfos[
i].subImage.imageRect.offset.x = 0;
1063 m_layerDepthInfos[
i].subImage.imageRect.offset.y = 0;
1064 m_layerDepthInfos[
i].subImage.imageRect.extent.width = vp.recommendedImageRectWidth;
1065 m_layerDepthInfos[
i].subImage.imageRect.extent.height = vp.recommendedImageRectHeight;
1069 if (m_foveationExtensionSupported)
1070 setupMetaQuestFoveation();
1088 return m_enabledExtensions;
1093 return m_runtimeName;
1098 return m_runtimeVersion;
1104 QRhi *rhi =
q->m_renderControl->rhi();
1105 if (m_multiviewRendering ==
enable || !rhi)
1108 qWarning(
"Quick 3D XR: Multiview rendering was enabled, but is reported as unsupported from the current QRhi backend (%s)",
1112 m_multiviewRendering =
enable;
1113 qDebug(
"Quick3D XR: multiview rendering %s", m_multiviewRendering ?
"enabled" :
"disabled");
1114 if (!m_swapchains.isEmpty()) {
1115 qDebug(
"Quick3D XR: OpenXR swapchain already exists, creating new one due to change in multiview mode");
1124 QRhi *rhi =
q->m_renderControl->rhi();
1130 m_enablePassthrough =
enable;
1132 if (m_passthroughSupported) {
1133 if (m_enablePassthrough) {
1134 if (m_passthroughFeature == XR_NULL_HANDLE)
1135 createMetaQuestPassthrough();
1137 startMetaQuestPassthrough();
1139 if (m_passthroughLayer == XR_NULL_HANDLE)
1140 createMetaQuestPassthroughLayer();
1142 resumeMetaQuestPassthroughLayer();
1145 if (m_passthroughLayer)
1146 pauseMetaQuestPassthroughLayer();
1148 if (m_passthroughFeature)
1149 pauseMetaQuestPassthrough();
1156 if (m_submitLayerDepth ==
enable)
1159 if (m_compositionLayerDepthSupported) {
1161 qDebug(
"Enabling submitLayerDepth");
1163 m_submitLayerDepth =
enable;
1170 if (m_referenceSpace == referenceSpace)
1173 m_requestedReferenceSpace = referenceSpace;
1184void QQuick3DXrManagerPrivate::pollEvents(
bool *exitRenderLoop,
bool *requestRestart) {
1185 *exitRenderLoop =
false;
1186 *requestRestart =
false;
1188 auto readNextEvent = [
this]() {
1191 XrEventDataBaseHeader* baseHeader =
reinterpret_cast<XrEventDataBaseHeader*
>(&m_eventDataBuffer);
1192 *baseHeader = {XR_TYPE_EVENT_DATA_BUFFER,
nullptr};
1193 const XrResult xr = xrPollEvent(m_instance, &m_eventDataBuffer);
1194 if (xr == XR_SUCCESS) {
1195 if (baseHeader->type == XR_TYPE_EVENT_DATA_EVENTS_LOST) {
1196 const XrEventDataEventsLost*
const eventsLost =
reinterpret_cast<const XrEventDataEventsLost*
>(baseHeader);
1197 qDebug(
"%d events lost", eventsLost->lostEventCount);
1203 return static_cast<XrEventDataBaseHeader*
>(
nullptr);
1206 auto handleSessionStateChangedEvent = [
this](
const XrEventDataSessionStateChanged& stateChangedEvent,
1207 bool* exitRenderLoop,
1208 bool* requestRestart) {
1209 const XrSessionState oldState = m_sessionState;
1210 m_sessionState = stateChangedEvent.state;
1212 qDebug(
"XrEventDataSessionStateChanged: state %s->%s time=%lld",
1213 to_string(oldState),
1214 to_string(m_sessionState),
1215 static_cast<long long int>(stateChangedEvent.time));
1217 if ((stateChangedEvent.session != XR_NULL_HANDLE) && (stateChangedEvent.session != m_session)) {
1218 qDebug(
"XrEventDataSessionStateChanged for unknown session");
1222 switch (m_sessionState) {
1223 case XR_SESSION_STATE_READY: {
1224 Q_ASSERT(m_session != XR_NULL_HANDLE);
1225 XrSessionBeginInfo sessionBeginInfo{};
1226 sessionBeginInfo.type = XR_TYPE_SESSION_BEGIN_INFO;
1227 sessionBeginInfo.primaryViewConfigurationType = m_viewConfigType;
1228 if (!checkXrResult(xrBeginSession(m_session, &sessionBeginInfo))) {
1232 m_sessionRunning =
true;
1235 case XR_SESSION_STATE_STOPPING: {
1236 Q_ASSERT(m_session != XR_NULL_HANDLE);
1237 m_sessionRunning =
false;
1238 if (!checkXrResult(xrEndSession(m_session)))
1242 case XR_SESSION_STATE_EXITING: {
1243 *exitRenderLoop =
true;
1245 *requestRestart =
false;
1248 case XR_SESSION_STATE_LOSS_PENDING: {
1249 *exitRenderLoop =
true;
1251 *requestRestart =
true;
1260 while (
const XrEventDataBaseHeader*
event = readNextEvent()) {
1261 switch (
event->type) {
1262 case XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING: {
1263 const auto& instanceLossPending = *
reinterpret_cast<const XrEventDataInstanceLossPending*
>(
event);
1264 qDebug(
"XrEventDataInstanceLossPending by %lld",
static_cast<long long int>(instanceLossPending.lossTime));
1265 *exitRenderLoop =
true;
1266 *requestRestart =
true;
1269 case XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED: {
1270 auto sessionStateChangedEvent = *
reinterpret_cast<const XrEventDataSessionStateChanged*
>(
event);
1271 handleSessionStateChangedEvent(sessionStateChangedEvent, exitRenderLoop, requestRestart);
1274 case XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED:
1276 case XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB:
1277 case XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB:
1278 case XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB:
1279 case XR_TYPE_EVENT_DATA_SCENE_CAPTURE_COMPLETE_FB:
1281 if (m_spaceExtension)
1284 case XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING:
1293bool QQuick3DXrManagerPrivate::renderLayer(XrTime predictedDisplayTime,
1294 XrDuration predictedDisplayPeriod,
1295 XrCompositionLayerProjection &
layer)
1298 auto *xrOrigin =
q->m_xrOrigin;
1299 auto *animationDriver =
q->m_animationDriver;
1300 auto *renderControl =
q->m_renderControl;
1304 XrViewState viewState{};
1305 viewState.type = XR_TYPE_VIEW_STATE;
1306 quint32 viewCapacityInput = m_views.size();
1310 updateAppSpace(predictedDisplayTime);
1312 XrViewLocateInfo viewLocateInfo{};
1313 viewLocateInfo.type = XR_TYPE_VIEW_LOCATE_INFO;
1314 viewLocateInfo.viewConfigurationType = m_viewConfigType;
1315 viewLocateInfo.displayTime = predictedDisplayTime;
1316 viewLocateInfo.space = m_appSpace;
1318 res = xrLocateViews(m_session, &viewLocateInfo, &viewState, viewCapacityInput, &viewCountOutput, m_views.data());
1319 if (XR_UNQUALIFIED_SUCCESS(
res)) {
1320 Q_ASSERT(viewCountOutput == viewCapacityInput);
1321 Q_ASSERT(viewCountOutput == m_configViews.size());
1322 Q_ASSERT(viewCountOutput == m_projectionLayerViews.size());
1323 Q_ASSERT(m_multiviewRendering ? viewCountOutput == m_swapchains[0].arraySize : viewCountOutput == m_swapchains.
size());
1330 location.type = XR_TYPE_SPACE_LOCATION;
1331 if (checkXrResult(xrLocateSpace(m_viewSpace, m_appSpace, predictedDisplayTime, &
location))) {
1334 location.pose.position.z) * 100.0f);
1346 if (m_spaceExtension)
1347 m_spaceExtension->
updateAnchors(predictedDisplayTime, m_appSpace);
1349 if (m_handtrackingExtensionSupported && m_inputManager)
1355 const qint64 displayPeriodMS = predictedDisplayPeriod / 1000000;
1356 const qint64 displayDeltaMS = (predictedDisplayTime - m_previousTime) / 1000000;
1358 if (m_previousTime == 0)
1359 animationDriver->setStep(displayPeriodMS);
1361 if (displayDeltaMS > displayPeriodMS)
1362 animationDriver->setStep(displayPeriodMS);
1364 animationDriver->setStep(displayDeltaMS);
1365 animationDriver->advance();
1367 m_previousTime = predictedDisplayTime;
1369#if QT_CONFIG(graphicsframecapture)
1371 m_frameCapture->startCaptureFrame();
1374 if (m_submitLayerDepth && m_samples > 1) {
1376 static bool warned =
false;
1379 qWarning(
"Quick3D XR: Submitting depth buffer with MSAA cannot be enabled"
1380 " when depth-stencil resolve is not supported by the underlying 3D API (%s)",
1381 renderControl->rhi()->backendName());
1383 m_submitLayerDepth =
false;
1387 if (m_multiviewRendering) {
1388 const Swapchain swapchain = m_swapchains[0];
1391 XrSwapchainImageAcquireInfo acquireInfo{};
1392 acquireInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO;
1393 uint32_t swapchainImageIndex = 0;
1394 if (!checkXrResult(xrAcquireSwapchainImage(swapchain.handle, &acquireInfo, &swapchainImageIndex))) {
1395 qWarning(
"Failed to acquire swapchain image (multiview)");
1398 XrSwapchainImageWaitInfo waitInfo{};
1399 waitInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO;
1400 waitInfo.timeout = XR_INFINITE_DURATION;
1401 if (!checkXrResult(xrWaitSwapchainImage(swapchain.handle, &waitInfo))) {
1402 qWarning(
"Failed to wait for swapchain image (multiview)");
1405 XrSwapchainImageBaseHeader *swapchainImage = m_swapchainImages[swapchain.handle][swapchainImageIndex];
1407 XrSwapchainImageBaseHeader *depthSwapchainImage =
nullptr;
1408 if (m_submitLayerDepth && !m_depthSwapchains.isEmpty()) {
1409 if (checkXrResult(xrAcquireSwapchainImage(m_depthSwapchains[0].
handle, &acquireInfo, &swapchainImageIndex))) {
1410 if (checkXrResult(xrWaitSwapchainImage(m_depthSwapchains[0].
handle, &waitInfo)))
1411 depthSwapchainImage = m_depthSwapchainImages[m_depthSwapchains[0].handle][swapchainImageIndex];
1413 qWarning(
"Failed to wait for depth swapchain image (multiview)");
1415 qWarning(
"Failed to acquire depth swapchain image (multiview)");
1422 for (uint32_t
i = 0;
i < viewCountOutput;
i++) {
1424 m_projectionLayerViews[
i].pose = m_views[
i].pose;
1425 m_projectionLayerViews[
i].fov = m_views[
i].fov;
1427 updateCameraMultiview(0, viewCountOutput);
1433 doRender(m_projectionLayerViews[0].subImage,
1435 depthSwapchainImage);
1437 for (uint32_t
i = 0;
i < viewCountOutput;
i++) {
1438 if (m_submitLayerDepth) {
1439 m_layerDepthInfos[
i].minDepth = 0;
1440 m_layerDepthInfos[
i].maxDepth = 1;
1442 m_layerDepthInfos[
i].nearZ = cam ? cam->clipNear() : 1.0f;
1443 m_layerDepthInfos[
i].farZ = cam ? cam->clipFar() : 10000.0f;
1444 m_projectionLayerViews[
i].next = &m_layerDepthInfos[
i];
1446 m_projectionLayerViews[
i].next =
nullptr;
1451 XrSwapchainImageReleaseInfo releaseInfo{};
1452 releaseInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO;
1453 if (!checkXrResult(xrReleaseSwapchainImage(swapchain.handle, &releaseInfo)))
1454 qWarning(
"Failed to release swapchain image");
1455 if (depthSwapchainImage) {
1456 if (!checkXrResult(xrReleaseSwapchainImage(m_depthSwapchains[0].
handle, &releaseInfo)))
1457 qWarning(
"Failed to release depth swapchain image");
1460 for (uint32_t
i = 0;
i < viewCountOutput;
i++) {
1462 const Swapchain viewSwapchain = m_swapchains[
i];
1465 XrSwapchainImageAcquireInfo acquireInfo{};
1466 acquireInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO;
1467 uint32_t swapchainImageIndex = 0;
1468 if (!checkXrResult(xrAcquireSwapchainImage(viewSwapchain.handle, &acquireInfo, &swapchainImageIndex))) {
1469 qWarning(
"Failed to acquire swapchain image");
1472 XrSwapchainImageWaitInfo waitInfo{};
1473 waitInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO;
1474 waitInfo.timeout = XR_INFINITE_DURATION;
1475 if (!checkXrResult(xrWaitSwapchainImage(viewSwapchain.handle, &waitInfo))) {
1476 qWarning(
"Failed to wait for swapchain image");
1479 XrSwapchainImageBaseHeader *swapchainImage = m_swapchainImages[viewSwapchain.handle][swapchainImageIndex];
1481 XrSwapchainImageBaseHeader *depthSwapchainImage =
nullptr;
1482 if (m_submitLayerDepth && !m_depthSwapchains.isEmpty()) {
1483 if (checkXrResult(xrAcquireSwapchainImage(m_depthSwapchains[
i].
handle, &acquireInfo, &swapchainImageIndex))) {
1484 if (checkXrResult(xrWaitSwapchainImage(m_depthSwapchains[
i].
handle, &waitInfo)))
1485 depthSwapchainImage = m_depthSwapchainImages[m_depthSwapchains[
i].handle][swapchainImageIndex];
1487 qWarning(
"Failed to wait for depth swapchain image");
1489 qWarning(
"Failed to acquire depth swapchain image");
1493 m_projectionLayerViews[
i].subImage.swapchain = viewSwapchain.handle;
1494 m_projectionLayerViews[
i].subImage.imageArrayIndex = 0;
1495 m_projectionLayerViews[
i].pose = m_views[
i].pose;
1496 m_projectionLayerViews[
i].fov = m_views[
i].fov;
1498 updateCameraNonMultiview(
i, m_projectionLayerViews[
i]);
1500 doRender(m_projectionLayerViews[
i].subImage,
1502 depthSwapchainImage);
1504 if (depthSwapchainImage) {
1505 m_layerDepthInfos[
i].subImage.swapchain = m_depthSwapchains[
i].handle;
1506 m_layerDepthInfos[
i].subImage.imageArrayIndex = 0;
1507 m_layerDepthInfos[
i].minDepth = 0;
1508 m_layerDepthInfos[
i].maxDepth = 1;
1510 m_layerDepthInfos[
i].nearZ = cam ? cam->clipNear() : 1.0f;
1511 m_layerDepthInfos[
i].farZ = cam ? cam->clipFar() : 10000.0f;
1512 m_projectionLayerViews[
i].next = &m_layerDepthInfos[
i];
1514 m_projectionLayerViews[
i].next =
nullptr;
1517 XrSwapchainImageReleaseInfo releaseInfo{};
1518 releaseInfo.type = XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO;
1519 if (!checkXrResult(xrReleaseSwapchainImage(viewSwapchain.handle, &releaseInfo)))
1520 qWarning(
"Failed to release swapchain image");
1521 if (depthSwapchainImage) {
1522 if (!checkXrResult(xrReleaseSwapchainImage(m_depthSwapchains[
i].
handle, &releaseInfo)))
1523 qWarning(
"Failed to release depth swapchain image");
1528#if QT_CONFIG(graphicsframecapture)
1530 m_frameCapture->endCaptureFrame();
1533 layer.space = m_appSpace;
1534 layer.viewCount = (uint32_t)m_projectionLayerViews.size();
1535 layer.views = m_projectionLayerViews.data();
1539 qDebug(
"xrLocateViews returned qualified success code: %s", to_string(
res));
1543void QQuick3DXrManagerPrivate::doRender(
const XrSwapchainSubImage &subImage,
1544 const XrSwapchainImageBaseHeader *swapchainImage,
1545 const XrSwapchainImageBaseHeader *depthSwapchainImage)
1549 auto *quickWindow =
q->m_quickWindow;
1550 auto *renderControl =
q->m_renderControl;
1552 const int arraySize = m_multiviewRendering ? m_swapchains[0].arraySize : 1;
1553 quickWindow->setRenderTarget(m_graphics->
renderTarget(subImage,
1555 m_colorSwapchainFormat,
1558 depthSwapchainImage,
1559 m_depthSwapchainFormat));
1561 quickWindow->setGeometry(0,
1563 subImage.imageRect.extent.width,
1564 subImage.imageRect.extent.height);
1565 quickWindow->contentItem()->setSize(
QSizeF(subImage.imageRect.extent.width,
1566 subImage.imageRect.extent.height));
1568 renderControl->polishItems();
1569 renderControl->beginFrame();
1570 renderControl->sync();
1571 renderControl->render();
1572 renderControl->endFrame();
1579 emit q->frameReady();
1582void QQuick3DXrManagerPrivate::setupMetaQuestColorSpaces()
1584 PFN_xrEnumerateColorSpacesFB pfnxrEnumerateColorSpacesFB = NULL;
1585 resolveXrFunction(
"xrEnumerateColorSpacesFB", (PFN_xrVoidFunction*)(&pfnxrEnumerateColorSpacesFB));
1586 if (!pfnxrEnumerateColorSpacesFB)
1589 uint32_t colorSpaceCountOutput = 0;
1590 if (!checkXrResult(pfnxrEnumerateColorSpacesFB(m_session, 0, &colorSpaceCountOutput,
nullptr))) {
1591 qWarning(
"Failed to enumerate color spaces");
1595 XrColorSpaceFB* colorSpaces =
1596 (XrColorSpaceFB*)malloc(colorSpaceCountOutput *
sizeof(XrColorSpaceFB));
1598 if (!checkXrResult(pfnxrEnumerateColorSpacesFB(m_session, colorSpaceCountOutput, &colorSpaceCountOutput, colorSpaces))) {
1599 qWarning(
"Failed to enumerate color spaces");
1603 qDebug(
"Supported ColorSpaces:");
1604 for (uint32_t
i = 0;
i < colorSpaceCountOutput;
i++) {
1605 qDebug(
"%d:%d",
i, colorSpaces[
i]);
1608 const XrColorSpaceFB requestColorSpace = XR_COLOR_SPACE_QUEST_FB;
1610 PFN_xrSetColorSpaceFB pfnxrSetColorSpaceFB = NULL;
1611 resolveXrFunction(
"xrSetColorSpaceFB", (PFN_xrVoidFunction*)(&pfnxrSetColorSpaceFB));
1613 if (!checkXrResult(pfnxrSetColorSpaceFB(m_session, requestColorSpace)))
1614 qWarning(
"Failed to set color space");
1619void QQuick3DXrManagerPrivate::setupMetaQuestRefreshRates()
1621 PFN_xrEnumerateDisplayRefreshRatesFB pfnxrEnumerateDisplayRefreshRatesFB = NULL;
1622 resolveXrFunction(
"xrEnumerateDisplayRefreshRatesFB", (PFN_xrVoidFunction*)(&pfnxrEnumerateDisplayRefreshRatesFB));
1623 if (!pfnxrEnumerateDisplayRefreshRatesFB)
1626 uint32_t numSupportedDisplayRefreshRates;
1627 QVector<float> supportedDisplayRefreshRates;
1629 if (!checkXrResult(pfnxrEnumerateDisplayRefreshRatesFB(m_session, 0, &numSupportedDisplayRefreshRates,
nullptr))) {
1630 qWarning(
"Failed to enumerate display refresh rates");
1634 supportedDisplayRefreshRates.resize(numSupportedDisplayRefreshRates);
1636 if (!checkXrResult(pfnxrEnumerateDisplayRefreshRatesFB(
1638 numSupportedDisplayRefreshRates,
1639 &numSupportedDisplayRefreshRates,
1640 supportedDisplayRefreshRates.data())))
1642 qWarning(
"Failed to enumerate display refresh rates");
1646 qDebug(
"Supported Refresh Rates:");
1647 for (uint32_t
i = 0;
i < numSupportedDisplayRefreshRates;
i++) {
1648 qDebug(
"%d:%f",
i, supportedDisplayRefreshRates[
i]);
1651 PFN_xrGetDisplayRefreshRateFB pfnGetDisplayRefreshRate;
1652 resolveXrFunction(
"xrGetDisplayRefreshRateFB", (PFN_xrVoidFunction*)(&pfnGetDisplayRefreshRate));
1654 float currentDisplayRefreshRate = 0.0f;
1655 if (!checkXrResult(pfnGetDisplayRefreshRate(m_session, ¤tDisplayRefreshRate)))
1656 qWarning(
"Failed to get display refresh rate");
1658 qDebug(
"Current System Display Refresh Rate: %f", currentDisplayRefreshRate);
1660 PFN_xrRequestDisplayRefreshRateFB pfnRequestDisplayRefreshRate;
1661 resolveXrFunction(
"xrRequestDisplayRefreshRateFB", (PFN_xrVoidFunction*)(&pfnRequestDisplayRefreshRate));
1664 if (!checkXrResult(pfnRequestDisplayRefreshRate(m_session, 0.0f)))
1665 qWarning(
"Failed to request display refresh rate");
1667 qDebug(
"Requesting system default display refresh rate");
1670void QQuick3DXrManagerPrivate::setupMetaQuestFoveation()
1672 PFN_xrCreateFoveationProfileFB pfnCreateFoveationProfileFB;
1673 resolveXrFunction(
"xrCreateFoveationProfileFB", (PFN_xrVoidFunction*)(&pfnCreateFoveationProfileFB));
1674 if (!pfnCreateFoveationProfileFB)
1677 PFN_xrDestroyFoveationProfileFB pfnDestroyFoveationProfileFB;
1678 resolveXrFunction(
"xrDestroyFoveationProfileFB", (PFN_xrVoidFunction*)(&pfnDestroyFoveationProfileFB));
1680 PFN_xrUpdateSwapchainFB pfnUpdateSwapchainFB;
1681 resolveXrFunction(
"xrUpdateSwapchainFB", (PFN_xrVoidFunction*)(&pfnUpdateSwapchainFB));
1683 for (
auto swapchain : m_swapchains) {
1684 XrFoveationLevelProfileCreateInfoFB levelProfileCreateInfo = {};
1685 levelProfileCreateInfo.type = XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB;
1686 levelProfileCreateInfo.level = m_foveationLevel;
1687 levelProfileCreateInfo.verticalOffset = 0;
1688 levelProfileCreateInfo.dynamic = XR_FOVEATION_DYNAMIC_DISABLED_FB;
1690 XrFoveationProfileCreateInfoFB profileCreateInfo = {};
1691 profileCreateInfo.type = XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB;
1692 profileCreateInfo.next = &levelProfileCreateInfo;
1694 XrFoveationProfileFB foveationProfile;
1695 pfnCreateFoveationProfileFB(m_session, &profileCreateInfo, &foveationProfile);
1697 XrSwapchainStateFoveationFB foveationUpdateState = {};
1698 memset(&foveationUpdateState, 0,
sizeof(foveationUpdateState));
1699 foveationUpdateState.type = XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB;
1700 foveationUpdateState.profile = foveationProfile;
1702 pfnUpdateSwapchainFB(
1704 (XrSwapchainStateBaseHeaderFB*)(&foveationUpdateState));
1706 pfnDestroyFoveationProfileFB(foveationProfile);
1708 qDebug(
"Fixed foveated rendering requested with level %d",
int(m_foveationLevel));
1712void QQuick3DXrManagerPrivate::createMetaQuestPassthrough()
1717 Q_ASSERT(m_passthroughSupported && m_enablePassthrough);
1719 PFN_xrCreatePassthroughFB pfnXrCreatePassthroughFBX =
nullptr;
1720 resolveXrFunction(
"xrCreatePassthroughFB", (PFN_xrVoidFunction*)(&pfnXrCreatePassthroughFBX));
1722 XrPassthroughCreateInfoFB passthroughCreateInfo{};
1723 passthroughCreateInfo.type = XR_TYPE_PASSTHROUGH_CREATE_INFO_FB;
1724 passthroughCreateInfo.flags = XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB;
1726 if (!checkXrResult(pfnXrCreatePassthroughFBX(m_session, &passthroughCreateInfo, &m_passthroughFeature)))
1727 qWarning(
"Failed to create passthrough object");
1730void QQuick3DXrManagerPrivate::destroyMetaQuestPassthrough()
1732 PFN_xrDestroyPassthroughFB pfnXrDestroyPassthroughFBX =
nullptr;
1733 resolveXrFunction(
"xrDestroyPassthroughFB", (PFN_xrVoidFunction*)(&pfnXrDestroyPassthroughFBX));
1735 if (!checkXrResult(pfnXrDestroyPassthroughFBX(m_passthroughFeature)))
1736 qWarning(
"Failed to destroy passthrough object");
1738 m_passthroughFeature = XR_NULL_HANDLE;
1741void QQuick3DXrManagerPrivate::startMetaQuestPassthrough()
1743 PFN_xrPassthroughStartFB pfnXrPassthroughStartFBX =
nullptr;
1744 resolveXrFunction(
"xrPassthroughStartFB", (PFN_xrVoidFunction*)(&pfnXrPassthroughStartFBX));
1746 if (!checkXrResult(pfnXrPassthroughStartFBX(m_passthroughFeature)))
1747 qWarning(
"Failed to start passthrough");
1750void QQuick3DXrManagerPrivate::pauseMetaQuestPassthrough()
1752 PFN_xrPassthroughPauseFB pfnXrPassthroughPauseFBX =
nullptr;
1753 resolveXrFunction(
"xrPassthroughPauseFB", (PFN_xrVoidFunction*)(&pfnXrPassthroughPauseFBX));
1755 if (!checkXrResult(pfnXrPassthroughPauseFBX(m_passthroughFeature)))
1756 qWarning(
"Failed to pause passthrough");
1759void QQuick3DXrManagerPrivate::createMetaQuestPassthroughLayer()
1761 PFN_xrCreatePassthroughLayerFB pfnXrCreatePassthroughLayerFBX =
nullptr;
1762 resolveXrFunction(
"xrCreatePassthroughLayerFB", (PFN_xrVoidFunction*)(&pfnXrCreatePassthroughLayerFBX));
1764 XrPassthroughLayerCreateInfoFB layerCreateInfo{};
1765 layerCreateInfo.type = XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB;
1766 layerCreateInfo.passthrough = m_passthroughFeature;
1767 layerCreateInfo.purpose = XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB;
1768 if (m_enablePassthrough)
1769 layerCreateInfo.flags = XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB;
1771 if (!checkXrResult(pfnXrCreatePassthroughLayerFBX(m_session, &layerCreateInfo, &m_passthroughLayer)))
1772 qWarning(
"Failed to create passthrough layer");
1775void QQuick3DXrManagerPrivate::destroyMetaQuestPassthroughLayer()
1777 PFN_xrDestroyPassthroughLayerFB pfnXrDestroyPassthroughLayerFBX =
nullptr;
1778 resolveXrFunction(
"xrDestroyPassthroughLayerFB", (PFN_xrVoidFunction*)(&pfnXrDestroyPassthroughLayerFBX));
1780 if (!checkXrResult(pfnXrDestroyPassthroughLayerFBX(m_passthroughLayer)))
1781 qWarning(
"Failed to destroy passthrough layer");
1783 m_passthroughLayer = XR_NULL_HANDLE;
1786void QQuick3DXrManagerPrivate::pauseMetaQuestPassthroughLayer()
1788 PFN_xrPassthroughLayerPauseFB pfnXrPassthroughLayerPauseFBX =
nullptr;
1789 resolveXrFunction(
"xrPassthroughLayerPauseFB", (PFN_xrVoidFunction*)(&pfnXrPassthroughLayerPauseFBX));
1791 if (!checkXrResult(pfnXrPassthroughLayerPauseFBX(m_passthroughLayer)))
1792 qWarning(
"Failed to pause passthrough layer");
1795void QQuick3DXrManagerPrivate::resumeMetaQuestPassthroughLayer()
1797 PFN_xrPassthroughLayerResumeFB pfnXrPassthroughLayerResumeFBX =
nullptr;
1798 resolveXrFunction(
"xrPassthroughLayerResumeFB", (PFN_xrVoidFunction*)(&pfnXrPassthroughLayerResumeFBX));
1800 if (!checkXrResult(pfnXrPassthroughLayerResumeFBX(m_passthroughLayer)))
1801 qWarning(
"Failed to resume passthrough layer");
1804void QQuick3DXrManagerPrivate::checkXrExtensions(
const char *layerName,
int indent)
1806 quint32 instanceExtensionCount;
1807 if (!checkXrResult(xrEnumerateInstanceExtensionProperties(layerName, 0, &instanceExtensionCount,
nullptr))) {
1808 qWarning(
"Failed to enumerate instance extension properties");
1812 QVector<XrExtensionProperties> extensions(instanceExtensionCount);
1813 for (XrExtensionProperties&
extension : extensions) {
1814 extension.type = XR_TYPE_EXTENSION_PROPERTIES;
1818 if (!checkXrResult(xrEnumerateInstanceExtensionProperties(layerName,
1820 &instanceExtensionCount,
1821 extensions.data())))
1823 qWarning(
"Failed to enumerate instance extension properties");
1827 qDebug(
"%sAvailable Extensions: (%d)", indentStr.data(), instanceExtensionCount);
1828 for (
const XrExtensionProperties&
extension : extensions) {
1829 qDebug(
"%s Name=%s Version=%d.%d.%d",
1832 XR_VERSION_MAJOR(
extension.extensionVersion),
1833 XR_VERSION_MINOR(
extension.extensionVersion),
1834 XR_VERSION_PATCH(
extension.extensionVersion));
1838void QQuick3DXrManagerPrivate::checkXrLayers()
1841 if (!checkXrResult(xrEnumerateApiLayerProperties(0, &layerCount,
nullptr))) {
1842 qWarning(
"Failed to enumerate API layer properties");
1846 QVector<XrApiLayerProperties>
layers(layerCount);
1848 layer.type = XR_TYPE_API_LAYER_PROPERTIES;
1849 layer.next =
nullptr;
1852 if (!checkXrResult(xrEnumerateApiLayerProperties(
quint32(
layers.size()), &layerCount,
layers.data()))) {
1853 qWarning(
"Failed to enumerate API layer properties");
1857 qDebug(
"Available Layers: (%d)", layerCount);
1858 for (
const XrApiLayerProperties&
layer :
layers) {
1859 qDebug(
" Name=%s SpecVersion=%d.%d.%d LayerVersion=%d.%d.%d Description=%s",
1861 XR_VERSION_MAJOR(
layer.specVersion),
1862 XR_VERSION_MINOR(
layer.specVersion),
1863 XR_VERSION_PATCH(
layer.specVersion),
1864 XR_VERSION_MAJOR(
layer.layerVersion),
1865 XR_VERSION_MINOR(
layer.layerVersion),
1866 XR_VERSION_PATCH(
layer.layerVersion),
1868 checkXrExtensions(
layer.layerName, 4);
1872XrResult QQuick3DXrManagerPrivate::createXrInstance()
1875 XrApplicationInfo appInfo;
1877 appInfo.applicationVersion = 7;
1879 appInfo.engineVersion = 6;
1880 appInfo.apiVersion = XR_CURRENT_API_VERSION;
1883 uint32_t apiLayerCount = 0;
1884 xrEnumerateApiLayerProperties(0, &apiLayerCount,
nullptr);
1885 QVector<XrApiLayerProperties> apiLayerProperties(apiLayerCount);
1886 for (uint32_t
i = 0;
i < apiLayerCount;
i++) {
1887 apiLayerProperties[
i].type = XR_TYPE_API_LAYER_PROPERTIES;
1888 apiLayerProperties[
i].next =
nullptr;
1890 xrEnumerateApiLayerProperties(apiLayerCount, &apiLayerCount, apiLayerProperties.data());
1893 QVector<const char*> enabledApiLayers;
1899 if (wantsValidationLayer) {
1901 enabledApiLayers.append(
"XR_APILAYER_LUNARG_core_validation");
1903 qDebug(
"OpenXR validation layer requested, but not available");
1906 qDebug() <<
"Requesting to enable XR API layers:" << enabledApiLayers;
1908 m_enabledApiLayers.clear();
1909 for (
const char *
layer : enabledApiLayers)
1913 uint32_t extensionCount = 0;
1914 xrEnumerateInstanceExtensionProperties(
nullptr, 0, &extensionCount,
nullptr);
1915 QVector<XrExtensionProperties> extensionProperties(extensionCount);
1916 for (uint32_t
i = 0;
i < extensionCount;
i++) {
1919 extensionProperties[
i].type = XR_TYPE_EXTENSION_PROPERTIES;
1920 extensionProperties[
i].next =
nullptr;
1922 xrEnumerateInstanceExtensionProperties(
nullptr, extensionCount, &extensionCount, extensionProperties.data());
1934 m_handtrackingExtensionSupported =
isExtensionSupported(XR_EXT_HAND_TRACKING_EXTENSION_NAME, extensionProperties);
1935 if (m_handtrackingExtensionSupported)
1938 m_compositionLayerDepthSupported =
isExtensionSupported(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME, extensionProperties);
1939 if (m_compositionLayerDepthSupported) {
1944 if (m_submitLayerDepth)
1945 qDebug(
"submitLayerDepth defaults to true due to env.var.");
1947 m_submitLayerDepth =
false;
1952 m_handtrackingAimExtensionSupported =
isExtensionSupported(XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME, extensionProperties);
1953 if (m_handtrackingAimExtensionSupported)
1964 uint32_t passthroughSpecVersion = 0;
1965 m_passthroughSupported =
isExtensionSupported(XR_FB_PASSTHROUGH_EXTENSION_NAME, extensionProperties, &passthroughSpecVersion);
1966 if (m_passthroughSupported) {
1967 qDebug(
"Passthrough extension is supported, spec version %u", passthroughSpecVersion);
1970 qDebug(
"Passthrough extension is NOT supported");
1976 m_displayRefreshRateExtensionSupported =
isExtensionSupported(XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME, extensionProperties);
1977 if (m_displayRefreshRateExtensionSupported)
1980 m_colorspaceExtensionSupported =
isExtensionSupported(XR_FB_COLOR_SPACE_EXTENSION_NAME, extensionProperties);
1981 if (m_colorspaceExtensionSupported)
1987 m_foveationExtensionSupported =
isExtensionSupported(XR_FB_FOVEATION_EXTENSION_NAME, extensionProperties);
1988 if (m_foveationExtensionSupported)
1994 if (m_spaceExtension) {
1997 for (
const auto extension : requiredExtensions) {
2011 m_androidCreateInstanceExtensionSupported =
isExtensionSupported(XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME, extensionProperties);
2012 if (m_androidCreateInstanceExtensionSupported)
2015 auto graphicsAPI = QQuickWindow::graphicsApi();
2017 if (
isExtensionSupported(XR_FB_SWAPCHAIN_UPDATE_STATE_VULKAN_EXTENSION_NAME, extensionProperties))
2020 if (
isExtensionSupported(XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME, extensionProperties))
2021 enabledExtensions.append(XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME);
2027 m_enabledExtensions.clear();
2032 XrInstanceCreateInfo xrInstanceInfo{};
2033 xrInstanceInfo.type = XR_TYPE_INSTANCE_CREATE_INFO;
2036 XrInstanceCreateInfoAndroidKHR xrInstanceCreateInfoAndroid {};
2037 if (m_androidCreateInstanceExtensionSupported) {
2038 xrInstanceCreateInfoAndroid.type = XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR;
2039 xrInstanceCreateInfoAndroid.applicationVM =
m_javaVM;
2040 xrInstanceCreateInfoAndroid.applicationActivity = m_androidActivity.object();
2042 xrInstanceInfo.next = &xrInstanceCreateInfoAndroid;
2047 xrInstanceInfo.createFlags = 0;
2048 xrInstanceInfo.applicationInfo = appInfo;
2049 xrInstanceInfo.enabledApiLayerCount = enabledApiLayers.count();
2050 xrInstanceInfo.enabledApiLayerNames = enabledApiLayers.constData();
2054 return xrCreateInstance(&xrInstanceInfo, &m_instance);
2057void QQuick3DXrManagerPrivate::checkXrInstance()
2059 Q_ASSERT(m_instance != XR_NULL_HANDLE);
2060 XrInstanceProperties instanceProperties{};
2061 instanceProperties.type = XR_TYPE_INSTANCE_PROPERTIES;
2062 if (!checkXrResult(xrGetInstanceProperties(m_instance, &instanceProperties))) {
2063 qWarning(
"Failed to get instance properties");
2068 m_runtimeVersion =
QVersionNumber(XR_VERSION_MAJOR(instanceProperties.runtimeVersion),
2069 XR_VERSION_MINOR(instanceProperties.runtimeVersion),
2070 XR_VERSION_PATCH(instanceProperties.runtimeVersion));
2072 qDebug(
"Instance RuntimeName=%s RuntimeVersion=%d.%d.%d",
2079void QQuick3DXrManagerPrivate::setupDebugMessenger()
2082 qDebug(
"Quick 3D XR: No debug utils extension, message redirection not set up");
2086#ifdef XR_EXT_debug_utils
2087 PFN_xrCreateDebugUtilsMessengerEXT xrCreateDebugUtilsMessengerEXT =
nullptr;
2088 resolveXrFunction(
"xrCreateDebugUtilsMessengerEXT",
reinterpret_cast<PFN_xrVoidFunction *
>(&xrCreateDebugUtilsMessengerEXT));
2089 if (!xrCreateDebugUtilsMessengerEXT)
2092 resolveXrFunction(
"xrDestroyDebugUtilsMessengerEXT",
reinterpret_cast<PFN_xrVoidFunction *
>(&m_xrDestroyDebugUtilsMessengerEXT));
2094 XrDebugUtilsMessengerCreateInfoEXT messengerInfo = {};
2095 messengerInfo.type = XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
2096 messengerInfo.messageSeverities = XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
2097 | XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
2098 messengerInfo.messageTypes = XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
2099 | XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
2100 | XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT
2101 | XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT;
2102 messengerInfo.userCallback = defaultDebugCallbackFunc;
2103 messengerInfo.userData =
this;
2105 XrResult err = xrCreateDebugUtilsMessengerEXT(m_instance, &messengerInfo, &m_debugMessenger);
2106 if (!checkXrResult(err))
2107 qWarning(
"Quick 3D XR: Failed to create debug report callback, OpenXR messages will not get redirected (%d)", err);
2111XrResult QQuick3DXrManagerPrivate::initializeSystem()
2113 Q_ASSERT(m_instance != XR_NULL_HANDLE);
2114 Q_ASSERT(m_systemId == XR_NULL_SYSTEM_ID);
2116 XrSystemGetInfo hmdInfo{};
2117 hmdInfo.type = XR_TYPE_SYSTEM_GET_INFO;
2118 hmdInfo.next =
nullptr;
2119 hmdInfo.formFactor = m_formFactor;
2121 const XrResult
result = xrGetSystem(m_instance, &hmdInfo, &m_systemId);
2122 const bool success = checkXrResult(
result);
2128 checkViewConfiguration();
2133void QQuick3DXrManagerPrivate::checkViewConfiguration()
2136 if (!checkXrResult(xrEnumerateViewConfigurations(m_instance,
2139 &viewConfigTypeCount,
2142 qWarning(
"Failed to enumerate view configurations");
2145 QVector<XrViewConfigurationType> viewConfigTypes(viewConfigTypeCount);
2146 if (!checkXrResult(xrEnumerateViewConfigurations(m_instance,
2148 viewConfigTypeCount,
2149 &viewConfigTypeCount,
2150 viewConfigTypes.data())))
2152 qWarning(
"Failed to enumerate view configurations");
2156 qDebug(
"Available View Configuration Types: (%d)", viewConfigTypeCount);
2157 for (XrViewConfigurationType viewConfigType : viewConfigTypes) {
2158 qDebug(
" View Configuration Type: %s %s", to_string(viewConfigType), viewConfigType == m_viewConfigType ?
"(Selected)" :
"");
2159 XrViewConfigurationProperties viewConfigProperties{};
2160 viewConfigProperties.type = XR_TYPE_VIEW_CONFIGURATION_PROPERTIES;
2161 if (!checkXrResult(xrGetViewConfigurationProperties(m_instance,
2164 &viewConfigProperties)))
2166 qWarning(
"Failed to get view configuration properties");
2170 qDebug(
" View configuration FovMutable=%s", viewConfigProperties.fovMutable == XR_TRUE ?
"True" :
"False");
2173 if (!checkXrResult(xrEnumerateViewConfigurationViews(m_instance,
2180 qWarning(
"Failed to enumerate configuration views");
2184 if (viewCount > 0) {
2185 QVector<XrViewConfigurationView> views(viewCount, {XR_TYPE_VIEW_CONFIGURATION_VIEW,
nullptr, 0, 0, 0, 0, 0, 0});
2186 if (!checkXrResult(xrEnumerateViewConfigurationViews(m_instance,
2193 qWarning(
"Failed to enumerate configuration views");
2197 for (
int i = 0;
i < views.size(); ++
i) {
2198 const XrViewConfigurationView&
view = views[
i];
2199 qDebug(
" View [%d]: Recommended Width=%d Height=%d SampleCount=%d",
2201 view.recommendedImageRectWidth,
2202 view.recommendedImageRectHeight,
2203 view.recommendedSwapchainSampleCount);
2204 qDebug(
" View [%d]: Maximum Width=%d Height=%d SampleCount=%d",
2206 view.maxImageRectWidth,
2207 view.maxImageRectHeight,
2208 view.maxSwapchainSampleCount);
2211 qDebug(
"Empty view configuration type");
2213 checkEnvironmentBlendMode(viewConfigType);
2217bool QQuick3DXrManagerPrivate::checkXrResult(
const XrResult &
result)
2222bool QQuick3DXrManagerPrivate::resolveXrFunction(
const char *
name, PFN_xrVoidFunction *function)
2224 XrResult
result = xrGetInstanceProcAddr(m_instance,
name, function);
2226 qWarning(
"Failed to resolve OpenXR function %s",
name);
2227 *function =
nullptr;
2233void QQuick3DXrManagerPrivate::checkEnvironmentBlendMode(XrViewConfigurationType
type)
2236 if (!checkXrResult(xrEnumerateEnvironmentBlendModes(m_instance,
2243 qWarning(
"Failed to enumerate blend modes");
2247 qDebug(
"Available Environment Blend Mode count : (%d)",
count);
2249 QVector<XrEnvironmentBlendMode> blendModes(
count);
2250 if (!checkXrResult(xrEnumerateEnvironmentBlendModes(m_instance,
2255 blendModes.data())))
2257 qWarning(
"Failed to enumerate blend modes");
2261 bool blendModeFound =
false;
2262 for (XrEnvironmentBlendMode
mode : blendModes) {
2263 const bool blendModeMatch = (
mode == m_environmentBlendMode);
2264 qDebug(
"Environment Blend Mode (%s) : %s", to_string(
mode), blendModeMatch ?
"(Selected)" :
"");
2265 blendModeFound |= blendModeMatch;
2267 if (!blendModeFound)
2268 qWarning(
"No matching environment blend mode found");
static QT_BEGIN_NAMESPACE JavaVM * m_javaVM
virtual bool finializeGraphics(QRhi *rhi)=0
virtual bool isExtensionSupported(const QVector< XrExtensionProperties > &extensions) const =0
virtual void releaseResources()
virtual QRhi * rhi() const =0
virtual const char * extensionName() const =0
virtual const XrBaseInStructure * handle() const =0
virtual bool setupGraphics(const XrInstance &instance, XrSystemId &systemId, const QQuickGraphicsConfiguration &quickConfig)=0
virtual void setupWindow(QQuickWindow *)
virtual QQuickRenderTarget renderTarget(const XrSwapchainSubImage &subImage, const XrSwapchainImageBaseHeader *swapchainImage, quint64 swapchainFormat, int samples, int arraySize, const XrSwapchainImageBaseHeader *depthSwapchainImage, quint64 depthSwapchainFormat) const =0
virtual int64_t depthSwapchainFormat(const QVector< int64_t > &swapchainFormats) const =0
virtual int64_t colorSwapchainFormat(const QVector< int64_t > &swapchainFormats) const =0
virtual QVector< XrSwapchainImageBaseHeader * > allocateSwapchainImages(int count, XrSwapchain swapchain)=0
QString applicationName
the name of this application
The QQuaternion class represents a quaternion consisting of a vector and scalar.
void setRotation(const QQuaternion &rotation)
void setPosition(const QVector3D &position)
static QQuick3DXrAnchorManager * instance()
QList< const char * > requiredExtensions() const
void updateAnchors(XrTime predictedDisplayTime, XrSpace appSpace)
void handleEvent(const XrEventDataBaseHeader *event)
void initialize(XrInstance instance, XrSession session)
QQuick3DXrManagerPrivate(QQuick3DXrManager &manager)
void setupWindow(QQuickWindow *window)
bool finalizeGraphics(QRhi *rhi)
QVersionNumber runtimeVersion() const
QtQuick3DXr::ReferenceSpace getReferenceSpace() const
void setReferenceSpace(QtQuick3DXr::ReferenceSpace newReferenceSpace)
QStringList enabledExtensions() const
~QQuick3DXrManagerPrivate()
bool supportsPassthrough() const
bool isMultiViewRenderingSupported() const
bool setupGraphics(QQuickWindow *window)
void setDepthSubmissionEnabled(bool enable)
static QQuick3DXrManagerPrivate * get(QQuick3DXrManager *manager)
void setSamples(int samples)
bool isGraphicsInitialized() const
void setMultiviewRenderingEnabled(bool enable)
QString runtimeName() const
void setPassthroughEnabled(bool enable)
QQuick3DXrCamera * camera
static QQuickWindowPrivate * get(QQuickWindow *c)
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
QRhiTexture * texture() const
virtual Type resourceType() const =0
const QRhiColorAttachment * colorAttachmentAt(qsizetype index) const
QRhiTextureRenderTargetDescription description() const
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
bool isFeatureSupported(QRhi::Feature feature) const
const char * backendName() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray toUtf8() const &
The QVector3D class represents a vector or vertex in 3D space.
int minorVersion() const noexcept
Returns the minor version number, that is, the second segment.
int majorVersion() const noexcept
Returns the major version number, that is, the first segment.
Q_CORE_EXPORT QString toString() const
Returns a string with all of the segments delimited by a period ({.}).
int microVersion() const noexcept
Returns the micro version number, that is, the third segment.
list append(new Employee("Blackpool", "Stephen"))
bool checkXrResult(XrResult result, XrInstance instance)
QString getXrResultAsString(XrResult result, XrInstance instance)
Combined button and popup list for selecting options.
int toUtf8(char16_t u, OutputPtr &dst, InputPtr &src, InputPtr end)
@ ReferenceSpaceLocalFloor
const EGLAttrib EGLOutputLayerEXT * layers
GLuint64 GLenum void * handle
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum format
GLdouble GLdouble GLdouble GLdouble q
#define MAKE_TO_STRING_FUNC(enumType)
static bool isApiLayerSupported(const char *layerName, const QVector< XrApiLayerProperties > &apiLayerProperties)
static QtQuick3DXr::ReferenceSpace getReferenceSpaceType(XrReferenceSpaceType referenceSpace)
static XrReferenceSpaceType getXrReferenceSpaceType(QtQuick3DXr::ReferenceSpace referenceSpace)
static bool isExtensionSupported(const char *extensionName, const QVector< XrExtensionProperties > &instanceExtensionProperties, uint32_t *extensionVersion=nullptr)
#define QSSG_ASSERT(cond, action)
#define qPrintable(string)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
QNetworkAccessManager manager