XR_EXT_spatial_persistence

String de nome

XR_EXT_spatial_persistence

Tipo de extensão

Extensão de instância

Número de ramal registrado

764

Revisão

1

Status de ratificação

Ratified

Dependências de extensão e versão

XR_EXT_spatial_entity
e
XR_EXT_future

Colaboradores

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

Visão geral

Essa extensão permite que os aplicativos descubram e correlacionem entidades espaciais em sessões de aplicativos, sessões do OpenXR e vários contextos espaciais do OpenXR em uma sessão. A extensão XR_EXT_spatial_entity estabeleceu que uma entidade em um XrSpatialContextEXT é representada por um XrSpatialEntityIdEXT . Essa extensão amplia esse conceito ao estabelecer que uma entidade, se persistente, é representada por um XrUuid em sessões de aplicativos e do OpenXR. Ou seja, um aplicativo pode usar o XrUuid fornecido por essa extensão para identificar uma entidade em várias sessões. Essa extensão também oferece sobreposições úteis com a extensão XR_EXT_spatial_entity para descobrir entidades persistentes no ambiente do usuário e a capacidade de consultar os dados dos componentes.

Contexto de persistência espacial

Criar um contexto de persistência espacial

XR_DEFINE_HANDLE(XrSpatialPersistenceContextEXT)

O identificador XrSpatialPersistenceContextEXT representa a conexão com um armazenamento de entidade espacial persistente.

A função xrCreateSpatialPersistenceContextAsyncEXT é definida como:

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

Descrições dos parâmetros

  • session é uma XrSession em que o contexto de persistência espacial estará ativo.
  • createInfo é o XrSpatialPersistenceContextCreateInfoEXT usado para especificar os parâmetros de contexto de persistência espacial.
  • future é um ponteiro para um XrFutureEXT .

Um aplicativo pode criar um identificador XrSpatialPersistenceContextEXT usando a função xrCreateSpatialPersistenceContextAsyncEXT e configurar o escopo do contexto de persistência em createInfo .

O ambiente de execução precisa retornar XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT se XrSpatialPersistenceContextCreateInfoEXT :: scope não for enumerado por xrEnumerateSpatialPersistenceScopesEXT .

Se um ambiente de execução aplicar um sistema de permissões para controlar o acesso do aplicativo ao armazenamento permanente representado por XrSpatialPersistenceContextEXT , ele precisará retornar XR_ERROR_PERMISSION_INSUFFICIENT se essas permissões não tiverem sido concedidas ao aplicativo.

Uso válido (implícito)

Códigos de retorno

Sucesso

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Falha

  • 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

A estrutura XrSpatialPersistenceContextCreateInfoEXT é definida como:

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

Descrições dos membros

  • type é o XrStructureType dessa estrutura.
  • next é NULL ou um ponteiro para a próxima estrutura em uma cadeia de estruturas. Nenhuma estrutura desse tipo é definida no OpenXR principal ou nesta extensão.
  • scope é um XrSpatialPersistenceScopeEXT que define o escopo de armazenamento do contexto de persistência.

A estrutura XrSpatialPersistenceContextCreateInfoEXT descreve as informações para criar um identificador XrSpatialPersistenceContextEXT.

Uso válido (implícito)

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;

A enumeração XrSpatialPersistenceScopeEXT identifica os diferentes tipos de escopos de contexto de persistência.

Os tipos enumerados têm os seguintes significados:

Descrição do tipo enumerado

XR_SPATIAL_PERSISTENCE_SCOPE_SYSTEM_MANAGED_EXT

Dá ao aplicativo acesso somente leitura (ou seja, o aplicativo não pode modificar o armazenamento associado a esse escopo) a entidades espaciais mantidas e gerenciadas pelo sistema. O aplicativo pode usar o UUID no componente de persistência para esse escopo para correlacionar entidades em contextos espaciais e reinicializações de dispositivos.

XR_SPATIAL_PERSISTENCE_SCOPE_LOCAL_ANCHORS_EXT

As operações de persistência e o acesso aos dados são limitados a âncoras espaciais, no mesmo dispositivo, para o mesmo usuário e o mesmo app (adicionado pela extensão XR_EXT_spatial_persistence_operations).

XR_SPATIAL_PERSISTENCE_SCOPE_ANCHORS_FOR_CLOUD_SHARING_ANDROIDX1

As operações de persistência e o acesso aos dados são limitados a âncoras espaciais, que são de propriedade e gerenciadas pelo mesmo projeto na nuvem. (Adicionado pela extensão XR_ANDROIDX1_spatial_anchor_cloud_sharing)

