XR_EXT_spatial_persistence

Name String

XR_EXT_spatial_persistence

Type d'extension

Extension d'instance

Numéro d'extension enregistré

764

Révision

1

État de la ratification

Ratifié

Dépendances d'extension et de version

XR_EXT_spatial_entity
et
XR_EXT_future

Participants

Nihav Jain, Google
Jared Finder, Google
Natalie Fleury, Meta
Yuichi Taguchi, Meta
Ron Bessems, Meta
Yin Li, Microsoft
Jimmy Alamparambil, ByteDance
Zhipeng Liu, ByteDance
Jun Yan, ByteDance

Présentation

Cette extension permet aux applications de découvrir et de mettre en corrélation des entités spatiales entre les sessions d'application, les sessions OpenXR et plusieurs contextes spatiaux OpenXR au cours d'une session. L'extension XR_EXT_spatial_entity établit qu'une entité dans un XrSpatialContextEXT est représentée par un XrSpatialEntityIdEXT . Cette extension s'appuie sur ce concept en établissant qu'une entité, si elle est conservée, est représentée par un XrUuid dans les sessions d'application et OpenXR. Autrement dit, une application peut utiliser le XrUuid fourni par cette extension pour identifier une entité dans plusieurs sessions. Cette extension fournit également des chevauchements utiles avec l'extension XR_EXT_spatial_entity pour découvrir les entités persistantes dans l'environnement de l'utilisateur et la possibilité d'interroger leurs données de composant.

Contexte de persistance spatiale

Créer un contexte de persistance spatiale

XR_DEFINE_HANDLE(XrSpatialPersistenceContextEXT)

Le handle XrSpatialPersistenceContextEXT représente la connexion à un espace de stockage d'entités spatiales persistant.

La fonction xrCreateSpatialPersistenceContextAsyncEXT est définie comme suit :

XrResult xrCreateSpatialPersistenceContextAsyncEXT(
    XrSession                                   session,
    const XrSpatialPersistenceContextCreateInfoEXT* createInfo,
    XrFutureEXT*                                future);

Description des paramètres

  • session est une XrSession dans laquelle le contexte de persistance spatiale sera actif.
  • createInfo est le XrSpatialPersistenceContextCreateInfoEXT utilisé pour spécifier les paramètres de contexte de persistance spatiale.
  • future est un pointeur vers un XrFutureEXT .

Une application peut créer un handle XrSpatialPersistenceContextEXT à l'aide de la fonction xrCreateSpatialPersistenceContextAsyncEXT et configurer le champ d'application du contexte de persistance dans createInfo .

L'environnement d'exécution doit renvoyer XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT si XrSpatialPersistenceContextCreateInfoEXT :: scope n'est pas énuméré par xrEnumerateSpatialPersistenceScopesEXT .

Si un environnement d'exécution applique un système d'autorisation pour contrôler l'accès de l'application au stockage persistant représenté par XrSpatialPersistenceContextEXT , il doit renvoyer XR_ERROR_PERMISSION_INSUFFICIENT si ces autorisations n'ont pas été accordées à cette application.

Utilisation valide (implicite)

Codes renvoyés

Opération réussie

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Échec

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_LIMIT_REACHED
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT
  • XR_ERROR_VALIDATION_FAILURE

La structure XrSpatialPersistenceContextCreateInfoEXT est définie comme suit :

typedef struct XrSpatialPersistenceContextCreateInfoEXT {
    XrStructureType                 type;
    const void*                     next;
    XrSpatialPersistenceScopeEXT    scope;
} XrSpatialPersistenceContextCreateInfoEXT;

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures. Aucune structure de ce type n'est définie dans OpenXR de base ou dans cette extension.
  • scope est un XrSpatialPersistenceScopeEXT définissant le champ d'application du stockage du contexte de persistance.

La structure XrSpatialPersistenceContextCreateInfoEXT décrit les informations permettant de créer un handle XrSpatialPersistenceContextEXT.

Utilisation valide (implicite)

typedef enum XrSpatialPersistenceScopeEXT {
    XR_SPATIAL_PERSISTENCE_SCOPE_SYSTEM_MANAGED_EXT = 1,
    XR_SPATIAL_PERSISTENCE_SCOPE_LOCAL_ANCHORS_EXT = 1000781000,
    XR_SPATIAL_PERSISTENCE_SCOPE_ANCHORS_FOR_CLOUD_SHARING_ANDROIDX1 = 1000808000,
    XR_SPATIAL_PERSISTENCE_SCOPE_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialPersistenceScopeEXT;

L'énumération XrSpatialPersistenceScopeEXT identifie les différents types de champs d'application du contexte de persistance.

Les énumérations ont les significations suivantes :

Description de l'enum

XR_SPATIAL_PERSISTENCE_SCOPE_SYSTEM_MANAGED_EXT

Fournit à l'application un accès en lecture seule (c'est-à-dire que l'application ne peut pas modifier le magasin associé à ce champ d'application) aux entités spatiales conservées et gérées par le système. L'application peut utiliser l'UUID dans le composant de persistance pour ce champ d'application afin de mettre en corrélation les entités dans différents contextes spatiaux et redémarrages de l'appareil.

