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:
Víctor Aguilera Puerto
2020-11-25 10:48:49 +01:00
committed by GitHub
parent 89f72c4cb2
commit b18ee3ec49
19 changed files with 199 additions and 177 deletions

View File

@@ -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();

View File

@@ -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>()

View File

@@ -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;

View File

@@ -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();

View File

@@ -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))
{

View File

@@ -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;
}