홈 브루어 렌더링 시스템에서 리소스를 캐시하는 방법


10

배경:

C ++ 및 OpenGL을 사용하여 엔터티 구성 요소 시스템 유형 아키텍처를위한 간단한 3D 렌더링 시스템을 설계하고 있습니다. 이 시스템은 렌더러와 장면 그래프로 구성됩니다. 렌더러의 첫 번째 반복을 마치면 장면 그래프를 ECS 아키텍처에 배포 할 수 있습니다. 현재로서는 자리 표시 자입니다. 가능하면 렌더러의 목표는 다음과 같습니다.

  1. 단순성 . 이것은 연구 프로젝트를위한 것이며 시스템을 쉽게 변경하고 확장 할 수 있기를 원합니다 (따라서 ECS 접근 방식).
  2. 성능 . 내 장면에는 많은 작은 모델과 많은 기하학을 가진 큰 볼륨이있을 수 있습니다. 렌더 프레임마다 OGL 컨텍스트 및 버퍼 지오메트리에서 객체를 획득하는 것은 허용되지 않습니다. 캐시 누락을 피하기 위해 데이터 지역성을 목표로하고 있습니다.
  3. 유연성 . 스프라이트, 모델 및 볼륨 (복셀)을 렌더링 할 수 있어야합니다.
  4. 분리됨 . 렌더러를 작성한 후 장면 그래프가 핵심 ECS 아키텍처로 리팩터링 될 수 있습니다.
  5. 모듈 식 . 내 장면 그래프를 변경하지 않고 다른 렌더러에서 교체 할 수 있으면 좋을 것입니다.
  6. 참조 투명도 는 어느 시점에서나 유효한 장면을 제공 할 수 있으며 항상 해당 장면에 대해 동일한 이미지를 렌더링한다는 의미입니다. 특히이 목표는 반드시 필요한 것은 아닙니다. 장면 직렬화를 단순화하고 (씬을 저장하고로드 할 수 있어야 함) 테스트 / 실험 목적으로 런타임 중에 다른 장면으로 교체 할 수있는 유연성을 제공한다고 생각했습니다.

문제와 아이디어 :

나는 시도하는 몇 가지 다른 접근법을 생각해 냈지만 각 렌더 노드에 대해 OGL 리소스 (VAO, VBO, 쉐이더 등)를 캐시하는 방법으로 어려움을 겪고 있습니다. 다음은 지금까지 생각한 다양한 캐싱 개념입니다.

  1. 중앙 집중식 캐시. 각 장면 노드에는 ID가 있고 렌더러에는 ID를 렌더링 노드에 매핑하는 캐시가 있습니다. 각 렌더 노드에는 형상과 관련된 VAO 및 VBO가 포함됩니다. 캐시 미스는 리소스를 획득하고 캐시의 렌더링 노드에 지오메트리를 매핑합니다. 지오메트리가 변경되면 더티 플래그가 설정됩니다. 렌더러가 장면 노드를 반복하는 동안 더티 지오메트리 플래그가 표시되면 렌더 노드를 사용하여 데이터를 다시 버퍼링합니다. 장면 노드가 제거되면 이벤트가 브로드 캐스트되고 렌더러는 리소스를 해제하면서 캐시에서 관련 렌더 노드를 제거합니다. 또는 노드가 제거 대상으로 표시되고 렌더러가 노드를 제거해야합니다. 이 접근법은 목표 6을 가장 가깝게 달성하면서도 4와 5를 고려한다고 생각합니다. 2는 어레이 액세스 대신 맵 조회를 통해 데이터 복잡성의 추가 복잡성 및 손실로 인해 어려움을 겪고 있습니다.
  2. 분산 캐시 . 각 장면 노드에 렌더 노드가 있다는 점을 제외하면 위와 유사합니다. 지도 조회를 무시합니다. 데이터 지역성을 다루기 위해 렌더러에 렌더 노드를 저장할 수 있습니다. 그런 다음 장면 노드는 대신 노드를 렌더링하기위한 포인터를 가질 수 있으며 렌더러는 캐시 미스에 포인터를 설정합니다. 이런 종류의 개체는 엔터티 구성 요소 접근 방식을 모방한다고 생각하므로 나머지 아키텍처와 일치 할 것입니다. 여기서 문제는 이제 씬 노드가 렌더러 구현 관련 데이터를 보유한다는 것입니다. 렌더링 스프라이트와 볼륨과 같이 렌더러에서 렌더링되는 방식을 변경하면 렌더 노드를 변경하거나 장면 노드에 "구성 요소"를 더 추가해야합니다 (씬 그래프도 변경됨). 플러스 측면에서 이것은 첫 번째 반복 렌더러를 시작하고 실행하는 가장 간단한 방법처럼 보입니다.
  3. 분산 메타 데이터 . 렌더러 캐시 메타 데이터 컴포넌트는 각 장면 노드에 저장됩니다. 이 데이터는 구현 고유의 것이 아니라 캐시에 필요한 ID, 유형 및 기타 관련 데이터를 보유합니다. 그런 다음 ID를 사용하여 캐시 조회를 어레이에서 직접 수행 할 수 있으며, 유형은 사용할 렌더링 방식 유형 (예 : 스프라이트 및 볼륨)을 나타낼 수 있습니다.
  4. 방문자 + 분산 매핑 . 렌더러는 방문자이고 장면 노드는 방문자 패턴의 요소입니다. 각 장면 노드에는 렌더러 만 조작하는 캐시 키 (메타 데이터와 같지만 ID)가 있습니다. 일반화 된 맵 조회 대신 ID를 배열에 사용할 수 있습니다. 렌더러는 씬 노드가 씬 노드의 유형에 따라 다른 렌더링 기능을 디스패치 할 수 있도록하며, 모든 캐시에서 ID를 사용할 수 있습니다. 기본 또는 범위를 벗어난 ID는 캐시 누락을 나타냅니다.

