123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- using System;
- using System.Collections.Generic;
- using UnityEngine.Assertions;
- using Unity.Collections;
- using Unity.Collections.LowLevel.Unsafe;
- using Unity.Jobs;
- using Unity.Mathematics;
- using Unity.Burst;
- using UnityEngine.Jobs;
- using UnityEngine.Profiling;
-
- namespace UnityEngine.Rendering
- {
- internal struct RenderersBatchersContextDesc
- {
- public InstanceNumInfo instanceNumInfo;
- public bool supportDitheringCrossFade;
- public bool enableBoundingSpheresInstanceData;
- public float smallMeshScreenPercentage;
- public bool enableCullerDebugStats;
-
- public static RenderersBatchersContextDesc NewDefault()
- {
- return new RenderersBatchersContextDesc()
- {
- instanceNumInfo = new InstanceNumInfo(meshRendererNum: 1024, speedTreeNum: 32),
- };
- }
- }
-
- internal class RenderersBatchersContext : IDisposable
- {
- public RenderersParameters renderersParameters { get { return m_RenderersParameters; } }
- public GraphicsBuffer gpuInstanceDataBuffer { get { return m_InstanceDataBuffer.gpuBuffer; } }
- public int activeLodGroupCount { get { return m_LODGroupDataPool.activeLodGroupCount; } }
- public NativeArray<GPUInstanceComponentDesc>.ReadOnly defaultDescriptions { get { return m_InstanceDataBuffer.descriptions.AsReadOnly(); } }
- public NativeArray<MetadataValue> defaultMetadata { get { return m_InstanceDataBuffer.defaultMetadata; } }
- public NativeList<LODGroupCullingData> lodGroupCullingData { get { return m_LODGroupDataPool.lodGroupCullingData; } }
- public int instanceDataBufferVersion { get { return m_InstanceDataBuffer.version; } }
- public int instanceDataBufferLayoutVersion { get { return m_InstanceDataBuffer.layoutVersion; } }
- public int crossfadedRendererCount { get { return m_LODGroupDataPool.crossfadedRendererCount; } }
- public SphericalHarmonicsL2 cachedAmbientProbe { get { return m_CachedAmbientProbe; } }
-
- public bool hasBoundingSpheres { get { return m_InstanceDataSystem.hasBoundingSpheres; } }
- public CPUInstanceData.ReadOnly instanceData { get { return m_InstanceDataSystem.instanceData; } }
- public CPUSharedInstanceData.ReadOnly sharedInstanceData { get { return m_InstanceDataSystem.sharedInstanceData; } }
- public GPUInstanceDataBuffer.ReadOnly instanceDataBuffer { get { return m_InstanceDataBuffer.AsReadOnly(); } }
- public NativeArray<InstanceHandle> aliveInstances { get { return m_InstanceDataSystem.aliveInstances; } }
-
- public float smallMeshScreenPercentage { get { return m_SmallMeshScreenPercentage; } }
-
- private InstanceDataSystem m_InstanceDataSystem;
-
- public GPUResidentDrawerResources resources { get { return m_Resources; } }
-
- private GPUResidentDrawerResources m_Resources;
- private GPUDrivenProcessor m_GPUDrivenProcessor;
-
- private LODGroupDataPool m_LODGroupDataPool;
-
- internal GPUInstanceDataBuffer m_InstanceDataBuffer;
- private RenderersParameters m_RenderersParameters;
- private GPUInstanceDataBufferUploader.GPUResources m_UploadResources;
- private GPUInstanceDataBufferGrower.GPUResources m_GrowerResources;
-
- internal CommandBuffer m_CmdBuffer;
-
- private SphericalHarmonicsL2 m_CachedAmbientProbe;
-
- private float m_SmallMeshScreenPercentage;
-
- private GPUDrivenLODGroupDataCallback m_UpdateLODGroupCallback;
- private GPUDrivenLODGroupDataCallback m_TransformLODGroupCallback;
-
- private OcclusionCullingCommon m_OcclusionCullingCommon;
- private DebugRendererBatcherStats m_DebugStats;
-
- internal OcclusionCullingCommon occlusionCullingCommon { get => m_OcclusionCullingCommon; }
- internal DebugRendererBatcherStats debugStats { get => m_DebugStats; }
-
- public RenderersBatchersContext(in RenderersBatchersContextDesc desc, GPUDrivenProcessor gpuDrivenProcessor, GPUResidentDrawerResources resources)
- {
- m_Resources = resources;
- m_GPUDrivenProcessor = gpuDrivenProcessor;
-
- RenderersParameters.Flags rendererParametersFlags = RenderersParameters.Flags.None;
- if (desc.enableBoundingSpheresInstanceData)
- rendererParametersFlags |= RenderersParameters.Flags.UseBoundingSphereParameter;
-
- m_InstanceDataBuffer = RenderersParameters.CreateInstanceDataBuffer(rendererParametersFlags, desc.instanceNumInfo);
- m_RenderersParameters = new RenderersParameters(m_InstanceDataBuffer);
- m_LODGroupDataPool = new LODGroupDataPool(resources, desc.instanceNumInfo.GetInstanceNum(InstanceType.MeshRenderer), desc.supportDitheringCrossFade);
- m_UploadResources = new GPUInstanceDataBufferUploader.GPUResources();
- m_UploadResources.LoadShaders(resources);
-
- m_GrowerResources = new GPUInstanceDataBufferGrower.GPUResources();
- m_GrowerResources.LoadShaders(resources);
-
- m_CmdBuffer = new CommandBuffer();
- m_CmdBuffer.name = "GPUCullingCommands";
-
- m_CachedAmbientProbe = RenderSettings.ambientProbe;
-
- m_InstanceDataSystem = new InstanceDataSystem(desc.instanceNumInfo.GetTotalInstanceNum(), desc.enableBoundingSpheresInstanceData, resources);
- m_SmallMeshScreenPercentage = desc.smallMeshScreenPercentage;
-
- m_UpdateLODGroupCallback = UpdateLODGroupData;
- m_TransformLODGroupCallback = TransformLODGroupData;
-
- m_OcclusionCullingCommon = new OcclusionCullingCommon();
- m_OcclusionCullingCommon.Init(resources);
- m_DebugStats = desc.enableCullerDebugStats ? new DebugRendererBatcherStats() : null;
- }
-
- public void Dispose()
- {
- NativeArray<int>.ReadOnly rendererGroupIDs = m_InstanceDataSystem.sharedInstanceData.rendererGroupIDs;
-
- if (rendererGroupIDs.Length > 0)
- m_GPUDrivenProcessor.DisableGPUDrivenRendering(rendererGroupIDs);
-
- m_InstanceDataSystem.Dispose();
-
- m_CmdBuffer.Release();
- m_GrowerResources.Dispose();
- m_UploadResources.Dispose();
- m_LODGroupDataPool.Dispose();
- m_InstanceDataBuffer.Dispose();
-
- m_UpdateLODGroupCallback = null;
- m_TransformLODGroupCallback = null;
- m_DebugStats?.Dispose();
- m_DebugStats = null;
- m_OcclusionCullingCommon?.Dispose();
- m_OcclusionCullingCommon = null;
- }
-
- public int GetMaxInstancesOfType(InstanceType instanceType)
- {
- return m_InstanceDataSystem.GetMaxInstancesOfType(instanceType);
- }
-
- public int GetAliveInstancesOfType(InstanceType instanceType)
- {
- return m_InstanceDataSystem.GetAliveInstancesOfType(instanceType);
- }
-
- public void GrowInstanceBuffer(in InstanceNumInfo instanceNumInfo)
- {
- using (var grower = new GPUInstanceDataBufferGrower(m_InstanceDataBuffer, instanceNumInfo))
- {
- var newInstanceDataBuffer = grower.SubmitToGpu(ref m_GrowerResources);
-
- if (newInstanceDataBuffer != m_InstanceDataBuffer)
- {
- if (m_InstanceDataBuffer != null)
- m_InstanceDataBuffer.Dispose();
-
- m_InstanceDataBuffer = newInstanceDataBuffer;
- }
- }
-
- m_RenderersParameters = new RenderersParameters(m_InstanceDataBuffer);
- }
-
- private void EnsureInstanceBufferCapacity()
- {
- const int kMeshRendererGrowNum = 1024;
- const int kSpeedTreeGrowNum = 256;
-
- int maxCPUMeshRendererNum = m_InstanceDataSystem.GetMaxInstancesOfType(InstanceType.MeshRenderer);
- int maxCPUSpeedTreeNum = m_InstanceDataSystem.GetMaxInstancesOfType(InstanceType.SpeedTree);
-
- int maxGPUMeshRendererInstances = m_InstanceDataBuffer.instanceNumInfo.GetInstanceNum(InstanceType.MeshRenderer);
- int maxGPUSpeedTreeInstances = m_InstanceDataBuffer.instanceNumInfo.GetInstanceNum(InstanceType.SpeedTree);
-
- bool needToGrow = false;
-
- if(maxCPUMeshRendererNum > maxGPUMeshRendererInstances)
- {
- needToGrow = true;
- maxGPUMeshRendererInstances = maxCPUMeshRendererNum + kMeshRendererGrowNum;
- }
- if(maxCPUSpeedTreeNum > maxGPUSpeedTreeInstances)
- {
- needToGrow = true;
- maxGPUSpeedTreeInstances = maxCPUSpeedTreeNum + kSpeedTreeGrowNum;
- }
-
- if (needToGrow)
- GrowInstanceBuffer(new InstanceNumInfo(meshRendererNum: maxGPUMeshRendererInstances, speedTreeNum: maxGPUSpeedTreeInstances));
- }
-
- private void UpdateLODGroupData(in GPUDrivenLODGroupData lodGroupData)
- {
- Profiler.BeginSample("Convert LODGroups To BRG");
-
- m_LODGroupDataPool.UpdateLODGroupData(lodGroupData);
-
- Profiler.EndSample();
- }
-
- private void TransformLODGroupData(in GPUDrivenLODGroupData lodGroupData)
- {
- Profiler.BeginSample("Transform LODGroups");
-
- m_LODGroupDataPool.UpdateLODGroupTransformData(lodGroupData);
-
- Profiler.EndSample();
- }
-
- public void DestroyLODGroups(NativeArray<int> destroyed)
- {
- if (destroyed.Length == 0)
- return;
-
- m_LODGroupDataPool.FreeLODGroupData(destroyed);
- }
-
- public void UpdateLODGroups(NativeArray<int> changedID)
- {
- if (changedID.Length == 0)
- return;
-
- m_GPUDrivenProcessor.DispatchLODGroupData(changedID, m_UpdateLODGroupCallback);
- }
-
- public void ReallocateAndGetInstances(in GPUDrivenRendererGroupData rendererData, NativeArray<InstanceHandle> instances)
- {
- m_InstanceDataSystem.ReallocateAndGetInstances(rendererData, instances);
-
- EnsureInstanceBufferCapacity();
- }
-
- public JobHandle ScheduleUpdateInstanceDataJob(NativeArray<InstanceHandle> instances, in GPUDrivenRendererGroupData rendererData)
- {
- return m_InstanceDataSystem.ScheduleUpdateInstanceDataJob(instances, rendererData, m_LODGroupDataPool.lodGroupDataHash);
- }
-
- public void FreeRendererGroupInstances(NativeArray<int> rendererGroupsID)
- {
- m_InstanceDataSystem.FreeRendererGroupInstances(rendererGroupsID);
- }
-
- public void FreeInstances(NativeArray<InstanceHandle> instances)
- {
- m_InstanceDataSystem.FreeInstances(instances);
- }
-
- public JobHandle ScheduleQueryRendererGroupInstancesJob(NativeArray<int> rendererGroupIDs, NativeArray<InstanceHandle> instances)
- {
- return m_InstanceDataSystem.ScheduleQueryRendererGroupInstancesJob(rendererGroupIDs, instances);
- }
-
- public JobHandle ScheduleQueryRendererGroupInstancesJob(NativeArray<int> rendererGroupIDs, NativeList<InstanceHandle> instances)
- {
- return m_InstanceDataSystem.ScheduleQueryRendererGroupInstancesJob(rendererGroupIDs, instances);
- }
-
- public JobHandle ScheduleQueryRendererGroupInstancesJob(NativeArray<int> rendererGroupIDs, NativeArray<int> instancesOffset, NativeArray<int> instancesCount, NativeList<InstanceHandle> instances)
- {
- return m_InstanceDataSystem.ScheduleQueryRendererGroupInstancesJob(rendererGroupIDs, instancesOffset, instancesCount, instances);
- }
-
- public JobHandle ScheduleQueryMeshInstancesJob(NativeArray<int> sortedMeshIDs, NativeList<InstanceHandle> instances)
- {
- return m_InstanceDataSystem.ScheduleQuerySortedMeshInstancesJob(sortedMeshIDs, instances);
- }
-
- public void ChangeInstanceBufferVersion()
- {
- ++m_InstanceDataBuffer.version;
- }
-
- public GPUInstanceDataBufferUploader CreateDataBufferUploader(int capacity, InstanceType instanceType)
- {
- //@ This is not quite efficient as we will allocate all the parameters/descriptions of an certain type but write only some of them later.
- //@ We should allow to preallocate space only for needed parameters/descriptions.
- return new GPUInstanceDataBufferUploader(m_InstanceDataBuffer.descriptions, capacity, instanceType);
- }
-
- public void SubmitToGpu(NativeArray<InstanceHandle> instances, ref GPUInstanceDataBufferUploader uploader, bool submitOnlyWrittenParams)
- {
- uploader.SubmitToGpu(m_InstanceDataBuffer, instances, ref m_UploadResources, submitOnlyWrittenParams);
- }
-
- public void SubmitToGpu(NativeArray<GPUInstanceIndex> gpuInstanceIndices, ref GPUInstanceDataBufferUploader uploader, bool submitOnlyWrittenParams)
- {
- uploader.SubmitToGpu(m_InstanceDataBuffer, gpuInstanceIndices, ref m_UploadResources, submitOnlyWrittenParams);
- }
-
- public void InitializeInstanceTransforms(NativeArray<InstanceHandle> instances, NativeArray<Matrix4x4> localToWorldMatrices, NativeArray<Matrix4x4> prevLocalToWorldMatrices)
- {
- if (instances.Length == 0)
- return;
-
- m_InstanceDataSystem.InitializeInstanceTransforms(instances, localToWorldMatrices, prevLocalToWorldMatrices, m_RenderersParameters, m_InstanceDataBuffer);
- ChangeInstanceBufferVersion();
- }
-
- public void UpdateInstanceTransforms(NativeArray<InstanceHandle> instances, NativeArray<Matrix4x4> localToWorldMatrices)
- {
- if(instances.Length == 0)
- return;
-
- m_InstanceDataSystem.UpdateInstanceTransforms(instances, localToWorldMatrices, m_RenderersParameters, m_InstanceDataBuffer);
- ChangeInstanceBufferVersion();
- }
-
- public void UpdateAmbientProbeAndGpuBuffer(bool forceUpdate)
- {
- if (forceUpdate || m_CachedAmbientProbe != RenderSettings.ambientProbe)
- {
- m_CachedAmbientProbe = RenderSettings.ambientProbe;
- m_InstanceDataSystem.UpdateAllInstanceProbes(m_RenderersParameters, m_InstanceDataBuffer);
- ChangeInstanceBufferVersion();
- }
- }
-
- public void UpdateInstanceWindDataHistory(NativeArray<GPUInstanceIndex> gpuInstanceIndices)
- {
- if (gpuInstanceIndices.Length == 0)
- return;
-
- m_InstanceDataSystem.UpdateInstanceWindDataHistory(gpuInstanceIndices, m_RenderersParameters, m_InstanceDataBuffer);
- ChangeInstanceBufferVersion();
- }
-
- // This should be called at the end of the frame loop to properly update motion vectors.
- public void UpdateInstanceMotions()
- {
- m_InstanceDataSystem.UpdateInstanceMotions(m_RenderersParameters, m_InstanceDataBuffer);
- ChangeInstanceBufferVersion();
- }
-
- public void TransformLODGroups(NativeArray<int> lodGroupsID)
- {
- if (lodGroupsID.Length == 0)
- return;
-
- m_GPUDrivenProcessor.DispatchLODGroupData(lodGroupsID, m_TransformLODGroupCallback);
- }
-
- public void UpdatePerFrameInstanceVisibility(in ParallelBitArray compactedVisibilityMasks)
- {
- m_InstanceDataSystem.UpdatePerFrameInstanceVisibility(compactedVisibilityMasks);
- }
-
- public JobHandle ScheduleCollectInstancesLODGroupAndMasksJob(NativeArray<InstanceHandle> instances, NativeArray<uint> lodGroupAndMasks)
- {
- return m_InstanceDataSystem.ScheduleCollectInstancesLODGroupAndMasksJob(instances, lodGroupAndMasks);
- }
-
- public InstanceHandle GetRendererInstanceHandle(int rendererID)
- {
- var rendererIDs = new NativeArray<int>(1, Allocator.TempJob);
- var instances = new NativeArray<InstanceHandle>(1, Allocator.TempJob);
-
- rendererIDs[0] = rendererID;
-
- m_InstanceDataSystem.ScheduleQueryRendererGroupInstancesJob(rendererIDs, instances).Complete();
-
- InstanceHandle instance = instances[0];
-
- rendererIDs.Dispose();
- instances.Dispose();
-
- return instance;
- }
-
- public void GetVisibleTreeInstances(in ParallelBitArray compactedVisibilityMasks, in ParallelBitArray processedBits, NativeList<int> visibeTreeRendererIDs,
- NativeList<InstanceHandle> visibeTreeInstances, bool becomeVisibleOnly, out int becomeVisibeTreeInstancesCount)
- {
- m_InstanceDataSystem.GetVisibleTreeInstances(compactedVisibilityMasks, processedBits, visibeTreeRendererIDs, visibeTreeInstances, becomeVisibleOnly, out becomeVisibeTreeInstancesCount);
- }
-
- public GPUInstanceDataBuffer GetInstanceDataBuffer()
- {
- return m_InstanceDataBuffer;
- }
-
- public void UpdateFrame()
- {
- m_OcclusionCullingCommon.UpdateFrame();
- if (m_DebugStats != null)
- m_OcclusionCullingCommon.UpdateOccluderStats(m_DebugStats);
- }
-
- #if UNITY_EDITOR
- public void UpdateSelectedInstances(NativeArray<InstanceHandle> instances)
- {
- m_InstanceDataSystem.UpdateSelectedInstances(instances);
- }
- #endif
- }
- }
|