스크립터블 랜더 파이프라인(SRP)
SRP 배처는 동일한 셰이더 배리언트를 사용하는 머티리얼에 대해서 작동합니다.
이게 무슨 소리냐?
셰이더란 조명 입력과 머티리얼 설정에 따라 랜더링된 각 픽셀의 컬러를 계산하는 수학 계산식과 알고리즘을 포함하는 작은 스크립트입니다.
동일한 쉐이더를 사용하는 머티리얼에서 쉐이더의 특정 요소를 변경하고 싶을 때, 최적화할 수 있는 방법이 바로 SRP 배치라는 의미입니다.
왜 사용하는가
SRP배처를 사용하면, 셰이더가 할 일이 줄어듦으로써 CPU랜더링 속도를 높일 수 있습니다.
(GPU 성능도 당연히 향상됩니다.)
그래픽과 관련된 얘기지만, GPU가 아닌 CPU의 속도를 높인다는 것에 조금 의아할 수 있습니다.
그래픽에서의 병목 현상은 GPU가 아무리 좋다고 하더라도 CPU가 일을 제대로 하지 못한다면, 발생할 수 있습니다. 그 반대의 경우도 마찬가지입니다.
그렇기에 최적화를 위해선 CPU와 GPU 모두 최적화를 해줘야만 합니다.
SRP 전제조건
SRP배처를 사용하기 위해선 아래의 세 가지 파이프라인과 지원하는 플랫폼을 사용해야 합니다.
플랫폼
Platform | Minimum Unity version required |
Windows DirectX 11 | 2018.2 |
PlayStation 4 | 2018.2 |
Vulkan | 2018.3 |
OSX Metal | 2018.3 |
iOS Metal | 2018.3 |
Nintendo Switch | 2018.3 |
Xbox One DirectX 11 | 2019.2 |
OpenGL 4.2 and higher | 2019.1 |
OpenGL ES 3.1 and higher | 2019.1 |
Xbox One DirectX 12 | 2019.1 |
Windows DirectX 12 | 2019.1 |
SRP 배처의 동작 방식
Unity를 하신 분은 모두 아시겠지만, 유니티는 런타임 동안 머티리얼의 프로퍼티를 수정할 수 있습니다. 하지만 이러한 점에 단점도 존재합니다.
새로운 머티리얼을 사용하는 경우 DrawCall이 더 많은 작업을 수행해야 하죠.
한 마디로 DrawCall이 더 많이 발생한다는 겁니다.
그래서 씬에 포함된 머티리얼의 수가 많을수록 Unity는 GPU 데이터를 설정하기 위해 더 많은 CPU를 사용해야 합니다.
이를 해결하기 위한 방법 SRP 배처는 SRP가 계산해야 될 일부 바이트를 GPU 커맨드 버퍼로 푸시하는 것입니다.
왼쪽은 일반 배치와 오른쪽은 SRP배치를 사용한 계산 과정입니다.
위 계산 과정은 CPU가 GPU에게 어떻게 DrawCall을 결정할 지를 계산하는 과정입니다.
일반 배치부터, 아주 쉽게 차근차근 살펴보겠습니다.
1.
빌트인 데이터를 수집하고 Object CBUFFER를 만듭니다.
2.
GPU에 위에서 생성한 Object CBUFFER를 업로드합니다.
3.
머티리얼 데이터를 수집하고 Material CBUFFER를 만듭니다.
4.
GPU에서 위에서 생성한 Material CBUFFER를 업로드합니다.
5.
Material CBUFFER를 바인딩합니다.
6.
Object CBUFFER를 바인딩합니다.
SRP도 차근차근 살펴보겠습니다.
1.
존재하는 Material CBUFFER를 바인딩합니다.
2.
여기서 SRP가 이전에 저장하고 있는 offeset Object CBUFFER와 바인딩합니다.
위 그림에서 생략된 부분이 있습니다. SRP 배치를 사용하면 동일한 셰이더를 사용하는 오브젝트들의 기본 정보가 최적화되어 한 번에 전송됩니다.
즉, Large Complete Gpu Setup 부분이 기본 렌더링 파이프라인과 다르게 최적화되어 한 번에 보내집니다.
SRP Offset Object CBUFFER 메모리 활용
다이나믹 프로그래밍처럼 메모리를 사용해서 동일한 배리언트에 대해선, 이전에 바인딩된 값을 저장해뒀다 사용한다는 것이죠.
실제로 custom shader를 만든 다면, SRP배처를 사용하기 위해 사용되는 배리언트들은 CBUFFER로 감싸줘야 합니다. 그래야 셰이더를 사용할 때 어떤 값을 offset으로 삶을지 Unity가 알 수 있죠.
이러한 이점 때문에, SRP 배처는 셰이더가 변하지 않는다면 계산 과정과 버퍼를 GPU 메모리에 업로드할 필요가 없습니다. 대신에 SRP 배처는 전용 코드 경로를 사용하여 대형 GPU 버퍼로 Unity 엔진 프로퍼티를 빠르게 업데이트합니다.
SRP 배처 렌더링 워크플로입니다. SRP 배처는 전용 코드 경로를 사용하여 대형 GPU 버퍼로 Unity 엔진 프로퍼티를 빠르게 업데이트합니다.
가장 위에 Unity Engine Properties부터 시작하는 것이 기본이 되는 Offset Object Buffer라고 생각하시면됩니다.
그리고 아래에 사용하는 각 머티리얼들의 CBUFFER들이 SRP Shader에서 CBUFFER로 설정된 머티리얼 CBUFFER들이죠.
그리고 위 두 가지를 잘 조합하여, Shader가 계산해서 DrawCall를 만들어줍니다.
여기서 중점으로 봐야될 건 우선, Per Object large Buffer는 메모리에 저장되어 있는 값입니다. 즉, 기존 배치에선 보내줘야 할 Object Buffer들의 단계를 건너 뛸 수 있다는 것이죠.
그리고 동일한 프로퍼티에 대해선, 바인딩하는 과정을 건너뛸 수 있죠.