XR_SPATIAL_PERSISTENCE_SCOPE_LOCAL_ANCHORS_EXT

Les opérations de persistance et l'accès aux données sont limités aux ancres spatiales, sur le même appareil, pour le même utilisateur et la même application (ajouté par l'extension XR_EXT_spatial_persistence_operations).

XR_SPATIAL_PERSISTENCE_SCOPE_ANCHORS_FOR_CLOUD_SHARING_ANDROIDX1

Les opérations de persistance et l'accès aux données sont limités aux ancres spatiales, détenues et gérées par le même projet cloud. (Ajouté par l'extension XR_ANDROIDX1_spatial_anchor_cloud_sharing)

La fonction xrEnumerateSpatialPersistenceScopesEXT est définie comme suit :

XrResult xrEnumerateSpatialPersistenceScopesEXT(
    XrInstance                                  instance,
    XrSystemId                                  systemId,
    uint32_t                                    persistenceScopeCapacityInput,
    uint32_t*                                   persistenceScopeCountOutput,
    XrSpatialPersistenceScopeEXT*               persistenceScopes);

Description des paramètres

  • instance est un handle vers un XrInstance .
  • systemId est l'XrSystemId dont les champs d'application de persistance spatiale seront énumérés.
  • persistenceScopeCapacityInput est la capacité du tableau persistenceScopes, ou 0 pour indiquer une requête de récupération de la capacité requise.
  • persistenceScopeCountOutput est le nombre de champs d'application de persistance ou la capacité requise si persistenceScopeCapacityInput est insuffisant.
  • persistenceScopes est un tableau de XrSpatialPersistenceScopeEXT . Il peut être NULL si persistenceScopeCapacityInput est égal à 0.
  • Consultez le chapitre Paramètres de taille de la mémoire tampon pour obtenir une description détaillée de la récupération de la taille persistenceScopes requise.

L'application peut énumérer la liste des champs d'application de persistance spatiale compatibles avec un XrSystemId donné à l'aide de xrEnumerateSpatialPersistenceScopesEXT .

Utilisation valide (implicite)

  • L'extension XR_EXT_spatial_persistence doit être activée avant d'appeler xrEnumerateSpatialPersistenceScopesEXT.
  • instance doit être un handle XrInstance valide
  • persistenceScopeCountOutput doit être un pointeur vers une valeur uint32_t
  • Si persistenceScopeCapacityInput n'est pas 0 , persistenceScopes doit être un pointeur vers un tableau de valeurs persistenceScopeCapacityInput XrSpatialPersistenceScopeEXT.

Codes renvoyés

Opération réussie

  • XR_SUCCESS

Échec

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SIZE_INSUFFICIENT
  • XR_ERROR_SYSTEM_INVALID
  • XR_ERROR_VALIDATION_FAILURE

La fonction xrCreateSpatialPersistenceContextCompleteEXT est définie comme suit :

XrResult xrCreateSpatialPersistenceContextCompleteEXT(
    XrSession                                   session,
    XrFutureEXT                                 future,
    XrCreateSpatialPersistenceContextCompletionEXT* completion);

Description des paramètres

xrCreateSpatialPersistenceContextCompleteEXT termine l'opération asynchrone lancée par xrCreateSpatialPersistenceContextAsyncEXT . L'environnement d'exécution doit renvoyer XR_ERROR_FUTURE_PENDING_EXT si future n'est pas à l'état prêt. L'environnement d'exécution doit renvoyer XR_ERROR_FUTURE_INVALID_EXT si future a déjà été terminé ou annulé.

Utilisation valide (implicite)

Codes renvoyés

Opération réussie

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Échec

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_FUTURE_INVALID_EXT
  • XR_ERROR_FUTURE_PENDING_EXT
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_LIMIT_REACHED
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_VALIDATION_FAILURE

La structure XrCreateSpatialPersistenceContextCompletionEXT est définie comme suit :

typedef struct XrCreateSpatialPersistenceContextCompletionEXT {
    XrStructureType                         type;
    void*                                   next;
    XrResult                                futureResult;
    XrSpatialPersistenceContextResultEXT    createResult;
    XrSpatialPersistenceContextEXT          persistenceContext;
} XrCreateSpatialPersistenceContextCompletionEXT;

Descriptions des membres

Codes de retour futurs

Valeurs de futureResult :

Opération réussie

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Échec

  • XR_ERROR_RUNTIME_FAILURE
  • XR_ERROR_INSTANCE_LOST
  • XR_ERROR_SESSION_LOST
  • XR_ERROR_OUT_OF_MEMORY
  • XR_ERROR_LIMIT_REACHED
  • XR_ERROR_PERMISSION_INSUFFICIENT

Si futureResult et createResult sont tous deux des codes de réussite, persistenceContext doit être valide. Si persistenceContext est valide, il doit le rester pendant le cycle de vie de xrCreateSpatialPersistenceContextAsyncEXT :: session ou jusqu'à ce que l'application utilise xrDestroySpatialPersistenceContextEXT avec persistenceContext , selon la première occurrence.

L'environnement d'exécution doit définir createResult uniquement si futureResult est un code de réussite.

