모든 것에 인스턴스를 사용합니까?


16

인스 턴싱은 한 번에 같은 메시의 여러 (수천에서 수천?) 복사본을 렌더링 할 때 성능을 크게 향상시킵니다. 그러나 하나의 그리기 호출로 정확히 하나의 사본을 렌더링 할 때 얼마나 많은 오버 헤드가 있습니까? 엔진이 렌더링하는 모든 지오메트리에 인스 턴싱을 사용하는 것이 좋거나 나쁜 생각입니까?

편집 : FPS 게임을 만들고 있다고 가정 해 봅시다. 대부분의 물체에는 칼, 총, 기관총, 건물 및 라디오 타워가 하나만 있습니다. 그러나 여러 인스턴스가있는 객체도 있습니다 : 나무 (예 : 수백 개의 인스턴스가있는 3 종류의 나무), 잔디 등. 인스 턴싱을 사용하는 잔디는 인스 턴싱을 사용하여 렌더링 합니다 . 따라서 라디오 타워에는 인스턴스 데이터 버퍼에 저장되는 정보가 하나 뿐인 인스턴스가 DrawInstanced()있으며 인스턴스 개수가 equal 인 호출을 사용하여 해당 타워를 렌더링합니다 1. 다른 모든 객체와 동일합니다 (물론 나무와 잔디에는 여러 인스턴스가 있습니다).

내 질문은 : 인스턴스화를 사용하여 객체의 단일 인스턴스를 그리는 것이 나쁜 생각입니까? 인스턴스화에 너무 많은 오버 헤드 (메모리 및 성능 측면)가 있거나 단일 인스턴스 오브젝트 렌더링에 바람직하지 않은가?

답변:


19

XPDM이 포함 된 D3D9에서는 거의 확실하게 인스턴스를 원합니다. 드로우 콜 오버 헤드는 너무 높아서 의미가 있습니다. 이 시나리오에서 크로스 오버 지점은 2 개 또는 3 개의 인스턴스 일 수 있습니다.

주어진 메쉬의 인스턴스를 하나만 가지고 있다면, 표면에 인스턴스화되지 않은 것으로 보일 수도 있습니다. 그러나 관련된 내용을 살펴보십시오.

  • 데이터를 인스턴스 별 버퍼로로드하는 것에서 쉐이더 상수 업로드로 전환해야합니다.
  • 정점 셰이더의 사본 두 개 (인스턴스 용 인스턴스와 비 인스턴스 용 사본)를 보관해야합니다.
  • 렌더링 코드 사본 두 개를 유지해야합니다.
  • 셰이더를 전환해야합니다.
  • 꼭짓점 형식을 전환해야합니다.
  • 꼭짓점 버퍼를 전환해야 할 수도 있습니다.
  • 그리고 다음 메시 그룹에 대해 인스턴스화 된 도면으로 돌아가려면 다시해야합니다.

FPS의 건 모델과 같이 단일 메시 만 가지고 있어도 인스 턴싱이 유용한 경우가 있습니다. 포워드 렌더러와 z 프리 패스로 멀티 패스 광 축적을 수행한다고 가정 해 봅시다. 각 조명에 대한 추가 패스 대신 조명을 인스턴스 별 데이터로 만들고 인스턴스를 그립니다.

첫 번째 시나리오를 기반으로 이야기의 교훈은 어떤 객체 클래스가 인스 턴싱을 전혀 사용할 수 없다면 항상 해당 클래스의 모든 객체에 인스 턴싱을 사용하는 것이 합리적이라는 것입니다.

두 번째 시나리오를 기반으로 이야기의 도덕은 인스턴스화가 단순히 "20 그루의 나무를 그릴 필요"라고 말하는 것 이상의 명백한 용도를 가질 수 있다는 것입니다.


당신이 준 이유는 처음 에이 질문을하게 한 것과 똑같은 이유입니다. 감사합니다.
NPS

12

(내 시스템에서는 다른 곳에서는 테스트하지 않았습니다.) GL에서 단일 메쉬 인스턴스 (개수 = 1로 그리기)는 약간의 오버 헤드가 있지만 어디에서 왔는지 모르겠습니다. 나는 그것을하지 않는 것이 좋습니다.

몇 달 전에 실용적인 응용 프로그램에서 이것을 테스트했습니다. Crytek Sponza 장면에서 일부 글로벌 일루미네이션 알고리즘을 코딩했습니다. 약 350여 개의 메시 (정확히 기억하지 못함)로 구성되어 있으며,이 중 몇 가지는 소수의 인스턴스를 공유합니다. 처음에는 렌더링 코드를 약간 단순화했기 때문에 모든 것을 인스턴스화하고 인스턴스 수 1로 나머지를 그립니다.

나중에 렌더러를 최적화 할 때 count = 객체를 인스턴스화하지 않고 일반적인 방법으로 제출하면 다시 i7 3770k (및 GTX 770)에서 프레임 당 약 3.5 밀리 초가 절약되었습니다. 여러 인스턴스가있는 메쉬를 기존 방식으로 전환하면 0.5ms 더 절약되었습니다. 전반적으로 응용 프로그램은 ~ 120FPS에서 ~ 230FPS로 증가했습니다.

물론 이러한 수치는 응용 프로그램에서 병목 현상이 발생하는 위치에 따라 달라지며 후자의 0.5ms는 실제로 응용 프로그램의 호출이 매우 제한적인 응용 프로그램에서 속도가 느려질 수 있습니다. 그러나 그렇지 않으면 내 경험에 따르면 인스턴스를 한 번에 많이 그리지 않으면 인스턴스화에 약간의 오버 헤드가 발생합니다.


흥미롭지 만 AMD 및 인텔 드라이버에 대한 데이터를 보는 것도 좋을 것입니다. 그렇지 않으면 "In GL"대신 "내 시스템"이라고 말해야합니다. 반면, 다른 구현에 문제가되지 않더라도 사용하지 않는 경우 인스턴스화를 피할 수있는 충분한 이유가 있습니다.
bcrist

2

인스턴스화 된 단일 객체를 그리는 것이 일반적으로 단일 객체를 그리는 것보다 비싸다는 것을 확신 할 수 있습니다. 인스턴스화를 위해 GPU는 많은 양의 객체를 준비하고 있으며이 준비는 단일 객체와는 다릅니다. 그러나이 성능 차이가 얼마나 큰지는 실험을 통해서만 찾을 수 있으며 실제 렌더링 설정에 따라 크게 다릅니다. 확실하게 알 수있는 유일한 방법은 직접 테스트하는 것입니다. 하나의 그리기 호출을 벤치마킹하는 것은 어렵다 여기 계속 진행할 수있는 방법에 대한 몇 가지 아이디어가 있습니다.


2

4 년이 지났고 1로 "인스턴스"드로우 콜을 제출하는 것이 안전하다고 생각하는 것이 안전하다고 생각합니다. 아시다시피 , 새로운 API DX12Vk는 모두 0부터 시작하는 인스턴스 수 를가 집니다. NUM_INSTANCES . 또한 DrawIndexed (...) 가 없습니다 .

편집하다

주의 사항으로, 위의 API는 아마도 현대의 API에서는 좋을 것입니다 .Gl <3.3 또는 DX11과 같은 오래된 것을 사용하면 다른 사용자가 언급 한 것처럼 프로파일 링이 필요할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.