public override void Close() { base.Close(); m_workTracker.CancelAll(); if (RunningBatchTask != null) { RunningBatchTask.Cancel(); RunningBatchTask = null; } if (ENABLE_AABB_PHANTOM) { m_aabbPhantom.Dispose(); m_aabbPhantom = null; } }
public override void UpdateBeforeSimulation() { if (m_highPriorityJobs.Count > 0) { // no upper bound on these, as there should be just a few high priority jobs for (int i = 0; i < Parallel.Scheduler.ThreadCount; ++i) { var work = m_workPool.Allocate(); work.Queue = m_highPriorityJobs; work.Priority = WorkPriority.Low; work.MaxPrecalcTime = (long)MyFakes.MAX_PRECALC_TIME_IN_MILLIS; Parallel.Start(work, work.CompletionCallback); } } if (m_lowPriorityJobs.Count > 0 && m_worksInUse < 2 * Parallel.Scheduler.ThreadCount) { for (int i = 0; i < Parallel.Scheduler.ThreadCount; ++i) { var work = m_workPool.Allocate(); work.Queue = m_lowPriorityJobs; work.Priority = WorkPriority.VeryLow; work.MaxPrecalcTime = (long)MyFakes.MAX_PRECALC_TIME_IN_MILLIS; ++m_worksInUse; Parallel.Start(work, work.CompletionCallback); } } foreach (var physics in PhysicsWithInvalidCells) { MyPrecalcJobPhysicsBatch.Start(physics, ref physics.InvalidCells); } PhysicsWithInvalidCells.Clear(); Stats.Generic.Write("Precalc jobs in queue (low)", m_lowPriorityJobs.Count, VRage.Stats.MyStatTypeEnum.CurrentValue, 100, 0); Stats.Generic.Write("Precalc jobs in queue (high)", m_highPriorityJobs.Count, VRage.Stats.MyStatTypeEnum.CurrentValue, 100, 0); if (!MySandboxGame.IsGameReady) { var work = m_workPool.Allocate(); work.Queue = m_lowPriorityJobs; work.MaxPrecalcTime = (long)MyFakes.MAX_PRECALC_TIME_IN_MILLIS; (work as IWork).DoWork(); work.CompletionCallback(); } base.UpdateAfterSimulation(); }
public override void Close() { base.Close(); m_workTracker.CancelAll(); if (RunningBatchTask != null) { RunningBatchTask.Cancel(); RunningBatchTask = null; } if (ENABLE_AABB_PHANTOM && m_aabbPhantom != null) { m_aabbPhantom.Dispose(); m_aabbPhantom = null; } }
public override void UpdateBeforeSimulation() { m_sortedJobs.Lock(); m_sortedJobs.List.AddList(m_addedJobs); m_sortedJobs.Unlock(); m_addedJobs.Clear(); m_counter++; if (m_counter % 30 == 0) { SortJobs(); //m_sortedJobs.Sort(m_comparer); } if (MyDebugDrawSettings.DEBUG_DRAW_SORTED_JOBS) { try { const float max = 255; float shade = m_sortedJobs.Count > 0 ? m_sortedJobs.ListUnsafe.ItemAt((int)Math.Min(m_sortedJobs.ListUnsafe.Count - 1, max)).Priority : 1; float minPriority = m_sortedJobs.Count > 0 ? m_sortedJobs.ListUnsafe.ItemAt(0).Priority : 1; shade -= minPriority; for (int xi = 0; xi < max; xi++) { if (xi + 5 > m_sortedJobs.Count) { break; } var job = m_sortedJobs.ListUnsafe.ItemAt(xi); var p = job.Priority - minPriority; job.DebugDraw(new Color((shade - p) / shade, 0.0f, p / shade, (max - xi) / max)); } } catch (Exception e) { } } if (m_sortedJobs.Count > 0) { while (m_workPool.Count > 0) { var work = m_workPool.Allocate(); work.Queue = m_sortedJobs; work.Priority = WorkPriority.Low; work.MaxPrecalcTime = (long)MyFakes.MAX_PRECALC_TIME_IN_MILLIS; if (MULTITHREADED) { Parallel.Start(work, work.CompletionCallback); } else { ((IWork)work).DoWork(); work.CompletionCallback(); } } } foreach (var physics in PhysicsWithInvalidCells) { for (int lod = 0; lod < physics.InvalidCells.Length; lod++) { if (physics.InvalidCells[lod].Count > 0 && physics.RunningBatchTask[lod] == null) { MyPrecalcJobPhysicsBatch.Start(physics, ref physics.InvalidCells[lod], lod); } } } PhysicsWithInvalidCells.Clear(); Stats.Generic.Write("Precalc jobs in sorted", m_sortedJobs.Count, VRage.Stats.MyStatTypeEnum.CurrentValue, 100, 0); Stats.Generic.Write("Clipmap triangle cache", MyClipmap.CellsCache.Usage, VRage.Stats.MyStatTypeEnum.CurrentValue, 100, 2); base.UpdateAfterSimulation(); }
/// <param name="minVoxelChanged">Inclusive min.</param> /// <param name="maxVoxelChanged">Inclusive max.</param> internal void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged) { MyPrecalcComponent.AssertUpdateThread(); ProfilerShort.Begin("MyVoxelPhysicsBody.InvalidateRange"); minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate; maxVoxelChanged += MyPrecalcComponent.InvalidatedRangeInflate; m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged); m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged); Vector3I minCellChanged, maxCellChanged; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCellChanged); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCellChanged); Vector3I minCellChangedVoxelMap, maxCellChangedVoxelMap; minCellChangedVoxelMap = minCellChanged - m_cellsOffset; maxCellChangedVoxelMap = maxCellChanged - m_cellsOffset; Debug.Assert(RigidBody != null, "RigidBody in voxel physics is null! This must not happen."); if (RigidBody != null) { var shape = (HkUniformGridShape)RigidBody.GetShape(); var tmpBuffer = m_cellsToGenerateBuffer; int invalidCount = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer); if (invalidCount > tmpBuffer.Length) { // Not storing this new buffer in static variable since this is just temporary and potentially large. // Static variable could be potentially the same as leak. tmpBuffer = new Vector3I[invalidCount]; int invalidCount2 = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer); Debug.Assert(invalidCount == invalidCount2); invalidCount = invalidCount2; } Debug.Assert(invalidCount <= tmpBuffer.Length); for (int i = 0; i < invalidCount; i++) { InvalidCells.Add(tmpBuffer[i]); } if (RunningBatchTask != null) { RunningBatchTask.Cancel(); foreach (var oldInvalidCell in RunningBatchTask.CellBatch) { InvalidCells.Add(oldInvalidCell); } RunningBatchTask = null; } if (InvalidCells.Count != 0) MyPrecalcComponent.PhysicsWithInvalidCells.Add(this); } var cell = minCellChanged; for (var it = new Vector3I.RangeIterator(ref minCellChanged, ref maxCellChanged); it.IsValid(); it.GetNext(out cell)) { m_workTracker.Cancel(cell); } m_needsShapeUpdate = true; ProfilerShort.End(); }
/// <param name="minVoxelChanged">Inclusive min.</param> /// <param name="maxVoxelChanged">Inclusive max.</param> internal void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged) { MyPrecalcComponent.AssertUpdateThread(); ProfilerShort.Begin("MyVoxelPhysicsBody.InvalidateRange"); minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate; maxVoxelChanged += MyPrecalcComponent.InvalidatedRangeInflate; m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged); m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged); Vector3I minCellChanged, maxCellChanged; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCellChanged); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCellChanged); Vector3I minCellChangedVoxelMap, maxCellChangedVoxelMap; minCellChangedVoxelMap = minCellChanged - m_cellsOffset; maxCellChangedVoxelMap = maxCellChanged - m_cellsOffset; Debug.Assert(RigidBody != null, "RigidBody in voxel physics is null! This must not happen."); if (RigidBody != null) { var shape = (HkUniformGridShape)RigidBody.GetShape(); var tmpBuffer = m_cellsToGenerateBuffer; int invalidCount = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer); if (invalidCount > tmpBuffer.Length) { // Not storing this new buffer in static variable since this is just temporary and potentially large. // Static variable could be potentially the same as leak. tmpBuffer = new Vector3I[invalidCount]; int invalidCount2 = shape.InvalidateRange(ref minCellChangedVoxelMap, ref maxCellChangedVoxelMap, tmpBuffer); Debug.Assert(invalidCount == invalidCount2); invalidCount = invalidCount2; } Debug.Assert(invalidCount <= tmpBuffer.Length); for (int i = 0; i < invalidCount; i++) { InvalidCells.Add(tmpBuffer[i]); } if (RunningBatchTask != null) { RunningBatchTask.Cancel(); foreach (var oldInvalidCell in RunningBatchTask.CellBatch) { InvalidCells.Add(oldInvalidCell); } RunningBatchTask = null; } if (InvalidCells.Count != 0) { MyPrecalcComponent.PhysicsWithInvalidCells.Add(this); } } var cell = minCellChanged; for (var it = new Vector3I.RangeIterator(ref minCellChanged, ref maxCellChanged); it.IsValid(); it.GetNext(out cell)) { m_workTracker.Cancel(cell); } m_needsShapeUpdate = true; ProfilerShort.End(); }
public override void UpdateBeforeSimulation() { m_sortedJobs.Lock(); m_sortedJobs.List.AddList(m_addedJobs); m_sortedJobs.Unlock(); m_addedJobs.Clear(); m_counter++; if (m_counter % 60 == 0) { SortJobs(); //m_sortedJobs.Sort(m_comparer); } if (MyDebugDrawSettings.DEBUG_DRAW_SORTED_JOBS) { try { const float max = 255; float shade = m_sortedJobs.Count > 0 ? m_sortedJobs.ListUnsafe.ItemAt((int)Math.Min(m_sortedJobs.ListUnsafe.Count - 1, max)).Priority : 1; float minPriority = m_sortedJobs.Count > 0 ? m_sortedJobs.ListUnsafe.ItemAt(0).Priority : 1; shade -= minPriority; for (int xi = 0; xi < max; xi++) { if (xi + 5 > m_sortedJobs.Count) { break; } var job = m_sortedJobs.ListUnsafe.ItemAt(xi); var p = job.Priority - minPriority; job.DebugDraw(new Color((shade - p) / shade, 0.0f, p / shade, (max - xi) / max)); } } catch (Exception e) { } } if (m_sortedJobs.Count > 0 && m_worksInUse < 2 * Parallel.Scheduler.ThreadCount) { // no upper bound on these, as there should be just a few high priority jobs for (int i = 0; i < Parallel.Scheduler.ThreadCount; ++i) { var work = m_workPool.Allocate(); work.Queue = m_sortedJobs; work.Priority = WorkPriority.Low; work.MaxPrecalcTime = (long)MyFakes.MAX_PRECALC_TIME_IN_MILLIS; ++m_worksInUse; if (MULTITHREADED) { Parallel.Start(work, work.CompletionCallback); } else { ((IWork)work).DoWork(); work.CompletionCallback(); } } } if (m_highPriorityJobs.Count > 0) { // no upper bound on these, as there should be just a few high priority jobs for (int i = 0; i < Parallel.Scheduler.ThreadCount; ++i) { var work = m_workPool.Allocate(); work.Queue = m_highPriorityJobs; work.Priority = WorkPriority.Low; work.MaxPrecalcTime = (long)MyFakes.MAX_PRECALC_TIME_IN_MILLIS; ++m_worksInUse; if (MULTITHREADED) { Parallel.Start(work, work.CompletionCallback); } else { ((IWork)work).DoWork(); work.CompletionCallback(); } } } if (m_lowPriorityJobs.Count > 0 && m_worksInUse < 2 * Parallel.Scheduler.ThreadCount) { for (int i = 0; i < Parallel.Scheduler.ThreadCount; ++i) { var work = m_workPool.Allocate(); work.Queue = m_lowPriorityJobs; work.Priority = WorkPriority.VeryLow; work.MaxPrecalcTime = (long)MyFakes.MAX_PRECALC_TIME_IN_MILLIS; ++m_worksInUse; if (MULTITHREADED) { Parallel.Start(work, work.CompletionCallback); } else { ((IWork)work).DoWork(); work.CompletionCallback(); } } } foreach (var physics in PhysicsWithInvalidCells) { MyPrecalcJobPhysicsBatch.Start(physics, ref physics.InvalidCells); } PhysicsWithInvalidCells.Clear(); Stats.Generic.Write("Precalc jobs in sorted", m_sortedJobs.Count, VRage.Stats.MyStatTypeEnum.CurrentValue, 100, 0); Stats.Generic.Write("Precalc jobs in queue (low)", m_lowPriorityJobs.Count, VRage.Stats.MyStatTypeEnum.CurrentValue, 100, 0); Stats.Generic.Write("Precalc jobs in queue (high)", m_highPriorityJobs.Count, VRage.Stats.MyStatTypeEnum.CurrentValue, 100, 0); if (!MySandboxGame.IsGameReady) { var work = m_workPool.Allocate(); work.Queue = m_lowPriorityJobs; work.MaxPrecalcTime = (long)MyFakes.MAX_PRECALC_TIME_IN_MILLIS; (work as IWork).DoWork(); work.CompletionCallback(); } base.UpdateAfterSimulation(); }