A função xrEnumerateSpatialPersistenceScopesEXT é definida como:

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

Descrições dos parâmetros

  • instance é um identificador para uma XrInstance .
  • systemId é o XrSystemId com os escopos de persistência espacial que serão enumerados.
  • persistenceScopeCapacityInput é a capacidade da matriz persistenceScopes ou 0 para indicar uma solicitação de recuperação da capacidade necessária.
  • persistenceScopeCountOutput é o número de escopos de persistência ou a capacidade necessária caso persistenceScopeCapacityInput seja insuficiente.
  • persistenceScopes é uma matriz de XrSpatialPersistenceScopeEXT . Pode ser NULL se persistenceScopeCapacityInput for 0.
  • Consulte o capítulo Parâmetros de tamanho do buffer para uma descrição detalhada de como recuperar o tamanho de persistenceScopes necessário.

O aplicativo pode enumerar a lista de escopos de persistência espacial compatíveis com um determinado XrSystemId usando xrEnumerateSpatialPersistenceScopesEXT .

Uso válido (implícito)

  • A extensão XR_EXT_spatial_persistence precisa ser ativada antes de chamar xrEnumerateSpatialPersistenceScopesEXT.
  • instance precisa ser um identificador XrInstance válido
  • persistenceScopeCountOutput precisa ser um ponteiro para um valor uint32_t
  • Se persistenceScopeCapacityInput não for 0 , persistenceScopes precisa ser um ponteiro para uma matriz de valores persistenceScopeCapacityInput XrSpatialPersistenceScopeEXT

Códigos de retorno

Sucesso

  • XR_SUCCESS

Falha

  • 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

A função xrCreateSpatialPersistenceContextCompleteEXT é definida como:

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

Descrições dos parâmetros

xrCreateSpatialPersistenceContextCompleteEXT conclui a operação assíncrona iniciada por xrCreateSpatialPersistenceContextAsyncEXT . O ambiente de execução precisa retornar XR_ERROR_FUTURE_PENDING_EXT se future não estiver no estado pronto. O ambiente de execução precisa retornar XR_ERROR_FUTURE_INVALID_EXT se future já tiver sido concluído ou cancelado.

Uso válido (implícito)

Códigos de retorno

Sucesso

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Falha

  • 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

A estrutura XrCreateSpatialPersistenceContextCompletionEXT é definida como:

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

Descrições dos membros

Códigos de retorno futuros

Valores de futureResult:

Sucesso

  • XR_SUCCESS
  • XR_SESSION_LOSS_PENDING

Falha

  • 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

Se futureResult e createResult forem códigos de sucesso, persistenceContext precisa ser válido. Se persistenceContext for válido, ele precisa permanecer assim no ciclo de vida de xrCreateSpatialPersistenceContextAsyncEXT :: session ou até que o aplicativo use xrDestroySpatialPersistenceContextEXT com persistenceContext , o que ocorrer primeiro.

O ambiente de execução precisa definir createResult somente se futureResult for um código de sucesso.

Uso válido (implícito)

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;

A enumeração XrSpatialPersistenceContextResultEXT identifica os diferentes tipos de códigos de resultado para uma operação de persistência. As falhas durante as operações de persistência nem sempre estão sob o controle do aplicativo, e essa enumeração é usada para transmitir esses casos. Semelhante a XrResult , os códigos de sucesso na enumeração XrSpatialPersistenceContextResultEXT são valores não negativos, e os códigos de falha são valores negativos.

Os tipos enumerados têm os seguintes significados:

Descrição do tipo enumerado

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_SUCCESS_EXT

A operação de contexto de persistência foi concluída.

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_ENTITY_NOT_TRACKING_EXT

A operação de persistência falhou porque a entidade não pôde ser rastreada pelo ambiente de execução. (Adicionado pela extensão XR_EXT_spatial_persistence_operations)

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_PERSIST_UUID_NOT_FOUND_EXT

O UUID de persistência fornecido não foi encontrado no armazenamento. (Adicionado pela extensão XR_EXT_spatial_persistence_operations)

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_LOCALIZATION_FAILURE_ANDROIDX1

A operação de persistência falhou porque a localização falhou. (Adicionado pela extensão XR_ANDROIDX1_spatial_anchor_cloud_sharing)

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_MAP_FEATURE_INSUFFICIENT_ANDROIDX1

A operação de persistência falhou porque o recurso de mapa de localização é insuficiente. (Adicionado pela extensão XR_ANDROIDX1_spatial_anchor_cloud_sharing)

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_NETWORK_FAILURE_ANDROIDX1

