Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 2 additions & 17 deletions DarkUI/DarkUI/Collections/ObservableList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,13 @@ public class ObservableList<T> : List<T>, IDisposable

#endregion

#region Destructor Region

~ObservableList()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please explain why Dispose methods were removed for this control. It's important because it's outside of TE codebase.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Dispose() methods weren't removed, they were restructured. The destructor was calling Dispose() for no reason, so the code has been simplified.

{
Dispose(false);
}

#endregion

#region Dispose Region

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
public virtual void Dispose()
{
if (_disposed)
return;

ItemsAdded = null;
ItemsRemoved = null;

Expand Down
5 changes: 4 additions & 1 deletion TombEditor/Controls/ImportedGeometryManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ public void Set(SetValue setValue)

private readonly Color _correctColor;
private readonly Color _wrongColor;
private ListChangedEventHandler _listChangedHandler;

public ImportedGeometryManager()
{
Expand Down Expand Up @@ -193,7 +194,7 @@ public ImportedGeometryManager()
};
dataGridView.DataSource = _dataGridViewDataSource;
dataGridViewControls.DeleteRowCheckIfCancel = MessageUserAboutHimDeletingRows;
_dataGridViewDataSource.ListChanged += delegate (object sender, ListChangedEventArgs e)
_listChangedHandler = delegate (object sender, ListChangedEventArgs e)
{
switch (e.ListChangedType)
{
Expand All @@ -203,6 +204,7 @@ public ImportedGeometryManager()
break;
}
};
_dataGridViewDataSource.ListChanged += _listChangedHandler;

Enabled = true;

Expand All @@ -214,6 +216,7 @@ protected override void Dispose(bool disposing)
{
if (disposing)
{
_dataGridViewDataSource.ListChanged -= _listChangedHandler;
components?.Dispose();
Editor.Instance.EditorEventRaised -= EditorEventRaised;
}
Expand Down
3 changes: 3 additions & 0 deletions TombEditor/Controls/Panel3D/Panel3D.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ public bool DisablePickingForHiddenRooms
private Buffer<SolidVertex> _objectHeightLineVertexBuffer;
private Buffer<SolidVertex> _flybyPathVertexBuffer;
private Buffer<SolidVertex> _ghostBlockVertexBuffer;
private SolidVertex[] _ghostBlockVertices = new SolidVertex[84];
private float[] _roomsDistanceCache;
private Buffer<SolidVertex> _boxVertexBuffer;

// Flyby stuff
Expand Down Expand Up @@ -228,6 +230,7 @@ protected override void Dispose(bool disposing)
_rasterizerStateDepthBias?.Dispose();
_currentContextMenu?.Dispose();
_wadRenderer?.Dispose();
_fontDefault?.Dispose();
}
base.Dispose(disposing);
}
Expand Down
5 changes: 3 additions & 2 deletions TombEditor/Controls/Panel3D/Panel3DDraw.cs
Original file line number Diff line number Diff line change
Expand Up @@ -668,8 +668,9 @@ private void DrawGhostBlockBodies(Effect effect, List<GhostBlockInstance> ghostB
if (!instance.Valid)
continue;

// Create a vertex array
SolidVertex[] vtxs = new SolidVertex[84]; // 78 with diagonal steps
// Reuse cached vertex array
SolidVertex[] vtxs = _ghostBlockVertices;
Array.Clear(vtxs, 0, vtxs.Length);

// Derive base sector colours
var p1c = new Vector4(baseColor.To3() * (selected ? 0.8f : 0.4f), selected ? 0.7f : 0.5f);
Expand Down
8 changes: 5 additions & 3 deletions TombEditor/Controls/Panel3D/Panel3DDrawCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,14 @@ Room[] CollectRoomsToDraw()
// Collect rooms to draw
var camPos = Camera.GetPosition();
var roomsToDraw = CollectRoomsToDraw(_editor.SelectedRoom).ToArray();
var roomsToDrawDistanceSquared = new float[roomsToDraw.Length];

if (_roomsDistanceCache == null || _roomsDistanceCache.Length < roomsToDraw.Length)
_roomsDistanceCache = new float[roomsToDraw.Length];

for (int i = 0; i < roomsToDraw.Length; ++i)
roomsToDrawDistanceSquared[i] = Vector3.DistanceSquared(camPos, roomsToDraw[i].WorldPos + roomsToDraw[i].GetLocalCenter());
_roomsDistanceCache[i] = Vector3.DistanceSquared(camPos, roomsToDraw[i].WorldPos + roomsToDraw[i].GetLocalCenter());

Array.Sort(roomsToDrawDistanceSquared, roomsToDraw);
Array.Sort(_roomsDistanceCache, roomsToDraw, 0, roomsToDraw.Length);
Array.Reverse(roomsToDraw);

return roomsToDraw;
Expand Down
19 changes: 13 additions & 6 deletions TombLib/TombLib.Rendering/Rendering/RenderingFont.cs
Original file line number Diff line number Diff line change
Expand Up @@ -315,23 +315,30 @@ public class GlyphRenderInfo

public void Dispose()
{
if (!_disposed)
if (_disposed)
return;
_disposed = true;

TextureAllocator?.Dispose();
ReleaseUnmanagedResources();

GC.SuppressFinalize(this);
}

~RenderingFont()
{
ReleaseUnmanagedResources();
}

private void ReleaseUnmanagedResources()
{
GDI.DeleteObject(_gdiFont);
GDI.DeleteDC(_gdiHdc);
Marshal.FreeHGlobal(_gdiGetCharacterPlacementOrder);
Marshal.FreeHGlobal(_gdiGetCharacterPlacementDx);
Marshal.FreeHGlobal(_gdiGetCharacterPlacementGlpyhs);
}

~RenderingFont()
{
Dispose();
}

private static class GDI
{
public class GDIException : Exception
Expand Down
2 changes: 2 additions & 0 deletions TombLib/TombLib/IO/BinaryWriterFast.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public void Dispose()
_ptr = null;
_startPtr = null;
_baseStream = null;

GC.SuppressFinalize(this);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of this code?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It avoids an unnecessary destructor call.

if (_handle.IsAllocated)
    _handle.Free();

Is already called in the Dispose() method, so the destructor does not have to be called again, saving one extra call. It also eases GC pressure ever so slightly, as you are marking it as "Hey, this is safe to be removed from memory now, no need to put it into the finalizer queue."

}

public Stream BaseStream
Expand Down
27 changes: 23 additions & 4 deletions TombLib/TombLib/LevelData/ImportedGeometry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@

namespace TombLib.LevelData
{
public class ImportedGeometryTexture : Texture
public class ImportedGeometryTexture : Texture, IDisposable
{
public Texture2D DirectXTexture { get; private set; }

private bool _disposed;

public ImportedGeometryTexture(string absolutePath)
{
AbsolutePath = absolutePath;
Expand All @@ -31,22 +33,39 @@ public ImportedGeometryTexture(string absolutePath)
if (SynchronizationContext.Current == null)
DirectXTexture = TextureLoad.Load(ImportedGeometry.Device, Image);
else
SynchronizationContext.Current.Post(unused => // Synchronize DirectX, we can't 'send' because that may deadlock with the level settings reloader
DirectXTexture = TextureLoad.Load(ImportedGeometry.Device, Image), null);
SynchronizationContext.Current.Post(unused => {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand what's happening here. This code prevents re-initialization of already disposed texture in race conditions?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is a very rare, but potential order of execution issue, as the posted lambda may happen after the object has been disposed. Extremely rare, but still good to add a defense mechanism just in case.

if (_disposed)
return;

DirectXTexture = TextureLoad.Load(ImportedGeometry.Device, Image);
}, null);
}

private ImportedGeometryTexture(ImportedGeometryTexture other)
{
DirectXTexture = other.DirectXTexture;
AbsolutePath = other.AbsolutePath;
Image = other.Image;
}

public void Assign(ImportedGeometryTexture other)
{
// Dispose old GPU texture if it differs from the new one.
if (DirectXTexture != null && DirectXTexture != other.DirectXTexture)
DirectXTexture.Dispose();

AbsolutePath = other.AbsolutePath;
Image = other.Image;
DirectXTexture = other.DirectXTexture;

_disposed = false;
}

public void Dispose()
{
_disposed = true;

DirectXTexture?.Dispose();
DirectXTexture = null;
}

public override Texture Clone() => new ImportedGeometryTexture(this);
Expand Down
24 changes: 16 additions & 8 deletions TombLib/TombLib/Wad/WadTexture.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Buffers.Binary;
using System.IO;
using TombLib.Graphics;
using TombLib.Utils;
using Blake3Hasher = Blake3.Hasher;

namespace TombLib.Wad
{
Expand All @@ -20,14 +22,20 @@ public WadTexture(ImageC image)
{
Image = image;

using (var ms = new MemoryStream())
{
var writer = new BinaryWriter(ms);
writer.Write(Image.Size.X);
writer.Write(Image.Size.Y);
Image.WriteToStreamRaw(ms);
Hash = Hash.FromByteArray(ms.ToArray());
}
// Hash image dimensions and pixel data directly without intermediate copies.
using var hasher = Blake3Hasher.New();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the advantage of Blake3 hasher over Hash.FromByteArray?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Less heap allocation, no MemoryStream buffer, no BinaryWriter overhead, no final ToArray() copy, less GC pressure, slightly less CPU work. Both use Blake3, but this approach is more memory efficient with less overhead.

Span<byte> header = stackalloc byte[8];
BinaryPrimitives.WriteInt32LittleEndian(header, Image.Size.X);
BinaryPrimitives.WriteInt32LittleEndian(header.Slice(4), Image.Size.Y);
hasher.Update(header);
hasher.Update(Image.ToByteArray());

Span<byte> digest = stackalloc byte[32];
hasher.Finalize(digest);

ulong low = BinaryPrimitives.ReadUInt64LittleEndian(digest.Slice(0, 8));
ulong high = BinaryPrimitives.ReadUInt64LittleEndian(digest.Slice(8, 8));
Hash = new Hash { HashLow = low, HashHigh = high };
}

public override Texture Clone() => this;
Expand Down
1 change: 0 additions & 1 deletion WadTool/Controls/PanelRenderingAnimationEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ protected override void Dispose(bool disposing)
{
if (disposing)
{
_fontTexture?.Dispose();
_fontDefault?.Dispose();
_gizmo?.Dispose();
_plane?.Dispose();
Expand Down
1 change: 1 addition & 0 deletions WadTool/Controls/PanelRenderingMesh.cs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ protected override void Dispose(bool disposing)
_bigSphere?.Dispose();
_plane?.Dispose();
_wadRenderer?.Dispose();
_fontDefault?.Dispose();
}
base.Dispose(disposing);
}
Expand Down
1 change: 0 additions & 1 deletion WadTool/Controls/PanelRenderingSkeleton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ protected override void Dispose(bool disposing)
{
if (disposing)
{
_fontTexture?.Dispose();
_fontDefault?.Dispose();
_rasterizerWireframe?.Dispose();
_vertexBufferVisibility?.Dispose();
Expand Down
1 change: 0 additions & 1 deletion WadTool/Controls/PanelRenderingStaticEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ protected override void Dispose(bool disposing)
{
if (disposing)
{
_fontTexture?.Dispose();
_fontDefault?.Dispose();
_gizmo?.Dispose();
_gizmoLight?.Dispose();
Expand Down
Loading