Utilisation valide (implicite)

typedef enum XrSpatialPersistenceContextResultEXT {
    XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_SUCCESS_EXT = 0,
    XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_ENTITY_NOT_TRACKING_EXT = -1000781001,
    XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_PERSIST_UUID_NOT_FOUND_EXT = -1000781002,
    XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_LOCALIZATION_FAILURE_ANDROIDX1 = -1000808000,
    XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_MAP_FEATURE_INSUFFICIENT_ANDROIDX1 = -1000808001,
    XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_NETWORK_FAILURE_ANDROIDX1 = -1000808002,
    XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_NETWORK_TIMEOUT_ANDROIDX1 = -1000808003,
    XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialPersistenceContextResultEXT;

L'énumération XrSpatialPersistenceContextResultEXT identifie les différents types de codes de résultat pour une opération de persistance. Les échecs lors des opérations de persistance ne sont pas toujours contrôlés par l'application, et cette énumération est utilisée pour signaler ces cas. Comme pour XrResult , les codes de réussite de l'énumération XrSpatialPersistenceContextResultEXT sont des valeurs non négatives, et les codes d'échec sont des valeurs négatives.

Les énumérations ont les significations suivantes :

Description de l'enum

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_SUCCESS_EXT

L'opération de contexte de persistance a réussi.

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_ENTITY_NOT_TRACKING_EXT

L'opération de persistance a échoué, car l'entité n'a pas pu être suivie par l'environnement d'exécution. (Ajouté par l'extension XR_EXT_spatial_persistence_operations)

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_PERSIST_UUID_NOT_FOUND_EXT

L'UUID de persistance fourni est introuvable dans l'espace de stockage. (Ajouté par l'extension XR_EXT_spatial_persistence_operations)

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_LOCALIZATION_FAILURE_ANDROIDX1

Échec de l'opération de persistance, car la localisation a échoué. (Ajouté par l'extension XR_ANDROIDX1_spatial_anchor_cloud_sharing)

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_MAP_FEATURE_INSUFFICIENT_ANDROIDX1

L'opération de persistance a échoué, car la fonctionnalité de carte de localisation est insuffisante. (Ajouté par l'extension XR_ANDROIDX1_spatial_anchor_cloud_sharing)

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_NETWORK_FAILURE_ANDROIDX1

L'opération de persistance a échoué, car la connexion réseau a échoué. (Ajouté par l'extension XR_ANDROIDX1_spatial_anchor_cloud_sharing)

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_NETWORK_TIMEOUT_ANDROIDX1

L'opération de persistance a échoué en raison d'un délai d'expiration du réseau. (Ajouté par l'extension XR_ANDROIDX1_spatial_anchor_cloud_sharing)

Détruire le contexte de persistance spatiale

La fonction xrDestroySpatialPersistenceContextEXT est définie comme suit :

XrResult xrDestroySpatialPersistenceContextEXT(
    XrSpatialPersistenceContextEXT              persistenceContext);

Description des paramètres

L'application peut utiliser xrDestroySpatialPersistenceContextEXT pour libérer le handle persistenceContext lorsqu'elle a terminé les tâches de persistance spatiale.

L'environnement d'exécution ne doit pas détruire les ressources sous-jacentes pour persistenceContext lorsque xrDestroySpatialPersistenceContextEXT est appelé s'il existe des poignées XrSpatialContextEXT valides auxquelles persistenceContext était associé via XrSpatialContextPersistenceConfigEXT . En effet, les ressources du contexte de persistance sont toujours utilisées par le contexte spatial pour découvrir les entités persistantes. Dans ce cas, la destruction du handle de contexte de persistance ne fait que supprimer l'accès de l'application à ces ressources.

Les ressources d'un XrSpatialPersistenceContextEXT détruit doivent être libérées lorsque tous les handles XrSpatialContextEXT auxquels le contexte de persistance était associé sont détruits.

Utilisation valide (implicite)

Thread safety

  • L'accès à persistenceContext et à tous les handles enfants doit être synchronisé en externe.

Codes renvoyés

Opération réussie

  • XR_SUCCESS

Échec

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_RUNTIME_FAILURE

Découvrir les entités persistantes

Composant de persistance

Les entités spatiales persistantes comportent le composant de persistance que l'environnement d'exécution doit inclure dans les instantanés de découverte et de mise à jour si XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT est activé lors de la création de XrSpatialContextEXT et inclus dans XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes ou XrSpatialUpdateSnapshotCreateInfoEXT :: componentTypes .

Données du composant

La structure XrSpatialPersistenceDataEXT est définie comme suit :

typedef struct XrSpatialPersistenceDataEXT {
    XrUuid                          persistUuid;
    XrSpatialPersistenceStateEXT    persistState;
} XrSpatialPersistenceDataEXT;

Descriptions des membres

Utilisation valide (implicite)

typedef enum XrSpatialPersistenceStateEXT {
    XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT = 1,
    XR_SPATIAL_PERSISTENCE_STATE_NOT_FOUND_EXT = 2,
    XR_SPATIAL_PERSISTENCE_STATE_MAX_ENUM_EXT = 0x7FFFFFFF
} XrSpatialPersistenceStateEXT;

