UnityInstancing头文件分析

Unity Instancing.hlsl

A.平台适配

UNITY_SUPPORT_INSTANCING

  • SHADER_TARGET >= 35且D3D11/GLES3/GLCore/XboxOne/GameCore/PSSL/Vulkan/Metal/Switch

UNITY_SUPPORT_STEREO_INSTANCING

  • D3D11/GLCore/GLES3/Vulkan

UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE

  • D3D11/GLCore/GLES3/Metal/PSSL/Vulkan/Switch

undef UNITY_SUPPORT_INSTANCING

defined(SHADER_TARGET_SURFACE_ANALYSIS) && defined(UNITY_SUPPORT_INSTANCING)

B.instancing paths (根据绘制指令选择不同的Instance路径)

  • UNITY_INSTANCING_ENABLED Defined if instancing path is taken.
  • UNITY_PROCEDURAL_INSTANCING_ENABLED Defined if procedural instancing path is taken.
  • UNITY_STEREO_INSTANCING_ENABLED Defined if stereo instancing path is taken.
  • UNITY_ANY_INSTANCING_ENABLED Defined if any instancing path is taken
    #if defined(UNITY_SUPPORT_INSTANCING) && defined(INSTANCING_ON)
        #define UNITY_INSTANCING_ENABLED
    #endif
    #if defined(UNITY_SUPPORT_INSTANCING) && defined(PROCEDURAL_INSTANCING_ON)
        #define UNITY_PROCEDURAL_INSTANCING_ENABLED
    #endif
    #if defined(UNITY_SUPPORT_INSTANCING) && defined(DOTS_INSTANCING_ON)
        #define UNITY_DOTS_INSTANCING_ENABLED
    #endif
    #if defined(UNITY_SUPPORT_STEREO_INSTANCING) && defined(STEREO_INSTANCING_ON)
        #define UNITY_STEREO_INSTANCING_ENABLED
    #endif

    #if defined(UNITY_INSTANCING_ENABLED) || defined(UNITY_PROCEDURAL_INSTANCING_ENABLED) || defined(UNITY_DOTS_INSTANCING_ENABLED) || defined(UNITY_STEREO_INSTANCING_ENABLED)
        #define UNITY_ANY_INSTANCING_ENABLED 1
    #else
        #define UNITY_ANY_INSTANCING_ENABLED 0
    #endif
  • UNITY_SUPPORT_INSTANCING 平台支持Instance的情况下,根据Instance的定义情况开启对应的InstancePath宏定义
    [UNITY_INSTANCING_ENABLED/UNITY_PROCEDURAL_INSTANCING_ENABLED/UNITY_DOTS_INSTANCING_ENABLED]
  • UNITY_SUPPORT_STEREO_INSTANCING 平台支持Stereo Instance的情况下,根据Stereo Instance的定义情况开启
    [UNITY_STEREO_INSTANCING_ENABLED]
  • instancing/procedural/dots procedural/stereo instancing
    只要有开Instance都会开启[UNITY_ANY_INSTANCING_ENABLED]

C.Instance的CBUFFER_SCOPE Begin/End

  • GLES3/GLCore/Metal/Vulkan
    • UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(name): cbuffer name {
    • UNITY_INSTANCING_CBUFFER_SCOPE_END: }
  • 其他平台
    • UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(name): CBUFFER_START(name)
    • UNITY_INSTANCING_CBUFFER_SCOPE_END: CBUFFER_END

