RayQuery 物件。不過,我們提供單一標頭的周遊實作 (具有數個變體),它與我們的 DXR 1.0 周遊邏輯共用大部分程式碼,並將其包裝在與 RayQuery 物件 API 大致相同的 API 中。此標頭可用於任何允許使用者配置 LDS 的著色器階段,包括計算著色器與像素著色器。
此系統應能讓依賴 DXR 1.1 RayQuery 的 PC 轉譯程式碼進行簡單 (幾乎 1:1) 的轉換。此外,在光線追蹤著色器 (AnyHit/ClosestHit 等) 數量不多的情況下,由於額外負荷較低,此系統在 XBOX 上通常明顯比 DXR 1.0 風格的光線追蹤更快。強烈建議陰影或環境光遮蔽等轉譯功能使用此內嵌標頭系統。
請注意,XDXR 目前不會針對 DXR 1.0 內嵌小型著色器繫結資料表。因此,部分 PC IHV 可能會有不同的建議。建議您獨立於 PC 驅動程式之外,分析 XBOX 光線追蹤的取捨。
使用方式
標頭
為取代 DXR 1.1 的RayQuery 物件,我們在 GDK 安裝目錄 GDK_Install_Path\GDK_Version\GXDK\gameKit\Include\Scarlett 中提供數個版本的 XDXRStandaloneTraverse***.hlsli 標頭檔。
這些標頭以原始程式碼形式提供,但開發人員必須負責確保其標頭檔版本與建置 BVH 所使用的 GDK 相容。較新的 GDK 不支援舊版標頭,而對標頭所做的修改必須與較新 GDK 中的任何變更合併。
目前的版本如下:
- XDXRStandaloneTraverseShortStack.hlsli
- 此周遊版本與 XDXR 中目前用於 DXR 1.0 支援的預設周遊演算法相同。建議用於所有可能具有發散性的光線追蹤,例如 AO 或光澤反射。
- XDXRStandaloneTraverseHT.hlsli
- 此周遊版本實作「一致性」(coherent) 周遊演算法,對於陰影光線或鏡面反射等高度一致的內容,可能比其他演算法更快。這等同於在 DXR 1.0
TraceRay()光線旗標中指定XBOX_RAY_FLAG_COHERENT_RAYS_HINT。
- 此周遊版本實作「一致性」(coherent) 周遊演算法,對於陰影光線或鏡面反射等高度一致的內容,可能比其他演算法更快。這等同於在 DXR 1.0
- XDXRStandaloneTraverseShortStackNoMultibox.hlsli
- 此周遊版本不支援離線建置的 BVH,但如果只執行執行階段 BVH 建置,可能會稍微快一些。
- XDXRStandaloneTraverseLongStack.hlsli
- 此周遊版本的堆疊大小上限為 32 個節點,在某些內容上可能更快,但可能導致遺漏光線命中。
整合
XDXRStandaloneTraverse 標頭提供與 DXR 1.1RayQuery 物件相對應的 XboxRayQuery 物件。除了命名之外,API 應與 DXR 1.1 相同,但有下列差異:
- 只有在 2024 年 3 月 GDK 或更新版本中以 HLSL 2021 編譯時,才支援
XboxRayQuery<RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES>之類的範本旗標。 - 在 HLSL 2021 與 2024 年 3 月 GDK 之前,使用者應以下列其中一種方式取代
RayQuery<RAY_FLAG_XXX | RAY_FLAG_YYY>:- 將所有旗標放在 TraceRayInline() 的 rayFlags 參數中。旗標建議使用編譯時期常值,而非常數緩衝區值,以產生更好的程式碼。如果您想切換旗標,請考慮以分支方式呼叫不同的 TraceRayInline()。
- 使用
XboxRayQuery.TraceRayInlineNoAHS()取代RayQuery<RAY_FLAG_FORCE_OPAQUE>;同樣地,使用XboxRayQuery.TraceRayInlineNoIS()或XboxRayQuery.TraceRayInlineNoAHSNoIS()停用交集著色器處理。- 同樣地,
XboxRayQuery物件上也有disableAHS與disableIS布林成員,可在呼叫TraceRayInline之後、第一次呼叫Proceed()之前設定為常值。
- 同樣地,
XboxRayQuery會維護全域狀態,一個XboxRayQuery物件的所有使用都必須在建立或使用第二個物件之前完成。這包括查詢最終命中狀態或資訊。- XDXR (以及
XboxRayQuery) 目前不支援RAY_FLAG_SKIP_TRIANGLES或RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES。如果需要分離,請考慮使用批次建置器 API 平行建置多個 TLAS。- 例外的是,HLSL2021 支援
XboxRayQuery<RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES>,其等同於XboxRayQuery.TraceRayInlineNoIS()。此旗標僅支援作為範本參數。
- 例外的是,HLSL2021 支援
- 由於一致性演算法的結構,
XDXRStandaloneTraverseHT.hlsli要求所有Proceed()處理常式程式碼在 AnyHit 或交集著色器邏輯之前加入if (query.CandidateType() == CANDIDATE_NON_OPAQUE_TRIANGLE || query.CandidateType() == CANDIDATE_PROCEDURAL_PRIMITIVE),以檢查確實回報了有效的命中。雖然在一般 DXR 1.1 中允許這樣做,但如果已知 BVH 只包含一種基本型別,通常會省略此檢查。這會導致XDXRStandaloneTraverseHT.hlsli實作中出現瑕疵。 XDXRStandaloneTraverseHT.hlsli周遊實作要求光線旗標與 TLAS 指標必須一致 (uniform)。- XDXR 獨立周遊包含數個 DXR 1.1 中沒有的延伸功能,將於下一節中討論。
CurrentNumIterations() 與 SetMaxNumIterations()
XDXR 獨立周遊新增了兩個與查詢及限制周遊反覆運算次數相關的簡單延伸功能。請注意,這些延伸功能都可能造成額外的 VGPR 壓力或 ALU 負擔。除非使用者打算設定夠低的反覆運算限制以抵銷額外成本,否則不應使用/啟用這些功能。XboxRayQuery.CurrentNumIterations()會傳回到目前為止已執行的周遊邏輯反覆運算次數。可以在周遊之後呼叫此函式以繪製熱度圖,或在 AHS 邏輯或類似邏輯中呼叫以做出決策。著色器中對此函式的任何參考都會為周遊增加些許成本,即使位於執行階段旗標之後也是如此。建議將任何「熱度圖」模式放在#ifdef旗標之後,以確保發行模式不受影響。XboxRayQuery.SetMaxNumIterations(uint maxNumIterations)可設定反覆運算次數上限,超過此上限後周遊將提早結束,結果將包含最近一次認可的命中 (若尚未找到則為無)。- 若要使用此功能,必須在包含周遊標頭之前設定
#define XDXR_ENABLE_ITERATION_LIMIT 1。 - 將
XboxRayQuery.SetMaxNumIterations(YOUR_ITERATION_LIMIT)呼叫放在XboxRayQuery.TraceRayInline()呼叫之後、XboxRayQuery.Proceed()呼叫之前。 - 若要測試周遊是否提早結束,請檢查是否
XboxRayQuery.CurrentNumIterations() >= YOUR_ITERATION_LIMIT。請注意,反覆運算次數可能高於限制,特別是在XDXRStandaloneTraverseHT.hlsli的情況下,因為周遊的某些階段無法在不產生大量成本的情況下提早結束。
- 若要使用此功能,必須在包含周遊標頭之前設定
InlineAHS 與 InlineIS
XDXR 獨立周遊提供兩個延伸功能,可在需要簡單的 AnyHit 或交集著色器邏輯時提升周遊速度。 根據預設,DXR 1.1 RayQuery 周遊必須跳出 BVH 周遊迴圈,才能將控制權交給使用者,以在while(query.Proceed()) 迴圈中處理 AnyHit 或交集著色器邏輯。這可能導致複雜的流程控制以及次佳的效能。
XDXR 獨立周遊提供 InlineAHS 與 InlineIS 機制,允許將 AHS 或 IS 邏輯內嵌於周遊迴圈中,以提升效能。
自 2024 年 3 月 GDK 起,XDXR_USE_INLINE_AHS_FUNCTION 與 XDXR_USE_INLINE_IS_FUNCTION 定義已被取代。InlineAHS 與 InlineIS 功能現在可透過以 HLSL 2021 範本為基礎的 API 使用,並具有數項優點。以下是 HLSL 2021 版本的說明,舊版的說明則位於下方的章節。
HLSL 2021 InlineAHS 與 InlineIS
- 根據您需要 AnyHit (AHS) 邏輯、程序式交集 (IS) 邏輯或兩者,建立一個延伸
InlineAHSBaseLambda、InlineISBaseLambda或InlineAHSAndISBaseLambda其中之一的 HLSL 結構。 - 在結構中建立簽章與名稱為
void InlineAHS(inout XboxRayQueryProxy rqp)和/或void InlineIS(inout XboxRayQueryProxy rqp)的函式。 - 將
while(query.Proceed()) {ISLogic(); AHSLogic()}迴圈中的所有 AHS 與 IS 邏輯剪下/貼上到InlineAHS或InlineIS函式中。 XboxRayQueryProxy物件支援與一般XboxRayQuery完全相同的功能,但XboxRayQuery.CandidateType()getter 除外。請在InlineAHS()中處理CANDIDATE_NON_OPAQUE_TRIANGLE邏輯,並在InlineIS()中處理CANDIDATE_PROCEDURAL_PRIMITIVE邏輯 (包括 Alpha 測試)。XboxRayQueryProxy可用來以與一般RayQuery物件完全相同的方式查詢周遊資訊,並透過rayQueryProxy.CommitNonOpaqueTriangleHit()或rayQueryProxy.Abort()函式處理命中。- 可在
InlineIS()中查詢rayQueryProxy.CandidateProceduralPrimitiveNonOpaque(),以判斷是否應針對程序式基本型別執行 AHS 邏輯。這與標準 DXR 1.1 內嵌光線追蹤相同。
- 可在
- 使用
InlineAHS或InlineIS(或兩者) 時,不需要將rayQuery.Proceed()呼叫放在 while 迴圈中,因為在周遊完成之前,控制權不會交還給使用者。所有 AHS 或 IS 邏輯都會使用提供的函式內嵌。
HLSL 2018 InlineAHS 與 InlineIS (已淘汰)
- 在
#include "XDXRStandaloneTraverse****.hlsli"之前指定#define XDXR_USE_INLINE_AHS_FUNCTION 1和/或#define XDXR_USE_INLINE_IS_FUNCTION 1。請注意,如果同時存在 AHS 與 IS 邏輯,兩者都必須使用內嵌系統,不能與一般 DXR 1.1 處理常式混用。 - 建立簽章與名稱為
void InlineAHS(inout XboxRayQueryProxy rqp)和/或void InlineIS(inout XboxRayQueryProxy rqp)的全域函式 - 依照上述 HLSL 2021 版本的說明操作,並將結構成員 InlineAHS 與 InlineIS 函式取代為全域定義的 InlineAHS 與 InlineIS 函式。
記憶體
XDXR 驅動程式會為 DXR 1.0TraceRay() 風格的周遊配置後備記憶體。如果您的遊戲只使用內嵌光線追蹤,您可能會想回收這些記憶體。截至 2022 年 6 月,此記憶體在 XBOX Series S 上為 12MB,在 XBOX Series X 上為 32MB。若要停用此記憶體,遊戲應在 D3D12XBOX_CREATE_DEVICE_PARAMETERS 中為 pDXRStackBuffer 指定 D3D12_GPU_VIRTUAL_ADDRESS_UNKNOWN,並為 DXRStackBufferOverrideSizeBytes 指定大小 0。
