O acesso à funcionalidade de ray tracing do TD é muito semelhante à forma como a amostragem e a filtragem de texturas são realizadas atualmente.
Duas novas instruções foram adicionadas ao conjunto de instruções da GPU.
- image_bvh_intersect_ray
- image_bvh64_intersect_ray
Descritor de BVH
O descritor de textura de BVH tem 128 bits e é organizado conforme mostrado na tabela a seguir. | Campo | Bits | Tamanho | Dados | |---|---| | Endereço base da BVH | 39:0 | 40 | Endereço base da BVH: alinhado a 256 bytes. Por exemplo, 0 = 0x0, 1 = 0x100 e 2 = 0x200. | | Não usado | 54:40 | 15 | Deve ser zero. | | Quantidade de crescimento da caixa | 62:55 | 8 | Número de ULPs a serem adicionados durante um teste raio-caixa, codificado como um inteiro sem sinal. | | Ordenação de caixas habilitada | 63 | 1 | Indica se os resultados do teste raio/AABB precisam ser ordenados. | | Tamanho | 105:64 | 42 | Número de nós da BVH menos 1. Impõe a verificação de limites no acesso. | | Não usado | 119:106 | 17 | Deve ser zero. | | Triangle Return Mode | 120 | 1 | 0: Triangle Return Mode 0. 1: Triangle Return Mode 1. Mais informações em uma seção posterior. | | Não usado | 122:121 | 2 | Deve ser zero. | | Páginas grandes | 123 | 1 | Indica que todas as páginas de memória usadas são menores ou iguais a 64 KB. Como o driver do XBOX não oferece suporte a tamanhos de página menores que 64 KB para acesso da GPU, esse valor deve ser sempre 1. | | Tipo | 127:124 | 4 | Deve ser definido como 0x8. |Tipos de nós da BVH
A instrução de interseção de raio descrita anteriormente não recebe a geometria (AABBs ou triângulos) como entrada por meio de VGPRs. Em vez disso, um endereço de 32 bits (“node_pointer”) especifica em relação a qual nó da BVH o teste de interseção deve ser realizado. A vantagem dessa abordagem é que a operação de memória e o teste de interseção podem ser combinados em uma única operação pelo TD. Como o maior nó tem 128 bytes, a abordagem alternativa teria sido carregar, armazenar e transmitir o equivalente a 32 VGPRs de payload adicional de “geometria”, além dos 11 VGPRs já usados para os dados do raio. A ocupação teria sido gravemente afetada pela necessidade de até 43 VGPRs de entrada para uma instrução image_bvh_intersect_ray. Consequentemente, há três formatos prescritos de nós de BVH compreendidos nativamente pelo hardware.- Nó AABB FP16 (armazenando 4 AABBs): 64 bytes
- Nó AABB FP32 (armazenando 4 AABBs): 128 bytes
- Nó de triângulo (armazenando até 4 triângulos): 64 bytes
Formato de nó de triângulo (tipos de nó 0, 1, 2 e 3)
A seção a seguir é precisa em relação ao suporte de hardware; no entanto, foi tomada a decisão no XDXR de usar apenas dois triângulos por nó folha e armazenar metadados nas entradas restantes._
- Triângulo 0:
- Triângulo 1:
- Triângulo 2:
- Triângulo 3:

