루트 서명 버전 1.1
루트 서명 버전 1.1의 목적은 설명자 힙의 설명자가 변경되지 않거나 데이터 설명자가 가리키면 변경되지 않을 때 애플리케이션이 드라이버를 나타낼 수 있도록 하는 것입니다. 이렇게 하면 드라이버가 특정 기간 동안 설명자 또는 가리키는 메모리가 정적임을 알 수 있는 최적화를 수행할 수 있습니다.
- 개요
- 정적 및 휘발성 플래그
- 버전 1.1 API 요약
- 정적 네스 플래그 위반의 결과
- 버전 관리
- 관련 항목
개요
루트 서명 버전 1.0을 사용하면 참조하는 명령 목록/번들이 GPU에서 진행 중일 수 있을 때마다 설명자 힙의 내용과 해당 설명자 힙이 가리키는 메모리를 애플리케이션에서 자유롭게 변경할 수 있습니다. 그러나 애플리케이션을 참조하는 명령이 기록된 후에 설명자 또는 메모리를 변경할 수 있는 유연성이 실제로 필요하지 않은 경우가 많습니다.
애플리케이션은 다음과 같이 간단하게 수행할 수 있는 경우가 많습니다.
- 명령 목록 또는 번들에 설명자 테이블 또는 루트 설명자를 바인딩하기 전에 설명자(및 해당 설명자가 가리키는 메모리 가능)를 설정합니다.
- 이러한 설명자는 참조하는 명령 목록 /번들이 마지막으로 실행을 완료할 때까지 변경되지 않도록 합니다.
- 설명자가 가리키는 데이터가 동일한 전체 기간 동안 변경되지 않는지 확인합니다.
또는 애플리케이션은 더 짧은 기간 동안 데이터가 변경되지 않는다는 점을 인식할 수 있습니다. 특정 데이터는 명령 목록 실행 중에 루트 매개 변수 바인딩(설명자 테이블 또는 루트 설명자)이 현재 데이터를 가리키는 기간 동안 정적일 수 있습니다. 즉, 애플리케이션은 루트 매개 변수를 통해 설정된 기간 사이에 일부 데이터를 업데이트하는 GPU 타임라인에서 실행을 수행하려고 할 수 있습니다. 이는 설정된 경우 정적이라는 것을 알고 있습니다.
설명자 또는 데이터 설명자가 가리키는 경우 드라이버가 수행할 수 있는 특정 최적화는 하드웨어 공급업체와 관련이 있으며, 중요한 것은 성능 향상 이외의 동작을 변경하지 않는다는 것입니다. 애플리케이션 의도에 대한 지식을 최대한 많이 유지해도 애플리케이션에 부담이 되지는 않습니다.
한 가지 최적화는 애플리케이션이 설명자 및 데이터의 정적 효율성에 대해 만들 수 있는 약속을 알고 있는 경우 셰이더가 보다 효율적인 메모리 액세스를 생성할 수 있다는 것입니다. 예를 들어 드라이버는 특정 하드웨어가 루트 인수 크기에 민감하지 않은 경우 루트 설명자로 변환하여 힙의 설명자에 액세스하기 위한 간접 참조 수준을 제거할 수 있습니다.
버전 1.1을 사용하는 개발자를 위한 추가 작업은 가능한 경우 데이터의 변동성과 정적 니스를 약속하여 드라이버가 적합한 최적화를 수행할 수 있도록 하는 것입니다. 개발자는 정적 성에 대한 약속을 할 필요가 없습니다.
루트 서명 버전 1.0은 변경되지 않고 계속 작동하지만 루트 서명을 다시 컴파일하는 애플리케이션은 이제 루트 서명 1.1로 기본 설정됩니다(원하는 경우 버전 1.0을 강제 적용하는 옵션 포함).
정적 및 휘발성 플래그
다음 플래그는 드라이버가 개별 루트 인수를 설정할 때 가장 잘 처리하는 방법에 대한 전략을 선택할 수 있도록 하는 루트 서명의 일부이며, 루트 서명이 PSO의 일부이므로 원래 컴파일될 때 PSO(파이프라인 상태 개체)에 동일한 가정을 포함할 수도 있습니다.
앱에서 다음 플래그를 설정하고 설명자 또는 데이터에 적용합니다.
typedef enum D3D12_DESCRIPTOR_RANGE_FLAGS
{
D3D12_DESCRIPTOR_RANGE_FLAG_NONE = 0,
D3D12_DESCRIPTOR_RANGE_FLAG_DESCRIPTORS_VOLATILE = 0x1,
D3D12_DESCRIPTOR_RANGE_FLAG_DATA_VOLATILE = 0x2,
D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
D3D12_DESCRIPTOR_RANGE_FLAG_DATA_STATIC = 0x8
} D3D12_DESCRIPTOR_RANGE_FLAGS;
typedef enum D3D12_ROOT_DESCRIPTOR_FLAGS
{
D3D12_ROOT_DESCRIPTOR_FLAG_NONE = 0,
D3D12_ROOT_DESCRIPTOR_FLAG_DATA_VOLATILE = 0x2,
D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC_WHILE_SET_AT_EXECUTE = 0x4,
D3D12_ROOT_DESCRIPTOR_FLAG_DATA_STATIC = 0x8
} D3D12_ROOT_DESCRIPTOR_FLAGS;
DESCRIPTORS_VOLATILE
이 플래그를 설정하면 설명자 테이블을 바인딩하는 명령 목록/번들이 제출되고 실행이 완료되지 않은 경우를 제외하고 언제든지 루트 설명자 테이블이 가리키는 설명자 힙의 설명자를 애플리케이션에서 변경할 수 있습니다. 예를 들어 명령 목록을 기록하고 실행용 명령 목록을 제출하는 전에 참조하는 설명자 힙에서 설명자를 변경합니다. 이는 루트 서명 버전 1.0에서 유일하게 지원되는 동작입니다.
DESCRIPTORS_VOLATILE 플래그가 설정되지 경우 설명자는 정적입니다. 이 모드에 대한 플래그가 없습니다. 정적 설명자는 설명자 테이블이 가리키는 설명자 힙의 설명자가 명령 목록/번들(기록 중)에서 설명자 테이블이 설정될 때까지 초기화되었으며 명령 목록/번들이 마지막으로 실행을 완료할 때까지 설명자를 변경할 수 없음을 의미합니다. 루트 서명 버전 1.1의 경우 정적 설명자는 기본 가정애플리케이션이 필요할 때 DESCRIPTORS_VOLATILE 플래그를 지정해야 합니다.
정적 설명자와 함께 설명자 테이블을 사용하는 번들의 경우 번들이 호출될 때와 달리 번들이 기록되는 시점부터 설명자를 준비해야 하며 번들이 마지막으로 실행을 완료할 때까지 변경되지 않습니다. 정적 설명자를 가리키는 설명자 테이블은 번들 기록 중에 설정해야 하며 번들에 상속되지 않습니다. 명령 목록에서는 번들에 설정되고 명령 목록으로 다시 반환된 정적 설명자가 있는 설명자 테이블을 사용하는 것이 유효합니다.
설명자가 정적이면 DESCRIPTORS_VOLATILE 플래그를 설정해야 하는 동작이 또 다른 변경됩니다. 버퍼 보기(Texture1D/2D/3D/Cube 뷰와는 반대)에 대한 액세스 범위를 벗어나는 것은 유효하지 않으며 읽기에 대한 기본값을 반환하거나 쓰기를 삭제하는 대신 가능한 디바이스 재설정을 포함하여 정의되지 않은 결과를 생성합니다. 애플리케이션이 하드웨어의 범위를 벗어난 액세스 검사에 의존하는 기능을 제거하는 목적은 드라이버가 더 효율적이라고 판단되는 경우 정적 설명자 액세스를 루트 설명자 액세스로 승격하도록 선택할 수 있도록 하는 것입니다. 루트 설명자는 범위를 벗어난 검사를 지원하지 않습니다.
애플리케이션이 설명자에 액세스할 때 안전한 범위를 벗어난 메모리 액세스 동작에 의존하는 경우 해당 설명자에 액세스하는 설명자 범위를 DESCRIPTORS_VOLATILE 표시해야 합니다.
DATA_VOLATILE
이 플래그 집합을 사용하면 설명자 테이블을 바인딩하는 명령 목록/번들이 제출되어 실행이 완료되지 않은 경우를 제외하고 언제든지 설명자가 가리키는 데이터를 CPU에서 변경할 수 있습니다. 이는 루트 서명 버전 1.0에서 유일하게 지원되는 동작입니다.
플래그는 설명자 범위 플래그와 루트 설명자 플래그 모두에서 사용할 수 있습니다.
DATA_STATIC_WHILE_SET_AT_EXECUTE
이 플래그 집합을 사용하면 GPU 타임라인에서 실행하는 동안 기본 루트 설명자 또는 설명자 테이블이 명령 목록/번들에 설정된 시점부터 설명자가 가리키는 데이터는 변경할 수 없으며 후속 그리기/디스패치가 더 이상 데이터를 참조하지 않을 때 종료됩니다.
GPU에서 루트 설명자 또는 설명자 테이블을 설정하기 전에 이 데이터 동일한 명령 목록/번들에 의해서도 변경될 있습니다. 데이터를 가리키는 루트 설명자 또는 설명자 테이블이 완료된 것을 참조하는 그리기/디스패치가 완료된 한 명령 목록/번들에 설정된 상태에서도 데이터를 변경할 수 있습니다. 그러나 이렇게 하려면 다음에 루트 설명자 또는 설명자 테이블이 역참조되기 전에 설명자 테이블을 다시 명령 목록으로 되감아야 합니다. 이를 통해 드라이버는 루트 설명자 또는 설명자 테이블이 가리키는 데이터가 변경되었음을 알 수 있습니다.
DATA_STATIC_WHILE_SET_AT_EXECUTE DATA_VOLATILE 가장 중요한 차이점은 드라이버가 추가 상태 추적을 수행하지 않고 명령 목록의 데이터 복사본이 설명자가 가리키는 데이터를 변경했는지 여부를 알 수 없다는 DATA_VOLATILE. 예를 들어 드라이버가 명령 목록에 모든 종류의 데이터 사전 인출 명령을 삽입할 수 있는 경우(예를 들어 알려진 데이터에 대한 셰이더 액세스를 보다 효율적으로 만들기 위해) DATA_STATIC_WHILE_SET_AT_EXECUTE SetGraphicsRootDescriptorTable통해 설정된 순간에만 데이터 사전 인출을 수행해야 한다는 것을 드라이버에 알릴 수 있습니다. SetComputeRootDescriptorTable 또는 상수 버퍼 뷰, 셰이더 리소스 뷰 또는 순서가 지정되지 않은 액세스 보기를 설정하는 방법 중 하나입니다.
번들의 경우 실행 시 설정된 동안 데이터가 정적이라는 약속은 번들의 각 실행에 고유하게 적용됩니다.
플래그는 설명자 범위 플래그와 루트 설명자 플래그 모두에서 사용할 수 있습니다.
DATA_STATIC
이 플래그를 설정하면 기록 중에 메모리를 참조하는 루트 설명자 또는 설명자 테이블이 명령 목록/번들에 설정될 때까지 설명자가 가리키는 데이터가 초기화되며 명령 목록/번들이 마지막으로 실행을 완료할 때까지 데이터를 변경할 수 없습니다.
번들의 경우 정적 기간은 호출 명령 목록의 기록과는 달리 번들을 기록하는 동안 루트 설명자 또는 설명자 테이블 설정에서 시작됩니다. 또한 정적 데이터를 가리키는 설명자 테이블은 번들에 설정되어야 하며 상속되지 않아야 합니다. 명령 목록에서 번들에 설정되어 명령 목록으로 다시 반환된 정적 데이터를 가리키는 설명자 테이블을 사용하는 것이 유효합니다.
플래그는 설명자 범위 플래그와 루트 설명자 플래그 모두에서 사용할 수 있습니다.
플래그 결합
샘플러가 데이터를 가리키지 않으므로 DATA 플래그를 전혀 지원하지 않는 샘플러 설명자 범위를 제외하고 데이터 플래그를 한 번에 하나만 지정할 수 있습니다.
SRV 및 CBV 설명자 범위에 대한 데이터 플래그가 없으면 기본 DATA_STATIC_WHILE_SET_AT_EXECUTE 동작이 가정됩니다. 이 기본값이 DATA_STATIC 대신 선택되는 이유는 DATA_STATIC_WHILE_SET_AT_EXECUTE 대부분의 경우에 안전한 기본값이 될 가능성이 훨씬 높지만 DATA_VOLATILE 기본값보다 최적화 기회를 더 잘 얻을 수 있기 때문입니다.
UAV 설명자 범위에 대한 데이터 플래그가 없으면 일반적으로 UAV가 기록되는 경우 DATA_VOLATILE 동작의 기본값이 가정됩니다.
DESCRIPTORS_VOLATILE DATA_STATIC 결합할 수는 없지만 다른 데이터 플래그와 결합할 있습니다. DESCRIPTORS_VOLATILE DATA_STATIC_WHILE_SET_AT_EXECUTE 결합할 수 있는 이유는 일시적 설명자가 명령 목록/번들 실행 중에 설명자를 준비해야 하며, DATA_STATIC_WHILE_SET_AT_EXECUTE 명령 목록/번들 실행의 하위 집합 내에서의 정적 성능에 대해서만 약속하기 때문입니다.
플래그 요약
다음 표에는 사용할 수 있는 플래그 조합이 요약되어 있습니다.
유효한 D3D12_DESCRIPTOR_RANGE_FLAGS 설정 | 묘사 |
---|---|
플래그가 설정되지 않음 | 설명자는 정적(기본값)입니다. 데이터에 대한 기본 가정: SRV/CBV: DATA_STATIC_WHILE_SET_AT_EXECUTE 및 UAV: DATA_VOLATILE. SRV/CBV에 대한 이러한 기본값은 대부분의 루트 서명에 대한 사용 패턴에 안전하게 맞습니다. |
DATA_STATIC | 설명자와 데이터는 모두 정적입니다. 이렇게 하면 드라이버 최적화 가능성이 최대화됩니다. |
DATA_VOLATILE | 설명자는 정적이며 데이터는 휘발성입니다. |
DATA_STATIC_WHILE_SET_AT_EXECUTE | 설명자는 정적이며 데이터는 실행 시 설정된 동안 정적입니다. |
DESCRIPTORS_VOLATILE | 설명자는 휘발성이며 SRV/CBV: DATA_STATIC_WHILE_SET_AT_EXECUTE 및 UAV: DATA_VOLATILE 데이터에 대한 기본 가정이 수행됩니다. |
DESCRIPTORS_VOLATILE | DATA_VOLATILE | 설명자와 데이터는 모두 일시적이며 루트 서명 1.0과 동일합니다. |
DESCRIPTORS_VOLATILE | DATA_STATIC_WHILE_SET_AT_EXECUTE | 설명자는 일시적이지만 명령 목록 실행 중에는 변경할 수 없습니다. 따라서 실행 중에 루트 설명자 테이블을 통해 설정하는 동안 데이터가 정적이라는 추가 선언을 결합하는 것이 유효합니다. 기본 설명자는 데이터가 정적으로 약속되는 것보다 오랫동안 효과적으로 정적입니다. |
유효한 D3D12_ROOT_DESCRIPTOR_FLAGS 설정 | 묘사 |
---|---|
플래그가 설정되지 않음 | 데이터에 대한 기본 가정: SRV/CBV: DATA_STATIC_WHILE_SET_AT_EXECUTE 및 UAV: DATA_VOLATILE. SRV/CBV에 대한 이러한 기본값은 대부분의 루트 서명에 대한 사용 패턴에 안전하게 맞습니다. |
DATA_STATIC | 데이터는 정적이며 드라이버 최적화에 가장 적합한 잠재력입니다. |
DATA_STATIC_WHILE_SET_AT_EXECUTE | 데이터는 실행 시 설정된 동안 정적입니다. |
DATA_VOLATILE | 루트 서명 1.0에 해당합니다. |
버전 1.1 API 요약
다음 API 호출은 버전 1.1을 사용하도록 설정합니다.
열거형
이러한 열거형에는 설명자 및 데이터 변동성을 지정하는 키 플래그가 포함됩니다.
- D3D_ROOT_SIGNATURE_VERSION: 버전 ID입니다.
- D3D12_DESCRIPTOR_RANGE_FLAGS: 설명자 또는 데이터가 휘발성인지 정적인지를 결정하는 플래그 범위입니다.
- D3D12_ROOT_DESCRIPTOR_FLAGS : 데이터 플래그만 루트 설명자에 적용된다는 점을 제외하고 D3D12_DESCRIPTOR_RANGE_FLAGS유사한 플래그 범위입니다.
구조
업데이트된 구조체(버전 1.0부터)에는 변동성/정적 플래그에 대한 참조가 포함되어 있습니다.
D3D12_FEATURE_DATA_ROOT_SIGNATURE: 이 구조를 CheckFeatureSupport 전달하여 루트 서명 버전 1.1 지원을 확인합니다.
D3D12_VERSIONED_ROOT_SIGNATURE_DESC : 루트 서명 설명의 모든 버전을 포함할 수 있으며 아래에 나열된 serialization/deserialization 함수와 함께 사용하도록 설계되었습니다.
이러한 구조는 설명자 범위 및 루트 설명자에 대한 새 플래그 필드를 추가하여 버전 1.0에서 사용되는 구조와 동일합니다.
함수
여기에 나열된 메서드는 모든 버전의 루트 서명에서 작동하도록 설계되었으므로 원래 D3D12SerializeRootSignature 대체하고 D3D12CreateRootSignatureDeserializer함수를. 직렬화된 양식은 CreateRootSignature API에 전달됩니다. 셰이더가 루트 서명으로 작성된 경우 컴파일된 셰이더에는 이미 직렬화된 루트 서명이 포함됩니다.
- D3D12SerializeVersionedRootSignature: 애플리케이션에서 D3D12_VERSIONED_ROOT_SIGNATURE 데이터 구조를 프로시저 방식으로 생성하는 경우 이 함수를 사용하여 직렬화된 폼을 만들어야 합니다.
- D3D12CreateVersionedRootSignatureDeserializer : GetUnconvertedRootSignatureDesc통해 역직렬화된 데이터 구조를 반환할 수 있는 인터페이스를 생성합니다.
방법
ID3D12VersionedRootSignatureDeserializer 인터페이스는 루트 서명 데이터 구조를 역직렬화하기 위해 만들어집니다.
- GetRootSignatureDescAtVersion : 루트 서명 설명 구조를 요청된 버전으로 변환합니다.
- GetUnconvertedRootSignatureDesc : D3D12_VERSIONED_ROOT_SIGNATURE_DESC 구조체에 대한 포인터를 반환합니다.
도우미 구조체
일부 버전 1.1 구조체의 초기화를 지원하기 위해 도우미 구조가 추가되었습니다.
- CD3DX12_DESCRIPTOR_RANGE1
- CD3DX12_ROOT_PARAMETER1
- CD3DX12_STATIC_SAMPLER1
- CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC
D3D12 대한도우미 구조 및 함수를 참조하세요.
정적 네스 플래그 위반의 결과
위에서 설명한 설명자 및 데이터 플래그(특정 플래그가 없는 경우 내포된 기본값)는 애플리케이션이 드라이버에 대한 작동 방식에 대한 약속을 정의합니다. 애플리케이션이 약속을 위반하는 경우 잘못된 동작입니다. 결과는 정의되지 않았으며 다른 드라이버와 하드웨어에서 다를 수 있습니다.
디버그 계층에는 플래그를 설정하지 않고 루트 서명 버전 1.1을 사용하는 기본 약속을 포함하여 애플리케이션이 약속을 지키도록 유효성을 검사하는 옵션이 있습니다.
버전 관리
셰이더에 연결된 루트 서명을 컴파일할 때 최신 HLSL 컴파일러는 기본적으로 버전 1.1에서 루트 서명을 컴파일하는 반면 이전 HLSL 컴파일러는 1.0만 지원합니다. 1.1 루트 서명은 루트 서명 1.1을 지원하지 않는 OS에서 작동하지 않습니다.
셰이더로 컴파일된 루트 서명 버전은 /force_rootsig_ver <version>
사용하여 특정 버전으로 강제 적용할 수 있습니다. 예를 들어 최적화 용도로만 사용되지만 동작에 영향을 미치지 않는 지원되지 않는 플래그를 루트 서명에 삭제하여 컴파일러가 강제 버전에서 컴파일되는 루트 서명의 동작을 유지할 수 있는 경우 버전 강제 적용이 성공합니다.
예를 들어 애플리케이션에서 애플리케이션을 빌드할 때 1.1 루트 서명을 1.0 및 1.1로 컴파일하고 OS 지원 수준에 따라 런타임에 적절한 버전을 선택할 수 있습니다. 그러나 애플리케이션이 셰이더와 별도로 루트 서명을 개별적으로 컴파일하는 것이 가장 공간 효율적입니다(특히 여러 버전이 필요한 경우). 셰이더가 처음에 루트 서명이 연결된 상태에서 컴파일되지 않더라도 /verifyrootsignature
컴파일러 옵션을 사용하여 셰이더와의 루트 서명 호환성에 대한 컴파일러 유효성 검사의 이점을 유지할 수 있습니다. 런타임에 나중에 원하는 루트 서명(OS에서 지원하는 적절한 버전)을 별도의 매개 변수로 전달하는 동안 루트 서명이 없는 셰이더를 사용하여 PSO를 만들 수 있습니다.
관련 항목