L'énumération XrSpatialPersistenceStateEXT identifie les différents états de l'UUID persistant.

Les énumérations ont les significations suivantes :

Description de l'enum

XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT

L'UUID persistant a bien été chargé depuis l'espace de stockage.

XR_SPATIAL_PERSISTENCE_STATE_NOT_FOUND_EXT

L'UUID persistant est introuvable dans l'espace de stockage. Il a été supprimé ou n'y a jamais figuré.

Structure de la liste des composants pour interroger les données

La structure XrSpatialComponentPersistenceListEXT est définie comme suit :

typedef struct XrSpatialComponentPersistenceListEXT {
    XrStructureType                 type;
    void*                           next;
    uint32_t                        persistDataCount;
    XrSpatialPersistenceDataEXT*    persistData;
} XrSpatialComponentPersistenceListEXT;

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures. Aucune structure de ce type n'est définie dans OpenXR de base ou dans cette extension.
  • persistDataCount est un uint32_t décrivant le nombre d'éléments dans le tableau persistData.
  • persistData est un tableau de XrSpatialPersistenceDataEXT .

L'environnement d'exécution doit renvoyer XR_ERROR_VALIDATION_FAILURE à partir de xrQuerySpatialComponentDataEXT si XrSpatialComponentPersistenceListEXT se trouve dans la chaîne suivante de XrSpatialComponentDataQueryResultEXT :: next, mais que XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT n'est pas inclus dans XrSpatialComponentDataQueryConditionEXT :: componentTypes .

L'environnement d'exécution doit renvoyer XR_ERROR_SIZE_INSUFFICIENT à partir de xrQuerySpatialComponentDataEXT si persistDataCount est inférieur à XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput .

Contrairement aux autres composants, l'environnement d'exécution doit définir les données pour XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT, quel que soit l'XrSpatialEntityTrackingStateEXT .

Utilisation valide (implicite)

Configuration

Si XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT est énuméré dans XrSpatialCapabilityComponentTypesEXT :: componentTypes pour une fonctionnalité, l'application peut l'activer en incluant l'énumération dans la liste XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents. Ce composant ne nécessite aucune configuration spéciale pour être inclus dans la chaîne suivante de XrSpatialCapabilityConfigurationBaseHeaderEXT . Si l'application inclut XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT dans la liste des composants activés, elle doit également inclure XrSpatialContextPersistenceConfigEXT dans la chaîne suivante de XrSpatialContextCreateInfoEXT. Sinon, l'environnement d'exécution doit renvoyer XR_ERROR_SPATIAL_CAPABILITY_CONFIGURATION_INVALID_EXT à partir de xrCreateSpatialContextAsyncEXT.

Configurer le contexte spatial avec des contextes de persistance

La structure XrSpatialContextPersistenceConfigEXT est définie comme suit :

typedef struct XrSpatialContextPersistenceConfigEXT {
    XrStructureType                          type;
    const void*                              next;
    uint32_t                                 persistenceContextCount;
    const XrSpatialPersistenceContextEXT*    persistenceContexts;
} XrSpatialContextPersistenceConfigEXT;

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures. Aucune structure de ce type n'est définie dans OpenXR de base ou dans cette extension.
  • persistenceContextCount est un uint32_t décrivant le nombre d'éléments dans le tableau persistenceContexts.
  • persistenceContexts est un tableau de XrSpatialPersistenceContextEXT .

Une application peut ajouter XrSpatialContextPersistenceConfigEXT à la chaîne suivante de XrSpatialContextCreateInfoEXT . Cela configurera le XrSpatialContextEXT créé avec persistenceContexts et permettra à l'application de découvrir les entités spatiales conservées dans l'espace de stockage représenté par les poignées XrSpatialPersistenceContextEXT dans persistenceContexts .

Utilisation valide (implicite)

Créer un instantané de découverte

Découvrir des entités avec des UUID spécifiques

La structure XrSpatialDiscoveryPersistenceUuidFilterEXT est définie comme suit :

typedef struct XrSpatialDiscoveryPersistenceUuidFilterEXT {
    XrStructureType    type;
    const void*        next;
    uint32_t           persistedUuidCount;
    const XrUuid*      persistedUuids;
} XrSpatialDiscoveryPersistenceUuidFilterEXT;

Descriptions des membres

  • type est le XrStructureType de cette structure.
  • next est NULL ou un pointeur vers la structure suivante dans une chaîne de structures. Aucune structure de ce type n'est définie dans OpenXR de base ou dans cette extension.
  • persistedUuidCount est un uint32_t décrivant le nombre d'éléments dans le tableau persistedUuids.
  • persistedUuids est un tableau de XrUuid .

L'application peut utiliser XrSpatialDiscoveryPersistenceUuidFilterEXT dans la chaîne suivante de XrSpatialDiscoverySnapshotCreateInfoEXT pour limiter l'opération de découverte aux entités dont les UUID persistants se trouvent dans l'ensemble des UUID fournis dans persistedUuids .

