123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802 |
- #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
|