Нет описания
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. #ifndef UNITY_DOTS_INSTANCING_INCLUDED
  2. #define UNITY_DOTS_INSTANCING_INCLUDED
  3. #ifdef UNITY_DOTS_INSTANCING_ENABLED
  4. #if UNITY_OLD_PREPROCESSOR
  5. #error DOTS Instancing requires the new shader preprocessor. Please enable Caching Preprocessor in the Editor settings!
  6. #endif
  7. // Config defines
  8. // ==========================================================================================
  9. // #define UNITY_DOTS_INSTANCED_PROP_OVERRIDE_DISABLED_BY_DEFAULT
  10. /*
  11. Here's a bit of python code to generate these repetitive typespecs without
  12. a lot of C macro magic
  13. def print_dots_instancing_typespecs(elem_type, id_char, elem_size):
  14. print(f"#define UNITY_DOTS_INSTANCING_TYPESPEC_{elem_type} {id_char}{elem_size}")
  15. for y in range(1, 5):
  16. for x in range(1, 5):
  17. rows = "" if y == 1 else f"x{y}"
  18. size = elem_size * x * y
  19. print(f"#define UNITY_DOTS_INSTANCING_TYPESPEC_{elem_type}{x}{rows} {id_char}{size}")
  20. for t, c, sz in (
  21. ('float', 'F', 4),
  22. ('int', 'I', 4),
  23. ('uint', 'U', 4),
  24. ('half', 'H', 2)
  25. ):
  26. print_dots_instancing_typespecs(t, c, sz)
  27. */
  28. #define UNITY_DOTS_INSTANCING_TYPESPEC_float F4
  29. #define UNITY_DOTS_INSTANCING_TYPESPEC_float1 F4
  30. #define UNITY_DOTS_INSTANCING_TYPESPEC_float2 F8
  31. #define UNITY_DOTS_INSTANCING_TYPESPEC_float3 F12
  32. #define UNITY_DOTS_INSTANCING_TYPESPEC_float4 F16
  33. #define UNITY_DOTS_INSTANCING_TYPESPEC_float1x2 F8
  34. #define UNITY_DOTS_INSTANCING_TYPESPEC_float2x2 F16
  35. #define UNITY_DOTS_INSTANCING_TYPESPEC_float3x2 F24
  36. #define UNITY_DOTS_INSTANCING_TYPESPEC_float4x2 F32
  37. #define UNITY_DOTS_INSTANCING_TYPESPEC_float1x3 F12
  38. #define UNITY_DOTS_INSTANCING_TYPESPEC_float2x3 F24
  39. #define UNITY_DOTS_INSTANCING_TYPESPEC_float3x3 F36
  40. #define UNITY_DOTS_INSTANCING_TYPESPEC_float4x3 F48
  41. #define UNITY_DOTS_INSTANCING_TYPESPEC_float1x4 F16
  42. #define UNITY_DOTS_INSTANCING_TYPESPEC_float2x4 F32
  43. #define UNITY_DOTS_INSTANCING_TYPESPEC_float3x4 F48
  44. #define UNITY_DOTS_INSTANCING_TYPESPEC_float4x4 F64
  45. #define UNITY_DOTS_INSTANCING_TYPESPEC_int I4
  46. #define UNITY_DOTS_INSTANCING_TYPESPEC_int1 I4
  47. #define UNITY_DOTS_INSTANCING_TYPESPEC_int2 I8
  48. #define UNITY_DOTS_INSTANCING_TYPESPEC_int3 I12
  49. #define UNITY_DOTS_INSTANCING_TYPESPEC_int4 I16
  50. #define UNITY_DOTS_INSTANCING_TYPESPEC_int1x2 I8
  51. #define UNITY_DOTS_INSTANCING_TYPESPEC_int2x2 I16
  52. #define UNITY_DOTS_INSTANCING_TYPESPEC_int3x2 I24
  53. #define UNITY_DOTS_INSTANCING_TYPESPEC_int4x2 I32
  54. #define UNITY_DOTS_INSTANCING_TYPESPEC_int1x3 I12
  55. #define UNITY_DOTS_INSTANCING_TYPESPEC_int2x3 I24
  56. #define UNITY_DOTS_INSTANCING_TYPESPEC_int3x3 I36
  57. #define UNITY_DOTS_INSTANCING_TYPESPEC_int4x3 I48
  58. #define UNITY_DOTS_INSTANCING_TYPESPEC_int1x4 I16
  59. #define UNITY_DOTS_INSTANCING_TYPESPEC_int2x4 I32
  60. #define UNITY_DOTS_INSTANCING_TYPESPEC_int3x4 I48
  61. #define UNITY_DOTS_INSTANCING_TYPESPEC_int4x4 I64
  62. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint U4
  63. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint1 U4
  64. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint2 U8
  65. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint3 U12
  66. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint4 U16
  67. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint1x2 U8
  68. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint2x2 U16
  69. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint3x2 U24
  70. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint4x2 U32
  71. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint1x3 U12
  72. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint2x3 U24
  73. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint3x3 U36
  74. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint4x3 U48
  75. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint1x4 U16
  76. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint2x4 U32
  77. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint3x4 U48
  78. #define UNITY_DOTS_INSTANCING_TYPESPEC_uint4x4 U64
  79. #define UNITY_DOTS_INSTANCING_TYPESPEC_half H2
  80. #define UNITY_DOTS_INSTANCING_TYPESPEC_half1 H2
  81. #define UNITY_DOTS_INSTANCING_TYPESPEC_half2 H4
  82. #define UNITY_DOTS_INSTANCING_TYPESPEC_half3 H6
  83. #define UNITY_DOTS_INSTANCING_TYPESPEC_half4 H8
  84. #define UNITY_DOTS_INSTANCING_TYPESPEC_half1x2 H4
  85. #define UNITY_DOTS_INSTANCING_TYPESPEC_half2x2 H8
  86. #define UNITY_DOTS_INSTANCING_TYPESPEC_half3x2 H12
  87. #define UNITY_DOTS_INSTANCING_TYPESPEC_half4x2 H16
  88. #define UNITY_DOTS_INSTANCING_TYPESPEC_half1x3 H6
  89. #define UNITY_DOTS_INSTANCING_TYPESPEC_half2x3 H12
  90. #define UNITY_DOTS_INSTANCING_TYPESPEC_half3x3 H18
  91. #define UNITY_DOTS_INSTANCING_TYPESPEC_half4x3 H24
  92. #define UNITY_DOTS_INSTANCING_TYPESPEC_half1x4 H8
  93. #define UNITY_DOTS_INSTANCING_TYPESPEC_half2x4 H16
  94. #define UNITY_DOTS_INSTANCING_TYPESPEC_half3x4 H24
  95. #define UNITY_DOTS_INSTANCING_TYPESPEC_half4x4 H32
  96. #define UNITY_DOTS_INSTANCING_TYPESPEC_min16float H2
  97. #define UNITY_DOTS_INSTANCING_TYPESPEC_min16float4 H8
  98. #define UNITY_DOTS_INSTANCING_TYPESPEC_SH F128
  99. static const int kDotsInstancedPropOverrideDisabled = 0;
  100. static const int kDotsInstancedPropOverrideSupported = 1;
  101. static const int kDotsInstancedPropOverrideRequired = 2;
  102. #define UNITY_DOTS_INSTANCING_CONCAT2(a, b) a ## b
  103. #define UNITY_DOTS_INSTANCING_CONCAT4(a, b, c, d) a ## b ## c ## d
  104. #define UNITY_DOTS_INSTANCING_CONCAT_WITH_METADATA(metadata_prefix, typespec, name) UNITY_DOTS_INSTANCING_CONCAT4(metadata_prefix, typespec, _Metadata, name)
  105. // Metadata constants for properties have the following name format:
  106. // unity_DOTSInstancing<Type><Size>_Metadata<Name>
  107. // where
  108. // <Type> is a single character element type specifier (e.g. F for float4x4)
  109. // F = float, I = int, U = uint, H = half
  110. // <Size> is the total size of the property in bytes (e.g. 64 for float4x4)
  111. // <Name> is the name of the property
  112. // NOTE: There is no underscore between 'Metadata' and <Name> to avoid a double
  113. // underscore in the common case where the property name starts with an underscore.
  114. // A prefix double underscore is illegal on some platforms like OpenGL.
  115. #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)
  116. #define UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) UNITY_DOTS_INSTANCING_CONCAT2(name, _DOTSInstancingOverrideMode)
  117. #define UNITY_DOTS_INSTANCING_START(name) cbuffer UnityDOTSInstancing_##name {
  118. #define UNITY_DOTS_INSTANCING_END(name) }
  119. #define UNITY_DOTS_INSTANCED_PROP_OVERRIDE_DISABLED(type, name) static const uint UNITY_DOTS_INSTANCED_METADATA_NAME(type, name) = 0; \
  120. static const int UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) = kDotsInstancedPropOverrideDisabled;
  121. #define UNITY_DOTS_INSTANCED_PROP_OVERRIDE_SUPPORTED(type, name) uint UNITY_DOTS_INSTANCED_METADATA_NAME(type, name); \
  122. static const int UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) = kDotsInstancedPropOverrideSupported;
  123. #define UNITY_DOTS_INSTANCED_PROP_OVERRIDE_REQUIRED(type, name) uint UNITY_DOTS_INSTANCED_METADATA_NAME(type, name); \
  124. static const int UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) = kDotsInstancedPropOverrideRequired;
  125. #ifdef UNITY_DOTS_INSTANCED_PROP_OVERRIDE_DISABLED_BY_DEFAULT
  126. #define UNITY_DOTS_INSTANCED_PROP(type, name) UNITY_DOTS_INSTANCED_PROP_OVERRIDE_DISABLED(type, name)
  127. #else
  128. #define UNITY_DOTS_INSTANCED_PROP(type, name) UNITY_DOTS_INSTANCED_PROP_OVERRIDE_SUPPORTED(type, name)
  129. #endif
  130. #define UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_DISABLED(name) (UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) == kDotsInstancedPropOverrideDisabled)
  131. #define UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_ENABLED(name) (UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) == kDotsInstancedPropOverrideSupported)
  132. #define UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_REQUIRED(name) (UNITY_DOTS_INSTANCED_PROP_OVERRIDE_MODE_NAME(name) == kDotsInstancedPropOverrideRequired)
  133. #define UNITY_ACCESS_DOTS_INSTANCED_PROP(type, var) ( /* Compile-time branches */ \
  134. UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_ENABLED(var) ? LoadDOTSInstancedData_##type(UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
  135. : UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_REQUIRED(var) ? LoadDOTSInstancedDataOverridden_##type(UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
  136. : ((type)0) \
  137. )
  138. #define UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(type, var) ( /* Compile-time branches */ \
  139. UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_ENABLED(var) ? LoadDOTSInstancedData_##type(var, UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
  140. : UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_REQUIRED(var) ? LoadDOTSInstancedDataOverridden_##type(UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
  141. : (var) \
  142. )
  143. #define UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_CUSTOM_DEFAULT(type, var, default_value) ( /* Compile-time branches */ \
  144. UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_ENABLED(var) ? LoadDOTSInstancedData_##type(default_value, UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
  145. : UNITY_DOTS_INSTANCED_PROP_IS_OVERRIDE_REQUIRED(var) ? LoadDOTSInstancedDataOverridden_##type(UNITY_DOTS_INSTANCED_METADATA_NAME(type, var)) \
  146. : (default_value) \
  147. )
  148. #define UNITY_ACCESS_DOTS_AND_TRADITIONAL_INSTANCED_PROP(type, arr, var) UNITY_ACCESS_DOTS_INSTANCED_PROP(type, var)
  149. #define UNITY_ACCESS_DOTS_AND_TRADITIONAL_INSTANCED_PROP_WITH_DEFAULT(type, arr, var) UNITY_ACCESS_DOTS_INSTANCED_PROP_WITH_DEFAULT(type, var)
  150. #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)
  151. #define UNITY_SETUP_DOTS_MATERIAL_PROPERTY_CACHES() // No-op by default
  152. #ifdef UNITY_DOTS_INSTANCING_UNIFORM_BUFFER
  153. CBUFFER_START(unity_DOTSInstanceData)
  154. float4 unity_DOTSInstanceDataRaw[1024]; // warning: if you change 1024 value, you should also change BatchRendererGroup::GetConstantBufferMaxWindowSize() function in the c++ code base
  155. CBUFFER_END
  156. #else
  157. ByteAddressBuffer unity_DOTSInstanceData;
  158. #endif
  159. // DOTS instanced shaders do not get globals from UnityPerDraw automatically.
  160. // Instead, the BatchRendererGroup user must provide this cbuffer and/or
  161. // set up DOTS instanced properties for the values.
  162. // NOTE: Do *NOT* use the string "Globals" in this cbuffer name, cbuffers
  163. // with those kinds of names will be automatically renamed.
  164. CBUFFER_START(unity_DOTSInstanceGlobalValues)
  165. float4 unity_DOTS_ProbesOcclusion;
  166. float4 unity_DOTS_SpecCube0_HDR;
  167. float4 unity_DOTS_SpecCube1_HDR;
  168. float4 unity_DOTS_SHAr;
  169. float4 unity_DOTS_SHAg;
  170. float4 unity_DOTS_SHAb;
  171. float4 unity_DOTS_SHBr;
  172. float4 unity_DOTS_SHBg;
  173. float4 unity_DOTS_SHBb;
  174. float4 unity_DOTS_SHC;
  175. CBUFFER_END
  176. // The data has to be wrapped inside a struct, otherwise the instancing code path
  177. // on some platforms does not trigger.
  178. struct DOTSVisibleData
  179. {
  180. uint4 VisibleData;
  181. };
  182. // The name of this cbuffer has to start with "UnityInstancing" and a struct so it's
  183. // detected as an "instancing cbuffer" by some platforms that use string matching
  184. // to detect this.
  185. CBUFFER_START(UnityInstancingDOTS_InstanceVisibility)
  186. DOTSVisibleData unity_DOTSVisibleInstances[256]; // warning: if you change this value you should also change kBRGVisibilityUBOShaderArraySize in c++ code base
  187. CBUFFER_END
  188. // Keep these in sync with SRP Batcher DOTSInstancingFlags
  189. static const uint kDOTSInstancingFlagFlipWinding = (1 << 0); // Flip triangle winding when rendering, e.g. when the scale is negative
  190. static const uint kDOTSInstancingFlagForceZeroMotion = (1 << 1); // Object should produce zero motion vectors when rendered in the motion pass
  191. static const uint kDOTSInstancingFlagCameraMotion = (1 << 2); // Object uses Camera motion (i.e. not per-Object motion)
  192. static const uint kDOTSInstancingFlagHasPrevPosition = (1 << 3); // Object has a separate previous frame position vertex streams (e.g. for deformed objects)
  193. static const uint kDOTSInstancingFlagMainLightEnabled = (1 << 4); // Object should receive direct lighting from the main light (e.g. light not baked into lightmap)
  194. static const uint kDOTSInstancingFlagLODCrossFadeValuePacked = (1 << 5); // Object's cross fade value is encoded in the higher 8 bits of the instance index
  195. static const uint kPerInstanceDataBit = 0x80000000;
  196. static const uint kAddressMask = 0x7fffffff;
  197. static const uint kIndirectVisibleOffsetEnabledBit = 0x80000000;
  198. static uint unity_SampledDOTSIndirectVisibleIndex;
  199. static uint unity_SampledDOTSInstanceIndex;
  200. static int unity_SampledLODCrossfade;
  201. static real4 unity_DOTS_Sampled_SHAr;
  202. static real4 unity_DOTS_Sampled_SHAg;
  203. static real4 unity_DOTS_Sampled_SHAb;
  204. static real4 unity_DOTS_Sampled_SHBr;
  205. static real4 unity_DOTS_Sampled_SHBg;
  206. static real4 unity_DOTS_Sampled_SHBb;
  207. static real4 unity_DOTS_Sampled_SHC;
  208. static real4 unity_DOTS_Sampled_ProbesOcclusion;
  209. static float3 unity_DOTS_RendererBounds_Min;
  210. static float3 unity_DOTS_RendererBounds_Max;
  211. uint GetDOTSIndirectVisibleIndex()
  212. {
  213. return unity_SampledDOTSIndirectVisibleIndex;
  214. }
  215. uint GetDOTSInstanceIndex()
  216. {
  217. return unity_SampledDOTSInstanceIndex;
  218. }
  219. #ifdef UNITY_DOTS_INSTANCING_UNIFORM_BUFFER
  220. // In UBO mode we precompute our select masks based on our instance index.
  221. // All base addresses are aligned by 16, so we already know which offsets
  222. // the instance index will load (modulo 16).
  223. // All float1 loads will share the select4 masks, and all float2 loads
  224. // will share the select2 mask.
  225. // These variables are single assignment only, and should hopefully be well
  226. // optimizable and dead code eliminatable for the compiler.
  227. static uint unity_DOTSInstanceData_Select4_Mask0;
  228. static uint unity_DOTSInstanceData_Select4_Mask1;
  229. static uint unity_DOTSInstanceData_Select2_Mask;
  230. // The compiler should dead code eliminate the parts of this that are not used by the shader.
  231. void SetupDOTSInstanceSelectMasks()
  232. {
  233. uint instanceIndex = GetDOTSInstanceIndex();
  234. uint offsetSingleChannel = instanceIndex << 2; // float: stride 4 bytes
  235. // x = 0 = 00
  236. // y = 1 = 01
  237. // z = 2 = 10
  238. // w = 3 = 11
  239. // Lowest 2 bits are zero, all accesses are aligned,
  240. // and base addresses are aligned by 16.
  241. // Bits 29 and 28 give the channel index.
  242. // NOTE: Mask generation was rewritten to this form specifically to avoid codegen
  243. // correctness issues on GLES.
  244. unity_DOTSInstanceData_Select4_Mask0 = (offsetSingleChannel & 0x4) ? 0xffffffff : 0;
  245. unity_DOTSInstanceData_Select4_Mask1 = (offsetSingleChannel & 0x8) ? 0xffffffff : 0;
  246. // Select2 mask is the same as the low bit mask of select4, since
  247. // (x << 3) << 28 == (x << 2) << 29
  248. unity_DOTSInstanceData_Select2_Mask = unity_DOTSInstanceData_Select4_Mask0;
  249. }
  250. #else
  251. // This is a no-op in SSBO mode
  252. void SetupDOTSInstanceSelectMasks() {}
  253. #endif
  254. #ifdef UNITY_DOTS_INSTANCING_UNIFORM_BUFFER
  255. CBUFFER_START(unity_DOTSInstancing_IndirectInstanceVisibility)
  256. float4 unity_DOTSInstancing_IndirectInstanceVisibilityRaw[4096];
  257. CBUFFER_END
  258. #else
  259. ByteAddressBuffer unity_DOTSInstancing_IndirectInstanceVisibility;
  260. #endif
  261. uint LoadDOTSIndirectInstanceIndex(uint indirectIndex)
  262. {
  263. #ifdef UNITY_DOTS_INSTANCING_UNIFORM_BUFFER
  264. uint4 raw = asuint(unity_DOTSInstancing_IndirectInstanceVisibilityRaw[indirectIndex >> 2]);
  265. uint2 tmp = (indirectIndex & 0x2) ? raw.zw : raw.xy;
  266. return (indirectIndex & 0x1) ? tmp.y : tmp.x;
  267. #else
  268. return unity_DOTSInstancing_IndirectInstanceVisibility.Load(indirectIndex << 2);
  269. #endif
  270. }
  271. void SetupDOTSVisibleInstancingData()
  272. {
  273. uint packedIndirectVisibleOffset = unity_DOTSVisibleInstances[0].VisibleData.y;
  274. uint crossFadeValuePacked = unity_DOTSVisibleInstances[0].VisibleData.w & kDOTSInstancingFlagLODCrossFadeValuePacked;
  275. unity_SampledDOTSIndirectVisibleIndex = (packedIndirectVisibleOffset & ~kIndirectVisibleOffsetEnabledBit) + unity_InstanceID;
  276. if (packedIndirectVisibleOffset != 0)
  277. unity_SampledDOTSInstanceIndex = LoadDOTSIndirectInstanceIndex(unity_SampledDOTSIndirectVisibleIndex);
  278. else
  279. unity_SampledDOTSInstanceIndex = unity_DOTSVisibleInstances[unity_InstanceID].VisibleData.x;
  280. if(crossFadeValuePacked != 0)
  281. {
  282. unity_SampledLODCrossfade = int(unity_SampledDOTSInstanceIndex) >> 24;
  283. unity_SampledDOTSInstanceIndex &= 0x00ffffff;
  284. }
  285. else
  286. {
  287. unity_SampledLODCrossfade = 0;
  288. }
  289. SetupDOTSInstanceSelectMasks();
  290. }
  291. int GetDOTSInstanceCrossfadeSnorm8()
  292. {
  293. return unity_SampledLODCrossfade;
  294. }
  295. bool IsDOTSInstancedProperty(uint metadata)
  296. {
  297. return (metadata & kPerInstanceDataBit) != 0;
  298. }
  299. // Stride is typically expected to be a compile-time literal here, so this should
  300. // be optimized into shifts and other cheap ALU ops by the compiler.
  301. uint ComputeDOTSInstanceOffset(uint instanceIndex, uint stride)
  302. {
  303. return instanceIndex * stride;
  304. }
  305. uint ComputeDOTSInstanceDataAddress(uint metadata, uint stride)
  306. {
  307. uint isOverridden = metadata & kPerInstanceDataBit;
  308. // Sign extend per-instance data bit so it can just be ANDed with the offset
  309. uint offsetMask = (uint)((int)isOverridden >> 31);
  310. uint baseAddress = metadata & kAddressMask;
  311. uint offset = ComputeDOTSInstanceOffset(GetDOTSInstanceIndex(), stride);
  312. offset &= offsetMask;
  313. return baseAddress + offset;
  314. }
  315. // This version assumes that the high bit of the metadata is set (= per instance data).
  316. // Useful if the call site has already branched over this.
  317. uint ComputeDOTSInstanceDataAddressOverridden(uint metadata, uint stride)
  318. {
  319. uint baseAddress = metadata & kAddressMask;
  320. uint offset = ComputeDOTSInstanceOffset(GetDOTSInstanceIndex(), stride);
  321. return baseAddress + offset;
  322. }
  323. #ifdef UNITY_DOTS_INSTANCING_UNIFORM_BUFFER
  324. uint DOTSInstanceData_Select(uint addressOrOffset, uint4 v)
  325. {
  326. uint mask0 = unity_DOTSInstanceData_Select4_Mask0;
  327. uint mask1 = unity_DOTSInstanceData_Select4_Mask1;
  328. return
  329. (((v.w & mask0) | (v.z & ~mask0)) & mask1) |
  330. (((v.y & mask0) | (v.x & ~mask0)) & ~mask1);
  331. }
  332. uint2 DOTSInstanceData_Select2(uint addressOrOffset, uint4 v)
  333. {
  334. uint mask0 = unity_DOTSInstanceData_Select2_Mask;
  335. return (v.zw & mask0) | (v.xy & ~mask0);
  336. }
  337. uint DOTSInstanceData_Load(uint address)
  338. {
  339. uint float4Index = address >> 4;
  340. uint4 raw = asuint(unity_DOTSInstanceDataRaw[float4Index]);
  341. return DOTSInstanceData_Select(address, raw);
  342. }
  343. uint2 DOTSInstanceData_Load2(uint address)
  344. {
  345. uint float4Index = address >> 4;
  346. uint4 raw = asuint(unity_DOTSInstanceDataRaw[float4Index]);
  347. return DOTSInstanceData_Select2(address, raw);
  348. }
  349. uint4 DOTSInstanceData_Load4(uint address)
  350. {
  351. uint float4Index = address >> 4;
  352. return asuint(unity_DOTSInstanceDataRaw[float4Index]);
  353. }
  354. uint3 DOTSInstanceData_Load3(uint address)
  355. {
  356. // This is likely to be slow, tightly packed float3s are tricky
  357. switch (address & 0xf)
  358. {
  359. default:
  360. case 0:
  361. return DOTSInstanceData_Load4(address).xyz;
  362. case 4:
  363. return DOTSInstanceData_Load4(address).yzw;
  364. case 8:
  365. {
  366. uint float4Index = address >> 4;
  367. uint4 raw0 = asuint(unity_DOTSInstanceDataRaw[float4Index]);
  368. uint4 raw1 = asuint(unity_DOTSInstanceDataRaw[float4Index + 1]);
  369. uint3 v;
  370. v.xy = raw0.zw;
  371. v.z = raw1.x;
  372. return v;
  373. }
  374. case 12:
  375. {
  376. uint float4Index = address >> 4;
  377. uint4 raw0 = asuint(unity_DOTSInstanceDataRaw[float4Index]);
  378. uint4 raw1 = asuint(unity_DOTSInstanceDataRaw[float4Index + 1]);
  379. uint3 v;
  380. v.x = raw0.w;
  381. v.yz = raw1.xy;
  382. return v;
  383. }
  384. }
  385. }
  386. #else
  387. uint DOTSInstanceData_Load(uint address)
  388. {
  389. return unity_DOTSInstanceData.Load(address);
  390. }
  391. uint2 DOTSInstanceData_Load2(uint address)
  392. {
  393. return unity_DOTSInstanceData.Load2(address);
  394. }
  395. uint3 DOTSInstanceData_Load3(uint address)
  396. {
  397. return unity_DOTSInstanceData.Load3(address);
  398. }
  399. uint4 DOTSInstanceData_Load4(uint address)
  400. {
  401. return unity_DOTSInstanceData.Load4(address);
  402. }
  403. #endif
  404. #define DEFINE_DOTS_LOAD_INSTANCE_SCALAR(type, conv, sizeof_type) \
  405. type LoadDOTSInstancedData_##type(uint metadata) \
  406. { \
  407. uint address = ComputeDOTSInstanceDataAddress(metadata, sizeof_type); \
  408. return conv(DOTSInstanceData_Load(address)); \
  409. } \
  410. type LoadDOTSInstancedDataOverridden_##type(uint metadata) \
  411. { \
  412. uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, sizeof_type); \
  413. return conv(DOTSInstanceData_Load(address)); \
  414. } \
  415. type LoadDOTSInstancedData_##type(type default_value, uint metadata) \
  416. { \
  417. uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, sizeof_type); \
  418. return IsDOTSInstancedProperty(metadata) ? \
  419. conv(DOTSInstanceData_Load(address)) : default_value; \
  420. }
  421. #define DEFINE_DOTS_LOAD_INSTANCE_VECTOR(type, width, conv, sizeof_type) \
  422. type##width LoadDOTSInstancedData_##type##width(uint metadata) \
  423. { \
  424. uint address = ComputeDOTSInstanceDataAddress(metadata, sizeof_type * width); \
  425. return conv(DOTSInstanceData_Load##width(address)); \
  426. } \
  427. type##width LoadDOTSInstancedDataOverridden_##type##width(uint metadata) \
  428. { \
  429. uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, sizeof_type * width); \
  430. return conv(DOTSInstanceData_Load##width(address)); \
  431. } \
  432. type##width LoadDOTSInstancedData_##type##width(type##width default_value, uint metadata) \
  433. { \
  434. uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, sizeof_type * width); \
  435. return IsDOTSInstancedProperty(metadata) ? \
  436. conv(DOTSInstanceData_Load##width(address)) : default_value; \
  437. }
  438. DEFINE_DOTS_LOAD_INSTANCE_SCALAR(float, asfloat, 4)
  439. DEFINE_DOTS_LOAD_INSTANCE_SCALAR(int, int, 4)
  440. DEFINE_DOTS_LOAD_INSTANCE_SCALAR(uint, uint, 4)
  441. //DEFINE_DOTS_LOAD_INSTANCE_SCALAR(half, half, 2)
  442. DEFINE_DOTS_LOAD_INSTANCE_VECTOR(float, 2, asfloat, 4)
  443. DEFINE_DOTS_LOAD_INSTANCE_VECTOR(float, 3, asfloat, 4)
  444. DEFINE_DOTS_LOAD_INSTANCE_VECTOR(float, 4, asfloat, 4)
  445. DEFINE_DOTS_LOAD_INSTANCE_VECTOR(int, 2, int2, 4)
  446. DEFINE_DOTS_LOAD_INSTANCE_VECTOR(int, 3, int3, 4)
  447. DEFINE_DOTS_LOAD_INSTANCE_VECTOR(int, 4, int4, 4)
  448. DEFINE_DOTS_LOAD_INSTANCE_VECTOR(uint, 2, uint2, 4)
  449. DEFINE_DOTS_LOAD_INSTANCE_VECTOR(uint, 3, uint3, 4)
  450. DEFINE_DOTS_LOAD_INSTANCE_VECTOR(uint, 4, uint4, 4)
  451. //DEFINE_DOTS_LOAD_INSTANCE_VECTOR(half, 2, half2, 2)
  452. //DEFINE_DOTS_LOAD_INSTANCE_VECTOR(half, 3, half3, 2)
  453. //DEFINE_DOTS_LOAD_INSTANCE_VECTOR(half, 4, half4, 2)
  454. half LoadDOTSInstancedData_half(uint metadata)
  455. {
  456. float f = LoadDOTSInstancedData_float(metadata);
  457. min16float f16 = min16float(f);
  458. return f16;
  459. }
  460. half LoadDOTSInstancedDataOverridden_half(uint metadata)
  461. {
  462. float f = LoadDOTSInstancedDataOverridden_float(metadata);
  463. min16float f16 = min16float(f);
  464. return f16;
  465. }
  466. half4 LoadDOTSInstancedData_half4(uint metadata)
  467. {
  468. float4 f = LoadDOTSInstancedData_float4(metadata);
  469. min16float4 f16x4 = min16float4(f.x, f.y, f.z, f.w);
  470. return f16x4;
  471. }
  472. half4 LoadDOTSInstancedDataOverridden_half4(uint metadata)
  473. {
  474. float4 f = LoadDOTSInstancedDataOverridden_float4(metadata);
  475. min16float4 f16x4 = min16float4(f.x, f.y, f.z, f.w);
  476. return f16x4;
  477. }
  478. min16float LoadDOTSInstancedData_min16float(uint metadata)
  479. {
  480. return min16float(LoadDOTSInstancedData_half(metadata));
  481. }
  482. min16float LoadDOTSInstancedDataOverridden_min16float(uint metadata)
  483. {
  484. return min16float(LoadDOTSInstancedDataOverridden_half(metadata));
  485. }
  486. min16float4 LoadDOTSInstancedData_min16float4(uint metadata)
  487. {
  488. return min16float4(LoadDOTSInstancedData_half4(metadata));
  489. }
  490. min16float4 LoadDOTSInstancedDataOverridden_min16float4(uint metadata)
  491. {
  492. return min16float4(LoadDOTSInstancedDataOverridden_half4(metadata));
  493. }
  494. min16float LoadDOTSInstancedData_min16float(min16float default_value, uint metadata)
  495. {
  496. return IsDOTSInstancedProperty(metadata) ?
  497. LoadDOTSInstancedData_min16float(metadata) : default_value;
  498. }
  499. min16float4 LoadDOTSInstancedData_min16float4(min16float4 default_value, uint metadata)
  500. {
  501. return IsDOTSInstancedProperty(metadata) ?
  502. LoadDOTSInstancedData_min16float4(metadata) : default_value;
  503. }
  504. // TODO: Other matrix sizes
  505. float4x4 LoadDOTSInstancedData_float4x4(uint metadata)
  506. {
  507. uint address = ComputeDOTSInstanceDataAddress(metadata, 4 * 16);
  508. float4 p1 = asfloat(DOTSInstanceData_Load4(address + 0 * 16));
  509. float4 p2 = asfloat(DOTSInstanceData_Load4(address + 1 * 16));
  510. float4 p3 = asfloat(DOTSInstanceData_Load4(address + 2 * 16));
  511. float4 p4 = asfloat(DOTSInstanceData_Load4(address + 3 * 16));
  512. return float4x4(
  513. p1.x, p2.x, p3.x, p4.x,
  514. p1.y, p2.y, p3.y, p4.y,
  515. p1.z, p2.z, p3.z, p4.z,
  516. p1.w, p2.w, p3.w, p4.w);
  517. }
  518. float4x4 LoadDOTSInstancedDataOverridden_float4x4(uint metadata)
  519. {
  520. uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, 4 * 16);
  521. float4 p1 = asfloat(DOTSInstanceData_Load4(address + 0 * 16));
  522. float4 p2 = asfloat(DOTSInstanceData_Load4(address + 1 * 16));
  523. float4 p3 = asfloat(DOTSInstanceData_Load4(address + 2 * 16));
  524. float4 p4 = asfloat(DOTSInstanceData_Load4(address + 3 * 16));
  525. return float4x4(
  526. p1.x, p2.x, p3.x, p4.x,
  527. p1.y, p2.y, p3.y, p4.y,
  528. p1.z, p2.z, p3.z, p4.z,
  529. p1.w, p2.w, p3.w, p4.w);
  530. }
  531. float4x4 LoadDOTSInstancedData_float4x4_from_float3x4(uint metadata)
  532. {
  533. uint address = ComputeDOTSInstanceDataAddress(metadata, 3 * 16);
  534. float4 p1 = asfloat(DOTSInstanceData_Load4(address + 0 * 16));
  535. float4 p2 = asfloat(DOTSInstanceData_Load4(address + 1 * 16));
  536. float4 p3 = asfloat(DOTSInstanceData_Load4(address + 2 * 16));
  537. return float4x4(
  538. p1.x, p1.w, p2.z, p3.y,
  539. p1.y, p2.x, p2.w, p3.z,
  540. p1.z, p2.y, p3.x, p3.w,
  541. 0.0, 0.0, 0.0, 1.0
  542. );
  543. }
  544. float4x4 LoadDOTSInstancedDataOverridden_float4x4_from_float3x4(uint metadata)
  545. {
  546. uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, 3 * 16);
  547. float4 p1 = asfloat(DOTSInstanceData_Load4(address + 0 * 16));
  548. float4 p2 = asfloat(DOTSInstanceData_Load4(address + 1 * 16));
  549. float4 p3 = asfloat(DOTSInstanceData_Load4(address + 2 * 16));
  550. return float4x4(
  551. p1.x, p1.w, p2.z, p3.y,
  552. p1.y, p2.x, p2.w, p3.z,
  553. p1.z, p2.y, p3.x, p3.w,
  554. 0.0, 0.0, 0.0, 1.0
  555. );
  556. }
  557. float2x4 LoadDOTSInstancedData_float2x4(uint metadata)
  558. {
  559. uint address = ComputeDOTSInstanceDataAddress(metadata, 4 * 8);
  560. return float2x4(
  561. asfloat(DOTSInstanceData_Load4(address + 0 * 8)),
  562. asfloat(DOTSInstanceData_Load4(address + 1 * 8)));
  563. }
  564. float2x4 LoadDOTSInstancedDataOverridden_float2x4(uint metadata)
  565. {
  566. uint address = ComputeDOTSInstanceDataAddressOverridden(metadata, 4 * 8);
  567. return float2x4(
  568. asfloat(DOTSInstanceData_Load4(address + 0 * 8)),
  569. asfloat(DOTSInstanceData_Load4(address + 1 * 8)));
  570. }
  571. float4x4 LoadDOTSInstancedData_float4x4(float4x4 default_value, uint metadata)
  572. {
  573. return IsDOTSInstancedProperty(metadata) ?
  574. LoadDOTSInstancedData_float4x4(metadata) : default_value;
  575. }
  576. float4x4 LoadDOTSInstancedData_float4x4_from_float3x4(float4x4 default_value, uint metadata)
  577. {
  578. return IsDOTSInstancedProperty(metadata) ?
  579. LoadDOTSInstancedData_float4x4_from_float3x4(metadata) : default_value;
  580. }
  581. float2x4 LoadDOTSInstancedData_float2x4(float4 default_value[2], uint metadata)
  582. {
  583. return IsDOTSInstancedProperty(metadata) ?
  584. LoadDOTSInstancedData_float2x4(metadata) : float2x4(default_value[0], default_value[1]);
  585. }
  586. float2x4 LoadDOTSInstancedData_float2x4(float2x4 default_value, uint metadata)
  587. {
  588. return IsDOTSInstancedProperty(metadata) ?
  589. LoadDOTSInstancedData_float2x4(metadata) : default_value;
  590. }
  591. float4 LoadDOTSInstancedData_RenderingLayer()
  592. {
  593. return float4(asfloat(unity_DOTSVisibleInstances[0].VisibleData.z), 0,0,0);
  594. }
  595. float3 LoadDOTSInstancedData_MeshLocalBoundCenter()
  596. {
  597. return float3(asfloat(unity_DOTSVisibleInstances[1].VisibleData.z), asfloat(unity_DOTSVisibleInstances[1].VisibleData.w), asfloat(unity_DOTSVisibleInstances[2].VisibleData.z));
  598. }
  599. float3 LoadDOTSInstancedData_MeshLocalBoundExtent()
  600. {
  601. return float3(asfloat(unity_DOTSVisibleInstances[2].VisibleData.w), asfloat(unity_DOTSVisibleInstances[3].VisibleData.z), asfloat(unity_DOTSVisibleInstances[3].VisibleData.w));
  602. }
  603. float4 LoadDOTSInstancedData_MotionVectorsParams()
  604. {
  605. // See MotionVectorRendererLoop.cpp
  606. static const float s_bias = -0.001;
  607. uint flags = unity_DOTSVisibleInstances[0].VisibleData.w;
  608. return float4(0, flags & kDOTSInstancingFlagForceZeroMotion ? 0.0f : 1.0f, s_bias, flags & kDOTSInstancingFlagCameraMotion ? 0.0f : 1.0f);
  609. }
  610. float4 LoadDOTSInstancedData_WorldTransformParams()
  611. {
  612. uint flags = unity_DOTSVisibleInstances[0].VisibleData.w;
  613. return float4(0, 0, 0, flags & kDOTSInstancingFlagFlipWinding ? -1.0f : 1.0f);
  614. }
  615. float4 LoadDOTSInstancedData_LightData()
  616. {
  617. uint flags = unity_DOTSVisibleInstances[0].VisibleData.w;
  618. // X channel = light start index (not supported in DOTS instancing)
  619. // Y channel = light count (not supported in DOTS instancing)
  620. // Z channel = main light strength
  621. return float4(0, 0, flags & kDOTSInstancingFlagMainLightEnabled ? 1.0f : 0.0f, 0);
  622. }
  623. float4 LoadDOTSInstancedData_LODFade()
  624. {
  625. int crossfadeSNorm8 = GetDOTSInstanceCrossfadeSnorm8();
  626. float crossfade = clamp((float)crossfadeSNorm8, -127, 127);
  627. crossfade *= 1.0 / 127;
  628. return crossfade;
  629. }
  630. void SetupDOTSRendererBounds(float4x4 objectToWorld)
  631. {
  632. float3 vCenter = mul(objectToWorld, float4(LoadDOTSInstancedData_MeshLocalBoundCenter(), 1.0f)).xyz;
  633. float3 vInputExt = LoadDOTSInstancedData_MeshLocalBoundExtent();
  634. float3 vExtent = abs(objectToWorld[0].xyz * vInputExt.x) +
  635. abs(objectToWorld[1].xyz * vInputExt.y) +
  636. abs(objectToWorld[2].xyz * vInputExt.z);
  637. unity_DOTS_RendererBounds_Min = vCenter - vExtent;
  638. unity_DOTS_RendererBounds_Max = vCenter + vExtent;
  639. }
  640. void SetupDOTSSHCoeffs(uint shMetadata)
  641. {
  642. if (IsDOTSInstancedProperty(shMetadata))
  643. {
  644. uint address = ComputeDOTSInstanceDataAddressOverridden(shMetadata, 8 * 16);
  645. unity_DOTS_Sampled_SHAr = real4(asfloat(DOTSInstanceData_Load4(address + 0 * 16)));
  646. unity_DOTS_Sampled_SHAg = real4(asfloat(DOTSInstanceData_Load4(address + 1 * 16)));
  647. unity_DOTS_Sampled_SHAb = real4(asfloat(DOTSInstanceData_Load4(address + 2 * 16)));
  648. unity_DOTS_Sampled_SHBr = real4(asfloat(DOTSInstanceData_Load4(address + 3 * 16)));
  649. unity_DOTS_Sampled_SHBg = real4(asfloat(DOTSInstanceData_Load4(address + 4 * 16)));
  650. unity_DOTS_Sampled_SHBb = real4(asfloat(DOTSInstanceData_Load4(address + 5 * 16)));
  651. unity_DOTS_Sampled_SHC = real4(asfloat(DOTSInstanceData_Load4(address + 6 * 16)));
  652. unity_DOTS_Sampled_ProbesOcclusion = real4(asfloat(DOTSInstanceData_Load4(address + 7 * 16)));
  653. }
  654. else
  655. {
  656. unity_DOTS_Sampled_SHAr = real4(unity_DOTS_SHAr);
  657. unity_DOTS_Sampled_SHAg = real4(unity_DOTS_SHAg);
  658. unity_DOTS_Sampled_SHAb = real4(unity_DOTS_SHAb);
  659. unity_DOTS_Sampled_SHBr = real4(unity_DOTS_SHBr);
  660. unity_DOTS_Sampled_SHBg = real4(unity_DOTS_SHBg);
  661. unity_DOTS_Sampled_SHBb = real4(unity_DOTS_SHBb);
  662. unity_DOTS_Sampled_SHC = real4(unity_DOTS_SHC);
  663. unity_DOTS_Sampled_ProbesOcclusion = real4(unity_DOTS_ProbesOcclusion);
  664. }
  665. }
  666. real4 LoadDOTSInstancedData_SHAr() { return unity_DOTS_Sampled_SHAr; }
  667. real4 LoadDOTSInstancedData_SHAg() { return unity_DOTS_Sampled_SHAg; }
  668. real4 LoadDOTSInstancedData_SHAb() { return unity_DOTS_Sampled_SHAb; }
  669. real4 LoadDOTSInstancedData_SHBr() { return unity_DOTS_Sampled_SHBr; }
  670. real4 LoadDOTSInstancedData_SHBg() { return unity_DOTS_Sampled_SHBg; }
  671. real4 LoadDOTSInstancedData_SHBb() { return unity_DOTS_Sampled_SHBb; }
  672. real4 LoadDOTSInstancedData_SHC() { return unity_DOTS_Sampled_SHC; }
  673. real4 LoadDOTSInstancedData_ProbesOcclusion() { return unity_DOTS_Sampled_ProbesOcclusion; }
  674. float3 LoadDOTSInstancedData_RendererBounds_Min() { return unity_DOTS_RendererBounds_Min; }
  675. float3 LoadDOTSInstancedData_RendererBounds_Max() { return unity_DOTS_RendererBounds_Max; }
  676. float4 LoadDOTSInstancedData_SelectionValue(uint metadata, uint submeshIndex, float4 globalSelectionID)
  677. {
  678. // If there is a DOTS instanced per-instance ID, get that.
  679. if (IsDOTSInstancedProperty(metadata))
  680. {
  681. // Add 1 to the EntityID, so the EntityID 0 gets a value that is not equal to the clear value.
  682. uint selectionID = LoadDOTSInstancedData_uint2(metadata).x;
  683. uint idValue = selectionID + 1;
  684. // 26 bits for the entity index.
  685. // 5 bits for the submesh index.
  686. // 1 bit which must be set when outputting an EntityID/SubmeshIndex bitpack to let Unity know that it is not a regular selection ID.
  687. // 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.
  688. // Encode entity index with 26 bits. idValue & ((1 << 26) - 1) == idValue % (1 << 26)
  689. uint idValueBits = idValue & ((1 << 26) - 1);
  690. // Encode submesh index with 5 bits. submeshIndex & ((1 << 5) - 1) == submeshIndex % (1 << 5)
  691. uint submeshBits = submeshIndex & ((1 << 5) - 1);
  692. // Shift to high-bits. The 26 first bits are used by the entity index.
  693. submeshBits <<= 26;
  694. uint pickingID = (1 << 31) | submeshBits | idValueBits;
  695. // Pack a 32-bit integer into four 8-bit color channels such that the integer can be exactly reconstructed afterwards.
  696. return float4(uint4(pickingID >> 0, pickingID >> 8, pickingID >> 16, pickingID >> 24) & 0xFF) / 255.0f;
  697. }
  698. else
  699. {
  700. return globalSelectionID;
  701. }
  702. }
  703. #define UNITY_ACCESS_DOTS_INSTANCED_SELECTION_VALUE(name, submesh, selectionID) \
  704. LoadDOTSInstancedData_SelectionValue(UNITY_DOTS_INSTANCED_METADATA_NAME(uint2, name), submesh, selectionID)
  705. #undef DEFINE_DOTS_LOAD_INSTANCE_SCALAR
  706. #undef DEFINE_DOTS_LOAD_INSTANCE_VECTOR
  707. #endif // UNITY_DOTS_INSTANCING_ENABLED
  708. #endif // UNITY_DOTS_INSTANCING_INCLUDED