Share via


在 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 子句會採用 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子句會指定根簽章中的根常數。 兩個必要參數為: num32BitConstantsbReg (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_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 目標的著色器,著色器來源位於著色器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目標) 。 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

著色器指定的樣板參考值

具類型的未排序存取檢視載入