Atomically call graphics resource destroy function
parent
528fb7ac7c
commit
450b08cbd8
|
@ -235,8 +235,6 @@ namespace MoonWorks
|
|||
|
||||
Draw(alpha);
|
||||
accumulatedDrawTime -= FramerateCapTimeSpan;
|
||||
|
||||
GraphicsDevice.FlushEmergencyDisposalQueue();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -355,21 +355,6 @@ namespace MoonWorks.Graphics
|
|||
}
|
||||
}
|
||||
|
||||
ConcurrentQueue<GraphicsResourceDisposalHandle> emergencyDisposalQueue = new ConcurrentQueue<GraphicsResourceDisposalHandle>();
|
||||
|
||||
internal void RegisterForEmergencyDisposal(GraphicsResourceDisposalHandle handle)
|
||||
{
|
||||
emergencyDisposalQueue.Enqueue(handle);
|
||||
}
|
||||
|
||||
internal void FlushEmergencyDisposalQueue()
|
||||
{
|
||||
while (emergencyDisposalQueue.TryDequeue(out var handle))
|
||||
{
|
||||
handle.Dispose(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!IsDisposed)
|
||||
|
@ -387,11 +372,9 @@ namespace MoonWorks.Graphics
|
|||
}
|
||||
resources.Clear();
|
||||
}
|
||||
|
||||
Refresh.Refresh_DestroyDevice(Handle);
|
||||
}
|
||||
|
||||
FlushEmergencyDisposalQueue();
|
||||
Refresh.Refresh_DestroyDevice(Handle);
|
||||
|
||||
IsDisposed = true;
|
||||
}
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace MoonWorks.Graphics
|
||||
{
|
||||
// TODO: give this a Name property for debugging use
|
||||
public abstract class GraphicsResource : IDisposable
|
||||
{
|
||||
public GraphicsDevice Device { get; }
|
||||
public IntPtr Handle { get; internal set; }
|
||||
public IntPtr Handle { get => handle; internal set => handle = value; }
|
||||
private nint handle;
|
||||
|
||||
public bool IsDisposed { get; private set; }
|
||||
protected abstract Action<IntPtr, IntPtr> QueueDestroyFunction { get; }
|
||||
|
||||
private GCHandle SelfReference;
|
||||
|
||||
protected GraphicsResource(GraphicsDevice device)
|
||||
{
|
||||
Device = device;
|
||||
|
@ -21,26 +23,21 @@ namespace MoonWorks.Graphics
|
|||
Device.AddResourceReference(SelfReference);
|
||||
}
|
||||
|
||||
private GraphicsResourceDisposalHandle CreateDisposalHandle()
|
||||
{
|
||||
return new GraphicsResourceDisposalHandle
|
||||
{
|
||||
QueueDestroyAction = QueueDestroyFunction,
|
||||
ResourceHandle = Handle
|
||||
};
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (!IsDisposed)
|
||||
{
|
||||
if (Handle != IntPtr.Zero)
|
||||
if (disposing)
|
||||
{
|
||||
QueueDestroyFunction(Device.Handle, Handle);
|
||||
Device.RemoveResourceReference(SelfReference);
|
||||
SelfReference.Free();
|
||||
}
|
||||
|
||||
Handle = IntPtr.Zero;
|
||||
// Atomically call destroy function in case this is called from the finalizer thread
|
||||
var toDispose = Interlocked.Exchange(ref handle, IntPtr.Zero);
|
||||
if (toDispose != IntPtr.Zero)
|
||||
{
|
||||
QueueDestroyFunction(Device.Handle, toDispose);
|
||||
}
|
||||
|
||||
IsDisposed = true;
|
||||
|
@ -50,20 +47,12 @@ namespace MoonWorks.Graphics
|
|||
~GraphicsResource()
|
||||
{
|
||||
#if DEBUG
|
||||
// If the graphics device associated with this resource was already disposed, we assume
|
||||
// that your game is in the middle of shutting down.
|
||||
if (!IsDisposed && Device != null && !Device.IsDisposed)
|
||||
{
|
||||
// If you see this log message, you leaked a graphics resource without disposing it!
|
||||
// This means your game may eventually run out of native memory for mysterious reasons.
|
||||
Logger.LogWarn($"A resource of type {GetType().Name} was not Disposed.");
|
||||
}
|
||||
// If you see this log message, you leaked a graphics resource without disposing it!
|
||||
// We'll try to clean it up for you but you really should fix this.
|
||||
Logger.LogWarn($"A resource of type {GetType().Name} was not Disposed.");
|
||||
#endif
|
||||
|
||||
// While we only log in debug builds, in both debug and release builds we want to free
|
||||
// any native resources associated with this object at the earliest opportunity.
|
||||
// This will at least prevent you from running out of memory rapidly.
|
||||
Device.RegisterForEmergencyDisposal(CreateDisposalHandle());
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace MoonWorks.Graphics
|
||||
{
|
||||
// This allows us to defer native disposal calls from the finalizer thread.
|
||||
internal struct GraphicsResourceDisposalHandle
|
||||
{
|
||||
internal Action<IntPtr, IntPtr> QueueDestroyAction;
|
||||
internal IntPtr ResourceHandle;
|
||||
|
||||
public void Dispose(GraphicsDevice device)
|
||||
{
|
||||
if (device == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(device));
|
||||
}
|
||||
|
||||
if (QueueDestroyAction == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QueueDestroyAction(device.Handle, ResourceHandle);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue