diff options
Diffstat (limited to 'src/Ryujinx.Graphics.OpenGL')
| -rw-r--r-- | src/Ryujinx.Graphics.OpenGL/Buffer.cs | 20 | ||||
| -rw-r--r-- | src/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs | 5 | ||||
| -rw-r--r-- | src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs | 21 | ||||
| -rw-r--r-- | src/Ryujinx.Graphics.OpenGL/OpenGLRenderer.cs | 30 | ||||
| -rw-r--r-- | src/Ryujinx.Graphics.OpenGL/PersistentBuffers.cs | 29 |
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 |