A operação de persistência falhou porque a conexão de rede falhou. (Adicionado pela extensão XR_ANDROIDX1_spatial_anchor_cloud_sharing)

XR_SPATIAL_PERSISTENCE_CONTEXT_RESULT_NETWORK_TIMEOUT_ANDROIDX1

A operação de persistência falhou devido ao tempo limite da rede. (Adicionado pela extensão XR_ANDROIDX1_spatial_anchor_cloud_sharing)

Destruir o contexto de persistência espacial

A função xrDestroySpatialPersistenceContextEXT é definida como:

XrResult xrDestroySpatialPersistenceContextEXT(
    XrSpatialPersistenceContextEXT              persistenceContext);

Descrições dos parâmetros

O aplicativo pode usar xrDestroySpatialPersistenceContextEXT para liberar o identificador persistenceContext quando terminar as tarefas de persistência espacial.

O ambiente de execução não pode destruir os recursos subjacentes de persistenceContext quando xrDestroySpatialPersistenceContextEXT é chamado se houver identificadores XrSpatialContextEXT válidos aos quais persistenceContext foi vinculado por XrSpatialContextPersistenceConfigEXT . Isso ocorre porque os recursos do contexto de persistência ainda são usados pelo contexto espacial para descobrir entidades persistentes. Destruir o identificador do contexto de persistência em uma situação como essa apenas remove o acesso do aplicativo a esses recursos.

Os recursos de um XrSpatialPersistenceContextEXT destruído precisam ser liberados quando todos os identificadores XrSpatialContextEXT aos quais o contexto de persistência estava vinculado forem destruídos.

Uso válido (implícito)

Concorrência segura

  • O acesso a persistenceContext e a qualquer identificador filho precisa ser sincronizado externamente.

Códigos de retorno

Sucesso

  • XR_SUCCESS

Falha

  • XR_ERROR_FUNCTION_UNSUPPORTED
  • XR_ERROR_HANDLE_INVALID
  • XR_ERROR_RUNTIME_FAILURE

Descobrir entidades persistentes

Componente de persistência

As entidades espaciais persistentes têm o componente de persistência que o ambiente de execução precisa incluir nos snapshots de descoberta e atualização se XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT estiver ativado durante a criação de XrSpatialContextEXT e incluído em XrSpatialDiscoverySnapshotCreateInfoEXT :: componentTypes ou XrSpatialUpdateSnapshotCreateInfoEXT :: componentTypes .

Dados do componente

A estrutura XrSpatialPersistenceDataEXT é definida como:

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

Descrições dos membros

Uso válido (implícito)

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;

A enumeração XrSpatialPersistenceStateEXT identifica os diferentes estados do UUID persistente.

Os tipos enumerados têm os seguintes significados:

Descrição do tipo enumerado

XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT

O UUID persistente foi carregado do armazenamento.

XR_SPATIAL_PERSISTENCE_STATE_NOT_FOUND_EXT

O UUID persistente não foi encontrado no armazenamento e foi removido dele ou nunca esteve nele.

Estrutura de lista de componentes para consultar dados

A estrutura XrSpatialComponentPersistenceListEXT é definida como:

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

Descrições dos membros

  • type é o XrStructureType dessa estrutura.
  • next é NULL ou um ponteiro para a próxima estrutura em uma cadeia de estruturas. Nenhuma estrutura desse tipo é definida no OpenXR principal ou nesta extensão.
  • persistDataCount é um uint32_t que descreve a contagem de elementos na matriz persistData.
  • persistData é uma matriz de XrSpatialPersistenceDataEXT .

O ambiente de execução precisa retornar XR_ERROR_VALIDATION_FAILURE de xrQuerySpatialComponentDataEXT se XrSpatialComponentPersistenceListEXT estiver na próxima cadeia de XrSpatialComponentDataQueryResultEXT :: next, mas XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT não estiver incluído em XrSpatialComponentDataQueryConditionEXT :: componentTypes .

O ambiente de execução precisa retornar XR_ERROR_SIZE_INSUFFICIENT de xrQuerySpatialComponentDataEXT se persistDataCount for menor que XrSpatialComponentDataQueryResultEXT :: entityIdCountOutput .

Ao contrário dos outros componentes, o ambiente de execução precisa definir os dados para XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT, independente do XrSpatialEntityTrackingStateEXT .

Uso válido (implícito)

Configuração

