private JobHandle OnPerformCulling(BatchRendererGroup rendererGroup, BatchCullingContext cullingContext) { // no culling at all! this just sets up everything as visible. for (int batch = 0; batch < cullingContext.batchVisibility.Length; batch++) { var bv = cullingContext.batchVisibility[batch]; bv.visibleCount = bv.instancesCount; cullingContext.batchVisibility[batch] = bv; for (int instance = 0; instance < bv.instancesCount; instance++) { cullingContext.visibleIndices[bv.offset + instance] = instance; } } return(new JobHandle()); }
// You can safely ignore this. It is just a pass-throught that performs no culling JobHandle CullingCallback(BatchRendererGroup rendererGroup, BatchCullingContext cullingContext) { // dummy culling for (var batchIndex = 0; batchIndex < cullingContext.batchVisibility.Length; ++batchIndex) { var batchVisibility = cullingContext.batchVisibility[batchIndex]; for (var i = 0; i < batchVisibility.instancesCount; ++i) { cullingContext.visibleIndices[batchVisibility.offset + i] = i; } batchVisibility.visibleCount = batchVisibility.instancesCount; cullingContext.batchVisibility[batchIndex] = batchVisibility; } return(default);
private JobHandle OnPerformCulling(BatchRendererGroup batchRendererGroup, BatchCullingContext cullingContext) { var planes = Unity.Rendering.FrustumPlanes.BuildSOAPlanePackets(cullingContext.cullingPlanes, Allocator.TempJob); var lodParms = LODGroupExtensions.CalculateLODParams(cullingContext.lodParameters); var cull = new MyCullJob() { Planes = planes, LODParams = lodParms, IndexList = cullingContext.visibleIndices, Batches = cullingContext.batchVisibility, CullDatas = _cullDic, }; // Debug.Log(_cullDic.GetKeyArray(Allocator.Temp).Length); ; var handle = cull.Schedule(batchIndex + 1, 1); return(handle); }
private JobHandle CullingCallback(BatchRendererGroup rendererGroup, BatchCullingContext cullingContext) { var inputDependency = _jobDependency; for (var i = 0; i < cullingContext.batchVisibility.Length; ++i) { var job = new CullingJob { CullingContext = cullingContext, Matrices = rendererGroup.GetBatchMatrices(i), BatchIndex = i }.Schedule(inputDependency); // Jobの依存関係を更新 _jobDependency = JobHandle.CombineDependencies(job, _jobDependency); } return(_jobDependency); }
private JobHandle OnPerformCulling( BatchRendererGroup rendererGroup, BatchCullingContext cullingContext) { var planes = FrustumPlanes.BuildSOAPlanePackets(cullingContext.cullingPlanes, Allocator.TempJob); var lodParams = LODGroupExtensions.CalculateLODParams(cullingContext.lodParameters); var cull = new MyCullJob() { Planes = planes, LODParams = lodParams, IndexList = cullingContext.visibleIndices, Batches = cullingContext.batchVisibility, CullDatas = cullData, }; var handle = cull.Schedule(100, 32, cullingDependency); cullingDependency = JobHandle.CombineDependencies(handle, cullingDependency); return(handle); }
private JobHandle MyOnPerformCulling(BatchRendererGroup renderergroup, BatchCullingContext cullingContext) { var planes = OtherUtils.BuildSOAPlanePackets(cullingContext.cullingPlanes, Allocator.TempJob); var lodParams = OtherUtils.CalculateLODParams(cullingContext.lodParameters); //传入visibleIndices和batchVisibility 在job里面修改 var cull = new MyCullJob() { planes = planes, lodParams = lodParams, indexList = cullingContext.visibleIndices, batches = cullingContext.batchVisibility, cullDatas = cullData, }; //50组lod0 + 50组lod1 = 100 // cullingDependency 形成队列关系 var handle = cull.Schedule(100, 32, cullingDependency); cullingDependency = JobHandle.CombineDependencies(handle, cullingDependency); return(handle); }
private JobHandle OnPerformCulling(BatchRendererGroup rendererGroup, BatchCullingContext cullingContext) { var planes = new NativeArray <float4>(cullingContext.cullingPlanes.Length, Allocator.TempJob); for (int i = 0; i < cullingContext.cullingPlanes.Length; ++i) { var p = cullingContext.cullingPlanes[i]; planes[i] = new float4(p.normal, p.distance); } var cull = new MTDetailCullJob() { Planes = planes, CamerPos = cullingContext.lodParameters.cameraPosition, IndexList = cullingContext.visibleIndices, Batches = cullingContext.batchVisibility, CullDataOffset = cullDataOffset, CullDatas = cullData, }; var handle = cull.Schedule(cullingContext.batchVisibility.Length, 16, cullingDependency); cullingDependency = JobHandle.CombineDependencies(handle, cullingDependency); return(handle); }
public JobHandle OnPerformCulling(BatchRendererGroup rendererGroup, BatchCullingContext cullingContext, BatchCullingOutput cullingOutput, IntPtr userContext) { if (!m_initialized) { return(new JobHandle()); } #if ENABLE_PICKING bool isPickingCulling = cullingContext.viewType == BatchCullingViewType.Picking; #endif var splitCounts = new NativeArray <int>(cullingContext.cullingSplits.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); for (int i = 0; i < splitCounts.Length; ++i) { var split = cullingContext.cullingSplits[i]; splitCounts[i] = split.cullingPlaneCount; } var planes = FrustumPlanes.BuildSOAPlanePacketsMulti(cullingContext.cullingPlanes, splitCounts, Allocator.TempJob); BatchCullingOutputDrawCommands drawCommands = new BatchCullingOutputDrawCommands(); drawCommands.drawRanges = Malloc <BatchDrawRange>(m_drawRanges.Length); drawCommands.drawCommands = Malloc <BatchDrawCommand>(m_drawBatches.Length * splitCounts.Length * 10); // TODO: Multiplying the DrawCommand count by splitCount*10 is NOT an conservative upper bound. But in practice is enough. Sorting would give us a real conservative bound... drawCommands.visibleInstances = Malloc <int>(m_instanceIndices.Length); #if ENABLE_PICKING drawCommands.drawCommandPickingInstanceIDs = isPickingCulling ? Malloc <int>(m_drawBatches.Length) : null; #endif // Zero init: Culling job sets the values! drawCommands.drawRangeCount = 0; drawCommands.drawCommandCount = 0; drawCommands.visibleInstanceCount = 0; drawCommands.instanceSortingPositions = null; drawCommands.instanceSortingPositionFloatCount = 0; cullingOutput.drawCommands[0] = drawCommands; var visibilityLength = (m_renderers.Length + 7) / 8; var rendererVisibility = new NativeArray <ulong>(visibilityLength, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var cullingJob = new CullingJob { planes = planes, splitCounts = splitCounts, renderers = m_renderers, rendererVisibility = rendererVisibility }; var drawOutputJob = new DrawCommandOutputJob { batchID = m_batchID, rendererVisibility = rendererVisibility, instanceIndices = m_instanceIndices, drawBatches = m_drawBatches, drawRanges = m_drawRanges, drawIndices = m_drawIndices, drawCommands = cullingOutput.drawCommands }; var jobHandleCulling = cullingJob.Schedule(visibilityLength, 8); var jobHandleOutput = drawOutputJob.Schedule(jobHandleCulling); return(jobHandleOutput); }
public JobHandle OnPerformCulling(BatchRendererGroup rendererGroup, BatchCullingContext cullingContext, BatchCullingOutput cullingOutput, IntPtr userContext) { if (!m_initialized) { return(new JobHandle()); } BatchCullingOutputDrawCommands drawCommands = new BatchCullingOutputDrawCommands(); drawCommands.drawRangeCount = 1; drawCommands.drawRanges = Malloc <BatchDrawRange>(1); drawCommands.drawRanges[0] = new BatchDrawRange { drawCommandsBegin = 0, drawCommandsCount = 1, filterSettings = new BatchFilterSettings { renderingLayerMask = 1, layer = 0, motionMode = m_motionVectorTest ? MotionVectorGenerationMode.Object : MotionVectorGenerationMode.Camera, shadowCastingMode = ShadowCastingMode.On, receiveShadows = true, staticShadowCaster = false, allDepthSorted = false } }; drawCommands.visibleInstances = Malloc <int>(m_itemCount); int n = 0; int radius = (itemGridSize / 2) * (itemGridSize / 2); // (grid/2)^2 int radiusO = (radius * 90) / 100; int radiusI = (radiusO * 85) / 100; for (int r = 0; r < itemGridSize; r++) { for (int i = 0; i < itemGridSize; i++) { bool visible = true; if (m_cullTest) { int dist = (r - itemGridSize / 2) * (r - itemGridSize / 2) + (i - itemGridSize / 2) * (i - itemGridSize / 2); if ((dist >= radiusI) && (dist <= radiusO)) { visible = false; } } if (visible) { drawCommands.visibleInstances[n++] = r * itemGridSize + i; } } } drawCommands.visibleInstanceCount = n; drawCommands.drawCommandCount = 1; drawCommands.drawCommands = Malloc <BatchDrawCommand>(1); drawCommands.drawCommands[0] = new BatchDrawCommand { visibleOffset = 0, visibleCount = (uint)n, batchID = m_batchID, materialID = m_materialID, meshID = m_meshID, submeshIndex = 0, splitVisibilityMask = 0xff, flags = m_motionVectorTest ? BatchDrawCommandFlags.HasMotion : BatchDrawCommandFlags.None, sortingPosition = 0 }; drawCommands.instanceSortingPositions = null; drawCommands.instanceSortingPositionFloatCount = 0; cullingOutput.drawCommands[0] = drawCommands; return(new JobHandle()); }
// The callback method called by Unity whenever it visibility culls to determine which // objects to draw. This method will output draw commands that describe to Unity what // should be drawn for this BatchRendererGroup. public unsafe JobHandle OnPerformCulling( BatchRendererGroup rendererGroup, BatchCullingContext cullingContext, BatchCullingOutput cullingOutput, IntPtr userContext) { // UnsafeUtility.Malloc() requires an alignment, so use the largest integer type's alignment // which is a reasonable default. int alignment = UnsafeUtility.AlignOf <long>(); // Acquire a pointer to the BatchCullingOutputDrawCommands struct so we can easily // modify it directly. var drawCommands = (BatchCullingOutputDrawCommands *)cullingOutput.drawCommands.GetUnsafePtr(); // Allocate memory for the output arrays. In a more complicated implementation the amount of memory // allocated could be dynamically calculated based on what we determined to be visible. // In this example, we will just assume that all of our instances are visible and allocate // memory for each of them. We need the following allocations: // - a single draw command (which draws kNumInstances instances) // - a single draw range (which covers our single draw command) // - kNumInstances visible instance indices. // The arrays must always be allocated using Allocator.TempJob. drawCommands->drawCommands = (BatchDrawCommand *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <BatchDrawCommand>(), alignment, Allocator.TempJob); drawCommands->drawRanges = (BatchDrawRange *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <BatchDrawRange>(), alignment, Allocator.TempJob); drawCommands->visibleInstances = (int *)UnsafeUtility.Malloc(kNumInstances * sizeof(int), alignment, Allocator.TempJob); drawCommands->drawCommandCount = 1; drawCommands->drawRangeCount = 1; drawCommands->visibleInstanceCount = kNumInstances; // Our example does not use depth sorting, so we can leave the instanceSortingPositions as null. drawCommands->instanceSortingPositions = null; drawCommands->instanceSortingPositionFloatCount = 0; // Configure our single draw command to draw kNumInstances instances // starting from offset 0 in the array, using the batch, material and mesh // IDs that we registered in the Start() method. No special flags are set. drawCommands->drawCommands[0].visibleOffset = 0; drawCommands->drawCommands[0].visibleCount = kNumInstances; drawCommands->drawCommands[0].batchID = m_BatchID; drawCommands->drawCommands[0].materialID = m_MaterialID; drawCommands->drawCommands[0].meshID = m_MeshID; drawCommands->drawCommands[0].submeshIndex = 0; drawCommands->drawCommands[0].flags = 0; drawCommands->drawCommands[0].sortingPosition = 0; // Configure our single draw range to cover our single draw command which // is at offset 0. drawCommands->drawRanges[0].drawCommandsBegin = 0; drawCommands->drawRanges[0].drawCommandsCount = 1; // In this example we don't care about shadows or motion vectors, so we leave everything // to the default zero values, except the renderingLayerMask which we have to set to all ones // so the instances will be drawn regardless of mask settings when rendering. drawCommands->drawRanges[0].filterSettings = new BatchFilterSettings { renderingLayerMask = 0xffffffff, }; // Finally, write the actual visible instance indices to their array. In a more complicated // implementation, this output would depend on what we determined to be visible, but in this example // we will just assume that everything is visible. for (int i = 0; i < kNumInstances; ++i) { drawCommands->visibleInstances[i] = i; } // This simple example does not use jobs, so we can just return an empty JobHandle. // Performance sensitive applications are encouraged to use Burst jobs to implement // culling and draw command output, in which case we would return a handle here that // completes when those jobs have finished. return(new JobHandle()); }
/// <summary> /// This is the culling callback. The batch renderer calls this once and you need schedule your culling jobs here. /// The culling context contains an array of visible indices of the total size of all batches. Each batch has an /// offset into that array in the batch visibility struct. To perform the culling, write the number of visible /// objects per batch back into that batch's batch visibility struct and write the indices of all visible objects /// into the array of visible indices. The indices must be the indices of the objects in the batch. /// </summary> JobHandle PerformCulling(BatchRendererGroup renderergroup, BatchCullingContext cullingcontext) { if (m_UseSimdCulling) { // kick-off your SIMD jobs here! return(default);
public JobHandle Cull(EntityManager entityManager, NativeArray <int> InternalToExternalIds, BatchCullingContext cullingContext, JobHandle cullingJobDependency) #endif { var occlusionSettings = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem <OcclusionSettingsSystem>(); if (!occlusionSettings.OcclusionEnabled) { return(new JobHandle()); } var occlusionMeshes = new NativeList <OcclusionMesh>(Allocator.TempJob); var proxyOcclusionMeshTransformJob = new ProxyOcclusionMeshTransformJob { OcclusionMeshComponent = entityManager.GetComponentTypeHandle <OcclusionMesh>(false), LocalToWorldComponent = entityManager.GetComponentTypeHandle <LocalToWorld>(true), OcclusionMeshes = occlusionMeshes, ViewProjection = cullingContext.cullingMatrix, }; //ScheduleSingle is required because we populate a list var proxyOcclusionMeshTransformJobHandle = proxyOcclusionMeshTransformJob.ScheduleSingle(m_ProxyOccluderGroup, cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(proxyOcclusionMeshTransformJobHandle, cullingJobDependency); var occlusionMeshTransformJob = new OcclusionMeshTransformJob { InternalToExternalRemappingTable = InternalToExternalIds, HybridChunkInfo = entityManager.GetComponentTypeHandle <HybridChunkInfo>(true), OcclusionMeshComponent = entityManager.GetComponentTypeHandle <OcclusionMesh>(false), LocalToWorldComponent = entityManager.GetComponentTypeHandle <LocalToWorld>(true), IndexList = cullingContext.visibleIndices, Batches = cullingContext.batchVisibility, OcclusionMeshes = occlusionMeshes, ViewProjection = cullingContext.cullingMatrix, #if UNITY_EDITOR Stats = cullingStats, #endif }; //ScheduleSingle is required because we populate a list var occlusionTransformJobHandle = occlusionMeshTransformJob.ScheduleSingle(m_OccluderGroup, proxyOcclusionMeshTransformJobHandle); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, occlusionTransformJobHandle); var occlusionComputeBoundsJob = new OcclusionComputeBoundsJob { ViewProjection = cullingContext.cullingMatrix, BoundsComponent = entityManager.GetComponentTypeHandle <RenderBounds>(true), LocalToWorld = entityManager.GetComponentTypeHandle <LocalToWorld>(true), OcclusionTest = entityManager.GetComponentTypeHandle <OcclusionTest>(false), }; var occlusionComputeBoundsJobHandle = occlusionComputeBoundsJob.Schedule(m_OcclusionTestTransformGroup, occlusionTransformJobHandle); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, occlusionComputeBoundsJobHandle); var occlusionMeshArray = occlusionMeshes.AsDeferredJobArray(); var occlusionSortJob = new OcclusionSortMeshesJob { Meshes = occlusionMeshArray, }; var occlusionSortJobHandle = occlusionSortJob.Schedule(occlusionComputeBoundsJobHandle); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, occlusionSortJobHandle); if (occlusionSettings.MocOcclusionMode == OcclusionSettingsSystem.MOCOcclusionMode.Intrinsic) { var mocSetResolutionJob = new MOCSetResolutionJob { mocBurstIntrinsicPtrArray = m_BurstIntrinsicsArray, wantedDepthWidth = m_MOCDepthSize, wantedDepthHeight = m_MOCDepthSize, wantedNearClipValue = cullingContext.nearPlane, //TODO: use when we handle correctly the debug view with multiple call to OnPerformCulling }; var mocSetResolutionJobHandle = mocSetResolutionJob.Schedule(cullingJobDependency); // mocSetResolutionJob.Schedule(m_BurstIntrinsicsArray.Length, 1, cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, mocSetResolutionJobHandle); var mocClearJob = new MOCClearJob { mocBurstIntrinsicPtrArray = m_BurstIntrinsicsArray, }; var mocClearJobHandle = mocClearJob.Schedule(m_BurstIntrinsicsArray.Length, 1, cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, mocClearJobHandle); var mocRasterizejob = new MOCRasterizeJob { mocBurstIntrinsicPtrArray = m_BurstIntrinsicsArray, Meshes = occlusionMeshArray, }; var mocRasterizeJobHandle = occlusionSettings.OcclusionParallelEnabled ? mocRasterizejob.Schedule(m_BurstIntrinsicsArray.Length, 1, cullingJobDependency) : mocRasterizejob.Schedule(cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, mocRasterizeJobHandle); //The amount of jobs to run should be based on our tilesWidth or height, but the MOCSetResolutionJob might modify our buffer size and we don't want to force a sync point int totalMergeJob = 10; var mocMergeJob = new MOCMergeJob { mocBurstIntrinsicPtrArray = m_BurstIntrinsicsArray, indexMergingTo = 0, totalJobCount = totalMergeJob, }; var mocMergeJobHandle = occlusionSettings.OcclusionParallelEnabled ? mocMergeJob.Schedule(totalMergeJob, 1, cullingJobDependency) : mocMergeJob.Schedule(cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, mocMergeJobHandle); var mocTestJob = new MOCTestJob() { mocBurstIntrinsicPtrArray = m_BurstIntrinsicsArray, burstIntrinsicIndexToUse = 0, OcclusionTest = entityManager.GetComponentTypeHandle <OcclusionTest>(true), HybridChunkInfo = entityManager.GetComponentTypeHandle <HybridChunkInfo>(true), IndexList = cullingContext.visibleIndices, Batches = cullingContext.batchVisibility, InternalToExternalRemappingTable = InternalToExternalIds, #if UNITY_EDITOR displayOccluded = occlusionSettings.DisplayOccluded, Stats = cullingStats, #endif }; var mocTestJobHandle = mocTestJob.Schedule(m_OcclusionTestGroup, cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, mocTestJobHandle); } #if UNITY_MOC_NATIVE_AVAILABLE else if (occlusionSettings.MocOcclusionMode == OcclusionSettingsSystem.MOCOcclusionMode.Native) { var mocSetResolutionJob = new MOCNativeSetResolutionJob { mocNativeArray = m_MocNativeArray, wantedDepthWidth = m_MOCDepthSize, wantedDepthHeight = m_MOCDepthSize, wantedNearClipValue = cullingContext.nearPlane, //TODO: use cullingContext.nearPlane when we handle correctly the debug view with multiple call to OnPerformCulling }; var mocSetResolutionJobHandle = mocSetResolutionJob.Schedule(m_BurstIntrinsicsArray.Length, 1, cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, mocSetResolutionJobHandle); var mocClearJob = new MOCNativeClearJob { mocNativeArray = m_MocNativeArray, }; var mocClearJobHandle = mocClearJob.Schedule(m_MocNativeArray.Length, 1, cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, mocClearJobHandle); //mocClearJobHandle.Complete(); var mocRasterizejob = new MOCNativeRasterizeJob { mocNativeArray = m_MocNativeArray, Meshes = occlusionMeshArray, }; var mocRasterizeJobHandle = occlusionSettings.OcclusionParallelEnabled ? mocRasterizejob.Schedule(m_MocNativeArray.Length, 1, cullingJobDependency) : mocRasterizejob.Schedule(cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, mocRasterizeJobHandle); //The amount of jobs to run should be based on our tilesWidth or height, but the MOCSetResolutionJob might modify our buffer size and we don't want to force a sync point int totalMergeJob = 10; var mocMergeJob = new MOCNativeMergeJob { mocNativePtrArray = m_MocNativeArray, indexMergingTo = 0, totalJobCount = totalMergeJob, }; var mocMergeJobHandle = occlusionSettings.OcclusionParallelEnabled ? mocMergeJob.Schedule(totalMergeJob, 1, cullingJobDependency) : mocMergeJob.Schedule(cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, mocMergeJobHandle); var mocTestJob = new MOCNativeTestJob() { mocNativePtrArray = m_MocNativeArray, mocNativeIndexToUse = 0, InternalToExternalRemappingTable = InternalToExternalIds, OcclusionTest = entityManager.GetComponentTypeHandle <OcclusionTest>(true), HybridChunkInfo = entityManager.GetComponentTypeHandle <HybridChunkInfo>(true), IndexList = cullingContext.visibleIndices, Batches = cullingContext.batchVisibility, #if UNITY_EDITOR displayOccluded = occlusionSettings.DisplayOccluded, Stats = cullingStats, #endif }; var mocTestJobHandle = mocTestJob.Schedule(m_OcclusionTestGroup, cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, mocTestJobHandle); } #endif var occlusionCompactBatchesJob = new OcclusionCompactBatchesJob { IndexList = cullingContext.visibleIndices, Batches = cullingContext.batchVisibility }; var occlusionCompactBatchesJobHandle = occlusionCompactBatchesJob.Schedule(cullingJobDependency); cullingJobDependency = JobHandle.CombineDependencies(cullingJobDependency, occlusionCompactBatchesJobHandle); occlusionMeshes.Dispose(cullingJobDependency); //We give a pointer to first depth buffer to the debugSystem, by the time it use it all the depth buffers would have been merged into the first one var debugSystem = World.DefaultGameObjectInjectionWorld.GetOrCreateSystem <OcclusionDebugRenderSystem>(); #if UNITY_MOC_NATIVE_AVAILABLE debugSystem.RenderMOCInstances(m_MocNativeArray, m_BurstIntrinsicsArray, occlusionSettings.MocOcclusionMode, cullingJobDependency); #else debugSystem.RenderMOCInstances(m_BurstIntrinsicsArray, occlusionSettings.MocOcclusionMode, cullingJobDependency); #endif return(cullingJobDependency); }
public JobHandle Cull(EntityManager entityManager, NativeArray <int> InternalToExternalIds, BatchCullingContext cullingContext, JobHandle cullingJobDependency, CullingStats *cullingStats)