D.基本的instancing宏定义函数设置

  • UNITY_VERTEX_INPUT_INSTANCE_ID
    • 用来定义instance ID field在顶点着色器的input / output struct.
  • UNITY_GET_INSTANCE_ID
    • (全局Instance唯一Id) 用Input struct获取instance ID
    #if UNITY_ANY_INSTANCING_ENABLED

        // A global instance ID variable that functions can directly access.
        static uint unity_InstanceID;

        // Don‘t make UnityDrawCallInfo an actual CB on GL
        #if !defined(SHADER_API_GLES3) && !defined(SHADER_API_GLCORE)
            UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityDrawCallInfo)
        #endif
                int unity_BaseInstanceID;
                int unity_InstanceCount;
        #if !defined(SHADER_API_GLES3) && !defined(SHADER_API_GLCORE)
            UNITY_INSTANCING_CBUFFER_SCOPE_END
        #endif

        #ifdef SHADER_API_PSSL
            #define DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID uint instanceID;
            #define UNITY_GET_INSTANCE_ID(input)    _GETINSTANCEID(input)
        #else
            #define DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID uint instanceID : SV_InstanceID;
            #define UNITY_GET_INSTANCE_ID(input)    input.instanceID
        #endif

    #else
        #define DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID
    #endif // UNITY_INSTANCING_ENABLED || UNITY_PROCEDURAL_INSTANCING_ENABLED || UNITY_STEREO_INSTANCING_ENABLED

    #if !defined(UNITY_VERTEX_INPUT_INSTANCE_0ID)
    #   define UNITY_VERTEX_INPUT_INSTANCE_ID DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID
    #endif
  • UNITY_ANY_INSTANCING_ENABLED[即任意Instance]
    • static uint unity_InstanceID;

    • Don‘t make UnityDrawCallInfo an actual CB on GL

      • 对非GL(ES3/Core)平台上定义
        • UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityDrawCallInfo)
          • int unity_BaseInstanceID;
          • int unity_InstanceCount;
        • UNITY_INSTANCING_CBUFFER_SCOPE_END
    • DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID

      • 在PS平台上定义
        • uint instanceID;
      • 其他平台
        • uint instanceID : SV_InstanceID;
    • UNITY_GET_INSTANCE_ID(input)

      • 在PS平台上定义
        • _GETINSTANCEID(input)
      • 其他平台
        • input.instanceID
    • DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID 对没有定义UNITY_ANY_INSTANCING_ENABLED的情况置空

  • UNITY_VERTEX_INPUT_INSTANCE_ID

    • 定义为 DEFAULT_UNITY_VERTEX_INPUT_INSTANCE_ID

E.basic stereo instancing setups 跳过

  • UNITY_VERTEX_OUTPUT_STEREO
    • Declare stereo target eye field in vertex shader output struct.
  • UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO
    • Assign the stereo target eye.
  • UNITY_TRANSFER_VERTEX_OUTPUT_STEREO
    • Copy stero target from input struct to output struct. Used in vertex shader.
  • UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX

F.UNITY_SETUP_INSTANCE_ID和UNITY_TRANSFER_INSTANCE_ID