Si l'application ajoute XrSpatialDiscoveryPersistenceUuidFilterEXT dans la chaîne suivante de XrSpatialDiscoverySnapshotCreateInfoEXT, mais que xrCreateSpatialDiscoverySnapshotAsyncEXT :: spatialContext n'a pas été configuré avec un XrSpatialPersistenceContextEXT à l'aide de XrSpatialContextPersistenceConfigEXT, l'environnement d'exécution doit renvoyer XR_ERROR_VALIDATION_FAILURE à partir de xrCreateSpatialDiscoverySnapshotAsyncEXT .

L'environnement d'exécution doit traiter le filtre XrSpatialDiscoveryPersistenceUuidFilterEXT comme une condition "AND" avec tous les autres filtres fournis dans XrSpatialDiscoverySnapshotCreateInfoEXT ou sa chaîne suivante. L'environnement d'exécution doit traiter le tableau persistedUuids lui-même comme une condition "OU", c'est-à-dire filtrer les entités qui possèdent l'un des UUID fournis dans ce tableau.

L'environnement d'exécution doit inclure une entrée dans l'instantané créé pour chacun des UUID de persistedUuids pour lesquels il a pu déterminer l'état XrSpatialPersistenceStateEXT à ce moment-là.

  • Si l'environnement d'exécution a bien trouvé l'UUID dans son espace de stockage, alors :

    • L'environnement d'exécution doit définir XrSpatialPersistenceStateEXT dans XrSpatialPersistenceDataEXT de cette entité sur XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT .
    • L'environnement d'exécution doit inclure un XrSpatialEntityIdEXT valide pour cette entité dans l'instantané créé.
    • L'environnement d'exécution doit définir l'élément XrSpatialEntityTrackingStateEXT de cette entité sur XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT s'il suit activement l'entité et dispose de données valides pour ses composants. Sinon, l'environnement d'exécution doit définir XrSpatialEntityTrackingStateEXT sur XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT .
  • Si l'environnement d'exécution a déterminé que l'UUID n'est pas présent dans son espace de stockage (qu'il n'y ait jamais été ou qu'il y ait été présent, mais qu'il n'ait pas été conservé depuis), alors :

    • L'environnement d'exécution doit définir XrSpatialPersistenceStateEXT dans XrSpatialPersistenceDataEXT de cette entité sur XR_SPATIAL_PERSISTENCE_STATE_NOT_FOUND_EXT pour indiquer à l'application que cet UUID n'est plus présent dans l'espace de stockage.
    • L'environnement d'exécution doit définir le XrSpatialEntityIdEXT de cette entité sur XR_NULL_SPATIAL_ENTITY_ID_EXT dans l'instantané créé.
    • L'environnement d'exécution doit définir l'élément XrSpatialEntityTrackingStateEXT de cette entité sur XR_SPATIAL_ENTITY_TRACKING_STATE_STOPPED_EXT pour indiquer à l'application que cette entité ne sera jamais suivie.
  • Si l'environnement d'exécution n'a pas pu déterminer si l'UUID est présent ou non dans son espace de stockage, il ne doit pas l'inclure dans l'instantané.

L'application peut également utiliser XrSpatialDiscoveryPersistenceUuidFilterEXT dans la chaîne suivante de XrSpatialComponentDataQueryConditionEXT pour interroger des entités d'UUID spécifiques dans des instantanés existants. Lorsqu'il est utilisé avec XrSpatialComponentDataQueryConditionEXT , si XrSpatialDiscoveryPersistenceUuidFilterEXT :: persistedUuids contient un XrUuid qui ne figure pas dans XrSpatialSnapshotEXT , l'environnement d'exécution ne doit pas inclure d'entrée pour ce XrUuid dans le résultat de la requête. De plus, l'ordre (la séquence) des entités dans le résultat de la requête peut ne pas correspondre à l'ordre des UUID fournis dans XrSpatialDiscoveryPersistenceUuidFilterEXT :: persistedUuids . L'application doit inclure XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT dans XrSpatialComponentDataQueryConditionEXT :: componentTypes et XrSpatialComponentPersistenceListEXT dans la chaîne suivante de XrSpatialComponentDataQueryResultEXT, puis vérifier XrSpatialPersistenceDataEXT :: persistUuid de chaque index de résultat de requête pour comprendre à quel UUID l'index de résultat actuel correspond.

Utilisation valide (implicite)

Découvrir toutes les entités persistantes

Si l'application utilise xrCreateSpatialDiscoverySnapshotAsyncEXT sans XrSpatialDiscoveryPersistenceUuidFilterEXT et avec un XrSpatialContextEXT configuré avec un XrSpatialPersistenceContextEXT , l'environnement d'exécution doit inclure dans l'instantané créé les entités qui sont conservées dans l'espace de stockage représenté par XrSpatialPersistenceContextEXT et qui répondent aux filtres fournis dans XrSpatialDiscoverySnapshotCreateInfoEXT . Pour ces entités :

  • L'environnement d'exécution doit définir XrSpatialPersistenceStateEXT dans XrSpatialPersistenceDataEXT de cette entité sur XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT .
  • L'environnement d'exécution doit inclure un XrSpatialEntityIdEXT valide pour cette entité dans l'instantané créé.
  • L'environnement d'exécution doit définir l'élément XrSpatialEntityTrackingStateEXT de cette entité sur XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT s'il suit activement l'entité et dispose de données valides pour ses composants. Sinon, l'environnement d'exécution doit définir XrSpatialEntityTrackingStateEXT sur XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT .

Nouveaux types d'objets

Nouvelles commandes

Nouvelles structures

Nouvelles énumérations

Nouvelles constantes d'énumération

  • XR_EXT_SPATIAL_PERSISTENCE_EXTENSION_NAME
  • XR_EXT_spatial_persistence_SPEC_VERSION
  • Extension de XrObjectType :

    • XR_OBJECT_TYPE_SPATIAL_PERSISTENCE_CONTEXT_EXT
  • Extension de XrResult :

    • XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT
  • Extension de XrSpatialComponentTypeEXT :

    • XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT
  • Extension de XrStructureType :

    • XR_TYPE_CREATE_SPATIAL_PERSISTENCE_CONTEXT_COMPLETION_EXT
    • XR_TYPE_SPATIAL_COMPONENT_PERSISTENCE_LIST_EXT
    • XR_TYPE_SPATIAL_CONTEXT_PERSISTENCE_CONFIG_EXT
    • XR_TYPE_SPATIAL_DISCOVERY_PERSISTENCE_UUID_FILTER_EXT
    • XR_TYPE_SPATIAL_PERSISTENCE_CONTEXT_CREATE_INFO_EXT

Exemple de code

Créer un contexte de persistance

// Check if the required persistence scope supported
uint32_t scopeCount;
CHK_XR(xrEnumerateSpatialPersistenceScopesEXT(instance, systemId, 0, &scopeCount, nullptr));
std::vector<XrSpatialPersistenceScopeEXT> persistenceScopes(scopeCount);
CHK_XR(xrEnumerateSpatialPersistenceScopesEXT(instance, systemId, scopeCount, &scopeCount, persistenceScopes.data()));

if (std::find(persistenceScopes.begin(), persistenceScopes.end(), XR_SPATIAL_PERSISTENCE_SCOPE_SYSTEM_MANAGED_EXT) == persistenceScopes.end()) {
  return;
}

XrSpatialPersistenceContextEXT persistenceContext{};

XrSpatialPersistenceContextCreateInfoEXT persistenceContextCreateInfo{XR_TYPE_SPATIAL_PERSISTENCE_CONTEXT_CREATE_INFO_EXT};
persistenceContextCreateInfo.scope = XR_SPATIAL_PERSISTENCE_SCOPE_SYSTEM_MANAGED_EXT;
XrFutureEXT createContextFuture;
CHK_XR(xrCreateSpatialPersistenceContextAsyncEXT(session, &persistenceContextCreateInfo, &createContextFuture));

waitUntilReady(createContextFuture);

XrCreateSpatialPersistenceContextCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_PERSISTENCE_CONTEXT_COMPLETION_EXT};
CHK_XR(xrCreateSpatialPersistenceContextCompleteEXT(session, createContextFuture, &completion));
if (completion.futureResult != XR_SUCCESS || completion.createResult != XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_SUCCESS_EXT) {
  return;
}

