> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Design de hardware de ray tracing

> Design de hardware de ray tracing

Integrado diretamente a cada Workgroup Processor (WGP) dos consoles XBOX Series, há um poderoso hardware de função fixa projetado para acelerar o processo de travessia de raios por estruturas de aceleração de bounding volume hierarchy (BVH).

Cada bloco de dados de textura (TD) é capaz de realizar quatro testes de interseção raio/caixa delimitadora alinhada aos eixos (AABB) por clock ou um teste de interseção raio/triângulo por clock. O número de blocos TD dos consoles XBOX Series é 20 (no XBOX Series S) e 56 (no XBOX Series X). Isso corresponde às seguintes taxas de "pico" de testes de interseção, conforme mostrado nas tabelas a seguir.

| Console | Taxa de pico de testes de interseção raio/AABB |
| - | - |
| XBOX Series S | 1563 MHz × 10 WGPs × 2 TDs por WGP × 4 AABBs por consulta = *125,0 giga testes raio/AABB por segundo* |
| XBOX Series X | 1825MHz × 26 WGPs × 2 TDs por WGP × 4 AABBs por consulta = *379,6 giga testes raio/AABB por segundo* |

| Console | Taxa de pico de testes de interseção raio/triângulo |
| - | - |
| XBOX Series S | 1563 MHz × 10 WGPs × 2 TDs por WGP × 1 triângulo por consulta = *31,26 giga testes raio/triângulo por segundo* |
| XBOX Series X | 1825 MHz × 26 WGPs × 2 TDs por WGP × 1 triângulo por consulta = *94,9 giga testes raio/triângulo por segundo* |

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.

1. image\_bvh\_intersect\_ray
2. image\_bvh64\_intersect\_ray

Essas instruções diferem apenas na largura do endereço recebido como entrada: 32 bits no caso de image\_bvh\_intersect\_ray e 64 bits no caso de image\_bvh64\_intersect\_ray. A versão de 32 bits da instrução pode endereçar BVHs de até 32 GB, portanto, na maioria dos casos, é improvável que a versão "bvh64" precise ser usada.

As entradas da instrução image\_bvh\_intersect\_ray são as seguintes: image\_bvh\_intersect\_ray vgpr\_output\[4], vgpr\_input\[11] e sgpr\_resource\[4].

Os 11 Vector General-Purpose Registers (VGPRs) de entrada são mostrados na tabela a seguir.

\| Índice do VGPR | Dados | Descrição | |---|---| | 0 | node\_pointer (u32) | Os bits 2:0 especificam qual tipo de teste de interseção de raio está sendo solicitado (veja a seguir). Os bits 31:3 são um endereço de 29 bits, alinhado a 64 bytes; por exemplo, 0 = 0x0, 1 = 0x40 e 2 = 0x80, em relação ao endereço base da BVH. | | 1 | ray\_extent (f32) | A distância máxima (geralmente chamada de "t") na qual os acertos podem ocorrer. Qualquer interseção potencial a uma distância maior que ray\_extent não é considerada um acerto e, em vez disso, é retornado um "erro". | | 2 | ray\_origin.x (f32) | A coordenada x da posição inicial do raio. | | 3 | ray\_origin.y (f32) | A coordenada y da posição inicial do raio. | | 4 | ray\_origin.z (f32) | A coordenada z da posição inicial do raio. | | 5 | ray\_direction.x (f32) | O componente x da direção do raio. | | 6 | ray\_direction.y (f32) | O componente y da direção do raio. | | 7 | ray\_direction.z (f32) | O componente z da direção do raio. | | 8 | ray\_inverse\_direction.x (f32) | O inverso do componente x da direção do raio. Infinitos são válidos se o componente direcional nesse eixo for 0.0f. | | 9 | ray\_inverse\_direction.y (f32) | O inverso do componente y da direção do raio. Infinitos são válidos se o componente direcional nesse eixo for 0.0f. | | 10 | ray\_inverse\_direction.z (f32) | O inverso do componente z da direção do raio. Infinitos são válidos se o componente direcional nesse eixo for 0.0f. |

Como o endereço de 29 bits em node\_pointer está efetivamente em múltiplos de 64 bytes, é por isso que a versão de 32 bits de image\_bvh\_intersect\_ray pode endereçar BVHs de até 32 GB.

Também está disponível uma codificação alternativa "A16", na qual ray\_direction e ray\_inverse\_direction são codificados como float16. Ela pode ser acessada passando ray\_direction e ray\_inverse\_direction como float16\_t3 para os intrínsecos image\_bvh\_intersect\_ray ou image\_bvh64\_intersect\_ray. Não constatamos que isso melhore o desempenho em nossa implementação de travessia.

