共用方式為


在 HLSL 中指定根簽章

在 HLSL 著色器模型 5.1 中指定根簽章是C++程式代碼中指定根簽章的替代方案。

範例 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 子句接受零(預設值表示無標誌),或透過 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 子句會指定根簽章中的根常數。 兩個強制參數為:num32BitConstantsbReg(與 C++ API 中的 BaseShaderRegister 對應的寄存器)的常量緩衝區。 C++ API 中的 space (RegisterSpace) 和可見度 (ShaderVisibility C++) 參數是選擇性的,預設值為:

RootConstants(num32BitConstants=N, bReg [, space=0, 
              visibility=SHADER_VISIBILITY_ALL ])

例如:

RootConstants(num32BitConstants=3, b3)

能見度

Visibility 是選擇性參數,可以從 D3D12_SHADER_VISIBILITY取得其中一個值。

SHADER_VISIBILITY_ALL將根引數廣播到所有著色器。 在某些硬體上,這不需要任何開銷,但在其他硬體上,將數據分叉到所有著色器階段會產生開銷。 設定其中一個選項,例如SHADER_VISIBILITY_VERTEX,會將根自變數限制為單一著色器階段。

將根自變數設定為單一著色器階段,可讓不同的階段使用相同的系結名稱。 例如,t0,SHADER_VISIBILITY_VERTEX 的SRV系結和 t0,SHADER_VISIBILITY_PIXEL 的SRV系結是有效的。 但是,如果其中一個系結的可見性設定 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 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 子句本身是逗號分隔描述符表子句的清單,以及可選的可見性參數。 描述元數據表 子句包括 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 等於「未系結」,範圍會 [Reg, UINT_MAX],這表示應用程式必須確保它不會參考超出範圍的區域。 位移 字段代表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 根簽章。 首先,可以透過 RootSignature 屬性,將根簽章字串附加至特定著色器(在下列範例中,使用 MyRS1 進入點):

[RootSignature(MyRS1)]
float4 main(float4 coord : COORD) : SV_Target
{
…
}

編譯器將為著色器創建並驗證根簽章 Blob,然後將它與著色器位元組代碼一起內嵌到著色器 Blob 中。 編譯程式支援著色器模型 5.0 和更新版本的根簽章語法。 如果根簽章嵌入在著色器模型 5.0 的著色器中,且該著色器會被傳送到 D3D11 執行階段而非 D3D12,則 D3D11 會靜默忽略根簽章部分。

另一個機制是建立獨立的根簽章 Blob,或許可以重複使用一組大型著色器,以節省空間。 Effect-Compiler 工具 (FXC) 同時支援 rootsig_1_0rootsig_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 目標的著色器,著色器來源位於 shaderWithRootSig.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) 巨集字串的名稱。

 

透過 FXC 提供的功能也可透過程式設計方式使用 D3DCompile 函式。 此呼叫會編譯具有根簽章或獨立根簽章的著色器(設定rootsig_1_0目標)。 D3DGetBlobPartD3DSetBlobPart 可以將根簽章擷取和附加至現有的 Blob。  D3D_BLOB_ROOT_SIGNATURE用來指定根簽章 Blob 元件類型。 D3DStripShader 會從 blob 中移除根簽章(使用 D3DCOMPILER_STRIP_ROOT_SIGNATURE 旗標)。

筆記

注意

強烈建議先進行著色器的脫機編譯,但如果必須在運行時間編譯著色器,請參閱 D3DCompile2的備註。

 

注意

現有的 HLSL 資產不需要變更,即可處理要與它們搭配使用的根簽章。

 

使用 HLSL 5.1 進行動態索引

適用於 Direct3D 12 的 HLSL 著色器模型 5.1 功能

資源系結

資源系結在 HLSL

根簽章

著色器模型 5.1

著色器指定的樣板參考值

類型化的非排序存取視圖載入