반응형

*Unity 6000.0.20f1 기준으로 작성된 자료입니다.

 

GPU Resident Drawer

  • Unity 6에 신규로 추가된 DOTS Instancing 기반 드로우콜 병목 최적화 시스템입니다.
  • Transform & Mesh 등, 흔히 드로우콜 속성의 렌더 API를 최적화하며, SRP Batcher와 병행해서 사용 가능합니다.
  • Mesh Renderer에 BatchRendererGroup 시스템이 내장된 것으로 보이며 DOTS Instancing 외에 GPU Culling 시스템까지 내장되어 있습니다.
  • GPU Occlusion Culling은 Hierarchical-Z Occlusion Culling 시스템 사용하는 것으로 추측됩니다.
  • Additional Light, SH, Reflection Probe 및 LOD 등 DOTS Instancing 셰이더 API가 이미 구현되어 있어 커스텀 셰이더 개발 시 활용 가능합니다.
  • Forward+만 지원하며 위 DOTS Instancing 셰이더 API 또한 Forward+ 전용으로 구현되어 있습니다.

확인 & 예상되는 한계점

  • Forward+만 지원.
  • Graphics API가 Vulkan 이상 디바이스만 지원. (Compute Shader & 구조화 버퍼 사용 가능해야함)
  • Mesh Renderer만 지원.
  • 동일한 Mesh & Material의 오브젝트끼리 배칭 가능. 종류가 다양하면 오히려 성능 저하 예상.
  • 모바일 환경에서 GPU Culling 안정성 여부 검증 필요. 

개인 평가

  • 기존 SRP Batcher만 사용했을때 많은 오브젝트에 의한 드로우콜 부하를 어느정도 완화 가능하겠지만 동일한 Mesh & Material끼리만 인스턴싱 가능하다는 부분에서 반쪽짜리 인스턴싱 시스템으로 평가함.
    • (Material 버퍼 인스턴싱은 추후 업데이트에서 될 가능성 있음)
  • Mesh Index & Material Property 구조화 버퍼 구현을 통해 커스텀 가능하겠지만 GPU Culling 등 내장 시스템과 연동되지 않을 것이기 때문에 어차피 커스텀 Renderer 구현 필요함.

 

DOTS 지원 셰이더 샘플

Shader "CatDarkGame/DOTSSample"
{
    Properties
    { 
        [MainTexture] _BaseMap("Texture", 2D) = "white" {}
        [MainColor] _BaseColor("Color", Color) = (1, 1, 1, 1)
    }

    SubShader
    {
        Tags { "RenderType" = "Opaque" "Queue"="Geometry" "RenderPipeline" = "UniversalPipeline" }
        LOD 100

        Pass
        {
            Name  "DOTSSample"
            Tags {"LightMode" = "UniversalForward"}

            HLSLPROGRAM
            #pragma target 4.5

            #pragma vertex vert
            #pragma fragment frag
            
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"

            CBUFFER_START(UnityPerMaterial)
                float4  _BaseMap_ST;
                half4   _BaseColor;
            CBUFFER_END

            #ifdef UNITY_DOTS_INSTANCING_ENABLED
                UNITY_DOTS_INSTANCING_START(MaterialPropertyMetadata)
                    UNITY_DOTS_INSTANCED_PROP(float4, _BaseColor)   // float 자료형만 지원
                UNITY_DOTS_INSTANCING_END(MaterialPropertyMetadata)

                // DOTS 전용 Static 변수에 값을 복제하여 사용하면 GPU 성능 높일 수 있다고함. (LitInput.hlsl 주석 참고)
                static float4 unity_DOTS_Sampled_BaseColor;
                void SetupDOTSLitMaterialPropertyCaches()  // UNITY_SETUP_INSTANCE_ID 디파인에서 호출됨
                {
                    unity_DOTS_Sampled_BaseColor            = UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(float4, _BaseColor);
                }
                #undef UNITY_SETUP_DOTS_MATERIAL_PROPERTY_CACHES
                #define UNITY_SETUP_DOTS_MATERIAL_PROPERTY_CACHES() SetupDOTSLitMaterialPropertyCaches()
            
                #define _BaseColor              unity_DOTS_Sampled_BaseColor
            #endif
            
            TEXTURE2D(_BaseMap);    SAMPLER(sampler_BaseMap);
            
            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 uv : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct Varyings
            {
                float4 positionCS : SV_POSITION;
                float2 uv : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            }; 
            
            Varyings vert(Attributes input)
            {
                Varyings output = (Varyings)0;
                UNITY_SETUP_INSTANCE_ID(input);
                
                float4 positionOS = input.positionOS;
                float3 positionWS = TransformObjectToWorld(positionOS.xyz);
                float4 positionCS = TransformWorldToHClip(positionWS);

                output.positionCS = positionCS;
                output.uv = input.uv;
                return output;
            }

            float4 frag(Varyings input) : SV_Target
            {
                UNITY_SETUP_INSTANCE_ID(input);
                float2 baseMapUV = input.uv.xy * _BaseMap_ST.xy + _BaseMap_ST.zw;
                float4 texColor = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, baseMapUV);
                
                float4 finalColor = texColor * _BaseColor;
                return finalColor;
            }
            
            ENDHLSL
        }
    }
}

 

 

 

참고 자료

 

 

반응형

WRITTEN BY
CatDarkGame
Technical Artist dhwlgn12@gmail.com

,