간접 그리기

간접 그리기를 사용하면 일부 장면 통과 및 선별이 CPU에서 GPU로 이동될 수 있으므로 성능이 향상될 수 있습니다. 명령 버퍼는 CPU 또는 GPU에서 생성할 수 있습니다.

명령 서명

명령 서명 개체(ID3D12CommandSignature)를 사용하여 앱에서 간접 그리기를 지정하고, 특히 다음을 설정할 수 있습니다.

시작 시, 앱은 작은 명령 서명 세트를 만듭니다. 런타임에 애플리케이션은 명령으로 버퍼를 채웁니다(앱 개발자가 선택하는 방법을 통해). 꼭짓점 버퍼 뷰, 인덱스 버퍼 뷰, 루트 상수 및 루트 설명자(원시 또는 구조화된 SRV/UAV/CBV)에 대해 설정할 상태를 선택적으로 포함하는 명령을 나타냅니다. 이러한 인수 레이아웃은 하드웨어별로 고유하지 않으므로 앱은 버퍼를 직접 생성할 수 있습니다. 명령 서명은 명령 목록에서 나머지 상태를 상속합니다. 그러면 앱은 ExecuteIndirect를 호출하여 GPU에 특정 명령 서명으로 정의된 형식에 따라 간접 인수 버퍼의 내용을 해석하도록 지시합니다.

명령 서명이 루트 인수를 변경하면 명령 서명 내에 루트 서명의 하위 세트로 저장됩니다.

실행이 완료되면, 명령 서명 상태가 명령 목록에 다시 누출되지 않습니다.

예를 들어, 앱 개발자는 고유한 루트 상수가 간접 인수 버퍼에서 그리기 호출별로 지정되도록 하려고 합니다. 앱은 간접 인수 버퍼가 그리기 호출별로 다음 매개 변수를 지정할 수 있도록 하는 명령 서명을 만듭니다.

  • 하나의 루트 상수 값
  • 그리기 인수(꼭짓점 수, 인스턴스 수 등)

애플리케이션에서 생성된 간접 인수 버퍼는 고정 크기 레코드 배열을 포함합니다. 각 구조는 하나의 그리기 호출에 해당합니다. 각 구조는 그리기 인수와 루트 상수 값을 포함합니다. 그리기 호출의 수는 별도의 GPU 표시 가능 버퍼에 지정됩니다.

앱에서 생성하는 예제 명령 버퍼는 다음과 같습니다.

명령 버퍼 형식

간접 인수 버퍼 구조

다음 주소는 특정 인수가 간접 인수 버퍼에 나타나는 방식을 정의합니다. 이러한 구조는 D3D12 API에서 표시되지 않습니다. 애플리케이션은 간접 인수 버퍼에 쓸 때(CPU 또는 GPU 사용) 이러한 정의를 사용합니다.

명령 서명 생성

명령 서명을 만들려면 다음과 같은 API 항목을 사용합니다.

간접 인수 버퍼 내의 인수 순서는 D3D12_COMMAND_SIGNATURE_DESCpArguments 매개 변수에 지정된 인수 순서와 정확히 일치하도록 정의됩니다. 간접 인수 버퍼 내의 한 그리기(그래픽)/디스패치(컴퓨팅) 호출에 대한 모든 인수가 견고히 압축됩니다. 그러나 애플리케이션은 간접 인수 버퍼의 그리기/디스패치 명령 사이에 임의 바이트 진행 속도를 지정하도록 허용됩니다.

루트 서명은 명령 서명이 루트 인수 중 하나를 변경하는 경우에만 지정해야 합니다.

루트 SRV/UAV/CBV의 경우 애플리케이션에서는 바이트 단위 크기를 지정합니다. 디버그 계층은 주소에서 다음과 같은 제한 사항이 유효한지 검사합니다.

  • CBV - 주소는 256바이트의 배수여야 합니다.
  • 원시 SRV/UAV – 주소는 4바이트의 배수여야 합니다.
  • 구조화된 SRV/UAV – 주소는 구조 바이트 진행 속도(셰이더에 선언)의 배수여야 합니다.

지정된 명령 서명은 그리기 또는 컴퓨팅 명령 서명입니다. 명령 서명에 그리기 작업이 포함되면 그래픽 명령 서명이 됩니다. 그렇지 않은 경우 명령 서명은 디스패치 작업을 포함해야 하며, 컴퓨팅 명령 서명이 됩니다.

다음 섹션에서는 몇 가지 명령 서명 예제를 보여 줍니다.

인수 변경 없음

이 예제에서 애플리케이션에서 생성된 간접 인수 버퍼는 36바이트 구조 배열을 포함합니다. 각 구조는 DrawIndexedInstanced(패딩 포함)에 전달된 5개 매개 변수만 포함합니다.

명령 서명 설명을 만드는 코드는 다음과 같습니다.

D3D12_INDIRECT_ARGUMENT_DESC Args[1];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 36;
ProgramDesc.NumArgumentDescs = 1;
ProgramDesc.pArguments = Args;

간접 인수 버퍼 내의 단일 구조 레이아웃은 다음과 같습니다.

바이트 설명
0:3 IndexCountPerInstance
4:7 InstanceCount
8:11 StartIndexLocation
12:15 BaseVertexLocation
16:19 StartInstanceLocation
20:35 안쪽 여백

 

루트 상수 및 꼭짓점 버퍼

이 예제에서는 간접 인수 버퍼의 각 구조가 2개의 루트 상수를 변경하고, 하나의 꼭짓점 버퍼 바인딩을 변경하고, 하나의 그리기 비인덱싱 작업을 수행합니다 구조 간에 패딩은 없습니다.

명령 서명 설명을 만드는 코드는 다음과 같습니다.

D3D12_INDIRECT_ARGUMENT_DESC Args[4];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[0].Constant.RootParameterIndex = 2;
Args[0].Constant.DestOffsetIn32BitValues = 0;
Args[0].Constant.Num32BitValuesToSet = 1;

Args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[1].Constant.RootParameterIndex = 6;
Args[1].Constant.DestOffsetIn32BitValues = 0;
Args[1].Constant.Num32BitValuesToSet = 1;

Args[2].Type = D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW;
Args[2].VertexBuffer.Slot = 3;

Args[3].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 40;
ProgramDesc.NumArgumentDescs = 4;
ProgramDesc.pArguments = Args;

간접 인수 버퍼 내의 단일 구조 레이아웃은 다음과 같습니다.

바이트 설명
0:3 루트 매개 변수 인덱스 2의 데이터
4:7 루트 매개 변수 인덱스 6의 데이터
8:15 슬롯 3의 VB 가상 주소(64비트)
16:19 VB 크기
20:23 VB 진행 속도
24:27 VertexCountPerInstance
28:31 InstanceCount
32:35 StartVertexLocation
36:39 StartInstanceLocation

 

DirectX 고급 학습 비디오 자습서: 간접 및 비동기 GPU 컬링 실행

간접 그리기 및 GPU 선별(culling): 코드 연습

렌더링