RayQuery descrito no DXR 1.1. No entanto, fornecemos uma implementação de travessia em um único cabeçalho (com diversas variantes) que compartilha a maior parte da nossa lógica de travessia do DXR 1.0 e a encapsula em uma API amplamente equivalente à API do objeto RayQuery. Esse cabeçalho pode ser usado em qualquer estágio de sombreador que permita a alocação de LDS pelo usuário, incluindo sombreadores de computação e de pixel.
Esse sistema deve permitir uma conversão simples (quase 1:1) de código de renderização de PC que dependa do RayQuery do DXR 1.1. Além disso, em situações com poucos sombreadores de raytracing (AnyHit/ClosestHit/etc.), esse sistema costuma ser significativamente mais rápido do que o raytracing no estilo DXR 1.0 no XBOX, devido à menor sobrecarga. É altamente recomendável que recursos de renderização como sombras ou oclusão de ambiente usem esse sistema de cabeçalho embutido.
Observe que, atualmente, o XDXR não realiza o inlining de pequenas tabelas de associação de sombreadores para o DXR 1.0. Alguns IHVs de PC podem ter recomendações diferentes por causa disso. Recomendamos criar perfis das compensações de raytracing do XBOX independentemente dos drivers de PC.
Uso
Cabeçalhos
No lugar do objetoRayQuery do DXR 1.1, fornecemos várias versões de um arquivo de cabeçalho XDXRStandaloneTraverse***.hlsli dentro do diretório de instalação do GDK: GDK_Install_Path\GDK_Version\GXDK\gameKit\Include\Scarlett.
Esses cabeçalhos são fornecidos como código-fonte; no entanto, cabe ao desenvolvedor garantir que a versão do arquivo de cabeçalho seja compatível com o GDK com o qual suas BVHs são construídas. Versões anteriores do cabeçalho não terão suporte em GDKs mais recentes, e modificações no cabeçalho devem ser mescladas com quaisquer alterações de um GDK mais recente.
Atualmente, as versões são as seguintes:
- XDXRStandaloneTraverseShortStack.hlsli
- Esta versão de travessia espelha o algoritmo de travessia padrão atual usado para o suporte ao DXR 1.0 no XDXR. Recomendada para todo raytracing que provavelmente será divergente, como AO ou reflexos brilhantes.
- XDXRStandaloneTraverseHT.hlsli
- Esta versão de travessia implementa um algoritmo de travessia “coerente” que pode ser mais rápido do que outros algoritmos para conteúdo altamente coerente, como raios de sombra ou reflexos espelhados. Isso equivale a especificar
XBOX_RAY_FLAG_COHERENT_RAYS_HINTnos sinalizadores de raio deTraceRay()do DXR 1.0.
- Esta versão de travessia implementa um algoritmo de travessia “coerente” que pode ser mais rápido do que outros algoritmos para conteúdo altamente coerente, como raios de sombra ou reflexos espelhados. Isso equivale a especificar
- XDXRStandaloneTraverseShortStackNoMultibox.hlsli
- Esta versão de travessia não oferece suporte a BVHs construídas offline, mas pode ser um pouco mais rápida se apenas builds de BVH em tempo de execução forem realizados.
- XDXRStandaloneTraverseLongStack.hlsli
- Esta versão de travessia tem um tamanho máximo de pilha de 32 nós; isso pode ser mais rápido em alguns conteúdos, mas pode resultar em acertos de raio ausentes.
Integração
Os cabeçalhos XDXRStandaloneTraverse fornecem um objetoXboxRayQuery que espelha o objeto RayQuery do DXR 1.1. Exceto pela nomenclatura, a API deve ser a mesma do DXR 1.1, com as seguintes diferenças:
- Sinalizadores de modelo como
XboxRayQuery<RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES>só têm suporte ao compilar com HLSL 2021, no GDK de março de 2024 ou posterior. - Antes do HLSL 2021 e do GDK de março de 2024, no lugar de
RayQuery<RAY_FLAG_XXX | RAY_FLAG_YYY>, os usuários devem fazer uma das seguintes ações:- Colocar todos os sinalizadores dentro do parâmetro rayFlags de TraceRayInline(). Prefira usar literais de tempo de compilação para os sinalizadores em vez de valores de buffer constante, para permitir uma melhor geração de código. Considere ramificar entre diferentes chamadas de TraceRayInline() se quiser alternar sinalizadores.
- No lugar de
RayQuery<RAY_FLAG_FORCE_OPAQUE>, useXboxRayQuery.TraceRayInlineNoAHS(); da mesma forma, useXboxRayQuery.TraceRayInlineNoIS()ouXboxRayQuery.TraceRayInlineNoAHSNoIS()para desabilitar o tratamento de sombreadores de interseção.- De forma equivalente, há os membros booleanos
disableAHSedisableISno objetoXboxRayQuery, que podem ser definidos como literais após a chamada paraTraceRayInline, mas antes da primeira chamada paraProceed().
- De forma equivalente, há os membros booleanos
- O
XboxRayQuerymantém estado global; todo o uso de um objetoXboxRayQuerydeve ser concluído antes da criação ou do uso de um segundo objeto. Isso inclui consultar o status ou as informações do acerto final. - O XDXR (e o
XboxRayQuery) atualmente não oferece suporte aRAY_FLAG_SKIP_TRIANGLESouRAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES. Se a separação for necessária, considere construir várias TLASes em paralelo com a API do construtor em lote.- Uma exceção é que
XboxRayQuery<RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES>tem suporte no HLSL2021 e equivale aXboxRayQuery.TraceRayInlineNoIS(). Esse sinalizador só tem suporte como parâmetro de modelo.
- Uma exceção é que
- Devido à estrutura do algoritmo coerente, o
XDXRStandaloneTraverseHT.hlsliexige que todo o código do manipulador deProceed()verifique se um acerto válido foi realmente relatado, adicionando umif (query.CandidateType() == CANDIDATE_NON_OPAQUE_TRIANGLE || query.CandidateType() == CANDIDATE_PROCEDURAL_PRIMITIVE)antes da lógica de AnyHit ou do sombreador de interseção. Embora isso seja permitido no DXR 1.1 normal, costuma ser omitido quando se sabe que a BVH contém apenas um tipo de primitiva. Isso causará artefatos na implementação deXDXRStandaloneTraverseHT.hlsli. - A implementação de travessia
XDXRStandaloneTraverseHT.hlsliexige que os sinalizadores de raio e o ponteiro da TLAS sejam uniformes. - A travessia autônoma do XDXR inclui várias extensões não presentes no DXR 1.1, discutidas na próxima seção.
CurrentNumIterations() e SetMaxNumIterations()
A travessia autônoma do XDXR adiciona duas extensões simples relacionadas à consulta e à limitação das contagens de iterações de travessia. Observe que cada uma dessas extensões pode causar pressão adicional de VGPR ou de ALU. Os usuários não devem usar/habilitar esses recursos, a menos que pretendam definir um limite de iterações baixo o suficiente para compensar o custo adicional.XboxRayQuery.CurrentNumIterations()retorna o número de iterações da lógica de travessia que ocorreram até o momento. Isso pode ser chamado após a travessia, para desenhar um mapa de calor, ou dentro da lógica de AHS ou semelhante para tomar decisões. Qualquer referência a essa função no seu sombreador adicionará um pequeno custo à travessia, inclusive quando estiver por trás de um sinalizador de tempo de execução. Recomendamos colocar quaisquer modos de “mapa de calor” por trás de um sinalizador#ifdefpara garantir que os modos de versão de lançamento não sejam afetados.XboxRayQuery.SetMaxNumIterations(uint maxNumIterations)permite definir uma contagem máxima de iterações, após a qual a travessia será encerrada antecipadamente, e os resultados incluirão o acerto confirmado mais recente (ou nada, se nenhum tiver sido encontrado ainda).- Para usar esse recurso,
#define XDXR_ENABLE_ITERATION_LIMIT 1deve ser definido antes de incluir o cabeçalho de travessia. - Coloque a chamada para
XboxRayQuery.SetMaxNumIterations(YOUR_ITERATION_LIMIT)após a chamada paraXboxRayQuery.TraceRayInline()e antes da chamada paraXboxRayQuery.Proceed(). - Para testar se a travessia foi encerrada antecipadamente, verifique se
XboxRayQuery.CurrentNumIterations() >= YOUR_ITERATION_LIMIT. Observe que a contagem de iterações pode ser maior que o limite, especialmente no caso deXDXRStandaloneTraverseHT.hlsli, pois alguns estágios da travessia não podem ser encerrados antecipadamente sem incorrer em um custo alto.
- Para usar esse recurso,
InlineAHS e InlineIS
A travessia autônoma do XDXR fornece duas extensões para melhorar a velocidade da travessia quando é necessária uma lógica simples de AnyHit ou de sombreador de interseção. Por padrão, a travessia de RayQuery do DXR 1.1 precisa sair do loop de travessia da BVH para dar controle ao usuário para tratar a lógica de AnyHit ou do sombreador de interseção em um loopwhile(query.Proceed()). Isso pode levar a um fluxo de controle complexo e a um desempenho abaixo do ideal.
A travessia autônoma do XDXR fornece os mecanismos InlineAHS e InlineIS para melhorar o desempenho, permitindo que a lógica de AHS ou IS seja embutida dentro do loop de travessia.
A partir do GDK de março de 2024, as definições XDXR_USE_INLINE_AHS_FUNCTION e XDXR_USE_INLINE_IS_FUNCTION foram preteridas. Os recursos InlineAHS e InlineIS agora estão disponíveis por meio de uma API baseada em modelos do HLSL 2021, com várias vantagens. As instruções para a versão do HLSL 2021 vêm a seguir, com uma seção sobre a versão anterior mais abaixo.
InlineAHS e InlineIS no HLSL 2021
- Crie uma struct HLSL que estenda
InlineAHSBaseLambda,InlineISBaseLambdaouInlineAHSAndISBaseLambda, dependendo de se você precisa de lógica de AnyHit (AHS), lógica de interseção procedural (IS) ou ambas. - Crie uma função com a assinatura e o nome
void InlineAHS(inout XboxRayQueryProxy rqp)e/ouvoid InlineIS(inout XboxRayQueryProxy rqp)dentro da sua struct. - Recorte/cole toda a lógica de AHS e IS do seu loop
while(query.Proceed()) {ISLogic(); AHSLogic()}nas funçõesInlineAHSouInlineIS. - O objeto
XboxRayQueryProxyoferece suporte a todas as mesmas funcionalidades doXboxRayQuerynormal, exceto o getterXboxRayQuery.CandidateType(). Trate a lógica deCANDIDATE_NON_OPAQUE_TRIANGLEemInlineAHS()e a lógica deCANDIDATE_PROCEDURAL_PRIMITIVE, incluindo o teste alfa, emInlineIS(). - O
XboxRayQueryProxypode ser usado para consultar informações de travessia exatamente da mesma forma que um objetoRayQuerynormal, e para tratar acertos por meio das funçõesrayQueryProxy.CommitNonOpaqueTriangleHit()ourayQueryProxy.Abort().rayQueryProxy.CandidateProceduralPrimitiveNonOpaque()pode ser consultado dentro deInlineIS()para determinar se a lógica de AHS deve ser executada para a primitiva procedural. Isso é o mesmo que no raytracing embutido padrão do DXR 1.1.
- Quando
InlineAHSouInlineIS(ou ambos) são usados, não há necessidade de colocar a chamadarayQuery.Proceed()dentro de um loop while, pois o controle não retornará ao usuário até que a travessia seja concluída. Toda a lógica de AHS ou IS será embutida usando as funções fornecidas.
InlineAHS e InlineIS no HLSL 2018 (preterido)
- Especifique
#define XDXR_USE_INLINE_AHS_FUNCTION 1e/ou#define XDXR_USE_INLINE_IS_FUNCTION 1antes de#include "XDXRStandaloneTraverse****.hlsli". Observe que, se houver lógica de AHS e de IS, ambas devem usar o sistema embutido e não podem ser misturadas com os manipuladores normais do DXR 1.1. - Crie uma função global com a assinatura e o nome
void InlineAHS(inout XboxRayQueryProxy rqp)e/ouvoid InlineIS(inout XboxRayQueryProxy rqp) - Siga as instruções da versão do HLSL 2021 acima, substituindo as funções InlineAHS e InlineIS membros da struct pelas funções InlineAHS e InlineIS definidas globalmente.
Memória
O driver do XDXR aloca memória de suporte para a travessia no estiloTraceRay() do DXR 1.0. Se o seu título usar apenas raytracing embutido, talvez você queira recuperar essa memória. Em junho de 2022, isso corresponde a 12 MB no XBOX Series S e 32 MB no XBOX Series X. Para desabilitar essa memória, o título deve especificar D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN para pDXRStackBuffer, além de especificar um tamanho de 0 para DXRStackBufferOverrideSizeBytes em D3D12XBOX_CREATE_DEVICE_PARAMETERS.