persistenceContext = completion.persistenceContext;

// ...
// Connect persistence context to a spatial context and discover persisted entities.
// ...

CHK_XR(xrDestroySpatialPersistenceContextEXT(persistenceContext));

Connecter un contexte de persistance à un contexte spatial

// Note: Anchor capability is just used as an example here. Persistence can be
// supported by other capabilities too. xrEnumerateSpatialCapabilityComponentTypesEXT() can
// be used to check if a certain capability supports persistence.
if (!isSpatialCapabilitySupported(instance, systemId, XR_SPATIAL_CAPABILITY_ANCHOR_EXT)) {
  return;
}

const bool supportsPersistenceComponent = isSpatialComponentSupported(instance, systemId, XR_SPATIAL_CAPABILITY_ANCHOR_EXT, XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT);

// Create a spatial spatial context
XrSpatialContextEXT spatialContext{};
{

  std::vector<XrSpatialComponentTypeEXT> enabledComponents = {
    XR_SPATIAL_COMPONENT_TYPE_ANCHOR_EXT,
  };

  if (supportsPersistenceComponent) {
    enabledComponents.push_back(XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT);
  }

  XrSpatialCapabilityConfigurationAnchorEXT anchorConfig{XR_TYPE_SPATIAL_CAPABILITY_CONFIGURATION_ANCHOR_EXT};
  anchorConfig.capability = XR_SPATIAL_CAPABILITY_ANCHOR_EXT;
  anchorConfig.enabledComponentCount = enabledComponents.size();
  anchorConfig.enabledComponents = enabledComponents.data();

  std::array<XrSpatialCapabilityConfigurationBaseHeaderEXT*, 1> capabilityConfigs = {
    reinterpret_cast<XrSpatialCapabilityConfigurationBaseHeaderEXT*>(&anchorConfig),
  };

  XrSpatialContextCreateInfoEXT spatialContextCreateInfo{XR_TYPE_SPATIAL_CONTEXT_CREATE_INFO_EXT};
  spatialContextCreateInfo.capabilityConfigCount = capabilityConfigs.size();
  spatialContextCreateInfo.capabilityConfigs = capabilityConfigs.data();

  XrSpatialContextPersistenceConfigEXT persistenceConfig{XR_TYPE_SPATIAL_CONTEXT_PERSISTENCE_CONFIG_EXT};
  persistenceConfig.persistenceContextCount = 1;
  persistenceConfig.persistenceContexts = &persistenceContext;

  if (supportsPersistenceComponent) {
    spatialContextCreateInfo.next = &persistenceConfig;
  }

  XrFutureEXT createContextFuture;
  CHK_XR(xrCreateSpatialContextAsyncEXT(session, &spatialContextCreateInfo, &createContextFuture));

  waitUntilReady(createContextFuture);

  XrCreateSpatialContextCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_CONTEXT_COMPLETION_EXT};
  CHK_XR(xrCreateSpatialContextCompleteEXT(session, createContextFuture, &completion));
  if (completion.futureResult != XR_SUCCESS) {
    return;
  }

  spatialContext = completion.spatialContext;
}

