No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RenderersBatchersContext.cs 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine.Assertions;
  4. using Unity.Collections;
  5. using Unity.Collections.LowLevel.Unsafe;
  6. using Unity.Jobs;
  7. using Unity.Mathematics;
  8. using Unity.Burst;
  9. using UnityEngine.Jobs;
  10. using UnityEngine.Profiling;
  11. namespace UnityEngine.Rendering
  12. {
  13. internal struct RenderersBatchersContextDesc
  14. {
  15. public InstanceNumInfo instanceNumInfo;
  16. public bool supportDitheringCrossFade;
  17. public bool enableBoundingSpheresInstanceData;
  18. public float smallMeshScreenPercentage;
  19. public bool enableCullerDebugStats;
  20. public static RenderersBatchersContextDesc NewDefault()
  21. {
  22. return new RenderersBatchersContextDesc()
  23. {
  24. instanceNumInfo = new InstanceNumInfo(meshRendererNum: 1024, speedTreeNum: 32),
  25. };
  26. }
  27. }
  28. internal class RenderersBatchersContext : IDisposable
  29. {
  30. public RenderersParameters renderersParameters { get { return m_RenderersParameters; } }
  31. public GraphicsBuffer gpuInstanceDataBuffer { get { return m_InstanceDataBuffer.gpuBuffer; } }
  32. public int activeLodGroupCount { get { return m_LODGroupDataPool.activeLodGroupCount; } }
  33. public NativeArray<GPUInstanceComponentDesc>.ReadOnly defaultDescriptions { get { return m_InstanceDataBuffer.descriptions.AsReadOnly(); } }
  34. public NativeArray<MetadataValue> defaultMetadata { get { return m_InstanceDataBuffer.defaultMetadata; } }
  35. public NativeList<LODGroupCullingData> lodGroupCullingData { get { return m_LODGroupDataPool.lodGroupCullingData; } }
  36. public int instanceDataBufferVersion { get { return m_InstanceDataBuffer.version; } }
  37. public int instanceDataBufferLayoutVersion { get { return m_InstanceDataBuffer.layoutVersion; } }
  38. public int crossfadedRendererCount { get { return m_LODGroupDataPool.crossfadedRendererCount; } }
  39. public SphericalHarmonicsL2 cachedAmbientProbe { get { return m_CachedAmbientProbe; } }
  40. public bool hasBoundingSpheres { get { return m_InstanceDataSystem.hasBoundingSpheres; } }
  41. public CPUInstanceData.ReadOnly instanceData { get { return m_InstanceDataSystem.instanceData; } }
  42. public CPUSharedInstanceData.ReadOnly sharedInstanceData { get { return m_InstanceDataSystem.sharedInstanceData; } }
  43. public GPUInstanceDataBuffer.ReadOnly instanceDataBuffer { get { return m_InstanceDataBuffer.AsReadOnly(); } }
  44. public NativeArray<InstanceHandle> aliveInstances { get { return m_InstanceDataSystem.aliveInstances; } }
  45. public float smallMeshScreenPercentage { get { return m_SmallMeshScreenPercentage; } }
  46. private InstanceDataSystem m_InstanceDataSystem;
  47. public GPUResidentDrawerResources resources { get { return m_Resources; } }
  48. private GPUResidentDrawerResources m_Resources;
  49. private GPUDrivenProcessor m_GPUDrivenProcessor;
  50. private LODGroupDataPool m_LODGroupDataPool;
  51. internal GPUInstanceDataBuffer m_InstanceDataBuffer;
  52. private RenderersParameters m_RenderersParameters;
  53. private GPUInstanceDataBufferUploader.GPUResources m_UploadResources;
  54. private GPUInstanceDataBufferGrower.GPUResources m_GrowerResources;
  55. internal CommandBuffer m_CmdBuffer;
  56. private SphericalHarmonicsL2 m_CachedAmbientProbe;
  57. private float m_SmallMeshScreenPercentage;
  58. private GPUDrivenLODGroupDataCallback m_UpdateLODGroupCallback;
  59. private GPUDrivenLODGroupDataCallback m_TransformLODGroupCallback;
  60. private OcclusionCullingCommon m_OcclusionCullingCommon;
  61. private DebugRendererBatcherStats m_DebugStats;
  62. internal OcclusionCullingCommon occlusionCullingCommon { get => m_OcclusionCullingCommon; }
  63. internal DebugRendererBatcherStats debugStats { get => m_DebugStats; }
  64. public RenderersBatchersContext(in RenderersBatchersContextDesc desc, GPUDrivenProcessor gpuDrivenProcessor, GPUResidentDrawerResources resources)
  65. {
  66. m_Resources = resources;
  67. m_GPUDrivenProcessor = gpuDrivenProcessor;
  68. RenderersParameters.Flags rendererParametersFlags = RenderersParameters.Flags.None;
  69. if (desc.enableBoundingSpheresInstanceData)
  70. rendererParametersFlags |= RenderersParameters.Flags.UseBoundingSphereParameter;
  71. m_InstanceDataBuffer = RenderersParameters.CreateInstanceDataBuffer(rendererParametersFlags, desc.instanceNumInfo);
  72. m_RenderersParameters = new RenderersParameters(m_InstanceDataBuffer);
  73. m_LODGroupDataPool = new LODGroupDataPool(resources, desc.instanceNumInfo.GetInstanceNum(InstanceType.MeshRenderer), desc.supportDitheringCrossFade);
  74. m_UploadResources = new GPUInstanceDataBufferUploader.GPUResources();
  75. m_UploadResources.LoadShaders(resources);
  76. m_GrowerResources = new GPUInstanceDataBufferGrower.GPUResources();
  77. m_GrowerResources.LoadShaders(resources);
  78. m_CmdBuffer = new CommandBuffer();
  79. m_CmdBuffer.name = "GPUCullingCommands";
  80. m_CachedAmbientProbe = RenderSettings.ambientProbe;
  81. m_InstanceDataSystem = new InstanceDataSystem(desc.instanceNumInfo.GetTotalInstanceNum(), desc.enableBoundingSpheresInstanceData, resources);
  82. m_SmallMeshScreenPercentage = desc.smallMeshScreenPercentage;
  83. m_UpdateLODGroupCallback = UpdateLODGroupData;
  84. m_TransformLODGroupCallback = TransformLODGroupData;
  85. m_OcclusionCullingCommon = new OcclusionCullingCommon();
  86. m_OcclusionCullingCommon.Init(resources);
  87. m_DebugStats = desc.enableCullerDebugStats ? new DebugRendererBatcherStats() : null;
  88. }
  89. public void Dispose()
  90. {
  91. NativeArray<int>.ReadOnly rendererGroupIDs = m_InstanceDataSystem.sharedInstanceData.rendererGroupIDs;
  92. if (rendererGroupIDs.Length > 0)
  93. m_GPUDrivenProcessor.DisableGPUDrivenRendering(rendererGroupIDs);
  94. m_InstanceDataSystem.Dispose();
  95. m_CmdBuffer.Release();
  96. m_GrowerResources.Dispose();
  97. m_UploadResources.Dispose();
  98. m_LODGroupDataPool.Dispose();
  99. m_InstanceDataBuffer.Dispose();
  100. m_UpdateLODGroupCallback = null;
  101. m_TransformLODGroupCallback = null;
  102. m_DebugStats?.Dispose();
  103. m_DebugStats = null;
  104. m_OcclusionCullingCommon?.Dispose();
  105. m_OcclusionCullingCommon = null;
  106. }
  107. public int GetMaxInstancesOfType(InstanceType instanceType)
  108. {
  109. return m_InstanceDataSystem.GetMaxInstancesOfType(instanceType);
  110. }
  111. public int GetAliveInstancesOfType(InstanceType instanceType)
  112. {
  113. return m_InstanceDataSystem.GetAliveInstancesOfType(instanceType);
  114. }
  115. public void GrowInstanceBuffer(in InstanceNumInfo instanceNumInfo)
  116. {
  117. using (var grower = new GPUInstanceDataBufferGrower(m_InstanceDataBuffer, instanceNumInfo))
  118. {
  119. var newInstanceDataBuffer = grower.SubmitToGpu(ref m_GrowerResources);
  120. if (newInstanceDataBuffer != m_InstanceDataBuffer)
  121. {
  122. if (m_InstanceDataBuffer != null)
  123. m_InstanceDataBuffer.Dispose();
  124. m_InstanceDataBuffer = newInstanceDataBuffer;
  125. }
  126. }
  127. m_RenderersParameters = new RenderersParameters(m_InstanceDataBuffer);
  128. }
  129. private void EnsureInstanceBufferCapacity()
  130. {
  131. const int kMeshRendererGrowNum = 1024;
  132. const int kSpeedTreeGrowNum = 256;
  133. int maxCPUMeshRendererNum = m_InstanceDataSystem.GetMaxInstancesOfType(InstanceType.MeshRenderer);
  134. int maxCPUSpeedTreeNum = m_InstanceDataSystem.GetMaxInstancesOfType(InstanceType.SpeedTree);
  135. int maxGPUMeshRendererInstances = m_InstanceDataBuffer.instanceNumInfo.GetInstanceNum(InstanceType.MeshRenderer);
  136. int maxGPUSpeedTreeInstances = m_InstanceDataBuffer.instanceNumInfo.GetInstanceNum(InstanceType.SpeedTree);
  137. bool needToGrow = false;
  138. if(maxCPUMeshRendererNum > maxGPUMeshRendererInstances)
  139. {
  140. needToGrow = true;
  141. maxGPUMeshRendererInstances = maxCPUMeshRendererNum + kMeshRendererGrowNum;
  142. }
  143. if(maxCPUSpeedTreeNum > maxGPUSpeedTreeInstances)
  144. {
  145. needToGrow = true;
  146. maxGPUSpeedTreeInstances = maxCPUSpeedTreeNum + kSpeedTreeGrowNum;
  147. }
  148. if (needToGrow)
  149. GrowInstanceBuffer(new InstanceNumInfo(meshRendererNum: maxGPUMeshRendererInstances, speedTreeNum: maxGPUSpeedTreeInstances));
  150. }
  151. private void UpdateLODGroupData(in GPUDrivenLODGroupData lodGroupData)
  152. {
  153. Profiler.BeginSample("Convert LODGroups To BRG");
  154. m_LODGroupDataPool.UpdateLODGroupData(lodGroupData);
  155. Profiler.EndSample();
  156. }
  157. private void TransformLODGroupData(in GPUDrivenLODGroupData lodGroupData)
  158. {
  159. Profiler.BeginSample("Transform LODGroups");
  160. m_LODGroupDataPool.UpdateLODGroupTransformData(lodGroupData);
  161. Profiler.EndSample();
  162. }
  163. public void DestroyLODGroups(NativeArray<int> destroyed)
  164. {
  165. if (destroyed.Length == 0)
  166. return;
  167. m_LODGroupDataPool.FreeLODGroupData(destroyed);
  168. }
  169. public void UpdateLODGroups(NativeArray<int> changedID)
  170. {
  171. if (changedID.Length == 0)
  172. return;
  173. m_GPUDrivenProcessor.DispatchLODGroupData(changedID, m_UpdateLODGroupCallback);
  174. }
  175. public void ReallocateAndGetInstances(in GPUDrivenRendererGroupData rendererData, NativeArray<InstanceHandle> instances)
  176. {
  177. m_InstanceDataSystem.ReallocateAndGetInstances(rendererData, instances);
  178. EnsureInstanceBufferCapacity();
  179. }
  180. public JobHandle ScheduleUpdateInstanceDataJob(NativeArray<InstanceHandle> instances, in GPUDrivenRendererGroupData rendererData)
  181. {
  182. return m_InstanceDataSystem.ScheduleUpdateInstanceDataJob(instances, rendererData, m_LODGroupDataPool.lodGroupDataHash);
  183. }
  184. public void FreeRendererGroupInstances(NativeArray<int> rendererGroupsID)
  185. {
  186. m_InstanceDataSystem.FreeRendererGroupInstances(rendererGroupsID);
  187. }
  188. public void FreeInstances(NativeArray<InstanceHandle> instances)
  189. {
  190. m_InstanceDataSystem.FreeInstances(instances);
  191. }
  192. public JobHandle ScheduleQueryRendererGroupInstancesJob(NativeArray<int> rendererGroupIDs, NativeArray<InstanceHandle> instances)
  193. {
  194. return m_InstanceDataSystem.ScheduleQueryRendererGroupInstancesJob(rendererGroupIDs, instances);
  195. }
  196. public JobHandle ScheduleQueryRendererGroupInstancesJob(NativeArray<int> rendererGroupIDs, NativeList<InstanceHandle> instances)
  197. {
  198. return m_InstanceDataSystem.ScheduleQueryRendererGroupInstancesJob(rendererGroupIDs, instances);
  199. }
  200. public JobHandle ScheduleQueryRendererGroupInstancesJob(NativeArray<int> rendererGroupIDs, NativeArray<int> instancesOffset, NativeArray<int> instancesCount, NativeList<InstanceHandle> instances)
  201. {
  202. return m_InstanceDataSystem.ScheduleQueryRendererGroupInstancesJob(rendererGroupIDs, instancesOffset, instancesCount, instances);
  203. }
  204. public JobHandle ScheduleQueryMeshInstancesJob(NativeArray<int> sortedMeshIDs, NativeList<InstanceHandle> instances)
  205. {
  206. return m_InstanceDataSystem.ScheduleQuerySortedMeshInstancesJob(sortedMeshIDs, instances);
  207. }
  208. public void ChangeInstanceBufferVersion()
  209. {
  210. ++m_InstanceDataBuffer.version;
  211. }
  212. public GPUInstanceDataBufferUploader CreateDataBufferUploader(int capacity, InstanceType instanceType)
  213. {
  214. //@ This is not quite efficient as we will allocate all the parameters/descriptions of an certain type but write only some of them later.
  215. //@ We should allow to preallocate space only for needed parameters/descriptions.
  216. return new GPUInstanceDataBufferUploader(m_InstanceDataBuffer.descriptions, capacity, instanceType);
  217. }
  218. public void SubmitToGpu(NativeArray<InstanceHandle> instances, ref GPUInstanceDataBufferUploader uploader, bool submitOnlyWrittenParams)
  219. {
  220. uploader.SubmitToGpu(m_InstanceDataBuffer, instances, ref m_UploadResources, submitOnlyWrittenParams);
  221. }
  222. public void SubmitToGpu(NativeArray<GPUInstanceIndex> gpuInstanceIndices, ref GPUInstanceDataBufferUploader uploader, bool submitOnlyWrittenParams)
  223. {
  224. uploader.SubmitToGpu(m_InstanceDataBuffer, gpuInstanceIndices, ref m_UploadResources, submitOnlyWrittenParams);
  225. }
  226. public void InitializeInstanceTransforms(NativeArray<InstanceHandle> instances, NativeArray<Matrix4x4> localToWorldMatrices, NativeArray<Matrix4x4> prevLocalToWorldMatrices)
  227. {
  228. if (instances.Length == 0)
  229. return;
  230. m_InstanceDataSystem.InitializeInstanceTransforms(instances, localToWorldMatrices, prevLocalToWorldMatrices, m_RenderersParameters, m_InstanceDataBuffer);
  231. ChangeInstanceBufferVersion();
  232. }
  233. public void UpdateInstanceTransforms(NativeArray<InstanceHandle> instances, NativeArray<Matrix4x4> localToWorldMatrices)
  234. {
  235. if(instances.Length == 0)
  236. return;
  237. m_InstanceDataSystem.UpdateInstanceTransforms(instances, localToWorldMatrices, m_RenderersParameters, m_InstanceDataBuffer);
  238. ChangeInstanceBufferVersion();
  239. }
  240. public void UpdateAmbientProbeAndGpuBuffer(bool forceUpdate)
  241. {
  242. if (forceUpdate || m_CachedAmbientProbe != RenderSettings.ambientProbe)
  243. {
  244. m_CachedAmbientProbe = RenderSettings.ambientProbe;
  245. m_InstanceDataSystem.UpdateAllInstanceProbes(m_RenderersParameters, m_InstanceDataBuffer);
  246. ChangeInstanceBufferVersion();
  247. }
  248. }
  249. public void UpdateInstanceWindDataHistory(NativeArray<GPUInstanceIndex> gpuInstanceIndices)
  250. {
  251. if (gpuInstanceIndices.Length == 0)
  252. return;
  253. m_InstanceDataSystem.UpdateInstanceWindDataHistory(gpuInstanceIndices, m_RenderersParameters, m_InstanceDataBuffer);
  254. ChangeInstanceBufferVersion();
  255. }
  256. // This should be called at the end of the frame loop to properly update motion vectors.
  257. public void UpdateInstanceMotions()
  258. {
  259. m_InstanceDataSystem.UpdateInstanceMotions(m_RenderersParameters, m_InstanceDataBuffer);
  260. ChangeInstanceBufferVersion();
  261. }
  262. public void TransformLODGroups(NativeArray<int> lodGroupsID)
  263. {
  264. if (lodGroupsID.Length == 0)
  265. return;
  266. m_GPUDrivenProcessor.DispatchLODGroupData(lodGroupsID, m_TransformLODGroupCallback);
  267. }
  268. public void UpdatePerFrameInstanceVisibility(in ParallelBitArray compactedVisibilityMasks)
  269. {
  270. m_InstanceDataSystem.UpdatePerFrameInstanceVisibility(compactedVisibilityMasks);
  271. }
  272. public JobHandle ScheduleCollectInstancesLODGroupAndMasksJob(NativeArray<InstanceHandle> instances, NativeArray<uint> lodGroupAndMasks)
  273. {
  274. return m_InstanceDataSystem.ScheduleCollectInstancesLODGroupAndMasksJob(instances, lodGroupAndMasks);
  275. }
  276. public InstanceHandle GetRendererInstanceHandle(int rendererID)
  277. {
  278. var rendererIDs = new NativeArray<int>(1, Allocator.TempJob);
  279. var instances = new NativeArray<InstanceHandle>(1, Allocator.TempJob);
  280. rendererIDs[0] = rendererID;
  281. m_InstanceDataSystem.ScheduleQueryRendererGroupInstancesJob(rendererIDs, instances).Complete();
  282. InstanceHandle instance = instances[0];
  283. rendererIDs.Dispose();
  284. instances.Dispose();
  285. return instance;
  286. }
  287. public void GetVisibleTreeInstances(in ParallelBitArray compactedVisibilityMasks, in ParallelBitArray processedBits, NativeList<int> visibeTreeRendererIDs,
  288. NativeList<InstanceHandle> visibeTreeInstances, bool becomeVisibleOnly, out int becomeVisibeTreeInstancesCount)
  289. {
  290. m_InstanceDataSystem.GetVisibleTreeInstances(compactedVisibilityMasks, processedBits, visibeTreeRendererIDs, visibeTreeInstances, becomeVisibleOnly, out becomeVisibeTreeInstancesCount);
  291. }
  292. public GPUInstanceDataBuffer GetInstanceDataBuffer()
  293. {
  294. return m_InstanceDataBuffer;
  295. }
  296. public void UpdateFrame()
  297. {
  298. m_OcclusionCullingCommon.UpdateFrame();
  299. if (m_DebugStats != null)
  300. m_OcclusionCullingCommon.UpdateOccluderStats(m_DebugStats);
  301. }
  302. #if UNITY_EDITOR
  303. public void UpdateSelectedInstances(NativeArray<InstanceHandle> instances)
  304. {
  305. m_InstanceDataSystem.UpdateSelectedInstances(instances);
  306. }
  307. #endif
  308. }
  309. }