在 HLSL 中指定根簽章
在 HLSL 著色器模型 5.1 中指定根簽章是 C++ 程式碼中指定根簽章的替代方案。
- 範例 HLSL 根簽章
- RootFlags
- 根常數
- 可見性
- 根層級 CBV
- 根層級 SRV
- 根層級 UAV
- 描述項資料表
- 靜態取樣器
- 編譯 HLSL 根簽章
- 使用 FXC 編譯器操作根簽章
- 注意事項
- 相關主題
範例 HLSL 根簽章
根簽章可以在 HLSL 中指定為字串。 字串包含逗號分隔子句的集合,描述根簽章組成元件。 任何一個管線狀態物件 (PSO) ,根簽章應該在著色器之間相同。 範例如下:
根簽章 1.0 版
#define MyRS1 "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
"DENY_VERTEX_SHADER_ROOT_ACCESS), " \
"CBV(b0, space = 1), " \
"SRV(t0), " \
"UAV(u0, visibility = SHADER_VISIBILITY_GEOMETRY), " \
"DescriptorTable( CBV(b0), " \
"UAV(u1, numDescriptors = 2), " \
"SRV(t1, numDescriptors = unbounded)), " \
"DescriptorTable(Sampler(s0, numDescriptors = 2)), " \
"RootConstants(num32BitConstants=1, b9), " \
"DescriptorTable( UAV(u3), " \
"UAV(u4), " \
"UAV(u5, offset=1)), " \
"StaticSampler(s2)," \
"StaticSampler(s3, " \
"addressU = TEXTURE_ADDRESS_CLAMP, " \
"filter = FILTER_MIN_MAG_MIP_LINEAR )"
此定義會提供下列根簽章,注意:
- 使用預設參數。
- b0 和 (b0, space=1) 不衝突
- u0 只對幾何著色器可見
- u4 和 u5 會別名為堆積中的相同描述項
根簽章 1.1 版
根簽章版本 1.1 可啟用根簽章描述元和資料上的驅動程式優化。
#define MyRS1 "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
"DENY_VERTEX_SHADER_ROOT_ACCESS), " \
"CBV(b0, space = 1, flags = DATA_STATIC), " \
"SRV(t0), " \
"UAV(u0), " \
"DescriptorTable( CBV(b1), " \
"SRV(t1, numDescriptors = 8, " \
" flags = DESCRIPTORS_VOLATILE), " \
"UAV(u1, numDescriptors = unbounded, " \
" flags = DESCRIPTORS_VOLATILE)), " \
"DescriptorTable(Sampler(s0, space=1, numDescriptors = 4)), " \
"RootConstants(num32BitConstants=3, b10), " \
"StaticSampler(s1)," \
"StaticSampler(s2, " \
"addressU = TEXTURE_ADDRESS_CLAMP, " \
"filter = FILTER_MIN_MAG_MIP_LINEAR )"
HLSL 根簽章語言與 C++ 根簽章 API 緊密對應,且具有同等的表達能力。 根簽章會指定為子句序列,並以逗號分隔。 子句的順序很重要,因為剖析的順序決定根簽章中的位置位置。 每個子句都會採用一或多個具名參數。 不過,參數的順序並不重要。
RootFlags
選擇性 的 RootFlags 子句會採用 0 (預設值來表示沒有旗標) ,或透過 OR '|' 運算子連線的一或多個預先定義根旗標值。 允許的根旗標值是由 D3D12_ROOT_SIGNATURE_FLAGS所定義。
例如:
RootFlags(0) // default value – no flags
RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)
RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | DENY_VERTEX_SHADER_ROOT_ACCESS)
根常數
RootConstants子句會指定根簽章中的根常數。 兩個必要參數為: num32BitConstants 和 bReg (c++ API 中 對應至 BaseShaderRegister) cbuffer的暫存器。 C++ API 中的 space (RegisterSpace) 和 visibility (C++) 參數中的 ShaderVisibility 是選擇性的,預設值為:
RootConstants(num32BitConstants=N, bReg [, space=0,
visibility=SHADER_VISIBILITY_ALL ])
例如:
RootConstants(num32BitConstants=3, b3)
可見性
可見度是選擇性參數,可以從 D3D12_SHADER_VISIBILITY取得其中一個值。
SHADER_VISIBILITY_ALL會將根引數廣播到所有著色器。 在某些硬體上,這不需要任何成本,但在其他硬體上,會將資料分叉至所有著色器階段的成本。 設定其中一個選項,例如SHADER_VISIBILITY_VERTEX,會將根引數限制為單一著色器階段。
將根引數設定為單一著色器階段,即可在不同的階段使用相同的系結名稱。 例如,的 SRV 系 t0,SHADER_VISIBILITY_VERTEX
結和 的 SRV 系 t0,SHADER_VISIBILITY_PIXEL
結是有效的。 但是,如果其中一個系結的可見度設定是 t0,SHADER_VISIBILITY_ALL
不正確,則根簽章會無效。
根層級 CBV
CBV
(常數緩衝區檢視) 子句會指定根層級常數緩衝區 b-register Reg 專案。 請注意,這是純量專案;無法指定根層級的範圍。
CBV(bReg [, space=0, visibility=SHADER_VISIBILITY_ALL ]) // Version 1.0
CBV(bReg [, space=0, visibility=SHADER_VISIBILITY_ALL, // Version 1.1
flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
根層級 SRV
SRV
(著色器資源檢視) 子句會指定根層級 SRV t-register Reg 專案。 請注意,這是純量專案;無法指定根層級的範圍。
SRV(tReg [, space=0, visibility=SHADER_VISIBILITY_ALL ]) // Version 1.0
SRV(tReg [, space=0, visibility=SHADER_VISIBILITY_ALL, // Version 1.1
flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
根層級 UAV
UAV
(未排序的存取檢視) 子句會指定根層級 UAV u-register Reg 專案。 請注意,這是純量專案;無法指定根層級的範圍。
UAV(uReg [, space=0, visibility=SHADER_VISIBILITY_ALL ]) // Version 1.0
UAV(uReg [, space=0, visibility=SHADER_VISIBILITY_ALL, // Version 1.1
flags=DATA_VOLATILE ])
例如:
UAV(u3)
描述項資料表
子 DescriptorTable
句本身是逗號分隔描述項資料表子句的清單,以及選擇性的可見度參數。
DescriptorTable子句包括 CBV、SRV、UAV 和 Sampler。 請注意,其參數與根層級子句的參數不同。
DescriptorTable( DTClause1, [ DTClause2, … DTClauseN,
visibility=SHADER_VISIBILITY_ALL ] )
描述項資料表 CBV
具有下列語法:
CBV(bReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
CBV(bReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND // Version 1.1
, flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
例如:
DescriptorTable(CBV(b0),SRV(t3, numDescriptors=unbounded))
強制參數 bReg 會指定 cbuffer 範圍的開始 Reg。
numDescriptors參數會指定連續 cbuffer 範圍中的描述元數目;預設值為 1。 當numDescriptors為數字時,此專案會宣告 cbuffer 範圍 [Reg, Reg + numDescriptors - 1]
。 如果 numDescriptors 等於 「unbounded」,則範圍是 [Reg, UINT_MAX]
,這表示應用程式必須確定它未參考超出範圍的區域。
offset欄位代表 C++ API 中的OffsetInDescriptorsFromTableStart參數,也就是從資料表開頭) 描述元中的位移 (。 如果位移設定為DESCRIPTOR_RANGE_OFFSET_APPEND (預設) ,表示範圍會直接在上一個範圍之後。 不過,輸入特定位移可讓範圍彼此重迭,並允許暫存器別名。
描述項資料表 SRV
具有下列語法:
SRV(tReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
SRV(tReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, // Version 1.1
flags=DATA_STATIC_WHILE_SET_AT_EXECUTE ])
這類似于描述項資料表 CBV
專案,但指定的範圍適用于著色器資源檢視。
描述項資料表 UAV
具有下列語法:
UAV(uReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
UAV(uReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, // Version 1.1
flags=DATA_VOLATILE ])
這類似于描述項資料表 CBV
專案,但指定的範圍是用於未排序的存取檢視。
描述項資料表 Sampler
具有下列語法:
Sampler(sReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND ]) // Version 1.0
Sampler(sReg [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, // Version 1.1
flags=0 ])
這類似于描述項資料表 CBV
專案,但指定的範圍是著色器取樣器。 請注意,取樣器無法與相同描述中繼資料表中的其他類型的描述元混合 (,因為它們位於個別的描述元堆積) 。
靜態取樣器
靜態取樣器代表 D3D12_STATIC_SAMPLER_DESC 結構。 StaticSampler的必要參數是純量取樣器 s-register Reg。其他參數是選擇性參數,預設值如下所示。 大部分的欄位都接受一組預先定義的列舉。
StaticSampler( sReg,
[ filter = FILTER_ANISOTROPIC,
addressU = TEXTURE_ADDRESS_WRAP,
addressV = TEXTURE_ADDRESS_WRAP,
addressW = TEXTURE_ADDRESS_WRAP,
mipLODBias = 0.f,
maxAnisotropy = 16,
comparisonFunc = COMPARISON_LESS_EQUAL,
borderColor = STATIC_BORDER_COLOR_OPAQUE_WHITE,
minLOD = 0.f,
maxLOD = 3.402823466e+38f,
space = 0,
visibility = SHADER_VISIBILITY_ALL ])
例如:
StaticSampler(s4, filter=FILTER_MIN_MAG_MIP_LINEAR)
參數選項與 C++ API 呼叫非常類似,但 borderColor除外,限制為 HLSL 中的列舉。
篩選欄位可以是 其中一個D3D12_FILTER。
位址欄位可以是其中一個 D3D12_TEXTURE_ADDRESS_MODE。
比較函式可以是 其中一個D3D12_COMPARISON_FUNC。
框線色彩欄位可以是 其中一個D3D12_STATIC_BORDER_COLOR。
可見度可以是 其中一個D3D12_SHADER_VISIBILITY。
編譯 HLSL 根簽章
有兩種機制可編譯 HLSL 根簽章。 首先,您可以使用MyRS1進入點) ,透過RootSignature屬性將根簽章字串附加至特定著色器 (:
[RootSignature(MyRS1)]
float4 main(float4 coord : COORD) : SV_Target
{
…
}
編譯器會建立並驗證著色器的根簽章 Blob,並將它與著色器位元組程式碼一起內嵌至著色器 Blob。 編譯器支援著色器模型 5.0 和更新版本的根簽章語法。 如果根簽章內嵌在著色器模型 5.0 著色器中,而且該著色器會傳送至 D3D11 執行時間,而不是 D3D12,則 D3D11 會以無訊息方式忽略根簽章部分。
另一個機制是建立獨立根目錄簽章 Blob,或許可以重複使用一組大型著色器,以節省空間。 效果編譯器工具 (FXC) 支援rootsig_1_0和rootsig_1_1著色器模型。 定義字串的名稱是透過一般的 /E 引數來指定。 例如:
fxc.exe /T rootsig_1_1 MyRS1.hlsl /E MyRS1 /Fo MyRS1.fxo
請注意,根簽章字串定義也可以在命令列上傳遞,例如 /D MyRS1=「...」。
使用 FXC 編譯器操作根簽章
FXC 編譯器會從 HLSL 原始程式檔建立著色器位元組程式碼。 此編譯器有許多選擇性參數,請參閱 Effect-Compiler Tool。
為了管理 HLSL 撰寫的根簽章,下表提供一些使用 FXC 的範例。
折線圖 | 命令列 | 描述 |
---|---|---|
1 | fxc /T ps_5_1 shaderWithRootSig.hlsl /Fo rs1.fxo |
編譯圖元著色器 5.1 目標的著色器,著色器來源位於著色器WithRootSig.hlsl 檔案中,其中包含根簽章。 著色器和根簽章會編譯為 rs1.fxo 二進位檔中的個別 Blob。 |
2 | fxc /dumpbin rs1.fxo /extractrootsignature /Fo rs1.rs.fxo |
從第 1 行所建立的檔案擷取根簽章,因此 rs1.rs.fxo 檔案只包含根簽章。 |
3 | fxc /dumpbin rs1.fxo /Qstrip_rootsignature /Fo rs1.stripped.fxo |
從第 1 行所建立的檔案中移除根簽章,因此 rs1.stripped.fxo 檔案包含沒有根簽章的著色器。 |
4 | fxc /dumpbin rs1.stripped.fxo /setrootsignature rs1.rs.fxo /Fo rs1.new.fxo |
將個別檔案中的著色器和根簽章合併成包含兩個 Blob 的二進位檔案。 在此範例中,rs1.new.fx0 與第 1 行中的 rs1.fx0 相同。 |
5 | fxc /T rootsig_1_0 rootSigAndMaybeShaderInHereToo.hlsl /E RS1 /Fo rs2.fxo |
從可能只包含根簽章的來源建立獨立根目錄簽章二進位檔案。 請注意rootsig_1_0目標,而 RS1 是 HLSL 檔案中根簽章 (#define) 宏字串的名稱。 |
您也可以使用 D3DCompile 函式,以程式設計方式使用 FXC 提供的功能。 此呼叫會使用根簽章或獨立根目錄簽章編譯著色器, (設定rootsig_1_0目標) 。 D3DGetBlobPart 和 D3DSetBlobPart 可以將根簽章擷取並附加至現有的 Blob。 D3D_BLOB_ROOT_SIGNATURE用來指定根簽章 Blob 元件類型。 D3DStripShader 會使用 blob D3DCOMPILER_STRIP_ROOT_SIGNATURE 旗標) 移除根簽章 (。
備註
注意
強烈建議離線編譯著色器,如果必須在執行時間編譯著色器,請參閱 D3DCompile2的備註。
注意
現有的 HLSL 資產不需要變更,即可處理要與它們搭配使用的根簽章。
相關主題