aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.OpenGL
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.OpenGL')
-rw-r--r--src/Ryujinx.Graphics.OpenGL/Buffer.cs20
-rw-r--r--src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs5
-rw-r--r--src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs21
-rw-r--r--src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs30
-rw-r--r--src/Ryujinx.Graphics.OpenGL/PersistentBuffers.cs29
5 files changed, 102 insertions, 3 deletions
diff --git a/src/Ryujinx.Graphics.OpenGL/Buffer.cs b/src/Ryujinx.Graphics.OpenGL/Buffer.cs
index af7d191a..2a514310 100644
--- a/src/Ryujinx.Graphics.OpenGL/Buffer.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Buffer.cs
@@ -42,6 +42,20 @@ namespace Ryujinx.Graphics.OpenGL
return Handle.FromInt32<BufferHandle>(handle);
}
+ public static BufferHandle CreatePersistent(int size)
+ {
+ int handle = GL.GenBuffer();
+
+ GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle);
+ GL.BufferStorage(BufferTarget.CopyWriteBuffer, size, IntPtr.Zero,
+ BufferStorageFlags.MapPersistentBit |
+ BufferStorageFlags.MapCoherentBit |
+ BufferStorageFlags.ClientStorageBit |
+ BufferStorageFlags.MapReadBit);
+
+ return Handle.FromInt32<BufferHandle>(handle);
+ }
+
public static void Copy(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
{
GL.BindBuffer(BufferTarget.CopyReadBuffer, source.ToInt32());
@@ -60,7 +74,11 @@ namespace Ryujinx.Graphics.OpenGL
// Data in the persistent buffer and host array is guaranteed to be available
// until the next time the host thread requests data.
- if (HwCapabilities.UsePersistentBufferForFlush)
+ if (renderer.PersistentBuffers.TryGet(buffer, out IntPtr ptr))
+ {
+ return new PinnedSpan<byte>(IntPtr.Add(ptr, offset).ToPointer(), size);
+ }
+ else if (HwCapabilities.UsePersistentBufferForFlush)
{
return PinnedSpan<byte>.UnsafeFromSpan(renderer.PersistentBuffers.Default.GetBufferData(buffer, offset, size));
}
diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs
index 1e9e4d6b..116f70cc 100644
--- a/src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs
@@ -49,6 +49,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
return GetData();
}
+ public void CopyTo(BufferRange range, int layer, int level, int stride)
+ {
+ throw new NotImplementedException();
+ }
+
public void SetData(SpanOrArray<byte> data)
{
var dataSpan = data.AsSpan();
diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
index 804b3b03..f24a58fc 100644
--- a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
@@ -3,6 +3,7 @@ using Ryujinx.Common;
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL;
using System;
+using System.Diagnostics;
namespace Ryujinx.Graphics.OpenGL.Image
{
@@ -287,6 +288,26 @@ namespace Ryujinx.Graphics.OpenGL.Image
}
}
+ public void CopyTo(BufferRange range, int layer, int level, int stride)
+ {
+ if (stride != 0 && stride != BitUtils.AlignUp(Info.Width * Info.BytesPerPixel, 4))
+ {
+ throw new NotSupportedException("Stride conversion for texture copy to buffer not supported.");
+ }
+
+ GL.BindBuffer(BufferTarget.PixelPackBuffer, range.Handle.ToInt32());
+
+ FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
+ if (format.PixelFormat == PixelFormat.DepthStencil)
+ {
+ throw new InvalidOperationException("DepthStencil copy to buffer is not supported for layer/level > 0.");
+ }
+
+ int offset = WriteToPbo2D(range.Offset, layer, level);
+
+ Debug.Assert(offset == 0);
+ }
+
public void WriteToPbo(int offset, bool forceBgra)
{
WriteTo(IntPtr.Zero + offset, forceBgra);
diff --git a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs
index 3903b4d4..7d5fe893 100644
--- a/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs
+++ b/src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs
@@ -59,9 +59,30 @@ namespace Ryujinx.Graphics.OpenGL
public BufferHandle CreateBuffer(int size, BufferHandle storageHint)
{
+ return CreateBuffer(size, GAL.BufferAccess.Default);
+ }
+
+ public BufferHandle CreateBuffer(int size, GAL.BufferAccess access)
+ {
BufferCount++;
- return Buffer.Create(size);
+ if (access == GAL.BufferAccess.FlushPersistent)
+ {
+ BufferHandle handle = Buffer.CreatePersistent(size);
+
+ PersistentBuffers.Map(handle, size);
+
+ return handle;
+ }
+ else
+ {
+ return Buffer.Create(size);
+ }
+ }
+
+ public BufferHandle CreateBuffer(nint pointer, int size)
+ {
+ throw new NotSupportedException();
}
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
@@ -88,6 +109,8 @@ namespace Ryujinx.Graphics.OpenGL
public void DeleteBuffer(BufferHandle buffer)
{
+ PersistentBuffers.Unmap(buffer);
+
Buffer.Delete(buffer);
}
@@ -272,5 +295,10 @@ namespace Ryujinx.Graphics.OpenGL
{
ScreenCaptured?.Invoke(this, bitmap);
}
+
+ public bool PrepareHostMapping(nint address, ulong size)
+ {
+ return false;
+ }
}
}
diff --git a/src/Ryujinx.Graphics.OpenGL/PersistentBuffers.cs b/src/Ryujinx.Graphics.OpenGL/PersistentBuffers.cs
index 654e25b9..aac288b7 100644
--- a/src/Ryujinx.Graphics.OpenGL/PersistentBuffers.cs
+++ b/src/Ryujinx.Graphics.OpenGL/PersistentBuffers.cs
@@ -1,8 +1,9 @@
-using OpenTK.Graphics.OpenGL;
+using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image;
using System;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -13,6 +14,8 @@ namespace Ryujinx.Graphics.OpenGL
private PersistentBuffer _main = new PersistentBuffer();
private PersistentBuffer _background = new PersistentBuffer();
+ private Dictionary<BufferHandle, IntPtr> _maps = new Dictionary<BufferHandle, IntPtr>();
+
public PersistentBuffer Default => BackgroundContextWorker.InBackground ? _background : _main;
public void Dispose()
@@ -20,6 +23,30 @@ namespace Ryujinx.Graphics.OpenGL
_main?.Dispose();
_background?.Dispose();
}
+
+ public void Map(BufferHandle handle, int size)
+ {
+ GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle.ToInt32());
+ IntPtr ptr = GL.MapBufferRange(BufferTarget.CopyWriteBuffer, IntPtr.Zero, size, BufferAccessMask.MapReadBit | BufferAccessMask.MapPersistentBit);
+
+ _maps[handle] = ptr;
+ }
+
+ public void Unmap(BufferHandle handle)
+ {
+ if (_maps.ContainsKey(handle))
+ {
+ GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle.ToInt32());
+ GL.UnmapBuffer(BufferTarget.CopyWriteBuffer);
+
+ _maps.Remove(handle);
+ }
+ }
+
+ public bool TryGet(BufferHandle handle, out IntPtr ptr)
+ {
+ return _maps.TryGetValue(handle, out ptr);
+ }
}
class PersistentBuffer : IDisposable