// ...
// Discover persisted anchors.
// ...

CHK_XR(xrDestroySpatialContextEXT(spatialContext));

Découvrir toutes les entités persistantes

XrFutureEXT future = XR_NULL_FUTURE_EXT;

// We want to look for entities that have the following components.
std::vector<XrSpatialComponentTypeEXT> snapshotComponents = {
  XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT,
};

auto discoverSpatialEntities = [&](XrSpatialContextEXT spatialContext, XrTime time) {
  XrSpatialDiscoverySnapshotCreateInfoEXT snapshotCreateInfo{XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT};
  snapshotCreateInfo.componentTypeCount = snapshotComponents.size();
  snapshotCreateInfo.componentTypes = snapshotComponents.data();
  CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT(spatialContext, &snapshotCreateInfo, &future));

  waitUntilReady(future);

  XrCreateSpatialDiscoverySnapshotCompletionInfoEXT completionInfo{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT};
  completionInfo.baseSpace = localSpace;
  completionInfo.time = time;
  completionInfo.future = future;

  XrCreateSpatialDiscoverySnapshotCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};
  CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(spatialContext, &completionInfo, &completion));
  if (completion.futureResult == XR_SUCCESS) {

    // Query for the semantic label component data
    XrSpatialComponentDataQueryConditionEXT queryCond{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT};
    queryCond.componentTypeCount = snapshotComponents.size();
    queryCond.componentTypes = snapshotComponents.data();

    XrSpatialComponentDataQueryResultEXT queryResult{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT};
    CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));

    std::vector<XrSpatialEntityIdEXT> entityIds(queryResult.entityIdCountOutput);
    std::vector<XrSpatialEntityTrackingStateEXT> entityStates(queryResult.entityIdCountOutput);
    queryResult.entityIdCapacityInput = entityIds.size();
    queryResult.entityIds = entityIds.data();
    queryResult.entityStateCapacityInput = entityStates.size();
    queryResult.entityStates = entityStates.data();

    std::vector<XrSpatialPersistenceDataEXT> persistenceData(queryResult.entityIdCountOutput);
    XrSpatialComponentPersistenceListEXT persistenceDataList{XR_TYPE_SPATIAL_COMPONENT_PERSISTENCE_LIST_EXT};
    persistenceDataList.persistDataCount = persistenceData.size();
    persistenceDataList.persistData = persistenceData.data();
    queryResult.next = &persistenceDataList;

    CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));

    for (int32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
      // persistenceData[i].persistUuid is the UUID of the persisted entity whose entity ID is entityIds[i].
      // The persistenceData array is essentially the uuids persisted in the scope that the current
      // XrSpatialPersistenceContextEXT is configured with.
    }

    CHK_XR(xrDestroySpatialSnapshotEXT(completion.snapshot));
  }
};

while (1) {
  // ...
  // For every frame in frame loop
  // ...

  XrFrameState frameState;  // previously returned from xrWaitFrame
  const XrTime time = frameState.predictedDisplayTime;

  // Poll for the XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT event
  XrEventDataBuffer event = {XR_TYPE_EVENT_DATA_BUFFER};
  XrResult result = xrPollEvent(instance, &event);
  if (result == XR_SUCCESS) {
      switch (event.type) {
          case XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT: {
              const XrEventDataSpatialDiscoveryRecommendedEXT& eventdata =
                  *reinterpret_cast<XrEventDataSpatialDiscoveryRecommendedEXT*>(&event);
              // Discover spatial entities for the context that we received the "discovery
              // recommended" event for.
              discoverSpatialEntities(eventdata.spatialContext, time);
              break;
          }
      }
  }

  // ...
  // Finish frame loop
  // ...
}

Découvrir des entités avec des UUID spécifiques

XrFutureEXT future = XR_NULL_FUTURE_EXT;

// Load up the uuids that the app has stored on its own i.e. the uuids it is interested in.
std::vector<XrUuid> uuidsStoredByApp = loadPersistedUuids();

// We want to look for entities that have the following components.
std::vector<XrSpatialComponentTypeEXT> snapshotComponents = {
  XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT,
};