Se XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT for enumerado em XrSpatialCapabilityComponentTypesEXT :: componentTypes para algum recurso, o aplicativo poderá ativá-lo incluindo o tipo enumerado na lista XrSpatialCapabilityConfigurationBaseHeaderEXT :: enabledComponents. Esse componente não requer nenhuma configuração especial para ser incluído na próxima cadeia de XrSpatialCapabilityConfigurationBaseHeaderEXT . Se o aplicativo incluir XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT na lista de componentes ativados, ele precisará incluir também XrSpatialContextPersistenceConfigEXT na próxima cadeia de XrSpatialContextCreateInfoEXT. Caso contrário, o ambiente de execução precisará retornar XR_ERROR_SPATIAL_CAPABILITY_CONFIGURATION_INVALID_EXT de xrCreateSpatialContextAsyncEXT.

Configurar o contexto espacial com contextos de persistência

A estrutura XrSpatialContextPersistenceConfigEXT é definida como:

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

Descrições dos membros

  • type é o XrStructureType dessa estrutura.
  • next é NULL ou um ponteiro para a próxima estrutura em uma cadeia de estruturas. Nenhuma estrutura desse tipo é definida no OpenXR principal ou nesta extensão.
  • persistenceContextCount é um uint32_t que descreve a contagem de elementos na matriz persistenceContexts.
  • persistenceContexts é uma matriz de XrSpatialPersistenceContextEXT .

Um aplicativo pode adicionar XrSpatialContextPersistenceConfigEXT à próxima cadeia de XrSpatialContextCreateInfoEXT . Isso vai configurar o XrSpatialContextEXT criado com persistenceContexts e permitir que o aplicativo descubra as entidades espaciais mantidas no armazenamento representado pelos identificadores XrSpatialPersistenceContextEXT em persistenceContexts .

Uso válido (implícito)

Criar snapshot de descoberta

Descobrir entidades com UUIDs específicos

A estrutura XrSpatialDiscoveryPersistenceUuidFilterEXT é definida como:

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

Descrições dos membros

  • type é o XrStructureType dessa estrutura.
  • next é NULL ou um ponteiro para a próxima estrutura em uma cadeia de estruturas. Nenhuma estrutura desse tipo é definida no OpenXR principal ou nesta extensão.
  • persistedUuidCount é um uint32_t que descreve a contagem de elementos na matriz persistedUuids.
  • persistedUuids é uma matriz de XrUuid .

O aplicativo pode usar XrSpatialDiscoveryPersistenceUuidFilterEXT na próxima cadeia de XrSpatialDiscoverySnapshotCreateInfoEXT para limitar a operação de descoberta apenas às entidades com UUIDs persistentes no conjunto de UUIDs fornecidos em persistedUuids .

Se o aplicativo adicionar XrSpatialDiscoveryPersistenceUuidFilterEXT na próxima cadeia de XrSpatialDiscoverySnapshotCreateInfoEXT, mas o xrCreateSpatialDiscoverySnapshotAsyncEXT :: spatialContext não tiver sido configurado com nenhum XrSpatialPersistenceContextEXT usando XrSpatialContextPersistenceConfigEXT, o ambiente de execução precisará retornar XR_ERROR_VALIDATION_FAILURE de xrCreateSpatialDiscoverySnapshotAsyncEXT .

O ambiente de execução precisa tratar o filtro XrSpatialDiscoveryPersistenceUuidFilterEXT como uma condição "AND" com qualquer outro filtro fornecido em XrSpatialDiscoverySnapshotCreateInfoEXT ou na próxima cadeia. O ambiente de execução precisa tratar a matriz persistedUuids como uma condição "OR", ou seja, filtrar as entidades que têm qualquer um dos UUIDs fornecidos nessa matriz.

O ambiente de execução precisa incluir uma entrada no snapshot criado para cada um dos UUIDs em persistedUuids para os quais ele conseguiu determinar o estado XrSpatialPersistenceStateEXT no momento.

  • Se o ambiente de execução encontrar o UUID no armazenamento, então:

    • O ambiente de execução precisa definir o XrSpatialPersistenceStateEXT no XrSpatialPersistenceDataEXT dessa entidade como XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT .
    • O ambiente de execução precisa incluir um XrSpatialEntityIdEXT válido para essa entidade no snapshot criado.
    • O ambiente de execução precisa definir o XrSpatialEntityTrackingStateEXT dessa entidade como XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT se estiver rastreando ativamente a entidade e tiver dados válidos para os componentes dela. Caso contrário, o ambiente de execução precisa definir o XrSpatialEntityTrackingStateEXT como XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT .
  • Se o ambiente de execução determinar que o UUID não está presente no armazenamento (independentemente de o UUID nunca ter estado no armazenamento ou de ter estado presente uma vez, mas ter sido removido), então:

    • O ambiente de execução precisa definir o XrSpatialPersistenceStateEXT no XrSpatialPersistenceDataEXT dessa entidade como XR_SPATIAL_PERSISTENCE_STATE_NOT_FOUND_EXT para indicar ao aplicativo que esse UUID não está mais presente no armazenamento.
    • O ambiente de execução precisa definir o XrSpatialEntityIdEXT para essa entidade no snapshot criado como XR_NULL_SPATIAL_ENTITY_ID_EXT .
    • O ambiente de execução precisa definir o XrSpatialEntityTrackingStateEXT dessa entidade como XR_SPATIAL_ENTITY_TRACKING_STATE_STOPPED_EXT para indicar ao aplicativo que essa entidade nunca será rastreada.
  • Se o ambiente de execução não conseguir determinar se o UUID está presente no armazenamento, ele não pode incluí-lo no snapshot.