A finalidade dos quatro VGPRs de saída é discutida a seguir e varia de acordo com o tipo de nó consultado.

### 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.

1. Nó AABB FP16 (armazenando 4 AABBs): 64 bytes
2. Nó AABB FP32 (armazenando 4 AABBs): 128 bytes
3. Nó de triângulo (armazenando até 4 triângulos): 64 bytes

Os três tipos de nós devem ser alinhados a 64 bytes.

### Formato de nó de triângulo (tipos de nó 0, 1, 2 e 3)

<Note>
  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.\_
</Note>

O formato de nó de triângulo armazena cinco vértices que são conectados implicitamente para formar até 4 triângulos. A conectividade implícita entre V0, V1, V2, V3 e V4 não é configurável e é a seguinte.

1. Triângulo 0: { V0, V1, V2 }
2. Triângulo 1: { V1, V3, V2 }
3. Triângulo 2: { V2, V3, V4 }
4. Triângulo 3: { V2, V4, V0 }

<img src="https://mintcdn.com/microsoft-4404708b/6hkHc7s12mHcTMCE/images/gdk/features/graphics/rt-trianglenode.png?fit=max&auto=format&n=6hkHc7s12mHcTMCE&q=85&s=e7e8db72abe9215d85d31dde74702abe" alt="Diagrama de um nó de triângulo, mostrando cinco vértices conectados implicitamente para formar quatro triângulos." width="1051" height="912" data-path="images/gdk/features/graphics/rt-trianglenode.png" />

| Bytes | Dados |
| - | - |
| 11:0 | V0.xyz (3xfloat32) |
| 23:12 | V1.xyz (3xfloat32) |
| 35:24 | V2.xyz (3xfloat32) |
| 47:36 | V3.xyz (3xfloat32) |
| 59:48 | V4.xyz (3xfloat32) |
| 63:60 | ID do triângulo (u32) |

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.

| Valor | Tipo de nó |
| - | - |
| 0 | Teste de interseção raio/triângulo em relação ao triângulo 0 |
| 1 | Teste de interseção raio/triângulo em relação ao triângulo 1 |
| 2 | Teste de interseção raio/triângulo em relação ao triângulo 2 |
| 3 | Teste de interseção raio/triângulo em relação ao triângulo 3 |
| 4 | Teste de interseção raio/AABB em relação a quatro AABBs FP16 |
| 5 | Teste de interseção raio/AABB em relação a quatro AABBs FP32 |
| 6 | Reservado |
| 7 | Reservado |

#### 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.

| VGPR | Dados | Descrição |
| - | - | - |
| 0 | t\_num (f32) | O numerador da distância "t" até a interseção. |
| 1 | t\_denom (f32) | O denominador da distância "t" até a interseção. A distância do acerto é calculada como t\_num/t\_denom. |
| 2 | triangle\_id (u32) | Retorna o ID do triângulo do nó (63:60) mais o índice do triângulo que está sendo testado (0-3). |
| 3 | hit\_status (u32) | Retorna um booliano que indica se o raio atingiu o triângulo. 0 = Erro, 1 = Acerto. |

Quando "Triangle Return Mode" no descritor de BVH é definido como 1, os quatro VGPRs retornados contêm os dados mostrados na tabela a seguir.

| VGPR | Dados | Descrição |
| - | - | - |
| 0 | t\_num (f32) | O numerador da distância "t" até a interseção. |
| 1 | t\_denom (f32) | O denominador da distância "t" até a interseção. A distância do acerto é calculada como t\_num/t\_denom. |
| 2 | i\_num (u32) | O numerador do valor "I" necessário para a interpolação baricêntrica. Deve ser dividido por t\_denom para calcular o valor "I" real. |
| 3 | j\_num (u32) | O numerador do valor "J" necessário para a interpolação baricêntrica. Deve ser dividido por t\_denom para calcular o valor "J" real. |

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).

{ 0, 1, 2 }, { 3, 2, 1 }, { 4, 2, 3 }, { 2, 4, 0 },

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 {3, 2, 1}, e não à ordenação implícita do triângulo 1 no hardware {1, 3, 2}.

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)

| Bytes | Dados |
| - | - |
| 3:0 | Ponteiro de nó filho 0 (u32) |
| 7:4 | Ponteiro de nó filho 1 (u32) |
| 11:8 | Ponteiro de nó filho 2 (u32) |
| 15:12 | Ponteiro de nó filho 3 (u32) |
| 21:16 | Caixa delimitadora 0 - xyz mínimo (3xfloat16) |
| 27:22 | Caixa delimitadora 0 - xyz máximo (3xfloat16) |
| 33:28 | Caixa delimitadora 1 - xyz mínimo (3xfloat16) |
| 39:34 | Caixa delimitadora 1 - xyz máximo (3xfloat16) |
| 45:40 | Caixa delimitadora 2 - xyz mínimo (3xfloat16) |
| 51:46 | Caixa delimitadora 2 - xyz máximo (3xfloat16) |
| 57:52 | Caixa delimitadora 3 - xyz mínimo (3xfloat16) |
| 63:58 | Caixa delimitadora 3 - xyz máximo (3xfloat16) |

