Improve tracking of resources
parent
b24b8a3869
commit
aa9baf2dff
|
@ -5,7 +5,7 @@ using WellspringCS;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics.Font
|
namespace MoonWorks.Graphics.Font
|
||||||
{
|
{
|
||||||
public unsafe class Font : IDisposable
|
public unsafe class Font : GraphicsResource
|
||||||
{
|
{
|
||||||
public Texture Texture { get; }
|
public Texture Texture { get; }
|
||||||
public float PixelsPerEm { get; }
|
public float PixelsPerEm { get; }
|
||||||
|
@ -16,8 +16,6 @@ namespace MoonWorks.Graphics.Font
|
||||||
private byte* StringBytes;
|
private byte* StringBytes;
|
||||||
private int StringBytesLength;
|
private int StringBytesLength;
|
||||||
|
|
||||||
private bool IsDisposed;
|
|
||||||
|
|
||||||
public unsafe static Font Load(
|
public unsafe static Font Load(
|
||||||
GraphicsDevice graphicsDevice,
|
GraphicsDevice graphicsDevice,
|
||||||
CommandBuffer commandBuffer,
|
CommandBuffer commandBuffer,
|
||||||
|
@ -49,10 +47,10 @@ namespace MoonWorks.Graphics.Font
|
||||||
NativeMemory.Free(fontFileByteBuffer);
|
NativeMemory.Free(fontFileByteBuffer);
|
||||||
NativeMemory.Free(atlasFileByteBuffer);
|
NativeMemory.Free(atlasFileByteBuffer);
|
||||||
|
|
||||||
return new Font(handle, texture, pixelsPerEm, distanceRange);
|
return new Font(graphicsDevice, handle, texture, pixelsPerEm, distanceRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Font(IntPtr handle, Texture texture, float pixelsPerEm, float distanceRange)
|
private Font(GraphicsDevice device, IntPtr handle, Texture texture, float pixelsPerEm, float distanceRange) : base(device)
|
||||||
{
|
{
|
||||||
Handle = handle;
|
Handle = handle;
|
||||||
Texture = texture;
|
Texture = texture;
|
||||||
|
@ -101,7 +99,7 @@ namespace MoonWorks.Graphics.Font
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
if (!IsDisposed)
|
||||||
{
|
{
|
||||||
|
@ -111,21 +109,8 @@ namespace MoonWorks.Graphics.Font
|
||||||
}
|
}
|
||||||
|
|
||||||
Wellspring.Wellspring_DestroyFont(Handle);
|
Wellspring.Wellspring_DestroyFont(Handle);
|
||||||
IsDisposed = true;
|
|
||||||
}
|
}
|
||||||
}
|
base.Dispose(disposing);
|
||||||
|
|
||||||
~Font()
|
|
||||||
{
|
|
||||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
|
||||||
Dispose(disposing: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
|
||||||
Dispose(disposing: true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ using WellspringCS;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics.Font
|
namespace MoonWorks.Graphics.Font
|
||||||
{
|
{
|
||||||
public unsafe class TextBatch : IDisposable
|
public unsafe class TextBatch : GraphicsResource
|
||||||
{
|
{
|
||||||
public const int MAX_CHARS = 4096;
|
public const int MAX_CHARS = 4096;
|
||||||
public const int MAX_VERTICES = MAX_CHARS * 4;
|
public const int MAX_VERTICES = MAX_CHARS * 4;
|
||||||
|
@ -22,11 +22,9 @@ namespace MoonWorks.Graphics.Font
|
||||||
private byte* StringBytes;
|
private byte* StringBytes;
|
||||||
private int StringBytesLength;
|
private int StringBytesLength;
|
||||||
|
|
||||||
private bool IsDisposed;
|
public TextBatch(GraphicsDevice device) : base(device)
|
||||||
|
|
||||||
public TextBatch(GraphicsDevice graphicsDevice)
|
|
||||||
{
|
{
|
||||||
GraphicsDevice = graphicsDevice;
|
GraphicsDevice = device;
|
||||||
Handle = Wellspring.Wellspring_CreateTextBatch();
|
Handle = Wellspring.Wellspring_CreateTextBatch();
|
||||||
|
|
||||||
StringBytesLength = 128;
|
StringBytesLength = 128;
|
||||||
|
@ -102,7 +100,7 @@ namespace MoonWorks.Graphics.Font
|
||||||
PrimitiveCount = vertexCount / 2; // FIXME: is this jank?
|
PrimitiveCount = vertexCount / 2; // FIXME: is this jank?
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
if (!IsDisposed)
|
||||||
{
|
{
|
||||||
|
@ -114,22 +112,8 @@ namespace MoonWorks.Graphics.Font
|
||||||
|
|
||||||
NativeMemory.Free(StringBytes);
|
NativeMemory.Free(StringBytes);
|
||||||
Wellspring.Wellspring_DestroyTextBatch(Handle);
|
Wellspring.Wellspring_DestroyTextBatch(Handle);
|
||||||
|
|
||||||
IsDisposed = true;
|
|
||||||
}
|
}
|
||||||
}
|
base.Dispose(disposing);
|
||||||
|
|
||||||
~TextBatch()
|
|
||||||
{
|
|
||||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
|
||||||
Dispose(disposing: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
|
||||||
Dispose(disposing: true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using MoonWorks.Video;
|
||||||
using RefreshCS;
|
using RefreshCS;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
namespace MoonWorks.Graphics
|
||||||
|
@ -363,6 +363,16 @@ namespace MoonWorks.Graphics
|
||||||
{
|
{
|
||||||
lock (resources)
|
lock (resources)
|
||||||
{
|
{
|
||||||
|
// Dispose video players first to avoid race condition on threaded decoding
|
||||||
|
foreach (var resource in resources)
|
||||||
|
{
|
||||||
|
if (resource.Target is VideoPlayer player)
|
||||||
|
{
|
||||||
|
player.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispose everything else
|
||||||
foreach (var resource in resources)
|
foreach (var resource in resources)
|
||||||
{
|
{
|
||||||
if (resource.Target is IDisposable disposable)
|
if (resource.Target is IDisposable disposable)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
namespace MoonWorks.Graphics
|
||||||
{
|
{
|
||||||
|
@ -8,13 +7,11 @@ namespace MoonWorks.Graphics
|
||||||
public abstract class GraphicsResource : IDisposable
|
public abstract class GraphicsResource : IDisposable
|
||||||
{
|
{
|
||||||
public GraphicsDevice Device { get; }
|
public GraphicsDevice Device { get; }
|
||||||
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;
|
private GCHandle SelfReference;
|
||||||
|
|
||||||
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
protected GraphicsResource(GraphicsDevice device)
|
protected GraphicsResource(GraphicsDevice device)
|
||||||
{
|
{
|
||||||
Device = device;
|
Device = device;
|
||||||
|
@ -23,7 +20,7 @@ namespace MoonWorks.Graphics
|
||||||
Device.AddResourceReference(SelfReference);
|
Device.AddResourceReference(SelfReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
if (!IsDisposed)
|
||||||
{
|
{
|
||||||
|
@ -33,13 +30,6 @@ namespace MoonWorks.Graphics
|
||||||
SelfReference.Free();
|
SelfReference.Free();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
IsDisposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace MoonWorks.Graphics;
|
||||||
|
|
||||||
|
public abstract class RefreshResource : GraphicsResource
|
||||||
|
{
|
||||||
|
public IntPtr Handle { get => handle; internal set => handle = value; }
|
||||||
|
private IntPtr handle;
|
||||||
|
|
||||||
|
protected abstract Action<IntPtr, IntPtr> QueueDestroyFunction { get; }
|
||||||
|
|
||||||
|
protected RefreshResource(GraphicsDevice device) : base(device)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!IsDisposed)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ namespace MoonWorks.Graphics
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Buffers are generic data containers that can be used by the GPU.
|
/// Buffers are generic data containers that can be used by the GPU.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Buffer : GraphicsResource
|
public class Buffer : RefreshResource
|
||||||
{
|
{
|
||||||
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyBuffer;
|
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyBuffer;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace MoonWorks.Graphics
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compute pipelines perform arbitrary parallel processing on input data.
|
/// Compute pipelines perform arbitrary parallel processing on input data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ComputePipeline : GraphicsResource
|
public class ComputePipeline : RefreshResource
|
||||||
{
|
{
|
||||||
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyComputePipeline;
|
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyComputePipeline;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace MoonWorks.Graphics
|
||||||
/// The Fence object itself is basically just a wrapper for the Refresh_Fence. <br/>
|
/// The Fence object itself is basically just a wrapper for the Refresh_Fence. <br/>
|
||||||
/// The internal handle is replaced so that we can pool Fence objects to manage garbage.
|
/// The internal handle is replaced so that we can pool Fence objects to manage garbage.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Fence : GraphicsResource
|
public class Fence : RefreshResource
|
||||||
{
|
{
|
||||||
protected override Action<nint, nint> QueueDestroyFunction => Refresh.Refresh_ReleaseFence;
|
protected override Action<nint, nint> QueueDestroyFunction => Refresh.Refresh_ReleaseFence;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace MoonWorks.Graphics
|
||||||
/// Graphics pipelines encapsulate all of the render state in a single object. <br/>
|
/// Graphics pipelines encapsulate all of the render state in a single object. <br/>
|
||||||
/// These pipelines are bound before draw calls are issued.
|
/// These pipelines are bound before draw calls are issued.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GraphicsPipeline : GraphicsResource
|
public class GraphicsPipeline : RefreshResource
|
||||||
{
|
{
|
||||||
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyGraphicsPipeline;
|
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyGraphicsPipeline;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace MoonWorks.Graphics
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A sampler specifies how a texture will be sampled in a shader.
|
/// A sampler specifies how a texture will be sampled in a shader.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Sampler : GraphicsResource
|
public class Sampler : RefreshResource
|
||||||
{
|
{
|
||||||
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroySampler;
|
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroySampler;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace MoonWorks.Graphics
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shader modules expect input in Refresh bytecode format.
|
/// Shader modules expect input in Refresh bytecode format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ShaderModule : GraphicsResource
|
public class ShaderModule : RefreshResource
|
||||||
{
|
{
|
||||||
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyShaderModule;
|
protected override Action<IntPtr, IntPtr> QueueDestroyFunction => Refresh.Refresh_QueueDestroyShaderModule;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace MoonWorks.Graphics
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A container for pixel data.
|
/// A container for pixel data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Texture : GraphicsResource
|
public class Texture : RefreshResource
|
||||||
{
|
{
|
||||||
public uint Width { get; internal set; }
|
public uint Width { get; internal set; }
|
||||||
public uint Height { get; internal set; }
|
public uint Height { get; internal set; }
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using MoonWorks.Graphics;
|
||||||
|
|
||||||
namespace MoonWorks.Video
|
namespace MoonWorks.Video
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class takes in a filename for AV1 data in .obu (open bitstream unit) format
|
/// This class takes in a filename for AV1 data in .obu (open bitstream unit) format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe class VideoAV1
|
public unsafe class VideoAV1 : GraphicsResource
|
||||||
{
|
{
|
||||||
public string Filename { get; }
|
public string Filename { get; }
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@ namespace MoonWorks.Video
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens an AV1 file so it can be loaded by VideoPlayer. You must also provide a playback framerate.
|
/// Opens an AV1 file so it can be loaded by VideoPlayer. You must also provide a playback framerate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public VideoAV1(string filename, double framesPerSecond)
|
public VideoAV1(GraphicsDevice device, string filename, double framesPerSecond) : base(device)
|
||||||
{
|
{
|
||||||
if (!File.Exists(filename))
|
if (!File.Exists(filename))
|
||||||
{
|
{
|
||||||
|
@ -67,8 +68,22 @@ namespace MoonWorks.Video
|
||||||
|
|
||||||
Filename = filename;
|
Filename = filename;
|
||||||
|
|
||||||
StreamA = new VideoAV1Stream(this);
|
StreamA = new VideoAV1Stream(device, this);
|
||||||
StreamB = new VideoAV1Stream(this);
|
StreamB = new VideoAV1Stream(device, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: if you call this while a VideoPlayer is playing the stream, your program will explode
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!IsDisposed)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
StreamA.Dispose();
|
||||||
|
StreamB.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
|
using MoonWorks.Graphics;
|
||||||
|
|
||||||
namespace MoonWorks.Video
|
namespace MoonWorks.Video
|
||||||
{
|
{
|
||||||
internal class VideoAV1Stream
|
internal class VideoAV1Stream : GraphicsResource
|
||||||
{
|
{
|
||||||
public IntPtr Handle => handle;
|
public IntPtr Handle => handle;
|
||||||
IntPtr handle;
|
IntPtr handle;
|
||||||
|
@ -19,9 +20,7 @@ namespace MoonWorks.Video
|
||||||
|
|
||||||
public bool FrameDataUpdated { get; set; }
|
public bool FrameDataUpdated { get; set; }
|
||||||
|
|
||||||
bool IsDisposed;
|
public VideoAV1Stream(GraphicsDevice device, VideoAV1 video) : base(device)
|
||||||
|
|
||||||
public VideoAV1Stream(VideoAV1 video)
|
|
||||||
{
|
{
|
||||||
if (Dav1dfile.df_fopen(video.Filename, out handle) == 0)
|
if (Dav1dfile.df_fopen(video.Filename, out handle) == 0)
|
||||||
{
|
{
|
||||||
|
@ -71,32 +70,13 @@ namespace MoonWorks.Video
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
if (!IsDisposed)
|
||||||
{
|
{
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
// dispose managed state (managed objects)
|
|
||||||
}
|
|
||||||
|
|
||||||
// free unmanaged resources (unmanaged objects)
|
|
||||||
Dav1dfile.df_close(Handle);
|
Dav1dfile.df_close(Handle);
|
||||||
|
|
||||||
IsDisposed = true;
|
|
||||||
}
|
}
|
||||||
}
|
base.Dispose(disposing);
|
||||||
|
|
||||||
~VideoAV1Stream()
|
|
||||||
{
|
|
||||||
Dispose(disposing: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
|
||||||
Dispose(disposing: true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace MoonWorks.Video
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A structure for continuous decoding of AV1 videos and rendering them into a texture.
|
/// A structure for continuous decoding of AV1 videos and rendering them into a texture.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe class VideoPlayer : IDisposable
|
public unsafe class VideoPlayer : GraphicsResource
|
||||||
{
|
{
|
||||||
public Texture RenderTexture { get; private set; } = null;
|
public Texture RenderTexture { get; private set; } = null;
|
||||||
public VideoState State { get; private set; } = VideoState.Stopped;
|
public VideoState State { get; private set; } = VideoState.Stopped;
|
||||||
|
@ -18,6 +18,10 @@ namespace MoonWorks.Video
|
||||||
private VideoAV1 Video = null;
|
private VideoAV1 Video = null;
|
||||||
private VideoAV1Stream CurrentStream = null;
|
private VideoAV1Stream CurrentStream = null;
|
||||||
|
|
||||||
|
private Task ReadNextFrameTask;
|
||||||
|
private Task ResetStreamATask;
|
||||||
|
private Task ResetStreamBTask;
|
||||||
|
|
||||||
private GraphicsDevice GraphicsDevice;
|
private GraphicsDevice GraphicsDevice;
|
||||||
private Texture yTexture = null;
|
private Texture yTexture = null;
|
||||||
private Texture uTexture = null;
|
private Texture uTexture = null;
|
||||||
|
@ -30,17 +34,15 @@ namespace MoonWorks.Video
|
||||||
private double lastTimestamp;
|
private double lastTimestamp;
|
||||||
private double timeElapsed;
|
private double timeElapsed;
|
||||||
|
|
||||||
private bool disposed;
|
public VideoPlayer(GraphicsDevice device) : base(device)
|
||||||
|
|
||||||
public VideoPlayer(GraphicsDevice graphicsDevice)
|
|
||||||
{
|
{
|
||||||
GraphicsDevice = graphicsDevice;
|
GraphicsDevice = device;
|
||||||
if (GraphicsDevice.VideoPipeline == null)
|
if (GraphicsDevice.VideoPipeline == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Missing video shaders!");
|
throw new InvalidOperationException("Missing video shaders!");
|
||||||
}
|
}
|
||||||
|
|
||||||
LinearSampler = new Sampler(graphicsDevice, SamplerCreateInfo.LinearClamp);
|
LinearSampler = new Sampler(device, SamplerCreateInfo.LinearClamp);
|
||||||
|
|
||||||
timer = new Stopwatch();
|
timer = new Stopwatch();
|
||||||
}
|
}
|
||||||
|
@ -168,6 +170,8 @@ namespace MoonWorks.Video
|
||||||
public void Unload()
|
public void Unload()
|
||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
|
ResetStreamATask?.Wait();
|
||||||
|
ResetStreamBTask?.Wait();
|
||||||
Video = null;
|
Video = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +198,8 @@ namespace MoonWorks.Video
|
||||||
}
|
}
|
||||||
|
|
||||||
currentFrame = thisFrame;
|
currentFrame = thisFrame;
|
||||||
Task.Run(CurrentStream.ReadNextFrame).ContinueWith(HandleTaskException, TaskContinuationOptions.OnlyOnFaulted);
|
ReadNextFrameTask = Task.Run(CurrentStream.ReadNextFrame);
|
||||||
|
ReadNextFrameTask.ContinueWith(HandleTaskException, TaskContinuationOptions.OnlyOnFaulted);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentStream.Ended)
|
if (CurrentStream.Ended)
|
||||||
|
@ -202,7 +207,17 @@ namespace MoonWorks.Video
|
||||||
timer.Stop();
|
timer.Stop();
|
||||||
timer.Reset();
|
timer.Reset();
|
||||||
|
|
||||||
Task.Run(CurrentStream.Reset).ContinueWith(HandleTaskException, TaskContinuationOptions.OnlyOnFaulted);
|
var task = Task.Run(CurrentStream.Reset);
|
||||||
|
task.ContinueWith(HandleTaskException, TaskContinuationOptions.OnlyOnFaulted);
|
||||||
|
|
||||||
|
if (CurrentStream == Video.StreamA)
|
||||||
|
{
|
||||||
|
ResetStreamATask = task;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ResetStreamBTask = task;
|
||||||
|
}
|
||||||
|
|
||||||
if (Loop)
|
if (Loop)
|
||||||
{
|
{
|
||||||
|
@ -280,8 +295,12 @@ namespace MoonWorks.Video
|
||||||
|
|
||||||
private void InitializeDav1dStream()
|
private void InitializeDav1dStream()
|
||||||
{
|
{
|
||||||
Task.Run(Video.StreamA.Reset).ContinueWith(HandleTaskException, TaskContinuationOptions.OnlyOnFaulted);
|
ReadNextFrameTask?.Wait();
|
||||||
Task.Run(Video.StreamB.Reset).ContinueWith(HandleTaskException, TaskContinuationOptions.OnlyOnFaulted);
|
|
||||||
|
ResetStreamATask = Task.Run(Video.StreamA.Reset);
|
||||||
|
ResetStreamATask.ContinueWith(HandleTaskException, TaskContinuationOptions.OnlyOnFaulted);
|
||||||
|
ResetStreamBTask = Task.Run(Video.StreamB.Reset);
|
||||||
|
ResetStreamBTask.ContinueWith(HandleTaskException, TaskContinuationOptions.OnlyOnFaulted);
|
||||||
|
|
||||||
CurrentStream = Video.StreamA;
|
CurrentStream = Video.StreamA;
|
||||||
currentFrame = -1;
|
currentFrame = -1;
|
||||||
|
@ -289,37 +308,27 @@ namespace MoonWorks.Video
|
||||||
|
|
||||||
private static void HandleTaskException(Task task)
|
private static void HandleTaskException(Task task)
|
||||||
{
|
{
|
||||||
throw task.Exception;
|
if (task.Exception.InnerException is not TaskCanceledException)
|
||||||
|
{
|
||||||
|
throw task.Exception;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!disposed)
|
if (!IsDisposed)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
// dispose managed state (managed objects)
|
Unload();
|
||||||
|
|
||||||
RenderTexture.Dispose();
|
RenderTexture.Dispose();
|
||||||
yTexture.Dispose();
|
yTexture.Dispose();
|
||||||
uTexture.Dispose();
|
uTexture.Dispose();
|
||||||
vTexture.Dispose();
|
vTexture.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
disposed = true;
|
|
||||||
}
|
}
|
||||||
}
|
base.Dispose(disposing);
|
||||||
|
|
||||||
~VideoPlayer()
|
|
||||||
{
|
|
||||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
|
||||||
Dispose(disposing: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
|
||||||
Dispose(disposing: true);
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue