From d10f018f141d9246f2c438e889c2ab3ec0d2716c Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Tue, 26 Jan 2021 21:06:15 -0800 Subject: [PATCH] fix graphics resources disposing out of order --- src/Graphics/GraphicsDevice.cs | 34 ++++++++++++++++++++++++++++++-- src/Graphics/GraphicsResource.cs | 14 +++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/Graphics/GraphicsDevice.cs b/src/Graphics/GraphicsDevice.cs index 9ba133f1..1975ccb0 100644 --- a/src/Graphics/GraphicsDevice.cs +++ b/src/Graphics/GraphicsDevice.cs @@ -12,6 +12,8 @@ namespace MoonWorks.Graphics private readonly Queue commandBufferPool; + private readonly List resources = new List(); + public GraphicsDevice( IntPtr deviceWindowHandle, Refresh.PresentMode presentMode, @@ -78,16 +80,44 @@ namespace MoonWorks.Graphics Refresh.Refresh_Wait(Handle); } + internal void AddResourceReference(WeakReference resourceReference) + { + lock (resources) + { + resources.Add(resourceReference); + } + } + + internal void RemoveResourceReference(WeakReference resourceReference) + { + lock (resources) + { + resources.Remove(resourceReference); + } + } + protected virtual void Dispose(bool disposing) { if (!IsDisposed) { if (disposing) { - // TODO: dispose managed state (managed objects) + lock (resources) + { + foreach (var resource in resources) + { + var target = resource.Target; + if (target != null) + { + (target as IDisposable).Dispose(); + } + } + resources.Clear(); + } + + Refresh.Refresh_DestroyDevice(Handle); } - Refresh.Refresh_DestroyDevice(Handle); IsDisposed = true; } } diff --git a/src/Graphics/GraphicsResource.cs b/src/Graphics/GraphicsResource.cs index 41ed1832..0dfcba88 100644 --- a/src/Graphics/GraphicsResource.cs +++ b/src/Graphics/GraphicsResource.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace MoonWorks.Graphics { @@ -12,9 +10,14 @@ namespace MoonWorks.Graphics public bool IsDisposed { get; private set; } protected abstract Action QueueDestroyFunction { get; } + private WeakReference selfReference; + public GraphicsResource(GraphicsDevice device) { Device = device; + + selfReference = new WeakReference(this); + Device.AddResourceReference(selfReference); } protected virtual void Dispose(bool disposing) @@ -22,6 +25,13 @@ namespace MoonWorks.Graphics if (!IsDisposed) { QueueDestroyFunction(Device.Handle, Handle); + + if (selfReference != null) + { + Device.RemoveResourceReference(selfReference); + selfReference = null; + } + IsDisposed = true; } }