Set Pass Call에 대한 클라이언트 개발자의 의견
Set Pass Call에 대한 이해는 사실 TA분들을 제외하고는, 클라이언트 개발자가 깊게 알 필요는 없다고 생각합니다.
이 기능의 구현과 최적화는 클라이언트의 영역이 아니기 때문입니다.
그러나, 클라이언트 개발자로서 Set Pass Call에 대한 그래픽스 지식은 필요하다고 생각합니다.
이는 TA분과의 소통을 위한 것입니다.
클라이언트 개발자는 CPU, GPU 성능이 부하가 발생한 지점을 파악하고, Set Pass Call이 많이 발생했다면 그 부분을 의심할 수 있어야 합니다.
그리고 이 성능 비용에 대해 TA분과 소통하면서 고쳐나가는 것이 바람직 하죠.
예를 들어, 성능 문제가 발생하는 부분을 단일 패스 셰이더로 변경했을 때, 그 성능 개선의 정도를 파악해야합니다.
또한 해당 패스를 단일 패스 셰이더로 바꿔도 그래픽적으로 크게 뒤떨어지지 않는지 검토해야 합니다. 이러한 사항은 TA와 상의한 후 수정해야 합니다.
Set Pass Call
Set Pass Call이란 CPU가 GPU에게 새로운 렌더링 패스를 시작하라는 명령입니다.
이는 주로 셰이더 변경이 필요할 때 발생하며, 머티리얼 내부의 셰이더 패스를 변경해야 할 때 필요한 호출입니다.
간단히 말해서, 셰이더 상태를 변경할 필요가 있을 때마다 Set Pass Call이 발생합니다.
최신 모바일 게임 개발에서는 Draw Call을 줄이는 것도 중요하지만, Set Pass Call을 줄이는 것이 더 중요하다는 의견이 많습니다.
과거에는 모바일에서 단일 셰이더를 사용하거나 많은 셰이더를 사용하지 않았지만, 모바일의 성능 향상과 함께 그래픽 향상을 위해 셰이더의 복잡성이 증가했습니다.
따라서 이전과 달리 Draw Call뿐만 아니라 Set Pass Call도 최적화해야 합니다.
그러나, Set Pass Call은 Draw Call과는 달리 유니티 내에서 직접 확인하기 어렵습니다.
그렇기에, 유니티 외부 툴인 아래 RenderDoc을 사용해서 Set Pass Call의 발생 원인이 무엇인지 확인하기도 합니다.
셰이더 패스
셰이더 패스는 셰이더 내에서 특정한 렌더링 작업을 수행하는 블록으로, 복수의 셰이더 패스를 사용하여 다양한 렌더링 효과를 순차적으로 적용할 수 있습니다.
각 패스는 독립적으로 버텍스 셰이더와 프래그먼트 셰이더를 포함할 수 있으며, 이를 통해 물체에 대한 조명, 텍스처링, 포스트 프로세싱 등 다양한 시각적 처리를 단계적으로 적용합니다.
셰이더 패스를 사용하는 이유 중 하나는 렌더링의 유연성을 높이기 위해서입니다.
예를 들어, 하나의 머티리얼이 여러 가지 렌더링 효과를 필요로 할 때, 각각의 효과를 별도의 패스로 구현하여 관리할 수 있습니다. 이렇게 함으로써, 개발자는 렌더링 파이프라인을 더 세밀하게 제어하고 최적화할 수 있습니다.
Shader "Custom/MultiPassShader" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_LightColor ("Light Color", Color) = (1,1,1,1)
}
SubShader {
// Pass 1: Ambient lighting
Pass {
Name "Ambient"
Tags { "LightMode" = "Always" }
CGPROGRAM
#pragma vertex vert
#pragma fragment fragAmbient
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
v2f vert (appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 fragAmbient (v2f i) : SV_Target {
// Apply a simple ambient light
fixed4 texColor = tex2D(_MainTex, i.uv);
return texColor * 0.5; // Dim the texture color for ambient effect
}
ENDCG
}
// Pass 2: Additive light
Pass {
Name "AdditiveLight"
Tags { "LightMode" = "Always" }
Blend One One // Additive blending
CGPROGRAM
#pragma vertex vert
#pragma fragment fragLight
uniform fixed4 _LightColor;
fixed4 fragLight (v2f i) : SV_Target {
return _LightColor; // Apply light color
}
ENDCG
}
}
}
C#
복사
•
첫 번째 Pass (Ambient) : 기본 텍스처에 앰비언트 조명 효과를 적용합니다. 여기서 텍스처 색상을 어둡게 조정하여 간단한 앰비언트 조명 효과를 구현합니다.
•
두 번째 Pass (AdditiveLight) : 물체에 추가적인 조명 효과를 적용합니다. 이 패스에서는 Blend One One 명령을 사용하여 앞서 렌더링된 이미지에 조명 색상을 더하는 방식(Additive Blending)으로 빛을 추가합니다.
그러나 위와 같이 Pass를 늘리면, Set Pass Call도 하나씩 증가하게 됩니다.
따라서 가능한 한 Pass를 단일화하여 최적화하는 환경이 중요합니다.
Set Pass Call의 비용
Set Pass Call은 CPU와 GPU 사이의 상호작용을 필요로 하며, 각각의 하드웨어에서 비용이 발생합니다.
CPU 관점에서의 비용
1.
명령 발행 비용 : CPU는 GPU에게 셰이더 변경이나 머티리얼 설정 같은 새로운 명령을 발행합니다. 이 과정에서 CPU는 필요한 데이터를 준비하고, 명령을 생성하여 GPU로 전송하는 작업을 수행합니다.
2.
CPU-GPU 동기화 비용 : 새로운 렌더링 상태를 설정하는 과정에서 CPU와 GPU 사이의 동기화가 필요할 수 있습니다. 만약 GPU가 이전 명령의 처리가 완료되지 않은 상태에서 새로운 상태 변경 명령을 받게 되면, CPU는 GPU가 준비될 때까지 기다려야 합니다. 이러한 동기화 대기 시간도 CPU에게는 추가적인 비용으로 작용합니다.
GPU 관점에서의 비용
1.
상태 변경 처리 비용 : GPU는 받은 명령에 따라 셰이더 프로그램을 변경하거나, 머티리얼의 속성을 업데이트하는 등의 상태 변경 작업을 수행합니다.