O TD realizará um teste de interseção raio/triângulo em relação a apenas um dos quatro triângulos armazenados no nó; isso difere do comportamento do teste raio/AABB, no qual todas as quatro AABBs são testadas. Qual dos quatro triângulos será testado é especificado pelos 3 bits mais baixos do “node_pointer” ao invocar image_bvh_intersect_ray. Esses valores são mostrados na tabela a seguir.
Dados de retorno da interseção
Quando “Triangle Return Mode” no descritor de BVH é definido como 0, os quatro VGPRs retornados contêm os dados mostrados na tabela a seguir.
Quando “Triangle Return Mode” no descritor de BVH é definido como 1, os quatro VGPRs retornados contêm os dados mostrados na tabela a seguir.
O status do acerto pode ser inferido calculando se (t_num/t_denom) é menor que ray_extent.
No Triangle Return Mode 1, o campo “triangle_id” do nó da BVH é usado para remapear a ordem dos vértices conforme foram armazenados no nó de triângulo em relação à ordem em que foram fornecidos ao construtor de BVH. Por exemplo, dado o index buffer a seguir, esta sequência de quatro triângulos/cinco vértices é compatível com o armazenamento em um único nó de triângulo (em que 0 = V0, 1 = V1, 2 = V2, 3 = V3 e 4 = V4).
, , , ,
No entanto, o segundo e o terceiro triângulos são rotações da ordenação implícita definida pelo hardware. O vértice comum (V2) é o 3º vértice do triângulo 1 conforme definido pelo hardware (V1,V3,V2), mas é especificado em segundo lugar no index buffer de entrada. A consequência é que as coordenadas baricêntricas “I” e “J” devem ser relativas à entrada no index buffer , e não à ordenação implícita do triângulo 1 no hardware .
Para atenuar esse problema, os bytes 63:60 do nó de triângulo passam a definir 4 conjuntos de bits de “remapeamento” que informam ao hardware a qual dos 3 vértices do triângulo as coordenadas baricêntricas I e J devem ser relativas. A interpretação dos bytes 63:60 para essa finalidade é mostrada na tabela a seguir.
| Campo | Bits | Tamanho | Dados | |---|---| | Triângulo 0, vértice de origem de “I” | 1:0 | 2 | 0: “I” é o peso baricêntrico de V0. 1: “I” é o peso baricêntrico de V1. 2: “I” é o peso baricêntrico de V2. 3: Não usado. | | Triângulo 0, vértice de origem de “J” | 3:2 | 2 | 0: “J” é o peso baricêntrico de V0. 1: “J” é o peso baricêntrico de V1. 2: “J” é o peso baricêntrico de V2. 3: Não usado. | | Não usado | 7:4 | 4 | 4 bits de espaço livre. Podem ser usados para qualquer finalidade; não precisam de nenhum valor específico. | | Triângulo 1, vértice de origem de “I” | 9:8 | 2 | 0: “I” é o peso baricêntrico de V1. 1: “I” é o peso baricêntrico de V3. 2: “I” é o peso baricêntrico de V2. 3: Não usado. | | Triângulo 1, vértice de origem de “J” | 11:10 | 2 | 0: “J” é o peso baricêntrico de V1. 1: “J” é o peso baricêntrico de V3. 2: “J” é o peso baricêntrico de V2. 3: Não usado. | | Não usado | 15:12 | 4 | 4 bits de espaço livre. Podem ser usados para qualquer finalidade; não precisam de nenhum valor específico. | | Triângulo 2, vértice de origem de “I” | 17:16 | 2 | 0: “I” é o peso baricêntrico de V2. 1: “I” é o peso baricêntrico de V3. 2: “I” é o peso baricêntrico de V4. 3: Não usado. | | Triângulo 2, vértice de origem de “J” | 19:18 | 2 | 0: “J” é o peso baricêntrico de V2. 1: “J” é o peso baricêntrico de V3. 2: “J” é o peso baricêntrico de V4. 3: Não usado. | | Não usado | 23:20 | 4 | 4 bits de espaço livre. Podem ser usados para qualquer finalidade; não precisam de nenhum valor específico. | | Triângulo 3, vértice de origem de “I” | 25:24 | 2 | 0: “I” é o peso baricêntrico de V2. 1: “I” é o peso baricêntrico de V4. 2: “I” é o peso baricêntrico de V0. 3: Não usado. | | Triângulo 3, vértice de origem de “J” | 27:26 | 2 | 0: “J” é o peso baricêntrico de V2. 1: “J” é o peso baricêntrico de V4. 2: “J” é o peso baricêntrico de V0. 3: Não usado. | | Não usado | 31:28 | 4 | 4 bits de espaço livre. Podem ser usados para qualquer finalidade; não precisam de nenhum valor específico. |
Com os bits de triangle_id usados para remapear as coordenadas baricêntricas para os vértices necessários, os bits de triangle_id não podem mais ser usados para armazenar um ID de triângulo base. Como ter um ID de triângulo disponível costuma ser necessário para cálculos adicionais de sombreamento (por exemplo, buscar dados de vértices/primitivos, como coordenadas de textura (UVs) e normais), esses dados precisarão ser armazenados em uma estrutura separada e buscados manualmente.
Formato de nó AABB FP16 (tipo de nó 4)
Formato de nó AABB FP32 (tipo de nó 5)
Dados de retorno da interseção de AABB FP16 e FP32
Se “Box Sorting Enabled” no descritor de BVH estiver definido como 0, a tabela a seguir descreve os 4 VGPRs retornados e sua finalidade.
Se “Box Sorting Enabled” no descritor de BVH estiver definido como 1, a tabela a seguir descreve os 4 VGPRs retornados e sua finalidade.
Informações adicionais
- Não há exigência de que todos os threads ativos em uma wave solicitem o mesmo endereço de nó ou o mesmo tipo de nó para interseção. Alguns threads podem solicitar testes de interseção raio/triângulo, enquanto outros fazem testes de interseção de AABB FP16 ou FP32 na mesma instrução.
- Todas as operações realizadas no TD são feitas usando ponto flutuante de precisão simples.
- Todos os testes de interseção raio/AABB e raio/triângulo são estanques (watertight).
- As lanes inativas podem ser consideradas, em grande parte, “gratuitas” e não custam ciclos no TD. Uma lane pode ser tornada inativa das seguintes formas:
- Usando a máscara exec (ou seja, controle de fluxo)
- Definindo como NaN qualquer componente dos seguintes: direção do raio, direção inversa do raio, origem do raio e extensão do raio
- Definindo como Inf qualquer componente dos seguintes: origem do raio
