Minor PVS stuff (#4573)

Co-authored-by: ElectroJr <leonsfriedrich@gmail.com>
This commit is contained in:
metalgearsloth
2023-11-22 21:54:07 +11:00
committed by GitHub
parent b459d2ce21
commit f69440b3f2
2 changed files with 51 additions and 26 deletions

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
@@ -271,6 +272,7 @@ internal sealed partial class PvsSystem : EntitySystem
{
sessionData.LastSeenAt.Remove(metadata.NetEntity);
sessionData.LastLeftView.Remove(metadata.NetEntity);
if (sessionData.SentEntities.TryGetValue(previousTick, out var ents))
ents.Remove(metadata.NetEntity);
}
@@ -433,10 +435,15 @@ internal sealed partial class PvsSystem : EntitySystem
#endregion
public (List<(int, IChunkIndexLocation)> , HashSet<int>[], EntityUid[][] viewers) GetChunks(ICommonSession[] sessions)
public List<(int, IChunkIndexLocation)> GetChunks(
ICommonSession[] sessions,
ref HashSet<int>[] playerChunks,
ref EntityUid[][] viewerEntities)
{
var playerChunks = new HashSet<int>[sessions.Length];
var viewerEntities = new EntityUid[sessions.Length][];
// Pass these in to avoid allocating new ones every tick, 99% of the time sessions length is going to be the same size.
// These values will get overridden here and the old values have already been returned to the pool by this point.
Array.Resize(ref playerChunks, sessions.Length);
Array.Resize(ref viewerEntities, sessions.Length);
_chunkList.Clear();
// Keep track of the index of each chunk we use for a faster index lookup.
@@ -459,8 +466,8 @@ internal sealed partial class PvsSystem : EntitySystem
var session = sessions[i];
playerChunks[i] = _playerChunkPool.Get();
var viewers = GetSessionViewers(session);
viewerEntities[i] = viewers;
ref var viewers = ref viewerEntities[i];
GetSessionViewers(session, ref viewers);
for (var j = 0; j < viewers.Length; j++)
{
@@ -552,7 +559,7 @@ internal sealed partial class PvsSystem : EntitySystem
}
}
return (_chunkList, playerChunks, viewerEntities);
return _chunkList;
}
public void RegisterNewPreviousChunkTrees(
@@ -569,23 +576,20 @@ internal sealed partial class PvsSystem : EntitySystem
_reusedTrees.Add(chunks[i]);
}
var previousIndices = _previousTrees.Keys.ToArray();
for (var i = 0; i < previousIndices.Length; i++)
foreach (var (index, chunk) in _previousTrees)
{
var index = previousIndices[i];
// ReSharper disable once InconsistentlySynchronizedField
if (_reusedTrees.Contains(index)) continue;
var chunk = _previousTrees[index];
if (chunk.HasValue)
if (_reusedTrees.Contains(index))
continue;
if (chunk != null)
{
_chunkCachePool.Return(chunk.Value.metadata);
_treePool.Return(chunk.Value.tree);
}
if (!chunks.Contains(index))
{
_previousTrees.Remove(index);
}
}
_previousTrees.EnsureCapacity(chunks.Count);
@@ -1313,26 +1317,44 @@ Transform last modified: {Transform(uid).LastModifiedTick}");
return entState;
}
private EntityUid[] GetSessionViewers(ICommonSession session)
private void GetSessionViewers(ICommonSession session, [NotNull] ref EntityUid[]? viewers)
{
if (session.Status != SessionStatus.InGame)
return Array.Empty<EntityUid>();
{
viewers = Array.Empty<EntityUid>();
return;
}
// Fast path
if (session.ViewSubscriptions.Count == 0)
{
if (session.AttachedEntity == null)
return Array.Empty<EntityUid>();
{
viewers = Array.Empty<EntityUid>();
return;
}
return new[] { session.AttachedEntity.Value };
Array.Resize(ref viewers, 1);
viewers[0] = session.AttachedEntity.Value;
return;
}
var viewers = new HashSet<EntityUid>();
if (session.AttachedEntity != null)
viewers.Add(session.AttachedEntity.Value);
int i = 0;
if (session.AttachedEntity is { } local)
{
DebugTools.Assert(!session.ViewSubscriptions.Contains(local));
Array.Resize(ref viewers, session.ViewSubscriptions.Count + 1);
viewers[i++] = local;
}
else
{
Array.Resize(ref viewers, session.ViewSubscriptions.Count);
}
viewers.UnionWith(session.ViewSubscriptions);
return viewers.ToArray();
foreach (var ent in session.ViewSubscriptions)
{
viewers[i++] = ent;
}
}
// Read Safe

View File

@@ -37,6 +37,9 @@ namespace Robust.Server.GameStates
// Mapping of net UID of clients -> last known acked state.
private GameTick _lastOldestAck = GameTick.Zero;
private HashSet<int>[] _playerChunks = Array.Empty<HashSet<int>>();
private EntityUid[][] _viewerEntities = Array.Empty<EntityUid[]>();
private PvsSystem _pvs = default!;
[Dependency] private readonly EntityManager _entityManager = default!;
@@ -267,7 +270,7 @@ Oldest acked clients: {string.Join(", ", players)}
private PvsData? GetPVSData(ICommonSession[] players)
{
var (chunks, playerChunks, viewerEntities) = _pvs.GetChunks(players);
var chunks= _pvs.GetChunks(players, ref _playerChunks, ref _viewerEntities);
const int ChunkBatchSize = 2;
var chunksCount = chunks.Count;
var chunkBatches = (int)MathF.Ceiling((float)chunksCount / ChunkBatchSize);
@@ -310,8 +313,8 @@ Oldest acked clients: {string.Join(", ", players)}
ArrayPool<bool>.Shared.Return(reuse);
return new PvsData()
{
PlayerChunks = playerChunks,
ViewerEntities = viewerEntities,
PlayerChunks = _playerChunks,
ViewerEntities = _viewerEntities,
ChunkCache = chunkCache,
};
}