803 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			HLSL
		
	
	
	
	
	
			
		
		
	
	
			803 lines
		
	
	
		
			33 KiB
		
	
	
	
		
			HLSL
		
	
	
	
	
	
| #ifndef UNITY_DOTS_INSTANCING_INCLUDED
 | |
| #define UNITY_DOTS_INSTANCING_INCLUDED
 | |
| 
 | |
| #ifdef UNITY_DOTS_INSTANCING_ENABLED
 | |
| 
 | |
| #if UNITY_OLD_PREPROCESSOR
 | |
| #error DOTS Instancing requires the new shader preprocessor. Please enable Caching Preprocessor in the Editor settings!
 | |
| #endif
 | |
| 
 | |
| // Config defines
 | |
| // ==========================================================================================
 | |
| // #define UNITY_DOTS_INSTANCED_PROP_OVERRIDE_DISABLED_BY_DEFAULT
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /*
 | |
| Here's a bit of python code to generate these repetitive typespecs without
 | |
| a lot of C macro magic
 | |
| 
 | |
| def print_dots_instancing_typespecs(elem_type, id_char, elem_size):
 | |
|     print(f"#define UNITY_DOTS_INSTANCING_TYPESPEC_{elem_type} {id_char}{elem_size}")
 | |
|     for y in range(1, 5):
 | |
|         for x in range(1, 5):
 | |
|             rows = "" if y == 1 else f"x{y}"
 | |
|             size = elem_size * x * y
 | |
|             print(f"#define UNITY_DOTS_INSTANCING_TYPESPEC_{elem_type}{x}{rows} {id_char}{size}")
 | |
| 
 | |
| for t, c, sz in (
 | |
|         ('float', 'F', 4),
 | |
|         ('int',   'I', 4),
 | |
|         ('uint',  'U', 4),
 | |
|         ('half',  'H', 2)
 | |
|         ):
 | |
|     print_dots_instancing_typespecs(t, c, sz)
 | |
| */
 | |
| 
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float F4
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float1 F4
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float2 F8
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float3 F12
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float4 F16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float1x2 F8
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float2x2 F16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float3x2 F24
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float4x2 F32
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float1x3 F12
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float2x3 F24
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float3x3 F36
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float4x3 F48
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float1x4 F16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float2x4 F32
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float3x4 F48
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_float4x4 F64
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int I4
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int1 I4
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int2 I8
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int3 I12
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int4 I16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int1x2 I8
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int2x2 I16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int3x2 I24
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int4x2 I32
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int1x3 I12
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int2x3 I24
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int3x3 I36
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int4x3 I48
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int1x4 I16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int2x4 I32
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int3x4 I48
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_int4x4 I64
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint U4
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint1 U4
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint2 U8
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint3 U12
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint4 U16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint1x2 U8
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint2x2 U16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint3x2 U24
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint4x2 U32
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint1x3 U12
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint2x3 U24
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint3x3 U36
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint4x3 U48
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint1x4 U16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint2x4 U32
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint3x4 U48
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_uint4x4 U64
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half H2
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half1 H2
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half2 H4
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half3 H6
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half4 H8
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half1x2 H4
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half2x2 H8
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half3x2 H12
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half4x2 H16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half1x3 H6
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half2x3 H12
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half3x3 H18
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half4x3 H24
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half1x4 H8
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half2x4 H16
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half3x4 H24
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_half4x4 H32
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_min16float H2
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_min16float4 H8
 | |
| #define UNITY_DOTS_INSTANCING_TYPESPEC_SH F128
 | |
| 
 | |
| static const int kDotsInstancedPropOverrideDisabled = 0;
 | |
| static const int kDotsInstancedPropOverrideSupported = 1;
 | |
| static const int kDotsInstancedPropOverrideRequired = 2;
 | |
| 
 | |
| #define UNITY_DOTS_INSTANCING_CONCAT2(a, b) a ## b
 | |
| #define UNITY_DOTS_INSTANCING_CONCAT4(a, b, c, d) a ## b ## c ## d
 | |
| #define UNITY_DOTS_INSTANCING_CONCAT_WITH_METADATA(metadata_prefix, typespec, name) UNITY_DOTS_INSTANCING_CONCAT4(metadata_prefix, typespec, _Metadata, name)
 | |
| 
 | |
| // Metadata constants for properties have the following name format:
 | |
| // unity_DOTSInstancing<Type><Size>_Metadata<Name>
 | |
| // where
 | |
| // <Type> is a single character element type specifier (e.g. F for float4x4)
 | |
| //          F = float, I = int, U = uint, H = half
 | |
| // <Size> is the total size of the property in bytes (e.g. 64 for float4x4)
 | |
| // <Name> is the name of the property
 | |
| // NOTE: There is no underscore between 'Metadata' and <Name> to avoid a double
 | |
| //       underscore in the common case where the property name starts with an underscore.
 | |
| //       A prefix double underscore is illegal on some platforms like OpenGL.
 | |
| #define UNITY_DOTS_INSTANCED_METADATA_NAME(type, name) UNITY_DOTS_INSTANCING_CONCAT_WITH_METADATA(unity_DOTSInstancing, UNITY_DOTS_INSTANCING_CONCAT2(UNITY_DOTS_INSTANCING_TYPESPEC_, type), name)
 | |
| #define UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) UNITY_DOTS_INSTANCING_CONCAT2(name, _DOTSInstancingOverrideMode)
 | |
| 
 | |
| #define UNITY_DOTS_INSTANCING_START(name) cbuffer UnityDOTSInstancing_##name {
 | |
| #define UNITY_DOTS_INSTANCING_END(name)   }
 | |
| 
 | |
| #define UNITY_DOTS_INSTANCED_PROP_OVERRIDE_DISABLED(type, name) static const uint UNITY_DOTS_INSTANCED_METADATA_NAME(type, name) = 0; \
 | |
| static const int UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) = kDotsInstancedPropOverrideDisabled;
 | |
| 
 | |