////////////////////////////////////////////////////////
// - UNITY_SETUP_INSTANCE_ID        Should be used at the very beginning of the vertex shader / fragment shader,
//                                  so that succeeding code can have access to the global unity_InstanceID.
//                                  Also procedural function is called to setup instance data.
// - UNITY_TRANSFER_INSTANCE_ID     Copy instance ID from input struct to output struct. Used in vertex shader.
  • 对任意的Instance
    • 初步定义void UnitySetupInstanceID(uint inputInstanceID)给下面DEFAULT_UNITY_SETUP_INSTANCE_ID使用
      • UNITY_STEREO_INSTANCING_ENABLED处理跳过
      • unity_InstanceID = inputInstanceID + unity_BaseInstanceID;
          #if UNITY_ANY_INSTANCING_ENABLED
              void UnitySetupInstanceID(uint inputInstanceID)
              {
                  #ifdef UNITY_STEREO_INSTANCING_ENABLED
                      #if !defined(SHADEROPTIONS_XR_MAX_VIEWS) || SHADEROPTIONS_XR_MAX_VIEWS <= 2
                          #if defined(SHADER_API_GLES3)
                              // We must calculate the stereo eye index differently for GLES3
                              // because otherwise,  the unity shader compiler will emit a bitfieldInsert function.
                              // bitfieldInsert requires support for glsl version 400 or later.  Therefore the
                              // generated glsl code will fail to compile on lower end devices.  By changing the
                              // way we calculate the stereo eye index,  we can help the shader compiler to avoid
                              // emitting the bitfieldInsert function and thereby increase the number of devices we
                              // can run stereo instancing on.
                              unity_StereoEyeIndex = round(fmod(inputInstanceID, 2.0));
                              unity_InstanceID = unity_BaseInstanceID + (inputInstanceID >> 1);
                          #else
                              // stereo eye index is automatically figured out from the instance ID
                              unity_StereoEyeIndex = inputInstanceID & 0x01;
                              unity_InstanceID = unity_BaseInstanceID + (inputInstanceID >> 1);
                          #endif
                      #else
                          unity_StereoEyeIndex = inputInstanceID % _XRViewCount;
                          unity_InstanceID = unity_BaseInstanceID + (inputInstanceID / _XRViewCount);
                      #endif
                  #else
                      unity_InstanceID = inputInstanceID + unity_BaseInstanceID;
                  #endif
              }
      
    • 定义DEFAULT_UNITY_SETUP_INSTANCE_ID(input)
      • 对Procedural instance处理
        • 检查Procedural函数没有就报错#error
        • 定义void UNITY_INSTANCING_PROCEDURAL_FUNC()
        • 定义DEFAULT_UNITY_SETUP_INSTANCE_ID为
          • UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input));
          • UNITY_INSTANCING_PROCEDURAL_FUNC();
      • 普通Instance
        • UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input));
        #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
            #ifndef UNITY_INSTANCING_PROCEDURAL_FUNC
                #error "UNITY_INSTANCING_PROCEDURAL_FUNC must be defined."
            #else
                void UNITY_INSTANCING_PROCEDURAL_FUNC(); // forward declaration of the procedural function
                #define DEFAULT_UNITY_SETUP_INSTANCE_ID(input)      { UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input)); UNITY_INSTANCING_PROCEDURAL_FUNC();}
            #endif
        #else
            #define DEFAULT_UNITY_SETUP_INSTANCE_ID(input)          { UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input));}
        #endif
    
    • UNITY_TRANSFER_INSTANCE_ID(input, output)
      • output.instanceID = UNITY_GET_INSTANCE_ID(input)
        #define UNITY_TRANSFER_INSTANCE_ID(input, output)   output.instanceID = UNITY_GET_INSTANCE_ID(input)
    
  • 对不是Instance的情况Fallback置空
        #else
            #define DEFAULT_UNITY_SETUP_INSTANCE_ID(input)
            #define UNITY_TRANSFER_INSTANCE_ID(input, output)
        #endif
    
  • 定义 UNITY_SETUP_INSTANCE_ID
    • DEFAULT_UNITY_SETUP_INSTANCE_ID(input)
        #if !defined(UNITY_SETUP_INSTANCE_ID)
            #define UNITY_SETUP_INSTANCE_ID(input) DEFAULT_UNITY_SETUP_INSTANCE_ID(input)
        #endif
    
  • 总结:

    • UNITY_SETUP_INSTANCE_ID(input)
      => DEFAULT_UNITY_SETUP_INSTANCE_ID
      =>1.Procedural
      UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input))
      UNITY_INSTANCING_PROCEDURAL_FUNC();
      =>2.非Procedural
      直接 UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input));
    • UNITY_TRANSFER_INSTANCE_ID(input, output)
      =>output.instanceID = UNITY_GET_INSTANCE_ID(input)
      =>input.instanceID

