aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.GAL
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.GAL')
-rw-r--r--Ryujinx.Graphics.GAL/IRenderer.cs9
-rw-r--r--Ryujinx.Graphics.GAL/ITexture.cs4
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs4
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs13
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataCommand.cs4
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataSliceCommand.cs4
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Model/PinnedSpan.cs23
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs8
-rw-r--r--Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs8
-rw-r--r--Ryujinx.Graphics.GAL/PinnedSpan.cs53
10 files changed, 87 insertions, 43 deletions
diff --git a/Ryujinx.Graphics.GAL/IRenderer.cs b/Ryujinx.Graphics.GAL/IRenderer.cs
index 1f2af559..2af7b5db 100644
--- a/Ryujinx.Graphics.GAL/IRenderer.cs
+++ b/Ryujinx.Graphics.GAL/IRenderer.cs
@@ -15,7 +15,12 @@ namespace Ryujinx.Graphics.GAL
void BackgroundContextAction(Action action, bool alwaysBackground = false);
- BufferHandle CreateBuffer(int size);
+ BufferHandle CreateBuffer(int size, BufferHandle storageHint);
+
+ BufferHandle CreateBuffer(int size)
+ {
+ return CreateBuffer(size, BufferHandle.Null);
+ }
IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info);
@@ -26,7 +31,7 @@ namespace Ryujinx.Graphics.GAL
void DeleteBuffer(BufferHandle buffer);
- ReadOnlySpan<byte> GetBufferData(BufferHandle buffer, int offset, int size);
+ PinnedSpan<byte> GetBufferData(BufferHandle buffer, int offset, int size);
Capabilities GetCapabilities();
ulong GetCurrentSync();
diff --git a/Ryujinx.Graphics.GAL/ITexture.cs b/Ryujinx.Graphics.GAL/ITexture.cs
index 4dc93303..792c863c 100644
--- a/Ryujinx.Graphics.GAL/ITexture.cs
+++ b/Ryujinx.Graphics.GAL/ITexture.cs
@@ -15,8 +15,8 @@ namespace Ryujinx.Graphics.GAL
ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel);
- ReadOnlySpan<byte> GetData();
- ReadOnlySpan<byte> GetData(int layer, int level);
+ PinnedSpan<byte> GetData();
+ PinnedSpan<byte> GetData(int layer, int level);
void SetData(SpanOrArray<byte> data);
void SetData(SpanOrArray<byte> data, int layer, int level);
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs
index d3a255e7..031c6153 100644
--- a/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Buffer/BufferGetDataCommand.cs
@@ -21,9 +21,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Buffer
public static void Run(ref BufferGetDataCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
- ReadOnlySpan<byte> result = renderer.GetBufferData(threaded.Buffers.MapBuffer(command._buffer), command._offset, command._size);
+ PinnedSpan<byte> result = renderer.GetBufferData(threaded.Buffers.MapBuffer(command._buffer), command._offset, command._size);
- command._result.Get(threaded).Result = new PinnedSpan<byte>(result);
+ command._result.Get(threaded).Result = result;
}
}
}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs
index 4f01dea2..b36d8bbe 100644
--- a/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Renderer/CreateBufferCommand.cs
@@ -5,16 +5,25 @@
public CommandType CommandType => CommandType.CreateBuffer;
private BufferHandle _threadedHandle;
private int _size;
+ private BufferHandle _storageHint;
- public void Set(BufferHandle threadedHandle, int size)
+ public void Set(BufferHandle threadedHandle, int size, BufferHandle storageHint)
{
_threadedHandle = threadedHandle;
_size = size;
+ _storageHint = storageHint;
}
public static void Run(ref CreateBufferCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
- threaded.Buffers.AssignBuffer(command._threadedHandle, renderer.CreateBuffer(command._size));
+ BufferHandle hint = BufferHandle.Null;
+
+ if (command._storageHint != BufferHandle.Null)
+ {
+ hint = threaded.Buffers.MapBuffer(command._storageHint);
+ }
+
+ threaded.Buffers.AssignBuffer(command._threadedHandle, renderer.CreateBuffer(command._size, hint));
}
}
}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataCommand.cs
index 1f519ccd..91320d45 100644
--- a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataCommand.cs
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataCommand.cs
@@ -18,9 +18,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
public static void Run(ref TextureGetDataCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
- ReadOnlySpan<byte> result = command._texture.Get(threaded).Base.GetData();
+ PinnedSpan<byte> result = command._texture.Get(threaded).Base.GetData();
- command._result.Get(threaded).Result = new PinnedSpan<byte>(result);
+ command._result.Get(threaded).Result = result;
}
}
}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataSliceCommand.cs b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataSliceCommand.cs
index 5ac05971..ec06cc4d 100644
--- a/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataSliceCommand.cs
+++ b/Ryujinx.Graphics.GAL/Multithreading/Commands/Texture/TextureGetDataSliceCommand.cs
@@ -22,9 +22,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands.Texture
public static void Run(ref TextureGetDataSliceCommand command, ThreadedRenderer threaded, IRenderer renderer)
{
- ReadOnlySpan<byte> result = command._texture.Get(threaded).Base.GetData(command._layer, command._level);
+ PinnedSpan<byte> result = command._texture.Get(threaded).Base.GetData(command._layer, command._level);
- command._result.Get(threaded).Result = new PinnedSpan<byte>(result);
+ command._result.Get(threaded).Result = result;
}
}
}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Model/PinnedSpan.cs b/Ryujinx.Graphics.GAL/Multithreading/Model/PinnedSpan.cs
deleted file mode 100644
index 16e148c2..00000000
--- a/Ryujinx.Graphics.GAL/Multithreading/Model/PinnedSpan.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace Ryujinx.Graphics.GAL.Multithreading.Model
-{
- unsafe struct PinnedSpan<T> where T : unmanaged
- {
- private void* _ptr;
- private int _size;
-
- public PinnedSpan(ReadOnlySpan<T> span)
- {
- _ptr = Unsafe.AsPointer(ref MemoryMarshal.GetReference(span));
- _size = span.Length;
- }
-
- public ReadOnlySpan<T> Get()
- {
- return new ReadOnlySpan<T>(_ptr, _size * Unsafe.SizeOf<T>());
- }
- }
-}
diff --git a/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs b/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs
index 1267ab79..ee1cfa29 100644
--- a/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs
+++ b/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTexture.cs
@@ -72,7 +72,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
return newTex;
}
- public ReadOnlySpan<byte> GetData()
+ public PinnedSpan<byte> GetData()
{
if (_renderer.IsGpuThread())
{
@@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
_renderer.New<TextureGetDataCommand>().Set(Ref(this), Ref(box));
_renderer.InvokeCommand();
- return box.Result.Get();
+ return box.Result;
}
else
{
@@ -90,7 +90,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
}
}
- public ReadOnlySpan<byte> GetData(int layer, int level)
+ public PinnedSpan<byte> GetData(int layer, int level)
{
if (_renderer.IsGpuThread())
{
@@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources
_renderer.New<TextureGetDataSliceCommand>().Set(Ref(this), Ref(box), layer, level);
_renderer.InvokeCommand();
- return box.Result.Get();
+ return box.Result;
}
else
{
diff --git a/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs b/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs
index 74326f1d..2148f43f 100644
--- a/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs
+++ b/Ryujinx.Graphics.GAL/Multithreading/ThreadedRenderer.cs
@@ -265,10 +265,10 @@ namespace Ryujinx.Graphics.GAL.Multithreading
}
}
- public BufferHandle CreateBuffer(int size)
+ public BufferHandle CreateBuffer(int size, BufferHandle storageHint)
{
BufferHandle handle = Buffers.CreateBufferHandle();
- New<CreateBufferCommand>().Set(handle, size);
+ New<CreateBufferCommand>().Set(handle, size, storageHint);
QueueCommand();
return handle;
@@ -329,7 +329,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
QueueCommand();
}
- public ReadOnlySpan<byte> GetBufferData(BufferHandle buffer, int offset, int size)
+ public PinnedSpan<byte> GetBufferData(BufferHandle buffer, int offset, int size)
{
if (IsGpuThread())
{
@@ -337,7 +337,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading
New<BufferGetDataCommand>().Set(buffer, offset, size, Ref(box));
InvokeCommand();
- return box.Result.Get();
+ return box.Result;
}
else
{
diff --git a/Ryujinx.Graphics.GAL/PinnedSpan.cs b/Ryujinx.Graphics.GAL/PinnedSpan.cs
new file mode 100644
index 00000000..275b3b86
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/PinnedSpan.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.Graphics.GAL
+{
+ public unsafe struct PinnedSpan<T> : IDisposable where T : unmanaged
+ {
+ private void* _ptr;
+ private int _size;
+ private Action _disposeAction;
+
+ /// <summary>
+ /// Creates a new PinnedSpan from an existing ReadOnlySpan. The span *must* be pinned in memory.
+ /// The data must be guaranteed to live until disposeAction is called.
+ /// </summary>
+ /// <param name="span">Existing span</param>
+ /// <param name="disposeAction">Action to call on dispose</param>
+ /// <remarks>
+ /// If a dispose action is not provided, it is safe to assume the resource will be available until the next call.
+ /// </remarks>
+ public static PinnedSpan<T> UnsafeFromSpan(ReadOnlySpan<T> span, Action disposeAction = null)
+ {
+ return new PinnedSpan<T>(Unsafe.AsPointer(ref MemoryMarshal.GetReference(span)), span.Length, disposeAction);
+ }
+
+ /// <summary>
+ /// Creates a new PinnedSpan from an existing unsafe region. The data must be guaranteed to live until disposeAction is called.
+ /// </summary>
+ /// <param name="ptr">Pointer to the region</param>
+ /// <param name="size">The total items of T the region contains</param>
+ /// <param name="disposeAction">Action to call on dispose</param>
+ /// <remarks>
+ /// If a dispose action is not provided, it is safe to assume the resource will be available until the next call.
+ /// </remarks>
+ public PinnedSpan(void* ptr, int size, Action disposeAction = null)
+ {
+ _ptr = ptr;
+ _size = size;
+ _disposeAction = disposeAction;
+ }
+
+ public ReadOnlySpan<T> Get()
+ {
+ return new ReadOnlySpan<T>(_ptr, _size * Unsafe.SizeOf<T>());
+ }
+
+ public void Dispose()
+ {
+ _disposeAction?.Invoke();
+ }
+ }
+}