### Formato de nó AABB FP32 (tipo de nó 5)

| Bytes | Dados |
| - | - |
| 3:0 | Ponteiro de nó filho 0 (u32) |
| 7:4 | Ponteiro de nó filho 1 (u32) |
| 11:8 | Ponteiro de nó filho 2 (u32) |
| 15:12 | Ponteiro de nó filho 3 (u32) |
| 27:16 | Caixa delimitadora 0 - xyz mínimo (3xfloat32) |
| 39:28 | Caixa delimitadora 0 - xyz máximo (3xfloat32) |
| 51:40 | Caixa delimitadora 1 - xyz mínimo (3xfloat32) |
| 63:52 | Caixa delimitadora 1 - xyz máximo (3xfloat32) |
| 75:64 | Caixa delimitadora 2 - xyz mínimo (3xfloat32) |
| 87:76 | Caixa delimitadora 2 - xyz máximo (3xfloat32) |
| 99:88 | Caixa delimitadora 3 - xyz mínimo (3xfloat32) |
| 111:100 | Caixa delimitadora 3 - xyz máximo (3xfloat32) |
| 127:112 | 16 bytes de espaço livre. Podem ser usados para qualquer finalidade; não precisam de nenhum valor específico. |
|  | |

#### 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.

| VGPR | Dados | Descrição |
| - | - | - |
| 0 | Ponteiro de nó filho 0 (u32) | Retorna o ponteiro de nó filho 0 em caso de acerto. Retorna 0xFFFFFFFF em caso de erro. |
| 1 | Ponteiro de nó filho 1 (u32) | Retorna o ponteiro de nó filho 1 em caso de acerto. Retorna 0xFFFFFFFF em caso de erro. |
| 2 | Ponteiro de nó filho 2 (u32) | Retorna o ponteiro de nó filho 2 em caso de acerto. Retorna 0xFFFFFFFF em caso de erro. |
| 3 | Ponteiro de nó filho 3 (u32) | Retorna o ponteiro de nó filho 3 em caso de acerto. Retorna 0xFFFFFFFF em caso de erro. |

Se "Box Sorting Enabled" no descritor de BVH estiver definido como 1, a tabela a seguir descreve os 4 VGPRs retornados e sua finalidade.

| VGPR | Dados | Descrição |
| - | - | - |
| 0 | Ponteiro de nó filho atingido mais próximo (u32) | Retorna o ponteiro de nó filho correspondente à mais próxima das quatro caixas atingidas. Retorna 0xFFFFFFFF se nenhuma das quatro caixas tiver sido atingida. |
| 1 | Segundo ponteiro de nó filho atingido mais próximo (u32) | Retorna o ponteiro de nó filho correspondente à segunda mais próxima das quatro caixas atingidas. Retorna 0xFFFFFFFF se uma ou nenhuma caixa tiver sido atingida. |
| 2 | Terceiro ponteiro de nó filho atingido mais próximo (u32) | Retorna o ponteiro de nó filho correspondente à terceira mais próxima das quatro caixas atingidas. Retorna 0xFFFFFFFF se duas ou menos caixas tiverem sido atingidas. |
| 3 | Quarto ponteiro de nó filho atingido mais próximo (u32) | Retorna o ponteiro de nó filho correspondente à quarta mais próxima das quatro caixas atingidas. Retorna 0xFFFFFFFF se três ou menos caixas tiverem sido atingidas. |

## 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

## Confira também

[Visão geral de ray tracing (e DXR)](/pt-BR/build/core-features/graphics/newfeatures/raytracing/rt-overview)


## Related topics

- [Ray tracing no XBOX Series X|S com XDXR](/pt-BR/build/core-features/graphics/newfeatures/raytracing/index.md)
- [CheckFeatureSupport](/pt-BR/reference/graphics/d3d12/interfaces/id3d12device/methods/id3d12device_checkfeaturesupport_public.md)
- [D3D12_RAYTRACING_TIER](/pt-BR/reference/graphics/d3d12/enums/d3d12_raytracing_tier_public.md)
- [Visão geral do hardware de áudio do XBOX Series X|S](/pt-BR/build/console-features/audio/overviews/scarlett-audio.md)
- [D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS](/pt-BR/reference/graphics/d3d12/structs/d3d12_build_raytracing_acceleration_structure_inputs_public.md)
