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

# BVH 建置器

> BVH 建置器

XDXR 目前使用 LBVH 演算法並接著進行 treelet 重建來執行執行階段 BVH 建置，並使用 Embree BVH 建置器來執行離線 BVH 建置。

## 離線建置器

XDXR 允許離線建置 BVH、選擇性地加以壓縮，並在執行階段從磁碟載入。這可以產生更高品質的 BVH 以獲得更好的周遊效能，且與執行階段建置器相比，所需的 GPU 時間要少得多。離線 BVH 建置器目前僅支援 BLAS 建置，包括可更新的 BLAS 以及靜態 BLAS。一般遊戲預期會離線建置大部分的 BLAS，並在執行階段的畫面期間只執行 TLAS 建置和 BLAS 更新。

離線建置器可以執行三角形分割，以避免細長且傾斜的三角形所造成的成本，這類三角形的週框方塊可能明顯大於其表面積。此外，它還能對分葉節點中的三角形執行更好的「四邊形化」，請參閱下方的「四邊形」一節。

如需離線建置 BVH，以及離線 BVH 之序列化、還原序列化和壓縮的相關資訊，請參閱 [OfflineRT](https://learn.microsoft.com/gaming/gdk/docs/gdk-dev/development-downloads/gdk-samples-list#graphics) 範例。此外，如需詳細資訊，請參閱 [XDXR BVH 壓縮](/zh-TW/build/core-features/graphics/newfeatures/raytracing/rt-compression)頁面。

請注意，離線建置的 BVH 只對其建置時所針對的 GDK 版本有效。更新 GDK 版本之後，必須重新建置 BVH。

## 批次建置

XDXR 支援「批次」BVH 建置。平行建置或更新多個 BVH，速度可比循序建置快 10 到 25 倍。

請參閱 [BuildRaytracingAccelerationStructureBatched2X](/zh-TW/reference/graphics/d3d12_xs/interfaces/ID3D12GraphicsCommandList6/methods/id3d12graphicscommandlist6_buildraytracingaccelerationstructurebatched2x)。

此外，請考慮使用非同步計算，讓 BVH 建置與陰影等工作負載重疊。這樣可能可以抵銷整個建置成本，或啟用額外的建置品質選項以加快周遊速度。

## FP16

RDNA2 BVH 交集測試支援兩種類型的 AABB 節點：32 位元和 16 位元浮點數。只有當 AABB 範圍落在 FP16 可表示的範圍內時，才能使用 FP16 方塊節點。

為了提供更多節省記憶體的機會，可以將幾何以 2 的次方重新縮放，以符合 FP16 的範圍。此功能可透過 `D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_MINIMIZE_MEMORY` 啟用。雖然 FP16 方塊較小，但由於精確度降低會導致 AABB 膨脹，因此可能會降低周遊效能。系統會使用方塊膨脹啟發學習法來判斷何時可以接受膨脹。若要覆寫預設的啟發學習法，請指定 `D3D12XBOX_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_PARAMS1:: FP16BoxInflationThreshold`。大於 `10.0f` 的值會強制所有 AABB 使用 FP16，並減少悲觀的 BVH 配置。小於 `1.0f` 的值會強制所有 AABB 使用 FP32。您也可以指定 `D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE` 且不指定 `D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_MINIMIZE_MEMORY` 來達到此效果。

## TAPU

XDXR 與大多數其他雙層 (TLAS + BLAS) BVH 建置器具有相同的效能最佳做法和陷阱。一個常見的問題是 BLAS 週框方塊很大且充滿空白空間，或與其他 BLAS 執行個體嚴重交集。如果兩個執行個體的週框方塊交集，周遊可能必須同時周遊這兩個執行個體，才能判斷最近的命中位置。當更多執行個體重疊，或光線原點位於週框方塊內時 (在此情況下無法執行任何排序)，情況會更糟。特別糟糕的物件範例包括懸垂的電線，與原始網格的體積相比，它們可能具有非常大的週框方塊，且可能涵蓋場景的大片區域。另一個範例是將數個小物件合併成單一 BLAS 時，界限會擴大以包含每個網格，但它們之間可能會有大片的空白空間。

有時，解決這些問題最適當的方法是在內容建立或編輯階段分割或合併物件。不過，在將光線追蹤效果新增至現有遊戲時，或在遊戲製作管線的後期，這可能很困難或無法做到。

為了在此提供某種程度的控制，XDXR 在我們的 BVH 建置器中實作了「TAPU」(TLAS-Pull-Up) 選項。這可讓使用者將個別執行個體標記為需要「向上提升」至此 TLAS。在執行個體描述上指定 `D3D12XBOX_RAYTRACING_INSTANCE_FLAG_TAPU4` 或 `D3D12XBOX_RAYTRACING_INSTANCE_FLAG_TAPU16` 旗標，建置器就會將 BLAS 階層的第一層 (TAPU4) 或第二層 (TAPU16) 直接「向上提升」至 TLAS。這實際上能將大型 BLAS 執行個體分割成 4 或 16 個節點，以便更有效地分割到 TLAS 階層中，並移除空白空間區域。

如需「執行個體分割」或「重新編結」(TAPU 的自動化版本) 的相關資訊，請參閱 [D3D12XBOX\_BUILD\_RAYTRACING\_ACCELERATION\_STRUCTURE\_PARAMS3](/zh-TW/reference/graphics/d3d12_xs/structs/d3d12xbox_build_raytracing_acceleration_structure_params3)。

除了指定 TAPU 旗標之外，還必須在 TLAS 中配置額外的節點。程式碼範例如下。

```cpp theme={null}
D3D12_RAYTRACING_INSTANCE_DESC desc[3] = {};
// This example enables TAPU4 on every instance, this probably will not help performance, and will have a memory cost.
// You'll want a more targeted solution, such as marking up problematic instances manually by name,
// or enabling based on world-space-size or volume.
for (unsigned i=0; i < _countof(desc); ++i)
{
    desc[i].AccelerationStructure = blas->GetGPUVirtualAddress();
    // Use TAPU16 to break up the object by a further level.
    desc[i].Flags = D3D12XBOX_RAYTRACING_INSTANCE_FLAG_TAPU4;
    desc[i].InstanceMask = 0xff;
    desc[i].InstanceContributionToHitGroupIndex = 0;
    desc[i].Transform[0][0] = desc[i].Transform[1][1] = desc[i].Transform[2][2] = 1.0f;
}

ComPtr<ID3D12Resource> pInstanceDescs;
UploadBuffer(desc, sizeof(desc), &pInstanceDescs);

// Set special options
struct
{
D3D12XBOX_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_PARAMS1 params1;
D3D12XBOX_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_PARAMS2 params2;
} options;
D3D12XboxMakeDefault_D3D12XBOX_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_PARAMS1(&options.params1);
D3D12XboxMakeDefault_D3D12XBOX_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_PARAMS2(&options.params2);

// Access via a batched build
D3D12XBOX_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_BATCHED_DESC2 tlasBatchedBuild {};
tlasBatchedBuild.NumPostbuildInfoDescs = 0;
tlasBatchedBuild.pPostbuildInfoDescs = nullptr;
tlasBatchedBuild.ExtraOptions.SizeInBytes = sizeof(options);
tlasBatchedBuild.ExtraOptions.pXdxrStreamDesc = &options;

// Tell the builder that this is how many outputs slots it can rely on!
// This should be the total number of instance nodes in your build.
// E.G. instances without a TAPU flag take up 1 element, instances with TAPU4 take up 4 elements, and instances with TAPU16 take up 16 elements.
options.params2.NumberOfElementsAllocated = _countof(desc) * 4;

D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC buildDesc {};
D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_INPUTS &topLevelInputs = buildDesc.Inputs;
topLevelInputs.DescsLayout = D3D12_ELEMENTS_LAYOUT_ARRAY;
topLevelInputs.Flags = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE;
// This is the number of instance descs, NOT multiplied by the TAPU factor.
topLevelInputs.NumDescs = _countof(desc); 
topLevelInputs.Type = D3D12_RAYTRACING_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL;
topLevelInputs.InstanceDescs = pInstanceDescs->GetGPUVirtualAddress();

// Get total size required including additional nodes for TAPU.
D3D12_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO topLevelPrebuildInfo;
m_pDxrDevice->GetRaytracingAccelerationStructurePrebuildInfoX(&topLevelInputs,
&tlasBatchedBuild.ExtraOptions,
&topLevelPrebuildInfo);

ComPtr<ID3D12Resource> pScratchResource;
ComPtr<ID3D12Resource> tlas;

AllocateRawUAVBuffer(topLevelPrebuildInfo.ScratchDataSizeInBytes, &pScratchResource);
auto tlasPointer = AllocateAccelerationStructureBuffer(topLevelPrebuildInfo.ResultDataMaxSizeInBytes, &tlas);

buildDesc.DestAccelerationStructureData = tlasPointer;
buildDesc.ScratchAccelerationStructureData = pScratchResource->GetGPUVirtualAddress();

// Make sure the number of incoming instances is clearly communicated!
tlasBatchedBuild.Desc = buildDesc;

// Build acceleration structure.
((ID3D12GraphicsCommandList6*)m_CommandList.Get())->BuildRaytracingAccelerationStructureBatched2X(1, &tlasBatchedBuild);
```

## 建置選項和旗標

除了支援 `D3D12_RAYTRACING_ACCELERATION_STRUCTURE_BUILD_FLAG_PREFER_FAST_TRACE` 等一般 DXR 建置器旗標之外，XDXR 也支援一個 API，可為 BVH 建置器指定其他選項。

請參閱 [D3D12XBOX\_BUILD\_RAYTRACING\_ACCELERATION\_STRUCTURE\_PARAMS1](/zh-TW/reference/graphics/d3d12_xs/structs/d3d12xbox_build_raytracing_acceleration_structure_params1)、[D3D12XBOX\_BUILD\_RAYTRACING\_ACCELERATION\_STRUCTURE\_PARAMS2](/zh-TW/reference/graphics/d3d12_xs/structs/d3d12xbox_build_raytracing_acceleration_structure_params2)、[D3D12XBOX\_BUILD\_RAYTRACING\_ACCELERATION\_STRUCTURE\_PARAMS3](/zh-TW/reference/graphics/d3d12_xs/structs/d3d12xbox_build_raytracing_acceleration_structure_params3)。

以 TLAS 建置時間換取周遊效能可能很有價值，尤其是當 TLAS 建置可以在非同步計算上執行時。如需在 TLAS 建置期間增加 treelet 反覆運算次數的程式碼範例，請參閱 [BuildRaytracingAccelerationStructureBatched2X](/zh-TW/reference/graphics/d3d12_xs/interfaces/ID3D12GraphicsCommandList6/methods/id3d12graphicscommandlist6_buildraytracingaccelerationstructurebatched2x) 備註一節中的範例 1。這可以大幅改善周遊效能，代價是 TLAS 建置時間會長得多。

## 四邊形

XDXR BVH 分葉節點最多包含兩個三角形。這些三角形可以有兩個獨立的週框方塊 AABB 節點，也可以合併成單一週框 AABB 並視為一個「四邊形」。執行階段和離線建置器都可以藉由尋找共用一條邊、且合併後的週框方塊相對於各三角形自身的週框方塊膨脹在可接受範圍內的相鄰三角形，來產生四邊形。良好的「四邊形化」是理想的，可以改善記憶體使用量和效能。由於搜尋相鄰三角形的空間較大，離線建置器能夠產生更多四邊形。執行階段建置器只能配對三角形清單中第 1 個和第 2 個相鄰的三角形，而無法配對第 2 個和第 3 個。

[PIX BVH 檢視器](/zh-TW/tools/tools-console/pix/gpu/pix-bvh-viewer)中所述的 PIX BVH 檢視器可以顯示有關四邊形的統計資料。

## k-DOP

建置 BLAS 時，建構 k-DOP 可能會改善周遊效能。這是以記憶體換取效能的取捨。k-DOP 可作為查閱資料表，以在世界空間中快速建構保守的執行個體 AABB。如需詳細資訊，請參閱 [k-DOP 文件](/zh-TW/build/core-features/graphics/newfeatures/raytracing/rt-kdop)。

## BVH 記憶體需求

XDXR BVH 的記憶體需求高於某些 PC 廠商。目前，在考量標頭、AABB、三角形資料和中繼資料的情況下，每個三角形需要 120 到 140 個位元組。離線建置的 BVH 和壓縮後的執行階段建置 BVH 皆是如此，且由於硬體節點格式的關係，不太可能有顯著的變化。

若要減少以執行階段建置器建置之 BLAS 的壓縮後記憶體大小，建議使用索引緩衝區，並針對「頂點快取重複使用」進行最佳化。這會排序三角形，讓連續的三角形更可能共用一條邊。這有助於形成四邊形，減少分葉數量和內部節點數量。

若要減少磁碟上的大小，請參閱 [XDXR BVH 壓縮](/zh-TW/build/core-features/graphics/newfeatures/raytracing/rt-compression)。這可以將磁碟大小減少 **3.5 倍到 6.6 倍**，且可以與 ZLIB 結合以進一步減少大小。這不會減少記憶體中的大小。

## 另請參閱

[XDXR BVH 壓縮](/zh-TW/build/core-features/graphics/newfeatures/raytracing/rt-compression) [D3D12XBOX\_BUILD\_RAYTRACING\_ACCELERATION\_STRUCTURE\_PARAMS1](/zh-TW/reference/graphics/d3d12_xs/structs/d3d12xbox_build_raytracing_acceleration_structure_params1)  [D3D12XBOX\_BUILD\_RAYTRACING\_ACCELERATION\_STRUCTURE\_PARAMS2](/zh-TW/reference/graphics/d3d12_xs/structs/d3d12xbox_build_raytracing_acceleration_structure_params2) [D3D12XBOX\_BUILD\_RAYTRACING\_ACCELERATION\_STRUCTURE\_PARAMS3](/zh-TW/reference/graphics/d3d12_xs/structs/d3d12xbox_build_raytracing_acceleration_structure_params3) [BuildRaytracingAccelerationStructureBatched2X](/zh-TW/reference/graphics/d3d12_xs/interfaces/ID3D12GraphicsCommandList6/methods/id3d12graphicscommandlist6_buildraytracingaccelerationstructurebatched2x) [光線追蹤 (與 DXR) 概觀](/zh-TW/build/core-features/graphics/newfeatures/raytracing/rt-overview)


## Related topics

- [NDA 主題目錄 - Microsoft Learn 線上連結](/zh-TW/nda/nda-topic-directory.md)
- [使用 GDKX 建置並執行你的第一個主機遊戲](/zh-TW/home/build-first-title/first-console-title-walkthrough.md)
- [Raytracing on XBOX Series X|S with XDXR](/build/core-features/graphics/newfeatures/raytracing/index.md)
- [安裝 GDK 工具鏈](/zh-TW/home/setup-install/download-install.md)
- [Raytracing en XBOX Series X|S con XDXR](/es/build/core-features/graphics/newfeatures/raytracing/index.md)