auto discoverSpatialEntities = [&](XrSpatialContextEXT spatialContext, XrTime time) {
  XrSpatialDiscoveryPersistenceUuidFilterEXT persistenceFilter{XR_TYPE_SPATIAL_DISCOVERY_PERSISTENCE_UUID_FILTER_EXT};
  persistenceFilter.persistedUuidCount = uuidsStoredByApp.size();
  persistenceFilter.persistedUuids = uuidsStoredByApp.data();

  XrSpatialDiscoverySnapshotCreateInfoEXT snapshotCreateInfo{XR_TYPE_SPATIAL_DISCOVERY_SNAPSHOT_CREATE_INFO_EXT};
  snapshotCreateInfo.componentTypeCount = snapshotComponents.size();
  snapshotCreateInfo.componentTypes = snapshotComponents.data();
  snapshotCreateInfo.next = &persistenceFilter;

  CHK_XR(xrCreateSpatialDiscoverySnapshotAsyncEXT(spatialContext, &snapshotCreateInfo, &future));

  waitUntilReady(future);

  XrCreateSpatialDiscoverySnapshotCompletionInfoEXT completionInfo{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_INFO_EXT};
  completionInfo.baseSpace = localSpace;
  completionInfo.time = time;
  completionInfo.future = future;

  XrCreateSpatialDiscoverySnapshotCompletionEXT completion{XR_TYPE_CREATE_SPATIAL_DISCOVERY_SNAPSHOT_COMPLETION_EXT};
  CHK_XR(xrCreateSpatialDiscoverySnapshotCompleteEXT(spatialContext, &completionInfo, &completion));
  if (completion.futureResult == XR_SUCCESS) {

    // Query for the semantic label component data
    XrSpatialComponentDataQueryConditionEXT queryCond{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_CONDITION_EXT};
    queryCond.componentTypeCount = snapshotComponents.size();
    queryCond.componentTypes = snapshotComponents.data();

    XrSpatialComponentDataQueryResultEXT queryResult{XR_TYPE_SPATIAL_COMPONENT_DATA_QUERY_RESULT_EXT};
    CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));

    std::vector<XrSpatialEntityIdEXT> entityIds(queryResult.entityIdCountOutput);
    std::vector<XrSpatialEntityTrackingStateEXT> entityStates(queryResult.entityIdCountOutput);
    queryResult.entityIdCapacityInput = entityIds.size();
    queryResult.entityIds = entityIds.data();
    queryResult.entityStateCapacityInput = entityStates.size();
    queryResult.entityStates = entityStates.data();

    std::vector<XrSpatialPersistenceDataEXT> persistenceData(queryResult.entityIdCountOutput);
    XrSpatialComponentPersistenceListEXT persistenceDataList{XR_TYPE_SPATIAL_COMPONENT_PERSISTENCE_LIST_EXT};
    persistenceDataList.persistDataCount = persistenceData.size();
    persistenceDataList.persistData = persistenceData.data();
    queryResult.next = &persistenceDataList;

    CHK_XR(xrQuerySpatialComponentDataEXT(completion.snapshot, &queryCond, &queryResult));

    for (int32_t i = 0; i < queryResult.entityIdCountOutput; ++i) {
      if (persistenceData[i].persistState == XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT) {
        // persistenceData[i].persistUuid, requested by the app, is present in the persistence scope
        // and its corresponding entity ID and state are entityIds[i] & entityStates[i] respectively.
      } else if (persistenceData[i].persistState == XR_SPATIAL_PERSISTENCE_STATE_NOT_FOUND_EXT) {
        // persistenceData[i].persistUuid, requested by the app, is NOT present in the persistence scope
        // and its corresponding entity ID (entityIds[i]) would be XR_NULL_SPATIAL_ENTITY_ID_EXT
        // and tracking state (entityStates[i]) would be XR_SPATIAL_ENTITY_TRACKING_STATE_STOPPED_EXT.
      }
    }

    CHK_XR(xrDestroySpatialSnapshotEXT(completion.snapshot));
  }
};

while (1) {
  // ...
  // For every frame in frame loop
  // ...

  XrFrameState frameState;  // previously returned from xrWaitFrame
  const XrTime time = frameState.predictedDisplayTime;

  // Poll for the XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT event
  XrEventDataBuffer event = {XR_TYPE_EVENT_DATA_BUFFER};
  XrResult result = xrPollEvent(instance, &event);
  if (result == XR_SUCCESS) {
      switch (event.type) {
          case XR_TYPE_EVENT_DATA_SPATIAL_DISCOVERY_RECOMMENDED_EXT: {
              const XrEventDataSpatialDiscoveryRecommendedEXT& eventdata =
                  *reinterpret_cast<XrEventDataSpatialDiscoveryRecommendedEXT*>(&event);
              // Discover spatial entities for the context that we received the "discovery
              // recommended" event for.
              discoverSpatialEntities(eventdata.spatialContext, time);
              break;
          }
      }
  }

  // ...
  // Finish frame loop
  // ...
}

Problèmes

Historique des versions

  • Révision 1, 29/08/2024 (Nihav Jain, Google)

    • Description initiale de l'extension