O aplicativo também pode usar XrSpatialDiscoveryPersistenceUuidFilterEXT na próxima cadeia de XrSpatialComponentDataQueryConditionEXT para consultar entidades de UUIDs específicos em snapshots atuais. Quando usado com XrSpatialComponentDataQueryConditionEXT , se XrSpatialDiscoveryPersistenceUuidFilterEXT :: persistedUuids contiver qualquer XrUuid que não esteja no XrSpatialSnapshotEXT , o ambiente de execução não pode incluir uma entrada para esse XrUuid no resultado da consulta. Além disso, a ordem (sequência) das entidades no resultado da consulta pode não corresponder à ordem dos UUIDs fornecidos em XrSpatialDiscoveryPersistenceUuidFilterEXT :: persistedUuids . O aplicativo precisa incluir XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT em XrSpatialComponentDataQueryConditionEXT :: componentTypes e XrSpatialComponentPersistenceListEXT na próxima cadeia de XrSpatialComponentDataQueryResultEXT e, em seguida, verificar o XrSpatialPersistenceDataEXT :: persistUuid de cada índice de resultado da consulta para entender a qual UUID o índice de resultado atual corresponde.

Uso válido (implícito)

Descobrir todas as entidades persistentes

Se o aplicativo usar xrCreateSpatialDiscoverySnapshotAsyncEXT sem XrSpatialDiscoveryPersistenceUuidFilterEXT e com um XrSpatialContextEXT que foi configurado com um XrSpatialPersistenceContextEXT , o ambiente de execução precisa incluir no snapshot criado as entidades que são mantidas no armazenamento representado por XrSpatialPersistenceContextEXT e que atendem aos filtros fornecidos em XrSpatialDiscoverySnapshotCreateInfoEXT . Para essas entidades,

  • O ambiente de execução precisa definir o XrSpatialPersistenceStateEXT no XrSpatialPersistenceDataEXT dessa entidade como XR_SPATIAL_PERSISTENCE_STATE_LOADED_EXT .
  • O ambiente de execução precisa incluir um XrSpatialEntityIdEXT válido para essa entidade no snapshot criado.
  • O ambiente de execução precisa definir o XrSpatialEntityTrackingStateEXT dessa entidade como XR_SPATIAL_ENTITY_TRACKING_STATE_TRACKING_EXT se estiver rastreando ativamente a entidade e tiver dados válidos para os componentes dela. Caso contrário, o ambiente de execução precisa definir o XrSpatialEntityTrackingStateEXT como XR_SPATIAL_ENTITY_TRACKING_STATE_PAUSED_EXT .

Novos tipos de objeto

Novos comandos

Novas estruturas

Novos tipos enumerados

Novas constantes de tipo enumerado

  • XR_EXT_SPATIAL_PERSISTENCE_EXTENSION_NAME
  • XR_EXT_spatial_persistence_SPEC_VERSION
  • Estendendo XrObjectType :

    • XR_OBJECT_TYPE_SPATIAL_PERSISTENCE_CONTEXT_EXT
  • Estendendo XrResult :

    • XR_ERROR_SPATIAL_PERSISTENCE_SCOPE_UNSUPPORTED_EXT
  • Estendendo XrSpatialComponentTypeEXT :

    • XR_SPATIAL_COMPONENT_TYPE_PERSISTENCE_EXT
  • Estendendo 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

Código de exemplo

Criar contexto de persistência

// 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));

Conectar o contexto de persistência a um contexto espacial

// 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));

Descobrir todas as entidades persistentes

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
  // ...
}

Descobrir entidades com UUIDs específicos

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
  // ...
}

Problemas

Histórico de versões

  • Revisão 1, 29/08/2024 (Nihav Jain, Google)

    • Descrição inicial da extensão