| #define UNITY_DOTS_INSTANCED_PROP_OVERRIDE_SUPPORTED(type, name) uint UNITY_DOTS_INSTANCED_METADATA_NAME(type, name); \
 | |
| static const int UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) = kDotsInstancedPropOverrideSupported;
 | |
| 
 | |
| #define UNITY_DOTS_INSTANCED_PROP_OVERRIDE_REQUIRED(type, name) uint UNITY_DOTS_INSTANCED_METADATA_NAME(type, name); \
 | |
| static const int UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) = kDotsInstancedPropOverrideRequired;
 | |
| 
 | |
| #ifdef UNITY_DOTS_INSTANCED_PROP_OVERRIDE_DISABLED_BY_DEFAULT
 | |
| #define UNITY_DOTS_INSTANCED_PROP(type, name) UNITY_DOTS_INSTANCED_PROP_OVERRIDE_DISABLED(type, name)
 | |
| #else
 | |
| #define UNITY_DOTS_INSTANCED_PROP(type, name) UNITY_DOTS_INSTANCED_PROP_OVERRIDE_SUPPORTED(type, name)
 | |
| #endif
 | |
| 
 | |
| #define UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_DISABLED(name) (UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) == kDotsInstancedPropOverrideDisabled)
 | |
| #define UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_ENABLED(name) (UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) == kDotsInstancedPropOverrideSupported)
 | |
| #define UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_REQUIRED(name) (UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) == kDotsInstancedPropOverrideRequired)
 | |
| 
 | |
| #define UNITY_ACCESS_DOTS_INSTANCED_PROP(type, var) ( /* Compile-time branches */ \
 | |
| UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_ENABLED(var) ? LoadDOTSInstancedData_##type(UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
 | |
| : UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_REQUIRED(var) ? LoadDOTSInstancedDataOverridden_##type(UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
 | |
| : ((type)0) \
 | |
| )
 | |
| 
 | |
| #define UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(type, var) ( /* Compile-time branches */ \
 | |
| UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_ENABLED(var) ? LoadDOTSInstancedData_##type(var, UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
 | |
| : UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_REQUIRED(var) ? LoadDOTSInstancedDataOverridden_##type(UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
 | |
| : (var) \
 | |
| )
 | |
| 
 | |
| #define UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_CUSTOM_DEFAULT(type, var, default_value) ( /* Compile-time branches */ \
 | |
| UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_ENABLED(var) ? LoadDOTSInstancedData_##type(default_value, UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
 | |
| : UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_REQUIRED(var) ? LoadDOTSInstancedDataOverridden_##type(UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
 | |
| : (default_value) \
 | |
| )
 | |
| 
 | |
| #define UNITY_ACCESS_DOTS_AND_TRADITIONAL_INSTANCED_PROP(type, arr, var) UNITY_ACCESS_DOTS_INSTANCED_PROP(type, var)
 | |
| #define UNITY_ACCESS_DOTS_AND_TRADITIONAL_INSTANCED_PROP_WITH_DEFAULT(type, arr, var) UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(type, var)
 | |
| #define UNITY_ACCESS_DOTS_AND_TRADITIONAL_INSTANCED_PROP_WITH_CUSTOM_DEFAULT(type, arr, var, default_value) UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_CUSTOM_DEFAULT(type, var, default_value)
 | |
| 
 | |
| #define UNITY_SETUP_DOTS_MATERIAL_PROPERTY_CACHES() // No-op by default
 | |
| 
 | |
| #ifdef UNITY_DOTS_INSTANCING_UNIFORM_BUFFER
 | |
| CBUFFER_START(unity_DOTSInstanceData)
 | |
|     float4 unity_DOTSInstanceDataRaw[1024];	// warning: if you change 1024 value, you should also change BatchRendererGroup::GetConstantBufferMaxWindowSize() function in the c++ code base
 | |
| CBUFFER_END
 | |
| #else
 | |
| ByteAddressBuffer unity_DOTSInstanceData;
 | |
| #endif
 | |
| 
 | |
| // DOTS instanced shaders do not get globals from UnityPerDraw automatically.
 | |
| // Instead, the BatchRendererGroup user must provide this cbuffer and/or
 | |
| // set up DOTS instanced properties for the values.
 | |
| // NOTE: Do *NOT* use the string "Globals" in this cbuffer name, cbuffers
 | |
| // with those kinds of names will be automatically renamed.
 | |
| CBUFFER_START(unity_DOTSInstanceGlobalValues)
 | |
|     float4 unity_DOTS_ProbesOcclusion;
 | |
|     float4 unity_DOTS_SpecCube0_HDR;
 | |
|     float4 unity_DOTS_SpecCube1_HDR;
 | |
|     float4 unity_DOTS_SHAr;
 | |
|     float4 unity_DOTS_SHAg;
 | |
|     float4 unity_DOTS_SHAb;
 | |
|     float4 unity_DOTS_SHBr;
 | |
|     float4 unity_DOTS_SHBg;
 | |
|     float4 unity_DOTS_SHBb;
 | |
|     float4 unity_DOTS_SHC;
 | |
| CBUFFER_END
 | |
| 
 | |
| // The data has to be wrapped inside a struct, otherwise the instancing code path
 | |
| // on some platforms does not trigger.
 | |
| struct DOTSVisibleData
 | |
| {
 | |
|     uint4 VisibleData;
 | |
| };
 | |
| 
 | |
| // The name of this cbuffer has to start with "UnityInstancing" and a struct so it's
 | |
| // detected as an "instancing cbuffer" by some platforms that use string matching
 | |
| // to detect this.
 | |
| CBUFFER_START(UnityInstancingDOTS_InstanceVisibility)
 | |
|     DOTSVisibleData unity_DOTSVisibleInstances[256];	// warning: if you change this value you should also change kBRGVisibilityUBOShaderArraySize in c++ code base
 | |
| CBUFFER_END
 | |
| 
 | |
| // Keep these in sync with SRP Batcher DOTSInstancingFlags
 | |
