@@ -320,82 +320,6 @@ static XrResult xrGetInstanceProcAddr(
320320 return XR_ERROR_FUNCTION_UNSUPPORTED;
321321}
322322
323- static void EnumerateExtensions (OpenXRNext* oxr) {
324- uint32_t extensionCount = 0 ;
325-
326- auto nextResult = oxr->xrEnumerateInstanceExtensionProperties (
327- nullptr , 0 , &extensionCount, nullptr );
328-
329- // Workaround for Meta Link PTC as of 2024-07-22:
330- //
331- // XR_ERROR_SIZE_SUFFICIENT should *never* be returned for a buffer size of 0:
332- // https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#buffer-size-parameters
333- const auto workAroundNonConformantImplementations
334- = Config::Quirk_Conformance_ExtensionCount
335- && (nextResult == XR_ERROR_SIZE_INSUFFICIENT) && (extensionCount > 0 );
336- if (workAroundNonConformantImplementations) {
337- DebugPrint (
338- " Buggy OpenXR runtime or other API layer; ignoring incorrect "
339- " XR_ERROR_SIZE_INSUFFICIENT response from "
340- " xrEnumerateInstanceExtensionProperties(nulllptr, 0, &count, nullptr)" );
341- }
342- if (nextResult != XR_SUCCESS && !workAroundNonConformantImplementations) {
343- DebugPrint (" Getting extension count failed: {}" , nextResult);
344- return ;
345- }
346-
347- if (extensionCount == 0 ) {
348- DebugPrint (
349- " Runtime supports no extensions, so definitely doesn't support hand "
350- " tracking. Reporting success but doing nothing." );
351- return ;
352- }
353-
354- std::vector<XrExtensionProperties> extensions (
355- extensionCount, XrExtensionProperties {XR_TYPE_EXTENSION_PROPERTIES});
356- nextResult = oxr->xrEnumerateInstanceExtensionProperties (
357- nullptr , extensionCount, &extensionCount, extensions.data ());
358- if (nextResult != XR_SUCCESS) {
359- DebugPrint (" Enumerating extensions failed: {}" , nextResult);
360- return ;
361- }
362-
363- for (const auto & it: extensions) {
364- const std::string_view name {it.extensionName };
365- if (Config::VerboseDebug) {
366- DebugPrint (" Found {}" , name);
367- }
368-
369- if (name == XR_EXT_HAND_TRACKING_EXTENSION_NAME) {
370- Environment::Have_XR_EXT_HandTracking = true ;
371- continue ;
372- }
373- if (
374- name == XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME
375- && Config::EnableFBOpenXRExtensions) {
376- Environment::Have_XR_FB_HandTracking_Aim = true ;
377- continue ;
378- }
379- if (name == XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME) {
380- Environment::Have_XR_KHR_win32_convert_performance_counter_time = true ;
381- continue ;
382- }
383- }
384-
385- DebugPrint (
386- " {}: {}" ,
387- XR_EXT_HAND_TRACKING_EXTENSION_NAME,
388- Environment::Have_XR_EXT_HandTracking);
389- DebugPrint (
390- " {}: {}" ,
391- XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME,
392- Environment::Have_XR_FB_HandTracking_Aim);
393- DebugPrint (
394- " {}: {}" ,
395- XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME,
396- Environment::Have_XR_KHR_win32_convert_performance_counter_time);
397- }
398-
399323static XrResult xrCreateApiLayerInstance (
400324 const XrInstanceCreateInfo* originalInfo,
401325 const struct XrApiLayerCreateInfo * layerInfo,
@@ -414,97 +338,97 @@ static XrResult xrCreateApiLayerInstance(
414338
415339 // TODO: check version fields etc in layerInfo
416340
417- XrInstance dummyInstance {};
418- {
419- // While the OpenXR specification says that
420- // `xrEnumerateInstanceExtensionProperties()` does not require an
421- // `XrInstance`, if there is a 'next' API layer, it will not be able to
422- // retrieve the extension list from the runtime or an n+2 API layer unless
423- // an instance has been created, as it won't have the next
424- // `xrGetInstanceProcAddr()` pointer yet.
425- XrInstanceCreateInfo dummyInfo {
426- .type = XR_TYPE_INSTANCE_CREATE_INFO,
427- .applicationInfo = {
428- .applicationVersion = originalInfo->applicationInfo .applicationVersion ,
429- .engineName = " FREDEMMOTT_HTCC" ,
430- .engineVersion = 1 ,
431- .apiVersion = XR_CURRENT_API_VERSION,
432- },
433- };
434- {
435- auto [it, count] = std::format_to_n (
436- dummyInfo.applicationInfo .applicationName ,
437- XR_MAX_APPLICATION_NAME_SIZE - 1 ,
438- " FREDEMMOTT_HTCC Init: {}" ,
439- originalInfo->applicationInfo .applicationName );
440- *it = ' \0 ' ;
441- }
442- auto dummyLayerInfo = *layerInfo;
443- dummyLayerInfo.nextInfo = dummyLayerInfo.nextInfo ->next ;
444- layerInfo->nextInfo ->nextCreateApiLayerInstance (
445- &dummyInfo, &dummyLayerInfo, &dummyInstance);
446- }
447-
448- OpenXRNext next (dummyInstance, layerInfo->nextInfo ->nextGetInstanceProcAddr );
449-
450341 XrInstanceCreateInfo info {XR_TYPE_INSTANCE_CREATE_INFO};
451342 if (originalInfo) {
452343 info = *originalInfo;
453344 }
454345
455346 std::vector<const char *> enabledExtensions;
456347 if (Config::Enabled) {
457- EnumerateExtensions (&next);
458- if (Environment::Have_XR_EXT_HandTracking) {
459- DebugPrint (" Original extensions:" );
460- for (auto i = 0 ; i < originalInfo->enabledExtensionCount ; ++i) {
461- DebugPrint (" - {}" , originalInfo->enabledExtensionNames [i]);
462- enabledExtensions.push_back (originalInfo->enabledExtensionNames [i]);
463- }
464-
465- enabledExtensions.push_back (XR_EXT_HAND_TRACKING_EXTENSION_NAME);
466- // We need 'real time' units to rotate the hand at a known speed for
467- // MSFS
468- if (Environment::Have_XR_KHR_win32_convert_performance_counter_time) {
469- enabledExtensions.push_back (
470- XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME);
471- }
472- // Required for enhanced pinch gestures on Quest
473- if (Environment::Have_XR_FB_HandTracking_Aim) {
474- enabledExtensions.push_back (XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME);
475- }
476-
477- {
478- auto last
479- = std::unique (enabledExtensions.begin (), enabledExtensions.end ());
480- enabledExtensions.erase (last, enabledExtensions.end ());
481- }
482-
483- DebugPrint (" Requesting extensions:" );
484- for (const auto & ext: enabledExtensions) {
485- DebugPrint (" - {}" , ext);
486- }
487-
488- info.enabledExtensionCount = enabledExtensions.size ();
489- info.enabledExtensionNames = enabledExtensions.data ();
348+ DebugPrint (" Original extensions:" );
349+ for (auto i = 0 ; i < originalInfo->enabledExtensionCount ; ++i) {
350+ DebugPrint (" - {}" , originalInfo->enabledExtensionNames [i]);
351+ enabledExtensions.push_back (originalInfo->enabledExtensionNames [i]);
352+ }
353+
354+ enabledExtensions.push_back (
355+ XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME);
356+ enabledExtensions.push_back (XR_EXT_HAND_TRACKING_EXTENSION_NAME);
357+ enabledExtensions.push_back (XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME);
358+
359+ {
360+ auto last
361+ = std::unique (enabledExtensions.begin (), enabledExtensions.end ());
362+ enabledExtensions.erase (last, enabledExtensions.end ());
490363 }
364+
365+ DebugPrint (" Requesting extensions:" );
366+ for (const auto & ext: enabledExtensions) {
367+ DebugPrint (" - {}" , ext);
368+ }
369+
370+ info.enabledExtensionCount = enabledExtensions.size ();
371+ info.enabledExtensionNames = enabledExtensions.data ();
491372 }
492- next.check_xrDestroyInstance (dummyInstance);
493373
494374 XrApiLayerCreateInfo nextLayerInfo = *layerInfo;
495375 nextLayerInfo.nextInfo = layerInfo->nextInfo ->next ;
496376
497- auto nextResult = layerInfo->nextInfo ->nextCreateApiLayerInstance (
498- &info, &nextLayerInfo, instance);
499- if (nextResult != XR_SUCCESS) {
500- DebugPrint (" Next failed." );
501- return nextResult;
377+ // // Attempt 1: all 3 extensions
378+ {
379+ const auto nextResult = layerInfo->nextInfo ->nextCreateApiLayerInstance (
380+ &info, &nextLayerInfo, instance);
381+ if (XR_SUCCEEDED (nextResult)) {
382+ Environment::Have_XR_EXT_HandTracking = true ;
383+ Environment::Have_XR_FB_HandTracking_Aim = true ;
384+ gNext = std::make_shared<OpenXRNext>(
385+ *instance, layerInfo->nextInfo ->nextGetInstanceProcAddr );
386+ DebugPrint (" Initialized with all extensions" );
387+ return nextResult;
388+ }
389+
390+ if (nextResult != XR_ERROR_EXTENSION_NOT_PRESENT) {
391+ DebugPrint (" all-in xrCreateApiLayerInstance failed: {}" , nextResult);
392+ return nextResult;
393+ }
502394 }
503395
504- gNext = std::make_shared<OpenXRNext>(
505- *instance, layerInfo->nextInfo ->nextGetInstanceProcAddr );
396+ // /// Attempt 2: without XR_FB_hand_tracking_aim
397+ enabledExtensions.erase (
398+ std::ranges::find (
399+ enabledExtensions, XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME));
400+ info.enabledExtensionCount = enabledExtensions.size ();
401+ info.enabledExtensionNames = enabledExtensions.data ();
402+ {
403+ const auto nextResult = layerInfo->nextInfo ->nextCreateApiLayerInstance (
404+ &info, &nextLayerInfo, instance);
405+ if (XR_SUCCEEDED (nextResult)) {
406+ Environment::Have_XR_EXT_HandTracking = true ;
407+ Environment::Have_XR_FB_HandTracking_Aim = false ;
408+ gNext = std::make_shared<OpenXRNext>(
409+ *instance, layerInfo->nextInfo ->nextGetInstanceProcAddr );
410+ DebugPrint (
411+ " Initialized without {}" , XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME);
412+ return nextResult;
413+ }
414+
415+ if (nextResult != XR_ERROR_EXTENSION_NOT_PRESENT) {
416+ DebugPrint (
417+ " bare-minimum xrCreateApiLayerInstance failed: {}" , nextResult);
418+ return nextResult;
419+ }
420+ }
506421
507- return XR_SUCCESS;
422+ // /// Attempt 3: nope, no hand tracking. Just pass through.
423+ const auto nextResult = layerInfo->nextInfo ->nextCreateApiLayerInstance (
424+ originalInfo, &nextLayerInfo, instance);
425+ if (XR_SUCCEEDED (nextResult)) {
426+ DebugPrint (" No-op passthrough xrCreateAPILayerInstance succeeded" );
427+ } else {
428+ DebugPrint (
429+ " No-op passthrough xrCreateApiLayerInstance failed: {}" , nextResult);
430+ }
431+ return nextResult;
508432}
509433
510434}// namespace HandTrackedCockpitClicking::Loader
0 commit comments