TECHARTNOMAD | TECHARTFLOWIO.COM

GRAPHICS PROGRAMMING

RHIDrawIndexedPrimitiveIndirect 또는 DrawMeshInstancedIndirect 와 GPU Buffer 개요.

jplee 2024. 10. 18. 03:17

IndirectDraw:

  • 드로우 콜(draw call)의 횟수를 줄여 렌더링 성능을 향상시키는 기술입니다.
  • GPU에게 드로우할 인스턴스의 개수, 시작 인덱스 등을 명령어 형태로 전달하여, CPU의 개입을 최소화하고 GPU가 스스로 드로잉 작업을 처리하도록 합니다.

Mesh Instance:

  • 하나의 메시를 여러 번 복제하여 화면에 렌더링하는 기술입니다.
  • 각 인스턴스는 위치, 회전, 크기 등의 변환 정보를 가지고 있어, 다양한 오브젝트를 효율적으로 생성할 수 있습니다.

Constant Buffer:

  • GPU가 쉽게 접근할 수 있는 메모리 공간으로, 쉐이더에서 자주 참조되는 데이터를 저장하는 데 사용됩니다.
  • 내용이 변경될 때마다 CPU에서 GPU로 데이터를 복사해야 하므로, 너무 자주 변경되는 데이터를 저장하기에는 비효율적입니다.

Constant Buffer를 사용하는 이유

  1. 변환 정보 전달:
    • 각 인스턴스마다 다른 변환 정보를 가지고 있기 때문에, 이 정보를 효율적으로 GPU에 전달해야 합니다.
    • Constant Buffer는 GPU가 쉽게 접근할 수 있는 메모리 공간이므로, 변환 정보를 저장하고 쉐이더에서 직접 참조하여 각 인스턴스를 렌더링하는 데 사용됩니다.
  2. 성능 향상:
    • Constant Buffer를 사용하면 CPU에서 GPU로 데이터를 전달하는 횟수를 줄일 수 있습니다.
    • 또한, GPU는 Constant Buffer에 저장된 데이터를 캐시하여 접근 속도를 높일 수 있습니다.
  3. 유연성:
    • Constant Buffer는 다양한 종류의 데이터를 저장할 수 있으므로, 변환 정보 외에도 다른 종류의 데이터를 쉐이더에 전달하는 데 사용될 수 있습니다.
IndirectDraw Mesh Instance는 GPU의 성능을 최대한 활용하여 많은 수의 인스턴스를 효율적으로 렌더링하는 기술입니다. Constant Buffer는 이러한 기술을 구현하는 데 필수적인 요소로, 각 인스턴스의 변환 정보를 GPU에 효율적으로 전달하고 쉐이더에서 쉽게 접근할 수 있도록 합니다.

언리얼 엔진 또는 유니티 엔진에서 IndirectDraw Mesh Instance가 사용하는 버퍼

IndirectDraw Mesh Instance는 일반적으로 GPU의 Constant Buffer를 주로 사용하며, Command Buffer는 간접적인 방식으로 활용됩니다.

왜 Constant Buffer를 주로 사용할까요?

  • 변환 정보의 효율적인 전달: 각 메시 인스턴스마다 다른 변환(위치, 회전, 크기 등) 정보가 필요한데, Constant Buffer는 이러한 변환 매트릭스를 효율적으로 저장하고 쉐이더에서 쉽게 접근할 수 있도록 해줍니다.
  • 쉐이더에서의 직접적인 접근: 쉐이더는 Constant Buffer에 저장된 데이터를 인덱스를 통해 직접 참조할 수 있어, 각 인스턴스에 대한 변환을 계산하는 과정이 간소화됩니다.
  • GPU의 병렬 처리에 적합: GPU는 Constant Buffer의 데이터를 병렬적으로 처리할 수 있어, 많은 수의 메시 인스턴스를 효율적으로 렌더링하는 데 유리합니다.

Command Buffer는 어떻게 활용될까요?

  • IndirectDraw 명령어 전달: IndirectDraw는 GPU에게 드로잉할 인스턴스의 개수, 시작 인덱스 등을 명령어 형태로 전달하는 방식입니다. 이러한 명령어들은 Command Buffer를 통해 GPU에 전달됩니다.
  • 렌더 파이프라인 제어: Command Buffer는 렌더링 파이프라인의 다양한 단계를 제어하는 데 사용될 수 있습니다. 예를 들어, 렌더 타겟 설정, 깊이 테스트 활성화/비활성화 등을 지정할 수 있습니다.

정리하면

  • Constant Buffer: 메시 인스턴스의 변환 정보를 저장하고, 쉐이더에서 직접 참조하여 각 인스턴스를 렌더링하는 데 사용됩니다.
  • Command Buffer: IndirectDraw 명령어를 비롯한 다양한 렌더링 명령을 GPU에 전달하고, 렌더링 파이프라인을 제어하는 데 사용됩니다.

즉, IndirectDraw Mesh Instance는 Constant Buffer를 통해 인스턴스별 변환 정보를 전달하고, Command Buffer를 통해 IndirectDraw 명령을 실행하여 실제 렌더링을 수행합니다.