| static const uint kDOTSInstancingFlagFlipWinding      = (1 << 0); // Flip triangle winding when rendering, e.g. when the scale is negative
 | |
| static const uint kDOTSInstancingFlagForceZeroMotion  = (1 << 1); // Object should produce zero motion vectors when rendered in the motion pass
 | |
| static const uint kDOTSInstancingFlagCameraMotion     = (1 << 2); // Object uses Camera motion (i.e. not per-Object motion)
 | |
| static const uint kDOTSInstancingFlagHasPrevPosition  = (1 << 3); // Object has a separate previous frame position vertex streams (e.g. for deformed objects)
 | |
| static const uint kDOTSInstancingFlagMainLightEnabled = (1 << 4); // Object should receive direct lighting from the main light (e.g. light not baked into lightmap)
 | |
| static const uint kDOTSInstancingFlagLODCrossFadeValuePacked = (1 << 5); // Object's cross fade value is encoded in the higher 8 bits of the instance index
 | |
| 
 | |
| static const uint kPerInstanceDataBit = 0x80000000;
 | |
| static const uint kAddressMask        = 0x7fffffff;
 | |
| 
 | |
| static const uint kIndirectVisibleOffsetEnabledBit = 0x80000000;
 | |
| static uint unity_SampledDOTSIndirectVisibleIndex;
 | |
| static uint unity_SampledDOTSInstanceIndex;
 | |
| static int unity_SampledLODCrossfade;
 | |
| static real4 unity_DOTS_Sampled_SHAr;
 | |
| static real4 unity_DOTS_Sampled_SHAg;
 | |
| static real4 unity_DOTS_Sampled_SHAb;
 | |
| static real4 unity_DOTS_Sampled_SHBr;
 | |
| static real4 unity_DOTS_Sampled_SHBg;
 | |
| static real4 unity_DOTS_Sampled_SHBb;
 | |
| static real4 unity_DOTS_Sampled_SHC;
 | |
| static real4 unity_DOTS_Sampled_ProbesOcclusion;
 | |
| static float3 unity_DOTS_RendererBounds_Min;
 | |
| static float3 unity_DOTS_RendererBounds_Max;
 | |
| 
 | |
| uint GetDOTSIndirectVisibleIndex()
 | |
| {
 | |
|     return unity_SampledDOTSIndirectVisibleIndex;
 | |
| }
 | |
| 
 | |
| uint GetDOTSInstanceIndex()
 | |
| {
 | |
|     return unity_SampledDOTSInstanceIndex;
 | |
| }
 | |
| 
 | |
| #ifdef UNITY_DOTS_INSTANCING_UNIFORM_BUFFER
 | |
| // In UBO mode we precompute our select masks based on our instance index.
 | |
| // All base addresses are aligned by 16, so we already know which offsets
 | |
| // the instance index will load (modulo 16).
 | |
| // All float1 loads will share the select4 masks, and all float2 loads
 | |
| // will share the select2 mask.
 | |
| // These variables are single assignment only, and should hopefully be well
 | |
| // optimizable and dead code eliminatable for the compiler.
 | |
| static uint unity_DOTSInstanceData_Select4_Mask0;
 | |
| static uint unity_DOTSInstanceData_Select4_Mask1;
 | |
| static uint unity_DOTSInstanceData_Select2_Mask;
 | |
| 
 | |
| // The compiler should dead code eliminate the parts of this that are not used by the shader.
 | |
| void SetupDOTSInstanceSelectMasks()
 | |
| {
 | |
|     uint instanceIndex = GetDOTSInstanceIndex();
 | |
|     uint offsetSingleChannel = instanceIndex << 2; // float: stride 4 bytes
 | |
| 
 | |
|     // x = 0 = 00
 | |
|     // y = 1 = 01
 | |
|     // z = 2 = 10
 | |
|     // w = 3 = 11
 | |
|     // Lowest 2 bits are zero, all accesses are aligned,
 | |
|     // and base addresses are aligned by 16.
 | |
|     // Bits 29 and 28 give the channel index.
 | |
|     // NOTE: Mask generation was rewritten to this form specifically to avoid codegen
 | |
|     // correctness issues on GLES.
 | |
|     unity_DOTSInstanceData_Select4_Mask0 = (offsetSingleChannel & 0x4) ? 0xffffffff : 0;
 | |
|     unity_DOTSInstanceData_Select4_Mask1 = (offsetSingleChannel & 0x8) ? 0xffffffff : 0;
 | |
|     // Select2 mask is the same as the low bit mask of select4, since
 | |
|     // (x << 3) << 28 == (x << 2) << 29
 | |
|     unity_DOTSInstanceData_Select2_Mask = unity_DOTSInstanceData_Select4_Mask0;
 | |
| }
 | |
| 
 | |
| #else
 | |
| 
 | |
| // This is a no-op in SSBO mode
 | |
| void SetupDOTSInstanceSelectMasks() {}
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #ifdef UNITY_DOTS_INSTANCING_UNIFORM_BUFFER
 | |
| CBUFFER_START(unity_DOTSInstancing_IndirectInstanceVisibility)
 | |
|     float4 unity_DOTSInstancing_IndirectInstanceVisibilityRaw[4096];
 | |
| CBUFFER_END
 | |
| #else
 | |
| ByteAddressBuffer unity_DOTSInstancing_IndirectInstanceVisibility;
 | |
| #endif
 | |
| 
 | |
| uint LoadDOTSIndirectInstanceIndex(uint indirectIndex)
 | |