G.instanced property arrays

  • 对一般的Instance以及DotsInstance,根据Options设置对应宏参数
    • UNITY_INSTANCED_ARRAY_SIZE[实例化数组大小]
      • Options:UNITY_FORCE_MAX_INSTANCE_COUNT forcemaxcount
        例如://#pragma instancing_options forcemaxcount:50
      • Options:UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE
      • Options:UNITY_MAX_INSTANCE_COUNT
      • FallBack:
        • Vulkan/Mobile/Switch:250
        • 其他平台:500
      ////////////////////////////////////////////////////////
      // instanced property arrays
      #if defined(UNITY_INSTANCING_ENABLED) || defined(UNITY_DOTS_INSTANCING_ENABLED)
          #ifdef UNITY_FORCE_MAX_INSTANCE_COUNT
              #define UNITY_INSTANCED_ARRAY_SIZE  UNITY_FORCE_MAX_INSTANCE_COUNT
          #elif defined(UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE)
              #define UNITY_INSTANCED_ARRAY_SIZE  2 // minimum array size that ensures dynamic indexing
          #elif defined(UNITY_MAX_INSTANCE_COUNT)
              #define UNITY_INSTANCED_ARRAY_SIZE  UNITY_MAX_INSTANCE_COUNT
          #else
              #if (defined(SHADER_API_VULKAN) && defined(SHADER_API_MOBILE)) || defined(SHADER_API_SWITCH)
                  #define UNITY_INSTANCED_ARRAY_SIZE  250
              #else
                  #define UNITY_INSTANCED_ARRAY_SIZE  500
              #endif
          #endif
      
    • UNITY_INSTANCING_BUFFER_START/UNITY_INSTANCING_BUFFER_END定义
      • Dots跳过
      • 非Dots情况
        • UNITY_INSTANCING_BUFFER_START(buf)
          • UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityInstancing_##buf)
        • UNITY_INSTANCING_BUFFER_END(arr)
          • } arr##Array[UNITY_INSTANCED_ARRAY_SIZE]; UNITY_INSTANCING_CBUFFER_SCOPE_END
        • UNITY_DEFINE_INSTANCED_PROP(type, var)
          • type var;
        • UNITY_ACCESS_INSTANCED_PROP(arr, var)
          • arr##Array[unity_InstanceID].var
        • Dots相关宏置空/实例化报错处理
          #if defined(UNITY_DOTS_INSTANCING_ENABLED)
          #define UNITY_INSTANCING_BUFFER_START(buf)      UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityInstancing_##buf)
          #define UNITY_INSTANCING_BUFFER_END(arr)        UNITY_INSTANCING_CBUFFER_SCOPE_END
          #define UNITY_DEFINE_INSTANCED_PROP(type, var)  type var;
          #define UNITY_ACCESS_INSTANCED_PROP(arr, var)   var
      
          #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityDOTSInstancing.hlsl"
      
      #else
          #define UNITY_INSTANCING_BUFFER_START(buf)      UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityInstancing_##buf) struct{
              #define UNITY_INSTANCING_BUFFER_END(arr)        } arr##Array[UNITY_INSTANCED_ARRAY_SIZE]; UNITY_INSTANCING_CBUFFER_SCOPE_END
              #define UNITY_DEFINE_INSTANCED_PROP(type, var)  type var;
              #define UNITY_ACCESS_INSTANCED_PROP(arr, var)   arr##Array[unity_InstanceID].var
      
              #define UNITY_DOTS_INSTANCING_START(name)
              #define UNITY_DOTS_INSTANCING_END(name)
              #define UNITY_DOTS_INSTANCED_PROP(type, name)
      
              #define UNITY_ACCESS_DOTS_INSTANCED_PROP(type, var) var
              #define UNITY_ACCESS_DOTS_INSTANCED_PROP_FROM_MACRO(type, metadata_underscore_var) This_macro_cannot_be_called_without_UNITY_DOTS_INSTANCING_ENABLED
              #define UNITY_ACCESS_DOTS_AND_TRADITIONAL_INSTANCED_PROP(type, arr, var) UNITY_ACCESS_INSTANCED_PROP(arr, var)
      #endif
      
    • Options:UNITY_ASSUME_UNIFORM_SCALING
      • UNITY_WORLDTOOBJECTARRAY_CB [1]
      • UNITY_WORLDTOOBJECTARRAY_CB [0]
      • 例如#pragma instancing_options assumeuniformscaling
    • Options:Lod fade相关
      • UNITY_INSTANCED_LOD_FADE/LOD_FADE_PERCENTAGE/LOD_FADE_CROSSFADE
        • UNITY_USE_LODFADE_ARRAY
    • Options:RENDERING_LAYER
      • UNITY_INSTANCED_RENDERING_LAYER
        • UNITY_USE_RENDERINGLAYER_ARRAY
    • Options:UNITY_INSTANCED_LIGHTMAPSTS LightMap数组
      • 如果开启LightMap[KeyWord:LIGHTMAP_ON]
        • UNITY_USE_LIGHTMAPST_ARRAY
      • 如果开启动态LightMap[KeyWord:DYNAMICLIGHTMAP_ON]
        • UNITY_USE_DYNAMICLIGHTMAPST_ARRAY
    • Options:UNITY_INSTANCED_SH 使用SH不使用LightMap
      • 不使用动态Lightmap
        • UNITY_USE_SHCOEFFS_ARRAYS 即使用SH数组
      • SHADOWS_SHADOWMASK
        • UNITY_USE_PROBESOCCLUSION_ARRAY ShadowMask使用SH+Occlusion数组
        // Put worldToObject array to a separate CB if UNITY_ASSUME_UNIFORM_SCALING is defined. Most of the time it will not be used.
        #ifdef UNITY_ASSUME_UNIFORM_SCALING
            #define UNITY_WORLDTOOBJECTARRAY_CB 1
        #else
            #define UNITY_WORLDTOOBJECTARRAY_CB 0
        #endif
    
        #if defined(UNITY_INSTANCED_LOD_FADE) && (defined(LOD_FADE_PERCENTAGE) || defined(LOD_FADE_CROSSFADE))
            #define UNITY_USE_LODFADE_ARRAY
        #endif
    
        #if defined(UNITY_INSTANCED_RENDERING_LAYER)
            #define UNITY_USE_RENDERINGLAYER_ARRAY
        #endif
    
        #ifdef UNITY_INSTANCED_LIGHTMAPSTS
            #ifdef LIGHTMAP_ON
                #define UNITY_USE_LIGHTMAPST_ARRAY
            #endif
            #ifdef DYNAMICLIGHTMAP_ON
                #define UNITY_USE_DYNAMICLIGHTMAPST_ARRAY
            #endif
        #endif
    
        #if defined(UNITY_INSTANCED_SH) && !defined(LIGHTMAP_ON)
            #if !defined(DYNAMICLIGHTMAP_ON)
                #define UNITY_USE_SHCOEFFS_ARRAYS
            #endif
            #if defined(SHADOWS_SHADOWMASK)
                #define UNITY_USE_PROBESOCCLUSION_ARRAY
            #endif
        #endif
    
    • 非Dots情况
      • UNITY_INSTANCING_BUFFER_START(PerDraw0) CB:0
        • 没定义UNITY_DONT_INSTANCE_OBJECT_MATRICES
          • 定义unity_ObjectToWorldArray M矩阵数组
          • 如果 UNITY_WORLDTOOBJECTARRAY_CB为0
            • 定义unity_WorldToObjectArray I_M数组
        • 如果使用了LodFade数组
          • 定义 unity_LODFadeArray数组
          • 复写 unity_LODFade
        • 如果使用了RenderLayer数组
          • 定义 unity_RenderingLayerArray数组
          • 复写 unity_RenderingLayer
        • HYBRID_V1_CUSTOM_ADDITIONAL_MATERIAL_VARS跳过,不清楚
      • UNITY_INSTANCING_BUFFER_END(unity_Builtins0)
      #if !defined(UNITY_DOTS_INSTANCING_ENABLED)
          UNITY_INSTANCING_BUFFER_START(PerDraw0)
          #ifndef UNITY_DONT_INSTANCE_OBJECT_MATRICES
              UNITY_DEFINE_INSTANCED_PROP(float4x4, unity_ObjectToWorldArray)
              #if UNITY_WORLDTOOBJECTARRAY_CB == 0
                  UNITY_DEFINE_INSTANCED_PROP(float4x4, unity_WorldToObjectArray)
              #endif
          #endif
          #if defined(UNITY_USE_LODFADE_ARRAY) && defined(UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE)
              UNITY_DEFINE_INSTANCED_PROP(float2, unity_LODFadeArray)
              #define unity_LODFade UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, unity_LODFadeArray).xyxx
          #endif
          #if defined(UNITY_USE_RENDERINGLAYER_ARRAY) && defined(UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE)
              UNITY_DEFINE_INSTANCED_PROP(float, unity_RenderingLayerArray)
              #define unity_RenderingLayer UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, unity_RenderingLayerArray).xxxx
          #endif
      
          // TODO: Hybrid V1 compatibility, remove once Hybrid V1 is removed
          #if defined(UNITY_HYBRID_V1_INSTANCING_ENABLED) && defined(HYBRID_V1_CUSTOM_ADDITIONAL_MATERIAL_VARS)
              HYBRID_V1_CUSTOM_ADDITIONAL_MATERIAL_VARS
          #endif
          UNITY_INSTANCING_BUFFER_END(unity_Builtins0)
      
      • UNITY_INSTANCING_BUFFER_START(PerDraw1)
        • 没定义UNITY_DONT_INSTANCE_OBJECT_MATRICES且 UNITY_WORLDTOOBJECTARRAY_CB=1
          • 定义unity_WorldToObjectArray数组
        • 如果使用了LodFade数组
          • 定义 unity_LODFadeArray数组
          • 复写 unity_LODFade
        • 如果使用了RenderLayer数组
          • 定义 unity_RenderingLayerArray数组
          • 复写 unity_RenderingLayer
      • UNITY_INSTANCING_BUFFER_END(unity_Builtins1)
          UNITY_INSTANCING_BUFFER_START(PerDraw1)
              #if !defined(UNITY_DONT_INSTANCE_OBJECT_MATRICES) && UNITY_WORLDTOOBJECTARRAY_CB == 1
                  UNITY_DEFINE_INSTANCED_PROP(float4x4, unity_WorldToObjectArray)
              #endif
              #if defined(UNITY_USE_LODFADE_ARRAY) && !defined(UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE)
                  UNITY_DEFINE_INSTANCED_PROP(float2, unity_LODFadeArray)
                  #define unity_LODFade UNITY_ACCESS_INSTANCED_PROP(unity_Builtins1, unity_LODFadeArray).xyxx
              #endif
              #if defined(UNITY_USE_RENDERINGLAYER_ARRAY) && !defined(UNITY_INSTANCING_SUPPORT_FLEXIBLE_ARRAY_SIZE)
                  UNITY_DEFINE_INSTANCED_PROP(float, unity_RenderingLayerArray)
                  #define unity_RenderingLayer UNITY_ACCESS_INSTANCED_PROP(unity_Builtins1, unity_RenderingLayerArray).xxxx
              #endif
          UNITY_INSTANCING_BUFFER_END(unity_Builtins1)
      
      • UNITY_INSTANCING_BUFFER_START(PerDraw2)
        • 使用LightMap数组
          • 定义unity_LightmapSTArray数组
          • 定义unity_LightmapIndexArray数组
          • 复写 unity_LightmapST
        • 使用动态LightMap数组
          • 定义 unity_DynamicLightmapSTArray数组
          • 复写 unity_DynamicLightmapST
        • 使用SH系数数组
          • 定义 unity_LODFadeArray数组
          • 复写 unity_LODFade
        • 使用SH+Occlusion数组
          • 定义 unity_SHArArray/unity_SHAgArray/unity_SHAbArray/unity_SHBrArray/unity_SHBgArray/unity_SHBbArray/unity_SHCArray数组
          • 复写 unity_SHAr/unity_SHAg/unity_SHAb/unity_SHBr/unity_SHBg/unity_SHBb/unity_SHC
        • 使用Occlusion数组
          • 定义 unity_ProbesOcclusionArray 数组
          • 复习 unity_ProbesOcclusion
      • UNITY_INSTANCING_BUFFER_END(unity_Builtins2)
          UNITY_INSTANCING_BUFFER_START(PerDraw2)
          #ifdef UNITY_USE_LIGHTMAPST_ARRAY
              UNITY_DEFINE_INSTANCED_PROP(float4, unity_LightmapSTArray)
              UNITY_DEFINE_INSTANCED_PROP(float4, unity_LightmapIndexArray)
              #define unity_LightmapST UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_LightmapSTArray)
          #endif
          #ifdef UNITY_USE_DYNAMICLIGHTMAPST_ARRAY
              UNITY_DEFINE_INSTANCED_PROP(float4, unity_DynamicLightmapSTArray)
              #define unity_DynamicLightmapST UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_DynamicLightmapSTArray)
          #endif
          #ifdef UNITY_USE_SHCOEFFS_ARRAYS
              UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHArArray)
              UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHAgArray)
              UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHAbArray)
              UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHBrArray)
              UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHBgArray)
              UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHBbArray)
              UNITY_DEFINE_INSTANCED_PROP(half4, unity_SHCArray)
              #define unity_SHAr UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHArArray)
              #define unity_SHAg UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHAgArray)
              #define unity_SHAb UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHAbArray)
              #define unity_SHBr UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHBrArray)
              #define unity_SHBg UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHBgArray)
              #define unity_SHBb UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHBbArray)
              #define unity_SHC  UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_SHCArray)
          #endif
          #ifdef UNITY_USE_PROBESOCCLUSION_ARRAY
              UNITY_DEFINE_INSTANCED_PROP(half4, unity_ProbesOcclusionArray)
              #define unity_ProbesOcclusion UNITY_ACCESS_INSTANCED_PROP(unity_Builtins2, unity_ProbesOcclusionArray)
          #endif
          UNITY_INSTANCING_BUFFER_END(unity_Builtins2)
      #endif
      
    • UNITY_DONT_INSTANCE_OBJECT_MATRICES对Dots处理跳过
    • UNITY_DONT_INSTANCE_OBJECT_MATRICES复写M,I_M
      • undef UNITY_MATRIX_M/UNITY_MATRIX_I_M
      • UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY
        • unity_Builtins0 [CB=0]
        • unity_Builtins1 [CB=1]
      • MODIFY_MATRIX_FOR_CAMERA_RELATIVE_RENDERING
        • UNITY_MATRIX_M
          复写 UNITY_MATRIX_M为ApplyCameraTranslationToMatrix(UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, unity_ObjectToWorldArray))
          • 复写 UNITY_MATRIX_I_M为ApplyCameraTranslationToMatrix(UNITY_ACCESS_INSTANCED_PROP(UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY, unity_WorldToObjectArray))
        • UNITY_MATRIX_I_M
      • 复写UNITY_MATRIX_M为获取在unity_ObjectToWorldArray数组中对应Instance的值
      • 复写UNITY_MATRIX_I_M为获取在unity_WorldToObjectArray数组中对应Instance的值
    #if defined(UNITY_DOTS_INSTANCING_ENABLED)
        #undef UNITY_MATRIX_M
        #undef UNITY_MATRIX_I_M
        #ifdef MODIFY_MATRIX_FOR_CAMERA_RELATIVE_RENDERING
            #define UNITY_MATRIX_M      ApplyCameraTranslationToMatrix(LoadDOTSInstancedData_float4x4_from_float3x4(UNITY_DOTS_INSTANCED_METADATA_NAME_FROM_MACRO(float3x4, Metadata_unity_ObjectToWorld)))
            #define UNITY_MATRIX_I_M    ApplyCameraTranslationToInverseMatrix(LoadDOTSInstancedData_float4x4_from_float3x4(UNITY_DOTS_INSTANCED_METADATA_NAME_FROM_MACRO(float3x4, Metadata_unity_WorldToObject)))
        #else
            #define UNITY_MATRIX_M      LoadDOTSInstancedData_float4x4_from_float3x4(UNITY_DOTS_INSTANCED_METADATA_NAME_FROM_MACRO(float3x4, Metadata_unity_ObjectToWorld))
            #define UNITY_MATRIX_I_M    LoadDOTSInstancedData_float4x4_from_float3x4(UNITY_DOTS_INSTANCED_METADATA_NAME_FROM_MACRO(float3x4, Metadata_unity_WorldToObject))
        #endif
    #else
        #ifndef UNITY_DONT_INSTANCE_OBJECT_MATRICES
            #undef UNITY_MATRIX_M
            #undef UNITY_MATRIX_I_M
    
            // Use #if instead of preprocessor concatenation to avoid really hard to debug
            // preprocessing issues in some cases.
            #if UNITY_WORLDTOOBJECTARRAY_CB == 0
                #define UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY unity_Builtins0
            #else
                #define UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY unity_Builtins1
            #endif
    
            #ifdef MODIFY_MATRIX_FOR_CAMERA_RELATIVE_RENDERING
                #define UNITY_MATRIX_M      ApplyCameraTranslationToMatrix(UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, unity_ObjectToWorldArray))
                #define UNITY_MATRIX_I_M    ApplyCameraTranslationToInverseMatrix(UNITY_ACCESS_INSTANCED_PROP(UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY, unity_WorldToObjectArray))
            #else
                #define UNITY_MATRIX_M      UNITY_ACCESS_INSTANCED_PROP(unity_Builtins0, unity_ObjectToWorldArray)
                #define UNITY_MATRIX_I_M    UNITY_ACCESS_INSTANCED_PROP(UNITY_BUILTINS_WITH_WORLDTOOBJECTARRAY, unity_WorldToObjectArray)
            #endif
        #endif
    #endif
    
  • 其他Instance情况
    • Procedural instance
      • 复写UNITY_INSTANCING_BUFFER_START/END为置空
      • 复写UNITY_DEFINE_INSTANCED_PROP为普通静态变量
        • static type var;
    • 非instance情况
      • 复写UNITY_INSTANCING_BUFFER_START/END为CBuffer
        • CBUFFER_START(buf)/END
      • 复写UNITY_DEFINE_INSTANCED_PROP为普通静态变量
        • type var
    • 复写UNITY_ACCESS_INSTANCED_PROP获取值方式为普通var
      • var
    // in procedural mode we don‘t need cbuffer, and properties are not uniforms
      #ifdef UNITY_PROCEDURAL_INSTANCING_ENABLED
          #define UNITY_INSTANCING_BUFFER_START(buf)
          #define UNITY_INSTANCING_BUFFER_END(arr)
          #define UNITY_DEFINE_INSTANCED_PROP(type, var)      static type var;
      #else
          #define UNITY_INSTANCING_BUFFER_START(buf)          CBUFFER_START(buf)
          #define UNITY_INSTANCING_BUFFER_END(arr)            CBUFFER_END
          #define UNITY_DEFINE_INSTANCED_PROP(type, var)      type var;
      #endif
      #define UNITY_ACCESS_INSTANCED_PROP(arr, var)           var
    
  • 总结:

    • 这一段主要是根据不同的Instance Path定义实例化数组大小
    • [普通Instance]
      • UNITY_INSTANCING_BUFFER_START/END CBuffer Scope宏处理
      • 根据Option定义宏参数然后影响CBuffer里生成的内容unity_Builtins0/unity_Builtins1/unity_Builtins2
        • unity_Builtins0:CB=0 非UNITY_ASSUME_UNIFORM_SCALING
        • unity_Builtins1:CB=1 UNITY_ASSUME_UNIFORM_SCALING
        • unity_Builtins2:
          • GI相关设置
            • LightMapArray
            • SHArray
            • OcclusionArray
      • M/I_M矩阵复写
    • [其他Instance情况处理]
      • Procedural instance 置空
      • 不是实例化的变回普通的CBuffer Scope