이 문제를 어떻게 해결 하시겠습니까? 아니면 어떤 제안이 있습니까? 내 벽을 읽어 주셔서 감사합니다!


1
진전이 있었습니까?
Andreas

이것은 매우 복잡한 질문이므로 여러 개의 개별 질문으로 나누어야합니다. 이것은 본질적으로 "엔진을 어떻게 설계해야합니까?"입니다. 내 조언은 더 간단한 구성 요소를 먼저 지원하는 기능을 디자인 한 다음 기능을 추가하고 리팩토링하는 것입니다. 또한 찾고자하는 많은 정보를 다루는 3D 게임 엔진 디자인 북을 찾아보십시오.
Ian Young

답변:


2

질문을 다시 읽은 후에는 문제가 너무 복잡하다고 생각합니다. 이유는 다음과 같습니다.

  1. 렌더링 시스템에는 실제로 순방향과 지연의 두 가지 유형 만 있으며 장면 그래프에 의존하는 것은 없습니다.

  2. 렌더링 시스템에서 실제로 발생하는 유일한 성능 문제는 많은 폴리 ​​카운트와 비효율적 인 셰이더 및 클라이언트 코드에서 비롯됩니다.

  3. 캐시 미스는 실제로 성능을 저하 시키지만 실제로 생각하는 괴물은 아닙니다. 성능 향상의 80 %는보다 효율적인 알고리즘에서 비롯됩니다. 코드를 미리 최적화하는 실수를 저 지르지 마십시오.

그것은 말했다 :

홈 브루 장면 그래프를 사용하는 경우 장면 그래프 코드의 렌더링 부분을 디자인하기 위해 이미 "렌더러"인터페이스 (또는 기본 클래스)를 사용해야합니다. 이중 디스패치를 ​​사용하는 방문자 패턴은 색상, 질감, 메쉬, 변형 등과 같은 많은 유형의 그래프 노드를 사용하고 있기 때문에이 방법에 대한 좋은 접근 방식입니다. 이러한 방식으로 렌더링주기 동안 렌더러가해야 할 일은 장면 트리 구조를 깊이 우선으로 걷고 인수로 전달합니다. 이런 식으로 렌더러는 기본적으로 단지 셰이더 모음 일뿐 아니라 프레임 버퍼 일 수도 있습니다. 그 결과 렌더링 시스템에 더 이상 검색 / 제거 코드가 필요하지 않고 장면 그래프 자체 만 있으면됩니다.

당신이 직면 한 문제를 해결할 수있는 다른 방법이 있지만, 너무 오래 대답하고 싶지 않습니다. 따라서 최선의 조언은 간단한 작업을 먼저 한 다음 확장하여 약점을 찾은 다음 다른 접근법을 실험하고 그들의 강점 / 약점이 실제로 어디에 있는지 확인하는 것입니다.

그런 다음 정보에 입각 한 결정을 내릴 수 있습니다.

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