Remove byte[] allocations for GasTileOverlaySystem.UpdateChunkTile (#12617)

This commit is contained in:
DrSmugleaf
2022-11-16 08:27:49 +01:00
committed by GitHub
parent 0350f635d1
commit f92f288047
4 changed files with 62 additions and 47 deletions

View File

@@ -166,7 +166,7 @@ namespace Content.Client.Atmos.Overlays
while (enumerator.MoveNext(out var gas)) while (enumerator.MoveNext(out var gas))
{ {
if (gas.Value.Opacity == null) if (gas.Opacity == null!)
continue; continue;
var tilePosition = chunk.Origin + (enumerator.X, enumerator.Y); var tilePosition = chunk.Origin + (enumerator.X, enumerator.Y);
@@ -175,7 +175,7 @@ namespace Content.Client.Atmos.Overlays
for (var i = 0; i < _gasCount; i++) for (var i = 0; i < _gasCount; i++)
{ {
var opacity = gas.Value.Opacity[i]; var opacity = gas.Opacity[i];
if (opacity > 0) if (opacity > 0)
drawHandle.DrawTexture(_frames[i][_frameCounter[i]], tilePosition, Color.White.WithAlpha(opacity)); drawHandle.DrawTexture(_frames[i][_frameCounter[i]], tilePosition, Color.White.WithAlpha(opacity));
} }
@@ -190,14 +190,14 @@ namespace Content.Client.Atmos.Overlays
while (enumerator.MoveNext(out var gas)) while (enumerator.MoveNext(out var gas))
{ {
if (gas.Value.FireState == 0) if (gas.FireState == 0)
continue; continue;
var index = chunk.Origin + (enumerator.X, enumerator.Y); var index = chunk.Origin + (enumerator.X, enumerator.Y);
if (!localBounds.Contains(index)) if (!localBounds.Contains(index))
continue; continue;
var state = gas.Value.FireState - 1; var state = gas.FireState - 1;
var texture = _fireFrames[state][_fireFrameCounter[state]]; var texture = _fireFrames[state][_fireFrameCounter[state]];
drawHandle.DrawTexture(texture, index); drawHandle.DrawTexture(texture, index);
} }

View File

@@ -1,3 +1,6 @@
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Content.Server.Atmos.Components; using Content.Server.Atmos.Components;
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Atmos.EntitySystems; using Content.Shared.Atmos.EntitySystems;
@@ -14,10 +17,6 @@ using Robust.Shared.Map;
using Robust.Shared.Threading; using Robust.Shared.Threading;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using DependencyAttribute = Robust.Shared.IoC.DependencyAttribute;
// ReSharper disable once RedundantUsingDirective // ReSharper disable once RedundantUsingDirective
@@ -26,13 +25,13 @@ namespace Content.Server.Atmos.EntitySystems
[UsedImplicitly] [UsedImplicitly]
internal sealed class GasTileOverlaySystem : SharedGasTileOverlaySystem internal sealed class GasTileOverlaySystem : SharedGasTileOverlaySystem
{ {
[Dependency] private readonly IGameTiming _gameTiming = default!; [Robust.Shared.IoC.Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IPlayerManager _playerManager = default!; [Robust.Shared.IoC.Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!; [Robust.Shared.IoC.Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IConfigurationManager _confMan = default!; [Robust.Shared.IoC.Dependency] private readonly IConfigurationManager _confMan = default!;
[Dependency] private readonly IParallelManager _parMan = default!; [Robust.Shared.IoC.Dependency] private readonly IParallelManager _parMan = default!;
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Robust.Shared.IoC.Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly ChunkingSystem _chunkingSys = default!; [Robust.Shared.IoC.Dependency] private readonly ChunkingSystem _chunkingSys = default!;
private readonly Dictionary<IPlayerSession, Dictionary<EntityUid, HashSet<Vector2i>>> _lastSentChunks = new(); private readonly Dictionary<IPlayerSession, Dictionary<EntityUid, HashSet<Vector2i>>> _lastSentChunks = new();
@@ -120,40 +119,57 @@ namespace Content.Server.Atmos.EntitySystems
/// </summary> /// </summary>
private void UpdateChunkTile(GridAtmosphereComponent gridAtmosphere, GasOverlayChunk chunk, Vector2i index, GameTick curTick) private void UpdateChunkTile(GridAtmosphereComponent gridAtmosphere, GasOverlayChunk chunk, Vector2i index, GameTick curTick)
{ {
var oldData = chunk.GetData(index); ref var oldData = ref chunk.GetData(index);
if (!gridAtmosphere.Tiles.TryGetValue(index, out var tile)) if (!gridAtmosphere.Tiles.TryGetValue(index, out var tile))
{ {
if (oldData == null) if (oldData.Equals(default))
return; return;
chunk.LastUpdate = curTick; chunk.LastUpdate = curTick;
chunk.SetData(index, null); oldData = default;
return; return;
} }
var opacity = new byte[VisibleGasId.Length]; var changed = oldData.Equals(default) || oldData.FireState != tile.Hotspot.State;
GasOverlayData newData = new(tile!.Hotspot.State, opacity); if (oldData.Equals(default))
oldData = new GasOverlayData(tile.Hotspot.State, new byte[VisibleGasId.Length]);
if (tile.Air != null) if (tile.Air != null)
{ {
var i = 0; for (var i = 0; i < VisibleGasId.Length; i++)
foreach (var id in VisibleGasId)
{ {
var id = VisibleGasId[i];
var gas = _atmosphereSystem.GetGas(id); var gas = _atmosphereSystem.GetGas(id);
var moles = tile.Air.Moles[id]; var moles = tile.Air.Moles[id];
ref var oldOpacity = ref oldData.Opacity[i];
if (moles >= gas.GasMolesVisible) if (moles < gas.GasMolesVisible)
{ {
opacity[i] = (byte) (ContentHelpers.RoundToLevels( if (oldOpacity != 0)
MathHelper.Clamp01((moles - gas.GasMolesVisible) / (gas.GasMolesVisibleMax - gas.GasMolesVisible)) * 255, byte.MaxValue, _thresholds) * 255 / (_thresholds - 1)); {
oldOpacity = 0;
changed = true;
} }
i++;
continue;
}
var opacity = (byte) (ContentHelpers.RoundToLevels(
MathHelper.Clamp01((moles - gas.GasMolesVisible) /
(gas.GasMolesVisibleMax - gas.GasMolesVisible)) * 255, byte.MaxValue,
_thresholds) * 255 / (_thresholds - 1));
if (oldOpacity == opacity)
continue;
oldOpacity = opacity;
changed = true;
} }
} }
if (oldData != null && oldData.Value.Equals(newData)) if (!changed)
return; return;
chunk.SetData(index, newData);
chunk.LastUpdate = curTick; chunk.LastUpdate = curTick;
} }

View File

@@ -63,11 +63,17 @@ namespace Content.Shared.Atmos.EntitySystems
if (FireState != other.FireState) if (FireState != other.FireState)
return false; return false;
if (Opacity?.Length != other.Opacity?.Length)
return false;
if (Opacity != null && other.Opacity != null)
{
for (var i = 0; i < Opacity.Length; i++) for (var i = 0; i < Opacity.Length; i++)
{ {
if (Opacity[i] != other.Opacity[i]) if (Opacity[i] != other.Opacity[i])
return false; return false;
} }
}
return true; return true;
} }

View File

@@ -2,7 +2,6 @@ using Content.Shared.Atmos.EntitySystems;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Timing; using Robust.Shared.Timing;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using System.Diagnostics.CodeAnalysis;
using static Content.Shared.Atmos.EntitySystems.SharedGasTileOverlaySystem; using static Content.Shared.Atmos.EntitySystems.SharedGasTileOverlaySystem;
namespace Content.Shared.Atmos namespace Content.Shared.Atmos
@@ -17,7 +16,7 @@ namespace Content.Shared.Atmos
public readonly Vector2i Index; public readonly Vector2i Index;
public readonly Vector2i Origin; public readonly Vector2i Origin;
public GasOverlayData?[][] TileData = new GasOverlayData?[ChunkSize][]; public GasOverlayData[][] TileData = new GasOverlayData[ChunkSize][];
[NonSerialized] [NonSerialized]
public GameTick LastUpdate; public GameTick LastUpdate;
@@ -30,20 +29,14 @@ namespace Content.Shared.Atmos
// For whatever reason, net serialize does not like multi_D arrays. So Jagged it is. // For whatever reason, net serialize does not like multi_D arrays. So Jagged it is.
for (var i = 0; i < ChunkSize; i++) for (var i = 0; i < ChunkSize; i++)
{ {
TileData[i] = new GasOverlayData?[ChunkSize]; TileData[i] = new GasOverlayData[ChunkSize];
} }
} }
public GasOverlayData? GetData(Vector2i gridIndices) public ref GasOverlayData GetData(Vector2i gridIndices)
{ {
DebugTools.Assert(InBounds(gridIndices)); DebugTools.Assert(InBounds(gridIndices));
return TileData[gridIndices.X - Origin.X][gridIndices.Y - Origin.Y]; return ref TileData[gridIndices.X - Origin.X][gridIndices.Y - Origin.Y];
}
public GasOverlayData? SetData(Vector2i gridIndices, GasOverlayData? data)
{
DebugTools.Assert(InBounds(gridIndices));
return TileData[gridIndices.X - Origin.X][gridIndices.Y - Origin.Y] = data;
} }
private bool InBounds(Vector2i gridIndices) private bool InBounds(Vector2i gridIndices)
@@ -60,7 +53,7 @@ namespace Content.Shared.Atmos
private GasOverlayChunk _chunk; private GasOverlayChunk _chunk;
public int X = 0; public int X = 0;
public int Y = -1; public int Y = -1;
private GasOverlayData?[] _column; private GasOverlayData[] _column;
public GasChunkEnumerator(GasOverlayChunk chunk) public GasChunkEnumerator(GasOverlayChunk chunk)
@@ -69,7 +62,7 @@ namespace Content.Shared.Atmos
_column = _chunk.TileData[0]; _column = _chunk.TileData[0];
} }
public bool MoveNext([NotNullWhen(true)] out GasOverlayData? gas) public bool MoveNext(out GasOverlayData gas)
{ {
while (X < ChunkSize) while (X < ChunkSize)
{ {
@@ -80,7 +73,7 @@ namespace Content.Shared.Atmos
Y++; Y++;
gas = _column[Y]; gas = _column[Y];
if (gas != null) if (!gas.Equals(default))
return true; return true;
} }
@@ -90,7 +83,7 @@ namespace Content.Shared.Atmos
Y = -1; Y = -1;
} }
gas = null; gas = default;
return false; return false;
} }
} }