H.One more thing

  • 分析下普通Instance的Scope构造
UNITY_INSTANCING_BUFFER_START(buf)
     UNITY_DEFINE_INSTANCED_PROP(type, var)
     UNITY_DEFINE_INSTANCED_PROP(type, var)
UNITY_INSTANCING_BUFFER_END(arr)

UNITY_INSTANCING_CBUFFER_SCOPE_BEGIN(UnityInstancing_##buf) struct{
    type var;
    type var;
} arr##Array[UNITY_INSTANCED_ARRAY_SIZE]; UNITY_INSTANCING_CBUFFER_SCOPE_END

[非GL平台]
CBUFFER_START(UnityInstancing_##buf) 

struct{
    type var;
    type var;
} arr##Array[UNITY_INSTANCED_ARRAY_SIZE]; 

CBUFFER_END

例子:
UNITY_INSTANCING_BUFFER_START(Props)
    UNITY_DEFINE_INSTANCED_PROP(float4, _TestColor)
UNITY_INSTANCING_BUFFER_END(Props)

name of arr=buf=Props

[非GL平台]
CBUFFER_START(UnityInstancing_Props) 

struct{
    float4 _TestColor;
} PropsArray[UNITY_INSTANCED_ARRAY_SIZE];

CBUFFER_END
  • 获取变量时:UNITY_ACCESS_INSTANCED_PROP(arr, var)
UNITY_ACCESS_INSTANCED_PROP(arr, var)  =>arrArray[unity_InstanceID].var
例子:
UNITY_ACCESS_INSTANCED_PROP(Props, _TestColor) =>PropsArray[unity_InstanceID]._TestColor
  • UNITY_SETUP_INSTANCE_ID和UNITY_TRANSFER_INSTANCE_ID(input, output)
- UNITY_SETUP_INSTANCE_ID(input)
    => DEFAULT_UNITY_SETUP_INSTANCE_ID 
        =>1.Procedural 
        UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input)); 
        UNITY_INSTANCING_PROCEDURAL_FUNC();
        =>2.非Procedural 
        UnitySetupInstanceID(UNITY_GET_INSTANCE_ID(input));
        [非PS平台] UnitySetupInstanceID(input.instanceID); 
        unity_InstanceID = input.instanceID + unity_BaseInstanceID;

- UNITY_TRANSFER_INSTANCE_ID(input, output) 
    =>output.instanceID = UNITY_GET_INSTANCE_ID(input)
    =>output.instanceID = input.instanceID

UnityInstancing头文件分析

上一篇:could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable',


下一篇:十字链表(C语言版本)