Share via


HLSL의 루트 서명 지정

C++ 코드에서 루트 서명을 지정하는 대신 HLSL 셰이더 모델 5.1에서 루트 서명을 지정할 수 있습니다.

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 절은 루트 서명의 루트 상수를 지정합니다. 두 개의 필수 매개 변수는 cbuffernum32BitConstantsbReg(C++ API의 BaseShaderRegister에 해당하는 레지스터)입니다. 공간(C++ API의 RegisterSpace) 및 표시 여부(C++의 ShaderVisibility) 매개 변수는 선택 사항이며 기본값은 다음과 같습니다.

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(순서가 지정되지 않은 액세스 보기) 절은 루트 수준 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 및 샘플러가 포함됩니다. 해당 매개 변수는 루트 수준 절의 매개변수와는 다릅니다.

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)

매개 변수 옵션은 HLSL의 열거로 제한되는 borderColor를 제외하고, C++ API 호출과 매우 유사합니다.

필터 필드는 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을 만드는 것인데, 아마도 큰 셰이더 세트로 재사용하여 공간을 절약할 수 있을 것입니다. 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 원본 파일에서 셰이더 바이트 코드를 만듭니다. 이 컴파일러에는 많은 선택적 매개 변수가 있습니다. 효과 컴파일러 도구를 참조하세요.

HLSL 인증 루트 서명 관리를 위한 FXC 사용의 몇 가지 예제가 다음 표에 나와 있습니다.

꺾은선형 명령 줄 Description
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

셰이더 지정 스텐실 참조 값

형식화된 UAV(순서가 지정되지 않은 액세스 뷰) 로드