SIMD-accelerated gas mixtures. (SIMD atmos) (#2479)
* SIMD atmos * Moles will always be a multiple of four. * Component dependencies for grid atmos. * Let's optimize allocations while we're at it! * Inline this * A bunch of atmos optimizations * Fix crimes against atmos * Microsoft moment * Remove nuget.config * do not reference Robust.UnitTests in Content.Benchmarks as it's unneeded. * Revert "Remove nuget.config" This reverts commit 872604ae6a51365af4075bb23687bd005befd8ac. * Gas overlay optimization and fixes * Lattice is now spess * minor atmos tweaks
This commit is contained in:
committed by
GitHub
parent
89f72c4cb2
commit
b18ee3ec49
@@ -113,7 +113,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||
{
|
||||
var direction = (AtmosDirection) (1 << i);
|
||||
if (!myDirection.HasFlag(direction)) continue;
|
||||
if (!myDirection.IsFlagSet(direction)) continue;
|
||||
var angle = direction.ToAngle();
|
||||
angle += myAngle;
|
||||
newAirBlockedDirs |= angle.ToAtmosDirectionCardinal();
|
||||
|
||||
@@ -233,6 +233,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
private InternalsComponent? GetInternalsComponent(IEntity? owner = null)
|
||||
{
|
||||
if (Owner.Deleted) return null;
|
||||
if (owner != null) return owner.GetComponentOrNull<InternalsComponent>();
|
||||
return Owner.TryGetContainer(out var container)
|
||||
? container.Owner.GetComponentOrNull<InternalsComponent>()
|
||||
|
||||
@@ -14,6 +14,7 @@ using Content.Shared.Maps;
|
||||
using Robust.Server.GameObjects.EntitySystems.TileLookup;
|
||||
using Robust.Server.Interfaces.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.GameObjects.ComponentDependencies;
|
||||
using Robust.Shared.GameObjects.Components.Map;
|
||||
using Robust.Shared.GameObjects.Components.Transform;
|
||||
using Robust.Shared.GameObjects.Systems;
|
||||
@@ -65,6 +66,8 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
private Stopwatch _stopwatch = new Stopwatch();
|
||||
private GridId _gridId;
|
||||
|
||||
[ComponentDependency] private IMapGridComponent? _mapGridComponent = default!;
|
||||
|
||||
[ViewVariables]
|
||||
public int UpdateCounter { get; private set; } = 0;
|
||||
|
||||
@@ -217,7 +220,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
|
||||
protected virtual void Revalidate()
|
||||
{
|
||||
foreach (var indices in _invalidatedCoords.ToArray())
|
||||
foreach (var indices in _invalidatedCoords)
|
||||
{
|
||||
var tile = GetTile(indices);
|
||||
|
||||
@@ -259,7 +262,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
// TODO ATMOS: Query all the contents of this tile (like walls) and calculate the correct thermal conductivity
|
||||
tile.ThermalConductivity = tile.Tile?.Tile.GetContentTileDefinition().ThermalConductivity ?? 0.5f;
|
||||
tile.UpdateAdjacent();
|
||||
tile.UpdateVisuals();
|
||||
GasTileOverlaySystem.Invalidate(_gridId, indices);
|
||||
|
||||
for (var i = 0; i < Atmospherics.Directions; i++)
|
||||
{
|
||||
@@ -420,12 +423,18 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
/// <inheritdoc />
|
||||
public bool IsAirBlocked(Vector2i indices, AtmosDirection direction = AtmosDirection.All)
|
||||
{
|
||||
var directions = AtmosDirection.Invalid;
|
||||
|
||||
foreach (var obstructingComponent in GetObstructingComponents(indices))
|
||||
{
|
||||
if (!obstructingComponent.AirBlocked)
|
||||
continue;
|
||||
|
||||
if (obstructingComponent.AirBlockedDirection.HasFlag(direction))
|
||||
// We set the directions that are air-blocked so far,
|
||||
// as you could have a full obstruction with only 4 directional air blockers.
|
||||
directions |= obstructingComponent.AirBlockedDirection;
|
||||
|
||||
if (directions.IsFlagSet(direction))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -435,10 +444,9 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
/// <inheritdoc />
|
||||
public virtual bool IsSpace(Vector2i indices)
|
||||
{
|
||||
// TODO ATMOS use ContentTileDefinition to define in YAML whether or not a tile is considered space
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default;
|
||||
if (_mapGridComponent == null) return default;
|
||||
|
||||
return mapGrid.Grid.GetTileRef(indices).Tile.IsEmpty;
|
||||
return _mapGridComponent.Grid.GetTileRef(indices).IsSpace();
|
||||
}
|
||||
|
||||
public Dictionary<AtmosDirection, TileAtmosphere> GetAdjacentTiles(Vector2i indices, bool includeAirBlocked = false)
|
||||
@@ -461,9 +469,9 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
/// <inheritdoc />
|
||||
public float GetVolumeForCells(int cellCount)
|
||||
{
|
||||
if (!Owner.TryGetComponent(out IMapGridComponent? mapGrid)) return default;
|
||||
if (_mapGridComponent == null) return default;
|
||||
|
||||
return mapGrid.Grid.TileSize * cellCount * Atmospherics.CellVolume;
|
||||
return _mapGridComponent.Grid.TileSize * cellCount * Atmospherics.CellVolume;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -797,15 +805,11 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
{
|
||||
var gridLookup = EntitySystem.Get<GridTileLookupSystem>();
|
||||
|
||||
var list = new List<AirtightComponent>();
|
||||
|
||||
foreach (var v in gridLookup.GetEntitiesIntersecting(_gridId, indices))
|
||||
{
|
||||
if (v.TryGetComponent<AirtightComponent>(out var ac))
|
||||
list.Add(ac);
|
||||
yield return ac;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private bool NeedsVacuumFixing(Vector2i indices)
|
||||
@@ -841,8 +845,7 @@ namespace Content.Server.GameObjects.Components.Atmos
|
||||
public override void ExposeData(ObjectSerializer serializer)
|
||||
{
|
||||
base.ExposeData(serializer);
|
||||
if (serializer.Reading &&
|
||||
Owner.TryGetComponent(out IMapGridComponent? mapGrid))
|
||||
if (serializer.Reading && Owner.TryGetComponent(out IMapGridComponent? mapGrid))
|
||||
{
|
||||
var gridId = mapGrid.Grid.Index;
|
||||
|
||||
|
||||
@@ -243,6 +243,7 @@ namespace Content.Server.GameObjects.Components.Medical
|
||||
public void EjectBody()
|
||||
{
|
||||
var containedEntity = _bodyContainer.ContainedEntity;
|
||||
if (containedEntity == null) return;
|
||||
_bodyContainer.Remove(containedEntity);
|
||||
containedEntity.Transform.WorldPosition += _ejectOffset;
|
||||
UpdateUserInterface();
|
||||
|
||||
@@ -156,21 +156,22 @@ namespace Content.Server.GameObjects.EntitySystems.Atmos
|
||||
|
||||
var tileData = new List<GasData>();
|
||||
|
||||
for (byte i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||
{
|
||||
var gas = _atmosphereSystem.GetGas(i);
|
||||
var overlay = _atmosphereSystem.GetOverlay(i);
|
||||
if (overlay == null || tile?.Air == null) continue;
|
||||
if(tile.Air != null)
|
||||
for (byte i = 0; i < Atmospherics.TotalNumberOfGases; i++)
|
||||
{
|
||||
var gas = _atmosphereSystem.GetGas(i);
|
||||
var overlay = _atmosphereSystem.GetOverlay(i);
|
||||
if (overlay == null) continue;
|
||||
|
||||
var moles = tile.Air.Gases[i];
|
||||
var moles = tile.Air.Gases[i];
|
||||
|
||||
if (moles < gas.GasMolesVisible) continue;
|
||||
if (moles < gas.GasMolesVisible) continue;
|
||||
|
||||
var data = new GasData(i, (byte) (MathHelper.Clamp01(moles / gas.GasMolesVisibleMax) * 255));
|
||||
tileData.Add(data);
|
||||
}
|
||||
var data = new GasData(i, (byte) (MathHelper.Clamp01(moles / gas.GasMolesVisibleMax) * 255));
|
||||
tileData.Add(data);
|
||||
}
|
||||
|
||||
overlayData = new GasOverlayData(tile!.Hotspot.State, tile.Hotspot.Temperature, tileData.Count == 0 ? null : tileData.ToArray());
|
||||
overlayData = new GasOverlayData(tile!.Hotspot.State, tile.Hotspot.Temperature, tileData.Count == 0 ? Array.Empty<GasData>() : tileData.ToArray());
|
||||
|
||||
if (overlayData.Equals(oldTile))
|
||||
{
|
||||
|
||||
@@ -5,7 +5,9 @@ using System.Linq;
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.Atmos.Reactions;
|
||||
using Content.Server.GameObjects.Components.Atmos;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.GameObjects.EntitySystems.Atmos;
|
||||
using Content.Shared.Maps;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects.EntitySystems.TileLookup;
|
||||
using Robust.Server.Interfaces.Timing;
|
||||
@@ -17,6 +19,7 @@ using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.Interfaces.Map;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.GameObjects.EntitySystems
|
||||
@@ -38,6 +41,9 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
/// </summary>
|
||||
public IEnumerable<GasReactionPrototype> GasReactions => _gasReactions!;
|
||||
|
||||
private float[] _gasSpecificHeats = new float[Atmospherics.TotalNumberOfGases];
|
||||
public float[] GasSpecificHeats => _gasSpecificHeats;
|
||||
|
||||
public GridTileLookupSystem GridTileLookupSystem => _gridTileLookup ??= Get<GridTileLookupSystem>();
|
||||
|
||||
public override void Initialize()
|
||||
@@ -53,6 +59,13 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
|
||||
_mapManager.TileChanged += OnTileChanged;
|
||||
|
||||
Array.Resize(ref _gasSpecificHeats, MathHelper.NextMultipleOf(Atmospherics.TotalNumberOfGases, 4));
|
||||
|
||||
for (var i = 0; i < GasPrototypes.Length; i++)
|
||||
{
|
||||
_gasSpecificHeats[i] = GasPrototypes[i].SpecificHeat;
|
||||
}
|
||||
|
||||
// Required for airtight components.
|
||||
EntityManager.EventBus.SubscribeEvent<RotateEvent>(EventSource.Local, this, RotateEvent);
|
||||
}
|
||||
@@ -104,7 +117,7 @@ namespace Content.Server.GameObjects.EntitySystems
|
||||
// space -> not space or vice versa. So if the old tile is the
|
||||
// same as the new tile in terms of space-ness, ignore the change
|
||||
|
||||
if (eventArgs.NewTile.Tile.IsEmpty == eventArgs.OldTile.IsEmpty)
|
||||
if (eventArgs.NewTile.IsSpace() == eventArgs.OldTile.IsSpace())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user