| {
 | |
| #ifdef UNITY_DOTS_INSTANCING_UNIFORM_BUFFER
 | |
|     uint4 raw = asuint(unity_DOTSInstancing_IndirectInstanceVisibilityRaw[indirectIndex >> 2]);
 | |
|     uint2 tmp = (indirectIndex & 0x2) ? raw.zw : raw.xy;
 | |
|     return (indirectIndex & 0x1) ? tmp.y : tmp.x;
 | |
| #else
 | |
|     return unity_DOTSInstancing_IndirectInstanceVisibility.Load(indirectIndex << 2);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void SetupDOTSVisibleInstancingData()
 | |
| {
 | |
|     uint packedIndirectVisibleOffset = unity_DOTSVisibleInstances[0].VisibleData.y;
 | |
|     uint crossFadeValuePacked = unity_DOTSVisibleInstances[0].VisibleData.w & kDOTSInstancingFlagLODCrossFadeValuePacked;
 | |
|     unity_SampledDOTSIndirectVisibleIndex = (packedIndirectVisibleOffset & ~kIndirectVisibleOffsetEnabledBit) + unity_InstanceID;
 | |
| 
 | |
|     if (packedIndirectVisibleOffset != 0)
 | |
|         unity_SampledDOTSInstanceIndex = LoadDOTSIndirectInstanceIndex(unity_SampledDOTSIndirectVisibleIndex);
 | |
|     else
 | |
|         unity_SampledDOTSInstanceIndex = unity_DOTSVisibleInstances[unity_InstanceID].VisibleData.x;
 | |
| 
 | |
|     if(crossFadeValuePacked != 0)
 | |
|     {
 | |
|         unity_SampledLODCrossfade = int(unity_SampledDOTSInstanceIndex) >> 24;
 | |
|         unity_SampledDOTSInstanceIndex &= 0x00ffffff;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         unity_SampledLODCrossfade = 0;
 | |
|     }
 | |
| 
 | |
|     SetupDOTSInstanceSelectMasks();
 | |
| }
 | |
| 
 | |
| int GetDOTSInstanceCrossfadeSnorm8()
 | |
| {
 | |
|     return unity_SampledLODCrossfade;
 | |
| }
 | |
| 
 | |
| bool IsDOTSInstancedProperty(uint metadata)
 | |
| {
 | |
|     return (metadata & kPerInstanceDataBit) != 0;
 | |
| }
 | |
| 
 | |
| // Stride is typically expected to be a compile-time literal here, so this should
 | |
| // be optimized into shifts and other cheap ALU ops by the compiler.
 | |
| uint ComputeDOTSInstanceOffset(uint instanceIndex, uint stride)
 | |
| {
 | |
|     return instanceIndex * stride;
 | |
| }
 | |
| 
 | |
| uint ComputeDOTSInstanceDataAddress(uint metadata, uint stride)
 | |
| {
 | |
|     uint isOverridden = metadata & kPerInstanceDataBit;
 | |
|     // Sign extend per-instance data bit so it can just be ANDed with the offset
 | |
|     uint offsetMask  = (uint)((int)isOverridden >> 31);
 | |
|     uint baseAddress = metadata & kAddressMask;
 | |
|     uint offset      = ComputeDOTSInstanceOffset(GetDOTSInstanceIndex(), stride);
 | |
|     offset          &= offsetMask;
 | |
|     return baseAddress + offset;
 | |
| }
 | |
| 
 | |
| // This version assumes that the high bit of the metadata is set (= per instance data).
 | |
| // Useful if the call site has already branched over this.
 | |
| uint ComputeDOTSInstanceDataAddressOverridden(uint metadata, uint stride)
 | |
| {
 | |
|     uint baseAddress = metadata & kAddressMask;
 | |
|     uint offset      = ComputeDOTSInstanceOffset(GetDOTSInstanceIndex(), stride);
 | |
|     return baseAddress + offset;
 | |
| }
 | |
| 
 | |
| #ifdef UNITY_DOTS_INSTANCING_UNIFORM_BUFFER
 | |
| uint DOTSInstanceData_Select(uint addressOrOffset, uint4 v)
 | |
| {
 | |
|     uint mask0 = unity_DOTSInstanceData_Select4_Mask0;
 | |
|     uint mask1 = unity_DOTSInstanceData_Select4_Mask1;
 | |
|     return
 | |
|         (((v.w & mask0) | (v.z & ~mask0)) & mask1) |
 | |
|         (((v.y & mask0) | (v.x & ~mask0)) & ~mask1);
 | |
| }
 | |
| 
 | |
| uint2 DOTSInstanceData_Select2(uint addressOrOffset, uint4 v)
 | |
| {
 | |
|     uint mask0 = unity_DOTSInstanceData_Select2_Mask;
 | |
|     return (v.zw & mask0) | (v.xy & ~mask0);
 | |
| }
 | |
| 
 | |
| uint DOTSInstanceData_Load(uint address)
 | |
| {
 | |
|     uint float4Index = address >> 4;
 | |
|     uint4 raw = asuint(unity_DOTSInstanceDataRaw[float4Index]);
 | |
|     return DOTSInstanceData_Select(address, raw);
 | |
| }
 | |
| uint2 DOTSInstanceData_Load2(uint address)
 | |
| {
 | |
|     uint float4Index = address >> 4;
 | |
|     uint4 raw = asuint(unity_DOTSInstanceDataRaw[float4Index]);
 | |
|     return DOTSInstanceData_Select2(address, raw);
 | |
| }
 | |
| uint4 DOTSInstanceData_Load4(uint address)
 | |
| {
 | |
|     uint float4Index = address >> 4;
 | |
|     return asuint(unity_DOTSInstanceDataRaw[float4Index]);
 | |
| }
 | |
| uint3 DOTSInstanceData_Load3(uint address)
 | |
| {
 | |
|     // This is likely to be slow, tightly packed float3s are tricky
 | |
|     switch (address & 0xf)
 | |
|     {
 | |
|     default:
 | |
|     case 0:
 | |
|         return DOTSInstanceData_Load4(address).xyz;
 | |
|     case 4:
 | |
|         return DOTSInstanceData_Load4(address).yzw;
 | |
|     case 8:
 | |
|         {
 | |
|             uint float4Index = address >> 4;
 | |
|             uint4 raw0 = asuint(unity_DOTSInstanceDataRaw[float4Index]);
 | |
|             uint4 raw1 = asuint(unity_DOTSInstanceDataRaw[float4Index + 1]);
 | |
|             uint3 v;
 | |
|             v.xy = raw0.zw;
 | |
|             v.z  = raw1.x;
 | |
|             return v;
 | |
|         }
 | |
|     case 12:
 | |
|         {
 | |
|             uint float4Index = address >> 4;
 | |
|             uint4 raw0 = asuint(unity_DOTSInstanceDataRaw[float4Index]);
 | |
|             uint4 raw1 = asuint(unity_DOTSInstanceDataRaw[float4Index + 1]);
 | |
|             uint3 v;
 | |
|             v.x  = raw0.w;
 | |
|             v.yz = raw1.xy;
 | |
|             return v;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| #else
 | |
| uint DOTSInstanceData_Load(uint address)
 | |
| {
 | |
|     return unity_DOTSInstanceData.Load(address);
 | |
| }
 | |
| uint2 DOTSInstanceData_Load2(uint address)
 | |
| {
 | |
|     return unity_DOTSInstanceData.Load2(address);
 | |
| }
 | |
| uint3 DOTSInstanceData_Load3(uint address)
 | |
| {
 | |
|     return unity_DOTSInstanceData.Load3(address);
 | |
| }
 | |
| uint4 DOTSInstanceData_Load4(uint address)
 | |
| {
 | |
|     return unity_DOTSInstanceData.Load4(address);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #define DEFINE_DOTS_LOAD_INSTANCE_SCALAR(type, conv, sizeof_type) \
 | |
| type LoadDOTSInstancedData_##type(uint metadata) \
 | |
| { \
 | |
|     uint address = ComputeDOTSInstanceDataAddress(metadata, sizeof_type); \
 | |
|     return conv(DOTSInstanceData_Load(address)); \
 | |
| } \
 | |
| type LoadDOTSInstancedDataOverridden_##type(uint metadata) \
 | |
| { \
 | |
|     uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, sizeof_type); \
 | |
|     return conv(DOTSInstanceData_Load(address)); \
 | |
| } \
 | |
| type LoadDOTSInstancedData_##type(type default_value, uint metadata) \
 | |
| { \
 | |
|     uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, sizeof_type); \
 | |
|     return IsDOTSInstancedProperty(metadata) ? \
 | |
|         conv(DOTSInstanceData_Load(address)) : default_value; \
 | |
| }
 | |
| 
 | |
| #define DEFINE_DOTS_LOAD_INSTANCE_VECTOR(type, width, conv, sizeof_type) \
 | |
| type##width LoadDOTSInstancedData_##type##width(uint metadata) \
 | |
| { \
 | |
|     uint address = ComputeDOTSInstanceDataAddress(metadata, sizeof_type * width); \
 | |
|     return conv(DOTSInstanceData_Load##width(address)); \
 | |
| } \
 | |
| type##width LoadDOTSInstancedDataOverridden_##type##width(uint metadata) \
 | |
| { \
 | |
|     uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, sizeof_type * width); \
 | |
|     return conv(DOTSInstanceData_Load##width(address)); \
 | |
| } \
 | |
| type##width LoadDOTSInstancedData_##type##width(type##width default_value, uint metadata) \
 | |
| { \
 | |
|     uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, sizeof_type * width); \
 | |
|     return IsDOTSInstancedProperty(metadata) ? \
 | |
|         conv(DOTSInstanceData_Load##width(address)) : default_value; \
 | |
| }
 | |
| 
 | |
| DEFINE_DOTS_LOAD_INSTANCE_SCALAR(float, asfloat, 4)
 | |
| DEFINE_DOTS_LOAD_INSTANCE_SCALAR(int,   int,     4)
 | |
| DEFINE_DOTS_LOAD_INSTANCE_SCALAR(uint,  uint,    4)
 | |
| //DEFINE_DOTS_LOAD_INSTANCE_SCALAR(half,  half,    2)
 | |
| 
 | |
| DEFINE_DOTS_LOAD_INSTANCE_VECTOR(float, 2, asfloat, 4)
 | |
| DEFINE_DOTS_LOAD_INSTANCE_VECTOR(float, 3, asfloat, 4)
 | |
| DEFINE_DOTS_LOAD_INSTANCE_VECTOR(float, 4, asfloat, 4)
 | |
| DEFINE_DOTS_LOAD_INSTANCE_VECTOR(int,   2, int2,    4)
 | |
| DEFINE_DOTS_LOAD_INSTANCE_VECTOR(int,   3, int3,    4)
 | |
| DEFINE_DOTS_LOAD_INSTANCE_VECTOR(int,   4, int4,    4)
 | |
| DEFINE_DOTS_LOAD_INSTANCE_VECTOR(uint,  2, uint2,   4)
 | |
| DEFINE_DOTS_LOAD_INSTANCE_VECTOR(uint,  3, uint3,   4)
 | |
| DEFINE_DOTS_LOAD_INSTANCE_VECTOR(uint,  4, uint4,   4)
 | |
| //DEFINE_DOTS_LOAD_INSTANCE_VECTOR(half,  2, half2,   2)
 | |
| //DEFINE_DOTS_LOAD_INSTANCE_VECTOR(half,  3, half3,   2)
 | |
| //DEFINE_DOTS_LOAD_INSTANCE_VECTOR(half,  4, half4,   2)
 | |
| 
 | |
| half LoadDOTSInstancedData_half(uint metadata)
 | |
| {
 | |
|     float f = LoadDOTSInstancedData_float(metadata);
 | |
|     min16float f16 = min16float(f);
 | |
|     return f16;
 | |
| }
 | |
| half LoadDOTSInstancedDataOverridden_half(uint metadata)
 | |
| {
 | |
|     float f = LoadDOTSInstancedDataOverridden_float(metadata);
 | |
|     min16float f16 = min16float(f);
 | |
|     return f16;
 | |
| }
 | |
| 
 | |
| half4 LoadDOTSInstancedData_half4(uint metadata)
 | |
| {
 | |
|     float4 f = LoadDOTSInstancedData_float4(metadata);
 | |
|     min16float4 f16x4 = min16float4(f.x, f.y, f.z, f.w);
 | |
|     return f16x4;
 | |
| }
 | |
| half4 LoadDOTSInstancedDataOverridden_half4(uint metadata)
 | |
| {
 | |
|     float4 f = LoadDOTSInstancedDataOverridden_float4(metadata);
 | |
|     min16float4 f16x4 = min16float4(f.x, f.y, f.z, f.w);
 | |
|     return f16x4;
 | |
| }
 | |
| 
 | |
| min16float LoadDOTSInstancedData_min16float(uint metadata)
 | |
| {
 | |
|     return min16float(LoadDOTSInstancedData_half(metadata));
 | |
| }
 | |
| min16float LoadDOTSInstancedDataOverridden_min16float(uint metadata)
 | |
| {
 | |
|     return min16float(LoadDOTSInstancedDataOverridden_half(metadata));
 | |
| }
 | |
| 
 | |
| min16float4 LoadDOTSInstancedData_min16float4(uint metadata)
 | |
| {
 | |
|     return min16float4(LoadDOTSInstancedData_half4(metadata));
 | |
| }
 | |
| min16float4 LoadDOTSInstancedDataOverridden_min16float4(uint metadata)
 | |
| {
 | |
|     return min16float4(LoadDOTSInstancedDataOverridden_half4(metadata));
 | |
| }
 | |
| 
 | |
| min16float LoadDOTSInstancedData_min16float(min16float default_value, uint metadata)
 | |
| {
 | |
|     return IsDOTSInstancedProperty(metadata) ?
 | |
|         LoadDOTSInstancedData_min16float(metadata) : default_value;
 | |
| }
 | |
| 
 | |
| min16float4 LoadDOTSInstancedData_min16float4(min16float4 default_value, uint metadata)
 | |
| {
 | |
|     return IsDOTSInstancedProperty(metadata) ?
 | |
|         LoadDOTSInstancedData_min16float4(metadata) : default_value;
 | |
| }
 | |
| 
 | |
| // TODO: Other matrix sizes
 | |
| float4x4 LoadDOTSInstancedData_float4x4(uint metadata)
 | |
| {
 | |
|     uint address = ComputeDOTSInstanceDataAddress(metadata, 4 * 16);
 | |
|     float4 p1 = asfloat(DOTSInstanceData_Load4(address + 0 * 16));
 | |
|     float4 p2 = asfloat(DOTSInstanceData_Load4(address + 1 * 16));
 | |
|     float4 p3 = asfloat(DOTSInstanceData_Load4(address + 2 * 16));
 | |
|     float4 p4 = asfloat(DOTSInstanceData_Load4(address + 3 * 16));
 | |
|     return float4x4(
 | |
|         p1.x, p2.x, p3.x, p4.x,
 | |
|         p1.y, p2.y, p3.y, p4.y,
 | |
|         p1.z, p2.z, p3.z, p4.z,
 | |
|         p1.w, p2.w, p3.w, p4.w);
 | |
| }
 | |
| float4x4 LoadDOTSInstancedDataOverridden_float4x4(uint metadata)
 | |
| {
 | |
|     uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, 4 * 16);
 | |
|     float4 p1 = asfloat(DOTSInstanceData_Load4(address + 0 * 16));
 | |
|     float4 p2 = asfloat(DOTSInstanceData_Load4(address + 1 * 16));
 | |
|     float4 p3 = asfloat(DOTSInstanceData_Load4(address + 2 * 16));
 | |
|     float4 p4 = asfloat(DOTSInstanceData_Load4(address + 3 * 16));
 | |
|     return float4x4(
 | |
|         p1.x, p2.x, p3.x, p4.x,
 | |
|         p1.y, p2.y, p3.y, p4.y,
 | |
|         p1.z, p2.z, p3.z, p4.z,
 | |
|         p1.w, p2.w, p3.w, p4.w);
 | |
| }
 | |
| 
 | |
| float4x4 LoadDOTSInstancedData_float4x4_from_float3x4(uint metadata)
 | |
| {
 | |
|     uint address = ComputeDOTSInstanceDataAddress(metadata, 3 * 16);
 | |
|     float4 p1 = asfloat(DOTSInstanceData_Load4(address + 0 * 16));
 | |
|     float4 p2 = asfloat(DOTSInstanceData_Load4(address + 1 * 16));
 | |
|     float4 p3 = asfloat(DOTSInstanceData_Load4(address + 2 * 16));
 | |
| 
 | |
|     return float4x4(
 | |
|         p1.x, p1.w, p2.z, p3.y,
 | |
|         p1.y, p2.x, p2.w, p3.z,
 | |
|         p1.z, p2.y, p3.x, p3.w,
 | |
|         0.0,  0.0,  0.0,  1.0
 | |
|     );
 | |
| }
 | |
| float4x4 LoadDOTSInstancedDataOverridden_float4x4_from_float3x4(uint metadata)
 | |
| {
 | |
|     uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, 3 * 16);
 | |
|     float4 p1 = asfloat(DOTSInstanceData_Load4(address + 0 * 16));
 | |
|     float4 p2 = asfloat(DOTSInstanceData_Load4(address + 1 * 16));
 | |
|     float4 p3 = asfloat(DOTSInstanceData_Load4(address + 2 * 16));
 | |
| 
 | |
|     return float4x4(
 | |
|         p1.x, p1.w, p2.z, p3.y,
 | |
|         p1.y, p2.x, p2.w, p3.z,
 | |
|         p1.z, p2.y, p3.x, p3.w,
 | |
|         0.0,  0.0,  0.0,  1.0
 | |
|     );
 | |
| }
 | |
| 
 | |
| float2x4 LoadDOTSInstancedData_float2x4(uint metadata)
 | |
| {
 | |
|     uint address = ComputeDOTSInstanceDataAddress(metadata, 4 * 8);
 | |
|     return float2x4(
 | |
|         asfloat(DOTSInstanceData_Load4(address + 0 * 8)),
 | |
|         asfloat(DOTSInstanceData_Load4(address + 1 * 8)));
 | |
| }
 | |
| float2x4 LoadDOTSInstancedDataOverridden_float2x4(uint metadata)
 | |
| {
 | |
|     uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, 4 * 8);
 | |
|     return float2x4(
 | |
|         asfloat(DOTSInstanceData_Load4(address + 0 * 8)),
 | |
|         asfloat(DOTSInstanceData_Load4(address + 1 * 8)));
 | |
| }
 | |
| 
 | |
| float4x4 LoadDOTSInstancedData_float4x4(float4x4 default_value, uint metadata)
 | |
| {
 | |
|     return IsDOTSInstancedProperty(metadata) ?
 | |
|         LoadDOTSInstancedData_float4x4(metadata) : default_value;
 | |
| }
 | |
| 
 | |
| float4x4 LoadDOTSInstancedData_float4x4_from_float3x4(float4x4 default_value, uint metadata)
 | |
| {
 | |
|     return IsDOTSInstancedProperty(metadata) ?
 | |
|         LoadDOTSInstancedData_float4x4_from_float3x4(metadata) : default_value;
 | |
| }
 | |
| 
 | |
| float2x4 LoadDOTSInstancedData_float2x4(float4 default_value[2], uint metadata)
 | |
| {
 | |
|     return IsDOTSInstancedProperty(metadata) ?
 | |
|         LoadDOTSInstancedData_float2x4(metadata) : float2x4(default_value[0], default_value[1]);
 | |
| }
 | |
| 
 | |
| float2x4 LoadDOTSInstancedData_float2x4(float2x4 default_value, uint metadata)
 | |
| {
 | |
|     return IsDOTSInstancedProperty(metadata) ?
 | |
|         LoadDOTSInstancedData_float2x4(metadata) : default_value;
 | |
| }
 | |
| 
 | |
| float4 LoadDOTSInstancedData_RenderingLayer()
 | |
| {
 | |
|     return float4(asfloat(unity_DOTSVisibleInstances[0].VisibleData.z), 0,0,0);
 | |
| }
 | |
| 
 | |
| float3 LoadDOTSInstancedData_MeshLocalBoundCenter()
 | |
| {
 | |
|     return float3(asfloat(unity_DOTSVisibleInstances[1].VisibleData.z), asfloat(unity_DOTSVisibleInstances[1].VisibleData.w), asfloat(unity_DOTSVisibleInstances[2].VisibleData.z));
 | |
| }
 | |
| 
 | |
| float3 LoadDOTSInstancedData_MeshLocalBoundExtent()
 | |
| {
 | |
|     return float3(asfloat(unity_DOTSVisibleInstances[2].VisibleData.w), asfloat(unity_DOTSVisibleInstances[3].VisibleData.z), asfloat(unity_DOTSVisibleInstances[3].VisibleData.w));
 | |
| }
 | |
| 
 | |
| float4 LoadDOTSInstancedData_MotionVectorsParams()
 | |
| {
 | |
|     // See MotionVectorRendererLoop.cpp
 | |
|     static const float s_bias = -0.001;
 | |
|     uint flags = unity_DOTSVisibleInstances[0].VisibleData.w;
 | |
|     return float4(0, flags & kDOTSInstancingFlagForceZeroMotion ? 0.0f : 1.0f, s_bias, flags & kDOTSInstancingFlagCameraMotion ? 0.0f : 1.0f);
 | |
| }
 | |
| 
 | |
| float4 LoadDOTSInstancedData_WorldTransformParams()
 | |
| {
 | |
|     uint flags = unity_DOTSVisibleInstances[0].VisibleData.w;
 | |
|     return float4(0, 0, 0, flags & kDOTSInstancingFlagFlipWinding ? -1.0f : 1.0f);
 | |
| }
 | |
| 
 | |
| float4 LoadDOTSInstancedData_LightData()
 | |
| {
 | |
|     uint flags = unity_DOTSVisibleInstances[0].VisibleData.w;
 | |
|     // X channel = light start index (not supported in DOTS instancing)
 | |
|     // Y channel = light count (not supported in DOTS instancing)
 | |
|     // Z channel = main light strength
 | |
|     return float4(0, 0, flags & kDOTSInstancingFlagMainLightEnabled ? 1.0f : 0.0f, 0);
 | |
| }
 | |
| 
 | |
| float4 LoadDOTSInstancedData_LODFade()
 | |
| {
 | |
|     int crossfadeSNorm8 = GetDOTSInstanceCrossfadeSnorm8();
 | |
|     float crossfade = clamp((float)crossfadeSNorm8, -127, 127);
 | |
|     crossfade *= 1.0 / 127;
 | |
|     return crossfade;
 | |
| }
 | |
| 
 | |
| 
 | |
| void SetupDOTSRendererBounds(float4x4 objectToWorld)
 | |
| {
 | |
|     float3 vCenter = mul(objectToWorld, float4(LoadDOTSInstancedData_MeshLocalBoundCenter(), 1.0f)).xyz;
 | |
|     float3 vInputExt = LoadDOTSInstancedData_MeshLocalBoundExtent();
 | |
|     float3 vExtent = abs(objectToWorld[0].xyz * vInputExt.x) +
 | |
|                      abs(objectToWorld[1].xyz * vInputExt.y) +
 | |
|                      abs(objectToWorld[2].xyz * vInputExt.z);
 | |
| 
 | |
|     unity_DOTS_RendererBounds_Min = vCenter - vExtent;
 | |
|     unity_DOTS_RendererBounds_Max = vCenter + vExtent;
 | |
| }
 | |
| 
 | |
| void SetupDOTSSHCoeffs(uint shMetadata)
 | |
| {
 | |
|     if (IsDOTSInstancedProperty(shMetadata))
 | |
|     {
 | |
|         uint address = ComputeDOTSInstanceDataAddressOverridden(shMetadata, 8 * 16);
 | |
|         unity_DOTS_Sampled_SHAr = real4(asfloat(DOTSInstanceData_Load4(address + 0 * 16)));
 | |
|         unity_DOTS_Sampled_SHAg = real4(asfloat(DOTSInstanceData_Load4(address + 1 * 16)));
 | |
|         unity_DOTS_Sampled_SHAb = real4(asfloat(DOTSInstanceData_Load4(address + 2 * 16)));
 | |
|         unity_DOTS_Sampled_SHBr = real4(asfloat(DOTSInstanceData_Load4(address + 3 * 16)));
 | |
|         unity_DOTS_Sampled_SHBg = real4(asfloat(DOTSInstanceData_Load4(address + 4 * 16)));
 | |
|         unity_DOTS_Sampled_SHBb = real4(asfloat(DOTSInstanceData_Load4(address + 5 * 16)));
 | |
|         unity_DOTS_Sampled_SHC  = real4(asfloat(DOTSInstanceData_Load4(address + 6 * 16)));
 | |
|         unity_DOTS_Sampled_ProbesOcclusion = real4(asfloat(DOTSInstanceData_Load4(address + 7 * 16)));
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         unity_DOTS_Sampled_SHAr = real4(unity_DOTS_SHAr);
 | |
|         unity_DOTS_Sampled_SHAg = real4(unity_DOTS_SHAg);
 | |
|         unity_DOTS_Sampled_SHAb = real4(unity_DOTS_SHAb);
 | |
|         unity_DOTS_Sampled_SHBr = real4(unity_DOTS_SHBr);
 | |
|         unity_DOTS_Sampled_SHBg = real4(unity_DOTS_SHBg);
 | |
|         unity_DOTS_Sampled_SHBb = real4(unity_DOTS_SHBb);
 | |
|         unity_DOTS_Sampled_SHC  = real4(unity_DOTS_SHC);
 | |
|         unity_DOTS_Sampled_ProbesOcclusion = real4(unity_DOTS_ProbesOcclusion);
 | |
|     }
 | |
| }
 | |
| 
 | |
| real4 LoadDOTSInstancedData_SHAr() { return unity_DOTS_Sampled_SHAr; }
 | |
| real4 LoadDOTSInstancedData_SHAg() { return unity_DOTS_Sampled_SHAg; }
 | |
| real4 LoadDOTSInstancedData_SHAb() { return unity_DOTS_Sampled_SHAb; }
 | |
| real4 LoadDOTSInstancedData_SHBr() { return unity_DOTS_Sampled_SHBr; }
 | |
| real4 LoadDOTSInstancedData_SHBg() { return unity_DOTS_Sampled_SHBg; }
 | |
| real4 LoadDOTSInstancedData_SHBb() { return unity_DOTS_Sampled_SHBb; }
 | |
| real4 LoadDOTSInstancedData_SHC()  { return unity_DOTS_Sampled_SHC; }
 | |
| real4 LoadDOTSInstancedData_ProbesOcclusion()  { return unity_DOTS_Sampled_ProbesOcclusion; }
 | |
| float3 LoadDOTSInstancedData_RendererBounds_Min() { return unity_DOTS_RendererBounds_Min; }
 | |
| float3 LoadDOTSInstancedData_RendererBounds_Max() { return unity_DOTS_RendererBounds_Max; }
 | |
| 
 | |
| float4 LoadDOTSInstancedData_SelectionValue(uint metadata, uint submeshIndex, float4 globalSelectionID)
 | |
| {
 | |
|     // If there is a DOTS instanced per-instance ID, get that.
 | |
|     if (IsDOTSInstancedProperty(metadata))
 | |
|     {
 | |
|         // Add 1 to the EntityID, so the EntityID 0 gets a value that is not equal to the clear value.
 | |
|         uint selectionID = LoadDOTSInstancedData_uint2(metadata).x;
 | |
|         uint idValue = selectionID + 1;
 | |
| 
 | |
|         // 26 bits for the entity index.
 | |
|         // 5 bits for the submesh index.
 | |
|         // 1 bit which must be set when outputting an EntityID/SubmeshIndex bitpack to let Unity know that it is not a regular selection ID.
 | |
|         // When the high-bit is set, Unity will internally interpret the data as a 26-5-1 encoded bitmask and extract the EntityIndex/SubmeshIndex accordingly.
 | |
| 
 | |
|         // Encode entity index with 26 bits. idValue & ((1 << 26) - 1) == idValue % (1 << 26)
 | |
|         uint idValueBits = idValue & ((1 << 26) - 1);
 | |
| 
 | |
|         // Encode submesh index with 5 bits. submeshIndex & ((1 << 5) - 1) == submeshIndex % (1 << 5)
 | |
|         uint submeshBits = submeshIndex & ((1 << 5) - 1);
 | |
|         // Shift to high-bits. The 26 first bits are used by the entity index.
 | |
|         submeshBits <<= 26;
 | |
| 
 | |
|         uint pickingID = (1 << 31) | submeshBits | idValueBits;
 | |
| 
 | |
|         // Pack a 32-bit integer into four 8-bit color channels such that the integer can be exactly reconstructed afterwards.
 | |
|         return float4(uint4(pickingID >> 0, pickingID >> 8, pickingID >> 16, pickingID >> 24) & 0xFF) / 255.0f;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         return globalSelectionID;
 | |
|     }
 | |
| }
 | |
| #define UNITY_ACCESS_DOTS_INSTANCED_SELECTION_VALUE(name, submesh, selectionID) \
 | |
|     LoadDOTSInstancedData_SelectionValue(UNITY_DOTS_INSTANCED_METADATA_NAME(uint2, name), submesh, selectionID)
 | |
| 
 | |
| #undef DEFINE_DOTS_LOAD_INSTANCE_SCALAR
 | |
| #undef DEFINE_DOTS_LOAD_INSTANCE_VECTOR
 | |
| 
 | |
| #endif // UNITY_DOTS_INSTANCING_ENABLED
 | |
| 
 | |
| #endif // UNITY_DOTS_INSTANCING_INCLUDED
 |