Nenhuma descrição
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

InstanceCullingBatcher.cs 44KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. using System;
  2. using System.Threading;
  3. using UnityEngine.Assertions;
  4. using Unity.Collections;
  5. using Unity.Jobs;
  6. using Unity.Jobs.LowLevel.Unsafe;
  7. using Unity.Collections.LowLevel.Unsafe;
  8. using Unity.Burst;
  9. using UnityEngine.Profiling;
  10. [assembly: RegisterGenericJobType(typeof(UnityEngine.Rendering.RegisterNewInstancesJob<UnityEngine.Rendering.BatchMeshID>))]
  11. [assembly: RegisterGenericJobType(typeof(UnityEngine.Rendering.RegisterNewInstancesJob<UnityEngine.Rendering.BatchMaterialID>))]
  12. [assembly: RegisterGenericJobType(typeof(UnityEngine.Rendering.FindNonRegisteredInstancesJob<UnityEngine.Rendering.BatchMeshID>))]
  13. [assembly: RegisterGenericJobType(typeof(UnityEngine.Rendering.FindNonRegisteredInstancesJob<UnityEngine.Rendering.BatchMaterialID>))]
  14. namespace UnityEngine.Rendering
  15. {
  16. internal delegate void OnCullingCompleteCallback(JobHandle jobHandle, in BatchCullingContext cullingContext, in BatchCullingOutput cullingOutput);
  17. internal struct InstanceCullingBatcherDesc
  18. {
  19. public OnCullingCompleteCallback onCompleteCallback;
  20. #if UNITY_EDITOR
  21. public Shader brgPicking;
  22. public Shader brgLoading;
  23. public Shader brgError;
  24. #endif
  25. public static InstanceCullingBatcherDesc NewDefault()
  26. {
  27. return new InstanceCullingBatcherDesc()
  28. {
  29. onCompleteCallback = null
  30. #if UNITY_EDITOR
  31. ,brgPicking = null
  32. ,brgLoading = null
  33. ,brgError = null
  34. #endif
  35. };
  36. }
  37. }
  38. internal struct MeshProceduralInfo
  39. {
  40. public MeshTopology topology;
  41. public uint baseVertex;
  42. public uint firstIndex;
  43. public uint indexCount;
  44. }
  45. [BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
  46. internal struct PrefixSumDrawInstancesJob : IJob
  47. {
  48. [ReadOnly] public NativeParallelHashMap<RangeKey, int> rangeHash;
  49. public NativeList<DrawRange> drawRanges;
  50. public NativeList<DrawBatch> drawBatches;
  51. public NativeArray<int> drawBatchIndices;
  52. public void Execute()
  53. {
  54. Assert.AreEqual(rangeHash.Count(), drawRanges.Length);
  55. Assert.AreEqual(drawBatchIndices.Length, drawBatches.Length);
  56. // Prefix sum to calculate draw offsets for each DrawRange
  57. int drawPrefixSum = 0;
  58. for (int i = 0; i < drawRanges.Length; ++i)
  59. {
  60. ref DrawRange drawRange = ref drawRanges.ElementAt(i);
  61. drawRange.drawOffset = drawPrefixSum;
  62. drawPrefixSum += drawRange.drawCount;
  63. }
  64. // Generate DrawBatch index ranges for each DrawRange
  65. var internalRangeIndex = new NativeArray<int>(drawRanges.Length, Allocator.Temp);
  66. for (int i = 0; i < drawBatches.Length; ++i)
  67. {
  68. ref DrawBatch drawBatch = ref drawBatches.ElementAt(i);
  69. Assert.IsTrue(drawBatch.instanceCount > 0);
  70. if (rangeHash.TryGetValue(drawBatch.key.range, out int drawRangeIndex))
  71. {
  72. ref DrawRange drawRange = ref drawRanges.ElementAt(drawRangeIndex);
  73. drawBatchIndices[drawRange.drawOffset + internalRangeIndex[drawRangeIndex]] = i;
  74. internalRangeIndex[drawRangeIndex]++;
  75. }
  76. }
  77. // Prefix sum to calculate instance offsets for each DrawCommand
  78. int drawInstancesPrefixSum = 0;
  79. for (int i = 0; i < drawBatchIndices.Length; ++i)
  80. {
  81. // DrawIndices remap to get DrawCommands ordered by DrawRange
  82. var drawBatchIndex = drawBatchIndices[i];
  83. ref DrawBatch drawBatch = ref drawBatches.ElementAt(drawBatchIndex);
  84. drawBatch.instanceOffset = drawInstancesPrefixSum;
  85. drawInstancesPrefixSum += drawBatch.instanceCount;
  86. }
  87. internalRangeIndex.Dispose();
  88. }
  89. }
  90. [BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
  91. internal unsafe struct BuildDrawListsJob : IJobParallelFor
  92. {
  93. public const int k_BatchSize = 128;
  94. public const int k_IntsPerCacheLine = JobsUtility.CacheLineSize / sizeof(int);
  95. [ReadOnly] public NativeParallelHashMap<DrawKey, int> batchHash;
  96. [NativeDisableContainerSafetyRestriction, NoAlias] [ReadOnly] public NativeList<DrawInstance> drawInstances;
  97. [NativeDisableContainerSafetyRestriction, NoAlias] [ReadOnly] public NativeList<DrawBatch> drawBatches;
  98. [NativeDisableContainerSafetyRestriction, NoAlias] [WriteOnly] public NativeArray<int> internalDrawIndex;
  99. [NativeDisableContainerSafetyRestriction, NoAlias] [WriteOnly] public NativeArray<int> drawInstanceIndices;
  100. private unsafe static int IncrementCounter(int* counter)
  101. {
  102. return Interlocked.Increment(ref UnsafeUtility.AsRef<int>(counter)) - 1;
  103. }
  104. public void Execute(int index)
  105. {
  106. // Generate instance index ranges for each DrawCommand
  107. ref DrawInstance drawInstance = ref drawInstances.ElementAt(index);
  108. int drawBatchIndex = batchHash[drawInstance.key];
  109. ref DrawBatch drawBatch = ref drawBatches.ElementAt(drawBatchIndex);
  110. var offset = IncrementCounter((int*)internalDrawIndex.GetUnsafePtr() + drawBatchIndex * k_IntsPerCacheLine);
  111. var writeIndex = drawBatch.instanceOffset + offset;
  112. drawInstanceIndices[writeIndex] = drawInstance.instanceIndex;
  113. }
  114. }
  115. [BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
  116. internal unsafe struct FindDrawInstancesJob : IJobParallelForBatch
  117. {
  118. public const int k_BatchSize = 128;
  119. [ReadOnly] public NativeArray<InstanceHandle> instancesSorted;
  120. [NativeDisableContainerSafetyRestriction, NoAlias] [ReadOnly] public NativeList<DrawInstance> drawInstances;
  121. [WriteOnly] public NativeList<int>.ParallelWriter outDrawInstanceIndicesWriter;
  122. public void Execute(int startIndex, int count)
  123. {
  124. int* instancesToRemove = stackalloc int[k_BatchSize];
  125. int length = 0;
  126. for (int i = startIndex; i < startIndex + count; ++i)
  127. {
  128. ref DrawInstance drawInstance = ref drawInstances.ElementAt(i);
  129. if (instancesSorted.BinarySearch(InstanceHandle.FromInt(drawInstance.instanceIndex)) >= 0)
  130. instancesToRemove[length++] = i;
  131. }
  132. outDrawInstanceIndicesWriter.AddRangeNoResize(instancesToRemove, length);
  133. }
  134. }
  135. [BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
  136. internal unsafe struct FindMaterialDrawInstancesJob : IJobParallelForBatch
  137. {
  138. public const int k_BatchSize = 128;
  139. [ReadOnly] public NativeArray<uint> materialsSorted;
  140. [NativeDisableContainerSafetyRestriction, NoAlias] [ReadOnly] public NativeList<DrawInstance> drawInstances;
  141. [WriteOnly] public NativeList<int>.ParallelWriter outDrawInstanceIndicesWriter;
  142. public void Execute(int startIndex, int count)
  143. {
  144. int* instancesToRemove = stackalloc int[k_BatchSize];
  145. int length = 0;
  146. for (int i = startIndex; i < startIndex + count; ++i)
  147. {
  148. ref DrawInstance drawInstance = ref drawInstances.ElementAt(i);
  149. if (materialsSorted.BinarySearch(drawInstance.key.materialID.value) >= 0)
  150. instancesToRemove[length++] = i;
  151. }
  152. outDrawInstanceIndicesWriter.AddRangeNoResize(instancesToRemove, length);
  153. }
  154. }
  155. [BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
  156. internal struct FindNonRegisteredInstancesJob<T> : IJobParallelForBatch where T : unmanaged
  157. {
  158. public const int k_BatchSize = 128;
  159. [ReadOnly] public NativeArray<int> instanceIDs;
  160. [ReadOnly] public NativeParallelHashMap<int, T> hashMap;
  161. [WriteOnly] public NativeList<int>.ParallelWriter outInstancesWriter;
  162. public unsafe void Execute(int startIndex, int count)
  163. {
  164. int* notFoundinstanceIDs = stackalloc int[k_BatchSize];
  165. int length = 0;
  166. for (int i = startIndex; i < startIndex + count; ++i)
  167. {
  168. int instanceID = instanceIDs[i];
  169. if (!hashMap.ContainsKey(instanceID))
  170. notFoundinstanceIDs[length++] = instanceID;
  171. }
  172. outInstancesWriter.AddRangeNoResize(notFoundinstanceIDs, length);
  173. }
  174. }
  175. [BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
  176. internal struct RegisterNewInstancesJob<T> : IJobParallelFor where T : unmanaged
  177. {
  178. public const int k_BatchSize = 128;
  179. [ReadOnly] public NativeArray<int> instanceIDs;
  180. [ReadOnly] public NativeArray<T> batchIDs;
  181. [WriteOnly] public NativeParallelHashMap<int, T>.ParallelWriter hashMap;
  182. public unsafe void Execute(int index)
  183. {
  184. hashMap.TryAdd(instanceIDs[index], batchIDs[index]);
  185. }
  186. }
  187. [BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
  188. internal struct RemoveDrawInstanceIndicesJob : IJob
  189. {
  190. [NativeDisableContainerSafetyRestriction, NoAlias] [ReadOnly] public NativeArray<int> drawInstanceIndices;
  191. public NativeList<DrawInstance> drawInstances;
  192. public NativeParallelHashMap<RangeKey, int> rangeHash;
  193. public NativeParallelHashMap<DrawKey, int> batchHash;
  194. public NativeList<DrawRange> drawRanges;
  195. public NativeList<DrawBatch> drawBatches;
  196. public void RemoveDrawRange(in RangeKey key)
  197. {
  198. int drawRangeIndex = rangeHash[key];
  199. ref DrawRange lastDrawRange = ref drawRanges.ElementAt(drawRanges.Length - 1);
  200. rangeHash[lastDrawRange.key] = drawRangeIndex;
  201. rangeHash.Remove(key);
  202. drawRanges.RemoveAtSwapBack(drawRangeIndex);
  203. }
  204. public void RemoveDrawBatch(in DrawKey key)
  205. {
  206. int drawBatchIndex = batchHash[key];
  207. ref DrawBatch drawBatch = ref drawBatches.ElementAt(drawBatchIndex);
  208. int drawRangeIndex = rangeHash[key.range];
  209. ref DrawRange drawRange = ref drawRanges.ElementAt(drawRangeIndex);
  210. Assert.IsTrue(drawRange.drawCount > 0);
  211. if (--drawRange.drawCount == 0)
  212. RemoveDrawRange(drawRange.key);
  213. ref DrawBatch lastDrawBatch = ref drawBatches.ElementAt(drawBatches.Length - 1);
  214. batchHash[lastDrawBatch.key] = drawBatchIndex;
  215. batchHash.Remove(key);
  216. drawBatches.RemoveAtSwapBack(drawBatchIndex);
  217. }
  218. public unsafe void Execute()
  219. {
  220. var drawInstancesPtr = (DrawInstance*)drawInstances.GetUnsafePtr();
  221. var drawInstancesNewBack = drawInstances.Length - 1;
  222. for (int indexRev = drawInstanceIndices.Length - 1; indexRev >= 0; --indexRev)
  223. {
  224. int indexToRemove = drawInstanceIndices[indexRev];
  225. DrawInstance* drawInstance = drawInstancesPtr + indexToRemove;
  226. int drawBatchIndex = batchHash[drawInstance->key];
  227. ref DrawBatch drawBatch = ref drawBatches.ElementAt(drawBatchIndex);
  228. Assert.IsTrue(drawBatch.instanceCount > 0);
  229. if (--drawBatch.instanceCount == 0)
  230. RemoveDrawBatch(drawBatch.key);
  231. UnsafeUtility.MemCpy(drawInstance, drawInstancesPtr + drawInstancesNewBack--, sizeof(DrawInstance));
  232. }
  233. drawInstances.ResizeUninitialized(drawInstancesNewBack + 1);
  234. }
  235. }
  236. [BurstCompile(DisableSafetyChecks = true, OptimizeFor = OptimizeFor.Performance)]
  237. internal struct CreateDrawBatchesJob : IJob
  238. {
  239. [ReadOnly] public bool implicitInstanceIndices;
  240. [ReadOnly] public NativeArray<InstanceHandle> instances;
  241. [ReadOnly] public GPUDrivenRendererGroupData rendererData;
  242. [ReadOnly] public NativeParallelHashMap<int, BatchMeshID> batchMeshHash;
  243. [ReadOnly] public NativeParallelHashMap<int, BatchMaterialID> batchMaterialHash;
  244. public NativeParallelHashMap<RangeKey, int> rangeHash;
  245. public NativeList<DrawRange> drawRanges;
  246. public NativeParallelHashMap<DrawKey, int> batchHash;
  247. public NativeList<DrawBatch> drawBatches;
  248. [WriteOnly] public NativeList<DrawInstance> drawInstances;
  249. private ref DrawRange EditDrawRange(in RangeKey key)
  250. {
  251. int drawRangeIndex;
  252. if (!rangeHash.TryGetValue(key, out drawRangeIndex))
  253. {
  254. var drawRange = new DrawRange { key = key, drawCount = 0, drawOffset = 0 };
  255. drawRangeIndex = drawRanges.Length;
  256. rangeHash.Add(key, drawRangeIndex);
  257. drawRanges.Add(drawRange);
  258. }
  259. ref DrawRange data = ref drawRanges.ElementAt(drawRangeIndex);
  260. Assert.IsTrue(data.key.Equals(key));
  261. return ref data;
  262. }
  263. private ref DrawBatch EditDrawBatch(in DrawKey key, in SubMeshDescriptor subMeshDescriptor)
  264. {
  265. var procInfo = new MeshProceduralInfo();
  266. procInfo.topology = subMeshDescriptor.topology;
  267. procInfo.baseVertex = (uint)subMeshDescriptor.baseVertex;
  268. procInfo.firstIndex = (uint)subMeshDescriptor.indexStart;
  269. procInfo.indexCount = (uint)subMeshDescriptor.indexCount;
  270. int drawBatchIndex;
  271. if (!batchHash.TryGetValue(key, out drawBatchIndex))
  272. {
  273. var drawBatch = new DrawBatch() { key = key, instanceCount = 0, instanceOffset = 0, procInfo = procInfo };
  274. drawBatchIndex = drawBatches.Length;
  275. batchHash.Add(key, drawBatchIndex);
  276. drawBatches.Add(drawBatch);
  277. }
  278. ref DrawBatch data = ref drawBatches.ElementAt(drawBatchIndex);
  279. Assert.IsTrue(data.key.Equals(key));
  280. return ref data;
  281. }
  282. public void ProcessRenderer(int i)
  283. {
  284. var meshIndex = rendererData.meshIndex[i];
  285. var meshID = rendererData.meshID[meshIndex];
  286. var submeshCount = rendererData.subMeshCount[meshIndex];
  287. var subMeshDescOffset = rendererData.subMeshDescOffset[meshIndex];
  288. var batchMeshID = batchMeshHash[meshID];
  289. var rendererGroupID = rendererData.rendererGroupID[i];
  290. var startSubMesh = rendererData.subMeshStartIndex[i];
  291. var gameObjectLayer = rendererData.gameObjectLayer[i];
  292. var renderingLayerMask = rendererData.renderingLayerMask[i];
  293. var materialsOffset = rendererData.materialsOffset[i];
  294. var materialsCount = rendererData.materialsCount[i];
  295. var lightmapIndex = rendererData.lightmapIndex[i];
  296. var packedRendererData = rendererData.packedRendererData[i];
  297. var rendererPriority = rendererData.rendererPriority[i];
  298. var lodGroupID = rendererData.lodGroupID[i];
  299. int instanceCount;
  300. int instanceOffset;
  301. if (implicitInstanceIndices)
  302. {
  303. instanceCount = 1;
  304. instanceOffset = i;
  305. }
  306. else
  307. {
  308. instanceCount = rendererData.instancesCount[i];
  309. instanceOffset = rendererData.instancesOffset[i];
  310. }
  311. if (instanceCount == 0)
  312. return;
  313. const int kLightmapIndexMask = 0xffff;
  314. const int kLightmapIndexInfluenceOnly = 0xfffe;
  315. var overridenComponents = InstanceComponentGroup.Default;
  316. // Add per-instance wind parameters
  317. if(packedRendererData.hasTree)
  318. overridenComponents |= InstanceComponentGroup.Wind;
  319. var lmIndexMasked = lightmapIndex & kLightmapIndexMask;
  320. // Object doesn't have a valid lightmap Index, -> uses probes for lighting
  321. if (lmIndexMasked >= kLightmapIndexInfluenceOnly)
  322. {
  323. // Only add the component when needed to store blended results (shader will use the ambient probe when not present)
  324. if (packedRendererData.lightProbeUsage == LightProbeUsage.BlendProbes)
  325. overridenComponents |= InstanceComponentGroup.LightProbe;
  326. }
  327. else
  328. {
  329. // Add per-instance lightmap parameters
  330. overridenComponents |= InstanceComponentGroup.Lightmap;
  331. }
  332. // Scan all materials once to retrieve whether this renderer is indirect-compatible or not (and store it in the RangeKey).
  333. var supportsIndirect = true;
  334. for (int matIndex = 0; matIndex < materialsCount; ++matIndex)
  335. {
  336. if (matIndex >= submeshCount)
  337. {
  338. Debug.LogWarning("Material count in the shared material list is higher than sub mesh count for the mesh. Object may be corrupted.");
  339. continue;
  340. }
  341. var materialIndex = rendererData.materialIndex[materialsOffset + matIndex];
  342. var packedMaterialData = rendererData.packedMaterialData[materialIndex];
  343. supportsIndirect &= packedMaterialData.isIndirectSupported;
  344. }
  345. var rangeKey = new RangeKey
  346. {
  347. layer = (byte)gameObjectLayer,
  348. renderingLayerMask = renderingLayerMask,
  349. motionMode = packedRendererData.motionVecGenMode,
  350. shadowCastingMode = packedRendererData.shadowCastingMode,
  351. staticShadowCaster = packedRendererData.staticShadowCaster,
  352. rendererPriority = rendererPriority,
  353. supportsIndirect = supportsIndirect
  354. };
  355. ref DrawRange drawRange = ref EditDrawRange(rangeKey);
  356. for (int matIndex = 0; matIndex < materialsCount; ++matIndex)
  357. {
  358. if (matIndex >= submeshCount)
  359. {
  360. Debug.LogWarning("Material count in the shared material list is higher than sub mesh count for the mesh. Object may be corrupted.");
  361. continue;
  362. }
  363. var materialIndex = rendererData.materialIndex[materialsOffset + matIndex];
  364. var materialID = rendererData.materialID[materialIndex];
  365. var packedMaterialData = rendererData.packedMaterialData[materialIndex];
  366. if (materialID == 0)
  367. {
  368. Debug.LogWarning("Material in the shared materials list is null. Object will be partially rendered.");
  369. continue;
  370. }
  371. batchMaterialHash.TryGetValue(materialID, out BatchMaterialID batchMaterialID);
  372. // We always provide crossfade value packed in instance index. We don't use None even if there is no LOD to not split the batch.
  373. var flags = BatchDrawCommandFlags.LODCrossFadeValuePacked;
  374. // Let the engine know if we've opted out of lightmap texture arrays
  375. flags |= BatchDrawCommandFlags.UseLegacyLightmapsKeyword;
  376. // assume that a custom motion vectors pass contains deformation motion, so should always output motion vectors
  377. // (otherwise this flag is set dynamically during culling only when the transform is changing)
  378. if (packedMaterialData.isMotionVectorsPassEnabled)
  379. flags |= BatchDrawCommandFlags.HasMotion;
  380. if (packedMaterialData.isTransparent)
  381. flags |= BatchDrawCommandFlags.HasSortingPosition;
  382. {
  383. var submeshIndex = startSubMesh + matIndex;
  384. var subMeshDesc = rendererData.subMeshDesc[subMeshDescOffset + submeshIndex];
  385. var drawKey = new DrawKey
  386. {
  387. materialID = batchMaterialID,
  388. meshID = batchMeshID,
  389. submeshIndex = submeshIndex,
  390. flags = flags,
  391. transparentInstanceId = packedMaterialData.isTransparent ? rendererGroupID : 0,
  392. range = rangeKey,
  393. overridenComponents = (uint)overridenComponents,
  394. // When we've opted out of lightmap texture arrays, we
  395. // need to pass in a valid lightmap index. The engine
  396. // uses this index for sorting and for breaking the
  397. // batch when lightmaps change across draw calls, and
  398. // for binding the correct light map.
  399. lightmapIndex = lightmapIndex
  400. };
  401. ref DrawBatch drawBatch = ref EditDrawBatch(drawKey, subMeshDesc);
  402. if (drawBatch.instanceCount == 0)
  403. ++drawRange.drawCount;
  404. drawBatch.instanceCount += instanceCount;
  405. for (int j = 0; j < instanceCount; ++j)
  406. {
  407. var instanceIndex = instanceOffset + j;
  408. InstanceHandle instance = instances[instanceIndex];
  409. drawInstances.Add(new DrawInstance { key = drawKey, instanceIndex = instance.index });
  410. }
  411. }
  412. }
  413. }
  414. public void Execute()
  415. {
  416. {
  417. for (int i = 0; i < rendererData.rendererGroupID.Length; ++i)
  418. ProcessRenderer(i);
  419. }
  420. }
  421. }
  422. internal class CPUDrawInstanceData
  423. {
  424. public NativeList<DrawInstance> drawInstances => m_DrawInstances;
  425. public NativeParallelHashMap<DrawKey, int> batchHash => m_BatchHash;
  426. public NativeList<DrawBatch> drawBatches => m_DrawBatches;
  427. public NativeParallelHashMap<RangeKey, int> rangeHash => m_RangeHash;
  428. public NativeList<DrawRange> drawRanges => m_DrawRanges;
  429. public NativeArray<int> drawBatchIndices => m_DrawBatchIndices.AsArray();
  430. public NativeArray<int> drawInstanceIndices => m_DrawInstanceIndices.AsArray();
  431. private NativeParallelHashMap<RangeKey, int> m_RangeHash; // index in m_DrawRanges, hashes by range state
  432. private NativeList<DrawRange> m_DrawRanges;
  433. private NativeParallelHashMap<DrawKey, int> m_BatchHash; // index in m_DrawBatches, hashed by draw state
  434. private NativeList<DrawBatch> m_DrawBatches;
  435. private NativeList<DrawInstance> m_DrawInstances;
  436. private NativeList<int> m_DrawInstanceIndices; // DOTS instance index, arranged in contiguous blocks in m_DrawBatches order (see DrawBatch.instanceOffset, DrawBatch.instanceCount)
  437. private NativeList<int> m_DrawBatchIndices; // index in m_DrawBatches, arranged in contiguous blocks in m_DrawRanges order (see DrawRange.drawOffset, DrawRange.drawCount)
  438. private bool m_NeedsRebuild;
  439. public bool valid => m_DrawInstances.IsCreated;
  440. public void Initialize()
  441. {
  442. Assert.IsTrue(!valid);
  443. m_RangeHash = new NativeParallelHashMap<RangeKey, int>(1024, Allocator.Persistent);
  444. m_DrawRanges = new NativeList<DrawRange>(Allocator.Persistent);
  445. m_BatchHash = new NativeParallelHashMap<DrawKey, int>(1024, Allocator.Persistent);
  446. m_DrawBatches = new NativeList<DrawBatch>(Allocator.Persistent);
  447. m_DrawInstances = new NativeList<DrawInstance>(1024, Allocator.Persistent);
  448. m_DrawInstanceIndices = new NativeList<int>(1024, Allocator.Persistent);
  449. m_DrawBatchIndices = new NativeList<int>(1024, Allocator.Persistent);
  450. }
  451. public void Dispose()
  452. {
  453. if (m_DrawBatchIndices.IsCreated)
  454. m_DrawBatchIndices.Dispose();
  455. if (m_DrawInstanceIndices.IsCreated)
  456. m_DrawInstanceIndices.Dispose();
  457. if (m_DrawInstances.IsCreated)
  458. m_DrawInstances.Dispose();
  459. if (m_DrawBatches.IsCreated)
  460. m_DrawBatches.Dispose();
  461. if (m_BatchHash.IsCreated)
  462. m_BatchHash.Dispose();
  463. if (m_DrawRanges.IsCreated)
  464. m_DrawRanges.Dispose();
  465. if (m_RangeHash.IsCreated)
  466. m_RangeHash.Dispose();
  467. }
  468. public void RebuildDrawListsIfNeeded()
  469. {
  470. if (!m_NeedsRebuild)
  471. return;
  472. m_NeedsRebuild = false;
  473. Assert.IsTrue(m_RangeHash.Count() == m_DrawRanges.Length);
  474. Assert.IsTrue(m_BatchHash.Count() == m_DrawBatches.Length);
  475. m_DrawInstanceIndices.ResizeUninitialized(m_DrawInstances.Length);
  476. m_DrawBatchIndices.ResizeUninitialized(m_DrawBatches.Length);
  477. var internalDrawIndex = new NativeArray<int>(drawBatches.Length * BuildDrawListsJob.k_IntsPerCacheLine, Allocator.TempJob, NativeArrayOptions.ClearMemory);
  478. var prefixSumDrawInstancesJob = new PrefixSumDrawInstancesJob()
  479. {
  480. rangeHash = m_RangeHash,
  481. drawRanges = m_DrawRanges,
  482. drawBatches = m_DrawBatches,
  483. drawBatchIndices = m_DrawBatchIndices.AsArray()
  484. };
  485. var prefixSumJobHandle = prefixSumDrawInstancesJob.Schedule();
  486. var buildDrawListsJob = new BuildDrawListsJob()
  487. {
  488. drawInstances = m_DrawInstances,
  489. batchHash = m_BatchHash,
  490. drawBatches = m_DrawBatches,
  491. internalDrawIndex = internalDrawIndex,
  492. drawInstanceIndices = m_DrawInstanceIndices.AsArray(),
  493. };
  494. buildDrawListsJob.Schedule(m_DrawInstances.Length, BuildDrawListsJob.k_BatchSize, prefixSumJobHandle).Complete();
  495. internalDrawIndex.Dispose();
  496. }
  497. public unsafe void DestroyDrawInstanceIndices(NativeArray<int> drawInstanceIndicesToDestroy)
  498. {
  499. Profiler.BeginSample("DestroyDrawInstanceIndices.ParallelSort");
  500. drawInstanceIndicesToDestroy.ParallelSort().Complete();
  501. Profiler.EndSample();
  502. var removeDrawInstanceIndicesJob = new RemoveDrawInstanceIndicesJob
  503. {
  504. drawInstanceIndices = drawInstanceIndicesToDestroy,
  505. drawInstances = m_DrawInstances,
  506. drawBatches = m_DrawBatches,
  507. drawRanges = m_DrawRanges,
  508. batchHash = m_BatchHash,
  509. rangeHash = m_RangeHash
  510. };
  511. removeDrawInstanceIndicesJob.Run();
  512. }
  513. public unsafe void DestroyDrawInstances(NativeArray<InstanceHandle> destroyedInstances)
  514. {
  515. if (m_DrawInstances.IsEmpty || destroyedInstances.Length == 0)
  516. return;
  517. NeedsRebuild();
  518. var destroyedInstancesSorted = new NativeArray<InstanceHandle>(destroyedInstances, Allocator.TempJob);
  519. Assert.AreEqual(UnsafeUtility.SizeOf<InstanceHandle>(), UnsafeUtility.SizeOf<int>());
  520. Profiler.BeginSample("DestroyDrawInstances.ParallelSort");
  521. destroyedInstancesSorted.Reinterpret<int>().ParallelSort().Complete();
  522. Profiler.EndSample();
  523. var drawInstanceIndicesToDestroy = new NativeList<int>(m_DrawInstances.Length, Allocator.TempJob);
  524. var findDrawInstancesJobHandle = new FindDrawInstancesJob()
  525. {
  526. instancesSorted = destroyedInstancesSorted,
  527. drawInstances = m_DrawInstances,
  528. outDrawInstanceIndicesWriter = drawInstanceIndicesToDestroy.AsParallelWriter()
  529. };
  530. findDrawInstancesJobHandle.ScheduleBatch(m_DrawInstances.Length, FindDrawInstancesJob.k_BatchSize).Complete();
  531. DestroyDrawInstanceIndices(drawInstanceIndicesToDestroy.AsArray());
  532. destroyedInstancesSorted.Dispose();
  533. drawInstanceIndicesToDestroy.Dispose();
  534. }
  535. public unsafe void DestroyMaterialDrawInstances(NativeArray<uint> destroyedBatchMaterials)
  536. {
  537. if (m_DrawInstances.IsEmpty || destroyedBatchMaterials.Length == 0)
  538. return;
  539. NeedsRebuild();
  540. var destroyedBatchMaterialsSorted = new NativeArray<uint>(destroyedBatchMaterials, Allocator.TempJob);
  541. Profiler.BeginSample("DestroyedBatchMaterials.ParallelSort");
  542. destroyedBatchMaterialsSorted.Reinterpret<int>().ParallelSort().Complete();
  543. Profiler.EndSample();
  544. var drawInstanceIndicesToDestroy = new NativeList<int>(m_DrawInstances.Length, Allocator.TempJob);
  545. var findDrawInstancesJobHandle = new FindMaterialDrawInstancesJob()
  546. {
  547. materialsSorted = destroyedBatchMaterialsSorted,
  548. drawInstances = m_DrawInstances,
  549. outDrawInstanceIndicesWriter = drawInstanceIndicesToDestroy.AsParallelWriter()
  550. };
  551. findDrawInstancesJobHandle.ScheduleBatch(m_DrawInstances.Length, FindMaterialDrawInstancesJob.k_BatchSize).Complete();
  552. DestroyDrawInstanceIndices(drawInstanceIndicesToDestroy.AsArray());
  553. destroyedBatchMaterialsSorted.Dispose();
  554. drawInstanceIndicesToDestroy.Dispose();
  555. }
  556. public void NeedsRebuild()
  557. {
  558. m_NeedsRebuild = true;
  559. }
  560. }
  561. internal class InstanceCullingBatcher : IDisposable
  562. {
  563. private RenderersBatchersContext m_BatchersContext;
  564. private CPUDrawInstanceData m_DrawInstanceData;
  565. private BatchRendererGroup m_BRG;
  566. private NativeParallelHashMap<uint, BatchID> m_GlobalBatchIDs;
  567. private InstanceCuller m_Culler;
  568. private NativeParallelHashMap<int, BatchMaterialID> m_BatchMaterialHash;
  569. private NativeParallelHashMap<int, BatchMeshID> m_BatchMeshHash;
  570. private int m_CachedInstanceDataBufferLayoutVersion;
  571. private OnCullingCompleteCallback m_OnCompleteCallback;
  572. public InstanceCullingBatcher(RenderersBatchersContext batcherContext, InstanceCullingBatcherDesc desc, BatchRendererGroup.OnFinishedCulling onFinishedCulling)
  573. {
  574. m_BatchersContext = batcherContext;
  575. m_DrawInstanceData = new CPUDrawInstanceData();
  576. m_DrawInstanceData.Initialize();
  577. m_BRG = new BatchRendererGroup(new BatchRendererGroupCreateInfo()
  578. {
  579. cullingCallback = OnPerformCulling,
  580. finishedCullingCallback = onFinishedCulling,
  581. userContext = IntPtr.Zero
  582. });
  583. #if UNITY_EDITOR
  584. if (desc.brgPicking != null)
  585. {
  586. var mat = new Material(desc.brgPicking);
  587. mat.hideFlags = HideFlags.HideAndDontSave;
  588. m_BRG.SetPickingMaterial(mat);
  589. }
  590. if (desc.brgLoading != null)
  591. {
  592. var mat = new Material(desc.brgLoading);
  593. mat.hideFlags = HideFlags.HideAndDontSave;
  594. m_BRG.SetLoadingMaterial(mat);
  595. }
  596. if (desc.brgError != null)
  597. {
  598. var mat = new Material(desc.brgError);
  599. mat.hideFlags = HideFlags.HideAndDontSave;
  600. m_BRG.SetErrorMaterial(mat);
  601. }
  602. var viewTypes = new BatchCullingViewType[] {
  603. BatchCullingViewType.Light,
  604. BatchCullingViewType.Camera,
  605. BatchCullingViewType.Picking,
  606. BatchCullingViewType.SelectionOutline,
  607. BatchCullingViewType.Filtering
  608. };
  609. m_BRG.SetEnabledViewTypes(viewTypes);
  610. #endif
  611. m_Culler = new InstanceCuller();
  612. m_Culler.Init(batcherContext.resources, batcherContext.debugStats);
  613. m_CachedInstanceDataBufferLayoutVersion = -1;
  614. m_OnCompleteCallback = desc.onCompleteCallback;
  615. m_BatchMaterialHash = new NativeParallelHashMap<int, BatchMaterialID>(64, Allocator.Persistent);
  616. m_BatchMeshHash = new NativeParallelHashMap<int, BatchMeshID>(64, Allocator.Persistent);
  617. m_GlobalBatchIDs = new NativeParallelHashMap<uint, BatchID>(6, Allocator.Persistent);
  618. m_GlobalBatchIDs.Add((uint)InstanceComponentGroup.Default, GetBatchID(InstanceComponentGroup.Default));
  619. m_GlobalBatchIDs.Add((uint)InstanceComponentGroup.DefaultWind, GetBatchID(InstanceComponentGroup.DefaultWind));
  620. m_GlobalBatchIDs.Add((uint)InstanceComponentGroup.DefaultLightProbe, GetBatchID(InstanceComponentGroup.DefaultLightProbe));
  621. m_GlobalBatchIDs.Add((uint)InstanceComponentGroup.DefaultLightmap, GetBatchID(InstanceComponentGroup.DefaultLightmap));
  622. m_GlobalBatchIDs.Add((uint)InstanceComponentGroup.DefaultWindLightProbe, GetBatchID(InstanceComponentGroup.DefaultWindLightProbe));
  623. m_GlobalBatchIDs.Add((uint)InstanceComponentGroup.DefaultWindLightmap, GetBatchID(InstanceComponentGroup.DefaultWindLightmap));
  624. }
  625. internal ref InstanceCuller culler => ref m_Culler;
  626. public void Dispose()
  627. {
  628. m_OnCompleteCallback = null;
  629. m_Culler.Dispose();
  630. foreach (var batchID in m_GlobalBatchIDs)
  631. {
  632. if (!batchID.Value.Equals(BatchID.Null))
  633. m_BRG.RemoveBatch(batchID.Value);
  634. }
  635. m_GlobalBatchIDs.Dispose();
  636. if (m_BRG != null)
  637. m_BRG.Dispose();
  638. m_DrawInstanceData.Dispose();
  639. m_DrawInstanceData = null;
  640. m_BatchMaterialHash.Dispose();
  641. m_BatchMeshHash.Dispose();
  642. }
  643. private BatchID GetBatchID(InstanceComponentGroup componentsOverriden)
  644. {
  645. if (m_CachedInstanceDataBufferLayoutVersion != m_BatchersContext.instanceDataBufferLayoutVersion)
  646. return BatchID.Null;
  647. Assert.IsTrue(m_BatchersContext.defaultDescriptions.Length == m_BatchersContext.defaultMetadata.Length);
  648. const uint kClearIsOverriddenBit = 0x4FFFFFFF;
  649. var tempMetadata = new NativeList<MetadataValue>(m_BatchersContext.defaultMetadata.Length, Allocator.Temp);
  650. for(int i = 0; i < m_BatchersContext.defaultDescriptions.Length; ++i)
  651. {
  652. var componentGroup = m_BatchersContext.defaultDescriptions[i].componentGroup;
  653. var metadata = m_BatchersContext.defaultMetadata[i];
  654. var value = metadata.Value;
  655. // if instances in this batch do not override the component, clear the override bit
  656. if ((componentsOverriden & componentGroup) == 0)
  657. value &= kClearIsOverriddenBit;
  658. tempMetadata.Add(new MetadataValue
  659. {
  660. NameID = metadata.NameID,
  661. Value = value
  662. });
  663. }
  664. return m_BRG.AddBatch(tempMetadata.AsArray(), m_BatchersContext.gpuInstanceDataBuffer.bufferHandle);
  665. }
  666. private void UpdateInstanceDataBufferLayoutVersion()
  667. {
  668. if (m_CachedInstanceDataBufferLayoutVersion != m_BatchersContext.instanceDataBufferLayoutVersion)
  669. {
  670. m_CachedInstanceDataBufferLayoutVersion = m_BatchersContext.instanceDataBufferLayoutVersion;
  671. foreach (var componentsToBatchID in m_GlobalBatchIDs)
  672. {
  673. var batchID = componentsToBatchID.Value;
  674. if (!batchID.Equals(BatchID.Null))
  675. m_BRG.RemoveBatch(batchID);
  676. var componentsOverriden = (InstanceComponentGroup)componentsToBatchID.Key;
  677. componentsToBatchID.Value = GetBatchID(componentsOverriden);
  678. }
  679. }
  680. }
  681. public CPUDrawInstanceData GetDrawInstanceData()
  682. {
  683. return m_DrawInstanceData;
  684. }
  685. public unsafe JobHandle OnPerformCulling(
  686. BatchRendererGroup rendererGroup,
  687. BatchCullingContext cc,
  688. BatchCullingOutput cullingOutput,
  689. IntPtr userContext)
  690. {
  691. foreach (var batchID in m_GlobalBatchIDs)
  692. {
  693. if (batchID.Value.Equals(BatchID.Null))
  694. return new JobHandle();
  695. }
  696. m_DrawInstanceData.RebuildDrawListsIfNeeded();
  697. bool allowOcclusionCulling = m_BatchersContext.hasBoundingSpheres;
  698. JobHandle jobHandle = m_Culler.CreateCullJobTree(
  699. cc,
  700. cullingOutput,
  701. m_BatchersContext.instanceData,
  702. m_BatchersContext.sharedInstanceData,
  703. m_BatchersContext.instanceDataBuffer,
  704. m_BatchersContext.lodGroupCullingData,
  705. m_DrawInstanceData,
  706. m_GlobalBatchIDs,
  707. m_BatchersContext.crossfadedRendererCount,
  708. m_BatchersContext.smallMeshScreenPercentage,
  709. allowOcclusionCulling ? m_BatchersContext.occlusionCullingCommon : null);
  710. if (m_OnCompleteCallback != null)
  711. m_OnCompleteCallback(jobHandle, cc, cullingOutput);
  712. return jobHandle;
  713. }
  714. public void OnFinishedCulling(IntPtr customCullingResult)
  715. {
  716. int viewInstanceID = (int)customCullingResult;
  717. m_Culler.EnsureValidOcclusionTestResults(viewInstanceID);
  718. }
  719. public void DestroyInstances(NativeArray<InstanceHandle> instances)
  720. {
  721. if (instances.Length == 0)
  722. return;
  723. Profiler.BeginSample("DestroyInstances");
  724. m_DrawInstanceData.DestroyDrawInstances(instances);
  725. Profiler.EndSample();
  726. }
  727. public void DestroyMaterials(NativeArray<int> destroyedMaterials)
  728. {
  729. if (destroyedMaterials.Length == 0)
  730. return;
  731. Profiler.BeginSample("DestroyMaterials");
  732. var destroyedBatchMaterials = new NativeList<uint>(destroyedMaterials.Length, Allocator.TempJob);
  733. foreach (int destroyedMaterial in destroyedMaterials)
  734. {
  735. if (m_BatchMaterialHash.TryGetValue(destroyedMaterial, out var destroyedBatchMaterial))
  736. {
  737. destroyedBatchMaterials.Add(destroyedBatchMaterial.value);
  738. m_BatchMaterialHash.Remove(destroyedMaterial);
  739. m_BRG.UnregisterMaterial(destroyedBatchMaterial);
  740. }
  741. }
  742. m_DrawInstanceData.DestroyMaterialDrawInstances(destroyedBatchMaterials.AsArray());
  743. destroyedBatchMaterials.Dispose();
  744. Profiler.EndSample();
  745. }
  746. public void DestroyMeshes(NativeArray<int> destroyedMeshes)
  747. {
  748. if (destroyedMeshes.Length == 0)
  749. return;
  750. Profiler.BeginSample("DestroyMeshes");
  751. foreach (int destroyedMesh in destroyedMeshes)
  752. {
  753. if (m_BatchMeshHash.TryGetValue(destroyedMesh, out var destroyedBatchMesh))
  754. {
  755. m_BatchMeshHash.Remove(destroyedMesh);
  756. m_BRG.UnregisterMesh(destroyedBatchMesh);
  757. }
  758. }
  759. Profiler.EndSample();
  760. }
  761. public void PostCullBeginCameraRendering(RenderRequestBatcherContext context)
  762. {
  763. }
  764. private void RegisterBatchMeshes(NativeArray<int> meshIDs)
  765. {
  766. var newMeshIDs = new NativeList<int>(meshIDs.Length, Allocator.TempJob);
  767. new FindNonRegisteredInstancesJob<BatchMeshID>
  768. {
  769. instanceIDs = meshIDs,
  770. hashMap = m_BatchMeshHash,
  771. outInstancesWriter = newMeshIDs.AsParallelWriter()
  772. }
  773. .ScheduleBatch(meshIDs.Length, FindNonRegisteredInstancesJob<BatchMeshID>.k_BatchSize).Complete();
  774. var newBatchMeshIDs = new NativeArray<BatchMeshID>(newMeshIDs.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
  775. m_BRG.RegisterMeshes(newMeshIDs.AsArray(), newBatchMeshIDs);
  776. int totalMeshesNum = m_BatchMeshHash.Count() + newBatchMeshIDs.Length;
  777. m_BatchMeshHash.Capacity = Math.Max(m_BatchMeshHash.Capacity, Mathf.CeilToInt(totalMeshesNum / 1023.0f) * 1024);
  778. new RegisterNewInstancesJob<BatchMeshID>
  779. {
  780. instanceIDs = newMeshIDs.AsArray(),
  781. batchIDs = newBatchMeshIDs,
  782. hashMap = m_BatchMeshHash.AsParallelWriter()
  783. }
  784. .Schedule(newMeshIDs.Length, RegisterNewInstancesJob<BatchMeshID>.k_BatchSize).Complete();
  785. newMeshIDs.Dispose();
  786. newBatchMeshIDs.Dispose();
  787. }
  788. private void RegisterBatchMaterials(in NativeArray<int> usedMaterialIDs)
  789. {
  790. var newMaterialIDs = new NativeList<int>(usedMaterialIDs.Length, Allocator.TempJob);
  791. new FindNonRegisteredInstancesJob<BatchMaterialID>
  792. {
  793. instanceIDs = usedMaterialIDs,
  794. hashMap = m_BatchMaterialHash,
  795. outInstancesWriter = newMaterialIDs.AsParallelWriter()
  796. }
  797. .ScheduleBatch(usedMaterialIDs.Length, FindNonRegisteredInstancesJob<BatchMaterialID>.k_BatchSize).Complete();
  798. var newBatchMaterialIDs = new NativeArray<BatchMaterialID>(newMaterialIDs.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
  799. m_BRG.RegisterMaterials(newMaterialIDs.AsArray(), newBatchMaterialIDs);
  800. int totalMaterialsNum = m_BatchMaterialHash.Count() + newMaterialIDs.Length;
  801. m_BatchMaterialHash.Capacity = Math.Max(m_BatchMaterialHash.Capacity, Mathf.CeilToInt(totalMaterialsNum / 1023.0f) * 1024);
  802. new RegisterNewInstancesJob<BatchMaterialID>
  803. {
  804. instanceIDs = newMaterialIDs.AsArray(),
  805. batchIDs = newBatchMaterialIDs,
  806. hashMap = m_BatchMaterialHash.AsParallelWriter()
  807. }
  808. .Schedule(newMaterialIDs.Length, RegisterNewInstancesJob<BatchMaterialID>.k_BatchSize).Complete();
  809. newMaterialIDs.Dispose();
  810. newBatchMaterialIDs.Dispose();
  811. }
  812. public void BuildBatch(
  813. NativeArray<InstanceHandle> instances,
  814. NativeArray<int> usedMaterialIDs,
  815. NativeArray<int> usedMeshIDs,
  816. in GPUDrivenRendererGroupData rendererData)
  817. {
  818. RegisterBatchMaterials(usedMaterialIDs);
  819. RegisterBatchMeshes(usedMeshIDs);
  820. new CreateDrawBatchesJob
  821. {
  822. implicitInstanceIndices = rendererData.instancesCount.Length == 0,
  823. instances = instances,
  824. rendererData = rendererData,
  825. batchMeshHash = m_BatchMeshHash,
  826. batchMaterialHash = m_BatchMaterialHash,
  827. rangeHash = m_DrawInstanceData.rangeHash,
  828. drawRanges = m_DrawInstanceData.drawRanges,
  829. batchHash = m_DrawInstanceData.batchHash,
  830. drawBatches = m_DrawInstanceData.drawBatches,
  831. drawInstances = m_DrawInstanceData.drawInstances
  832. }.Run();
  833. m_DrawInstanceData.NeedsRebuild();
  834. UpdateInstanceDataBufferLayoutVersion();
  835. }
  836. public void InstanceOccludersUpdated(int viewInstanceID, int subviewMask)
  837. {
  838. m_Culler.InstanceOccludersUpdated(viewInstanceID, subviewMask, m_BatchersContext);
  839. }
  840. public void UpdateFrame()
  841. {
  842. m_Culler.UpdateFrame();
  843. }
  844. public ParallelBitArray GetCompactedVisibilityMasks(bool syncCullingJobs)
  845. {
  846. return m_Culler.GetCompactedVisibilityMasks(syncCullingJobs);
  847. }
  848. public void OnEndContextRendering()
  849. {
  850. ParallelBitArray compactedVisibilityMasks = GetCompactedVisibilityMasks(syncCullingJobs: true);
  851. if(compactedVisibilityMasks.IsCreated)
  852. m_BatchersContext.UpdatePerFrameInstanceVisibility(compactedVisibilityMasks);
  853. }
  854. public void OnBeginCameraRendering(Camera camera)
  855. {
  856. m_Culler.OnBeginCameraRendering(camera);
  857. }
  858. public void OnEndCameraRendering(Camera camera)
  859. {
  860. m_Culler.OnEndCameraRendering(camera);
  861. }
  862. }
  863. }