다음을 통해 공유


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 절은 OR '|' 연산자를 통해 연결된 0(플래그 없음을 나타내는 기본값) 또는 미리 정의된 루트 플래그 값 중 하나 또는 몇 가지를 사용합니다. 허용되는 루트 플래그 값은 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 및 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 숫자가면 항목은 [Reg, Reg + numDescriptors - 1]cbuffer 범위를 선언합니다. numDescriptors이 "unbounded"와 같으면, 범위가 [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)

매개 변수 옵션은 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 셰이더에 포함되어 있고 해당 셰이더가 D3D12와 달리 D3D11 런타임으로 전송되는 경우 루트 서명 부분은 D3D11에서 자동으로 무시됩니다.

또 다른 방법은 독립 실행형 루트 서명 Blob을 만들어 큰 셰이더 집합과 함께 재사용하여 사이즈를 절약하는 것입니다. FXC(Effect-Compiler Tool)는 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 도구참조하세요.

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

셰이더 지정 스텐실 참조 값

형식화된 정렬되지 않은 액세스 뷰 로드