추가 설명

  • 유니티 엔진: 유니티에서는 Command Buffer를 ComputeShader와 함께 사용하여 더욱 복잡한 컴퓨팅 작업을 수행할 수 있습니다.
  • 언리얼 엔진: 언리얼 엔진에서는 RenderCommand 시스템을 통해 Command Buffer와 유사한 기능을 제공합니다.

결론적으로, IndirectDraw Mesh Instance는 Constant Buffer와 Command Buffer를 효과적으로 활용하여 GPU의 성능을 최대한 이끌어내고, 많은 수의 메시 인스턴스를 실시간으로 렌더링하는 데 사용되는 강력한 기술입니다.


Constant Buffer와 Command Buffer의 차이

Constant BufferCommand Buffer는 GPU 프로그래밍에서 빈번하게 사용되는 개념으로, 각각 다른 역할을 수행합니다.

Constant Buffer

  • 정의: 쉐이더에서 자주 참조되는 데이터를 저장하는 메모리 공간입니다.
  • 주요 기능:
    • 쉐이더에 데이터 제공: 쉐이더는 Constant Buffer에 저장된 데이터를 인덱스를 통해 직접 참조하여 사용합니다.
    • 변환 매트릭스 저장: 메시 인스턴스의 변환(위치, 회전, 크기 등) 정보를 저장하는 데 주로 사용됩니다.
    • 재질 정보 저장: 재질의 색상, 반사율 등의 정보를 저장할 수도 있습니다.
  • 특징:
    • GPU가 직접 접근: GPU는 Constant Buffer에 저장된 데이터를 매우 빠르게 읽어올 수 있습니다.
    • 쉐이더에서 자주 참조되는 데이터: 쉐이더에서 반복적으로 사용되는 데이터를 저장하는 데 적합합니다.
    • 내용 변경 시: CPU에서 GPU로 데이터를 복사해야 합니다.

Command Buffer

  • 정의: GPU에게 실행할 명령을 저장하는 버퍼입니다.
  • 주요 기능:
    • 렌더링 파이프라인 제어: 렌더링 파이프라인의 다양한 단계를 제어하는 명령을 저장합니다. (예: 렌더 타겟 설정, 깊이 테스트 활성화/비활성화 등)
    • 드로우 명령: 드로잉을 수행하는 명령을 저장합니다. (예: IndirectDraw 명령)
    • 컴퓨트 셰이더 실행: 컴퓨팅 작업을 수행하는 컴퓨트 셰이더를 실행하는 명령을 저장합니다.
  • 특징:
    • GPU 작업 스케줄링: GPU가 어떤 작업을 언제 수행할지 결정하는 데 사용됩니다.
    • 렌더링 파이프라인의 유연성: 다양한 렌더링 효과를 구현하기 위해 Command Buffer를 활용할 수 있습니다.
    • 병렬 처리: GPU는 Command Buffer에 저장된 명령을 병렬적으로 실행할 수 있습니다.

두 버퍼의 차이점 요약

특징Constant Buffer Command Buffer

 

특징 Constant Buffer  Command Buffer
저장하는 데이터 쉐이더에서 사용되는 데이터 (변환 매트릭스, 재질 정보 등) GPU가 실행할 명령
주요 기능 쉐이더에 데이터 제공 렌더링 파이프라인 제어, 드로우 명령, 컴퓨트 셰이더 실행
접근 방식 쉐이더에서 직접 인덱스를 통해 접근 GPU가 순차적으로 실행
변경 빈도 상대적으로 적음 상대적으로 많음

Unity와 Unreal Engine 모두 Indirect Draw Mesh Instancing 기술을 사용하여 성능을 최적화하고, 여러 개의 객체를 효율적으로 렌더링할 수 있습니다. 
이 기술은 주로 GPU의 여러 기능을 활용하며, 특히 GPU의 Command Buffer를 많이 사용합니다. 그러나 Constant Buffer (또는 Uniform Buffer) 역시 중요한 역할을 할 때가 있습니다.

Unity

Unity의 경우, Indirect Draw Mesh Instancing은 Graphics.DrawMeshInstancedIndirect를 사용하는데, 이 API는 GPU Command Buffer를 사용하여 동일한 메시를 다수의 인스턴스로 렌더링합니다. 이를 위해 인스턴스 데이터와 렌더링 명령어를 GPU 메모리에 저장합니다.
Command Buffer: 인스턴스를 그리기 위한 명령어를 저장하고 실행합니다.
Constant Buffer: 각 인스턴스의 변환 행렬 및 기타 필요한 데이터를 저장합니다. 이 데이터는 셰이더로 전달됩니다.


Unreal Engine

Unreal Engine에서도 비슷한 방식으로 Indirect Draw Mesh Instancing을 처리합니다. Unreal에서는 RHIDrawIndexedPrimitiveIndirect와 같은 RHI (Render Hardware Interface) 명령을 통해 GPU Command Buffer에 렌더링 명령어를 전달합니다.
Command Buffer: 메쉬 인스턴스를 그리기 위한 명령을 포함합니다.
Constant Buffer: 각 인스턴스의 변환 데이터와 기타 속성들을 포함합니다.
결론적으로, Indirect Draw Mesh Instancing은 주로 GPU Command Buffer를 사용하여 많은 인스턴스를 효율적으로 렌더링합니다. 그러나 필요한 인스턴스 데이터는 Constant Buffer에 저장되어 셰이더로 전달되므로, 두 버퍼가 모두 사용됩니다.