diff --git a/Ryujinx.Graphics.GAL/BufferHandle.cs b/Ryujinx.Graphics.GAL/BufferHandle.cs new file mode 100644 index 000000000..49f834425 --- /dev/null +++ b/Ryujinx.Graphics.GAL/BufferHandle.cs @@ -0,0 +1,22 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.InteropServices; + +namespace Ryujinx.Graphics.GAL +{ + [StructLayout(LayoutKind.Sequential, Size = 8)] + public struct BufferHandle : IEquatable + { + private readonly ulong _value; + + public static BufferHandle Null => new BufferHandle(0); + + private BufferHandle(ulong value) => _value = value; + + public override bool Equals(object obj) => obj is BufferHandle handle && Equals(handle); + public bool Equals([AllowNull] BufferHandle other) => other._value == _value; + public override int GetHashCode() => _value.GetHashCode(); + public static bool operator ==(BufferHandle left, BufferHandle right) => left.Equals(right); + public static bool operator !=(BufferHandle left, BufferHandle right) => !(left == right); + } +} diff --git a/Ryujinx.Graphics.GAL/BufferRange.cs b/Ryujinx.Graphics.GAL/BufferRange.cs index a35636aa7..34d523f9f 100644 --- a/Ryujinx.Graphics.GAL/BufferRange.cs +++ b/Ryujinx.Graphics.GAL/BufferRange.cs @@ -2,18 +2,18 @@ namespace Ryujinx.Graphics.GAL { public struct BufferRange { - private static BufferRange _empty = new BufferRange(null, 0, 0); + private static readonly BufferRange _empty = new BufferRange(BufferHandle.Null, 0, 0); public BufferRange Empty => _empty; - public IBuffer Buffer { get; } + public BufferHandle Handle { get; } public int Offset { get; } public int Size { get; } - public BufferRange(IBuffer buffer, int offset, int size) + public BufferRange(BufferHandle handle, int offset, int size) { - Buffer = buffer; + Handle = handle; Offset = offset; Size = size; } diff --git a/Ryujinx.Graphics.GAL/IBuffer.cs b/Ryujinx.Graphics.GAL/IBuffer.cs deleted file mode 100644 index 43e376918..000000000 --- a/Ryujinx.Graphics.GAL/IBuffer.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace Ryujinx.Graphics.GAL -{ - public interface IBuffer : IDisposable - { - void CopyTo(IBuffer destination, int srcOffset, int dstOffset, int size); - - byte[] GetData(int offset, int size); - - void SetData(ReadOnlySpan data); - - void SetData(int offset, ReadOnlySpan data); - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs index 3bf7ab934..22e4e9e21 100644 --- a/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/Ryujinx.Graphics.GAL/IPipeline.cs @@ -1,4 +1,5 @@ using Ryujinx.Graphics.Shader; +using System; namespace Ryujinx.Graphics.GAL { @@ -14,6 +15,8 @@ namespace Ryujinx.Graphics.GAL int stencilValue, int stencilMask); + void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size); + void DispatchCompute(int groupsX, int groupsY, int groupsZ); void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance); @@ -49,7 +52,7 @@ namespace Ryujinx.Graphics.GAL void SetRasterizerDiscard(bool discard); - void SetRenderTargetColorMasks(uint[] componentMask); + void SetRenderTargetColorMasks(ReadOnlySpan componentMask); void SetRenderTargets(ITexture[] colors, ITexture depthStencil); @@ -68,10 +71,10 @@ namespace Ryujinx.Graphics.GAL void SetUserClipDistance(int index, bool enableClip); - void SetVertexAttribs(VertexAttribDescriptor[] vertexAttribs); - void SetVertexBuffers(VertexBufferDescriptor[] vertexBuffers); + void SetVertexAttribs(ReadOnlySpan vertexAttribs); + void SetVertexBuffers(ReadOnlySpan vertexBuffers); - void SetViewports(int first, Viewport[] viewports); + void SetViewports(int first, ReadOnlySpan viewports); void TextureBarrier(); void TextureBarrierTiled(); diff --git a/Ryujinx.Graphics.GAL/IRenderer.cs b/Ryujinx.Graphics.GAL/IRenderer.cs index 4a45f5cb4..c41b19fe5 100644 --- a/Ryujinx.Graphics.GAL/IRenderer.cs +++ b/Ryujinx.Graphics.GAL/IRenderer.cs @@ -11,15 +11,21 @@ namespace Ryujinx.Graphics.GAL IShader CompileShader(ShaderProgram shader); - IBuffer CreateBuffer(int size); + BufferHandle CreateBuffer(int size); IProgram CreateProgram(IShader[] shaders); ISampler CreateSampler(SamplerCreateInfo info); ITexture CreateTexture(TextureCreateInfo info); + void DeleteBuffer(BufferHandle buffer); + + byte[] GetBufferData(BufferHandle buffer, int offset, int size); + Capabilities GetCapabilities(); + void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan data); + void UpdateCounters(); ICounterEvent ReportCounter(CounterType type, EventHandler resultHandler); diff --git a/Ryujinx.Graphics.Gpu/Constants.cs b/Ryujinx.Graphics.Gpu/Constants.cs index 1ae902731..ac6b6139c 100644 --- a/Ryujinx.Graphics.Gpu/Constants.cs +++ b/Ryujinx.Graphics.Gpu/Constants.cs @@ -45,6 +45,11 @@ namespace Ryujinx.Graphics.Gpu /// public const int ShaderStages = 5; + /// + /// Maximum number of vertex attributes. + /// + public const int TotalVertexAttribs = 16; + /// /// Maximum number of vertex buffers. /// diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index 5ead87a0e..acb5ad5c4 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -570,9 +570,9 @@ namespace Ryujinx.Graphics.Gpu.Engine /// Current GPU state private void UpdateVertexAttribState(GpuState state) { - VertexAttribDescriptor[] vertexAttribs = new VertexAttribDescriptor[16]; + Span vertexAttribs = stackalloc VertexAttribDescriptor[Constants.TotalVertexAttribs]; - for (int index = 0; index < 16; index++) + for (int index = 0; index < Constants.TotalVertexAttribs; index++) { var vertexAttrib = state.Get(MethodOffset.VertexAttribState, index); @@ -660,7 +660,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { _isAnyVbInstanced = false; - for (int index = 0; index < 16; index++) + for (int index = 0; index < Constants.TotalVertexBuffers; index++) { var vertexBuffer = state.Get(MethodOffset.VertexBufferState, index); @@ -728,7 +728,7 @@ namespace Ryujinx.Graphics.Gpu.Engine { bool rtColorMaskShared = state.Get(MethodOffset.RtColorMaskShared); - uint[] componentMasks = new uint[Constants.TotalRenderTargets]; + Span componentMasks = stackalloc uint[Constants.TotalRenderTargets]; for (int index = 0; index < Constants.TotalRenderTargets; index++) { diff --git a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs index 4dd96878a..5fe85d2ea 100644 --- a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs +++ b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs @@ -11,9 +11,9 @@ namespace Ryujinx.Graphics.Gpu.Memory private readonly GpuContext _context; /// - /// Host buffer object. + /// Host buffer handle. /// - public IBuffer HostBuffer { get; } + public BufferHandle Handle { get; } /// /// Start address of the buffer in guest memory. @@ -46,7 +46,7 @@ namespace Ryujinx.Graphics.Gpu.Memory Address = address; Size = size; - HostBuffer = context.Renderer.CreateBuffer((int)size); + Handle = context.Renderer.CreateBuffer((int)size); _modifiedRanges = new (ulong, ulong)[size / PhysicalMemory.PageSize]; @@ -66,7 +66,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { int offset = (int)(address - Address); - return new BufferRange(HostBuffer, offset, (int)size); + return new BufferRange(Handle, offset, (int)size); } /// @@ -125,7 +125,7 @@ namespace Ryujinx.Graphics.Gpu.Memory int offset = (int)(mAddress - Address); - HostBuffer.SetData(offset, _context.PhysicalMemory.GetSpan(mAddress, (int)mSize)); + _context.Renderer.SetBufferData(Handle, offset, _context.PhysicalMemory.GetSpan(mAddress, (int)mSize)); } } @@ -136,7 +136,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// The offset of the destination buffer to copy into public void CopyTo(Buffer destination, int dstOffset) { - HostBuffer.CopyTo(destination.HostBuffer, 0, dstOffset, (int)Size); + _context.Renderer.Pipeline.CopyBuffer(Handle, destination.Handle, 0, dstOffset, (int)Size); } /// @@ -149,7 +149,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { int offset = (int)(address - Address); - byte[] data = HostBuffer.GetData(offset, (int)size); + byte[] data = _context.Renderer.GetBufferData(Handle, offset, (int)size); _context.PhysicalMemory.Write(address, data); } @@ -159,7 +159,7 @@ namespace Ryujinx.Graphics.Gpu.Memory /// public void Dispose() { - HostBuffer.Dispose(); + _context.Renderer.DeleteBuffer(Handle); } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs index 2fe0ecbb2..39d1cd6f1 100644 --- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs @@ -477,7 +477,7 @@ namespace Ryujinx.Graphics.Gpu.Memory { _vertexBuffersDirty = false; - VertexBufferDescriptor[] vertexBuffers = new VertexBufferDescriptor[Constants.TotalVertexBuffers]; + Span vertexBuffers = stackalloc VertexBufferDescriptor[Constants.TotalVertexBuffers]; for (int index = 0; (vbEnableMask >> index) != 0; index++) { @@ -666,8 +666,9 @@ namespace Ryujinx.Graphics.Gpu.Memory int srcOffset = (int)(srcAddress - srcBuffer.Address); int dstOffset = (int)(dstAddress - dstBuffer.Address); - srcBuffer.HostBuffer.CopyTo( - dstBuffer.HostBuffer, + _context.Renderer.Pipeline.CopyBuffer( + srcBuffer.Handle, + dstBuffer.Handle, srcOffset, dstOffset, (int)size); diff --git a/Ryujinx.Graphics.OpenGL/Buffer.cs b/Ryujinx.Graphics.OpenGL/Buffer.cs index db3e94ba5..e8fd9a6bf 100644 --- a/Ryujinx.Graphics.OpenGL/Buffer.cs +++ b/Ryujinx.Graphics.OpenGL/Buffer.cs @@ -4,22 +4,22 @@ using System; namespace Ryujinx.Graphics.OpenGL { - class Buffer : IBuffer + static class Buffer { - public int Handle { get; } - - public Buffer(int size) + public static BufferHandle Create(int size) { - Handle = GL.GenBuffer(); + int handle = GL.GenBuffer(); - GL.BindBuffer(BufferTarget.CopyWriteBuffer, Handle); + GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle); GL.BufferData(BufferTarget.CopyWriteBuffer, size, IntPtr.Zero, BufferUsageHint.DynamicDraw); + + return Handle.FromInt32(handle); } - public void CopyTo(IBuffer destination, int srcOffset, int dstOffset, int size) + public static void Copy(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size) { - GL.BindBuffer(BufferTarget.CopyReadBuffer, Handle); - GL.BindBuffer(BufferTarget.CopyWriteBuffer, ((Buffer)destination).Handle); + GL.BindBuffer(BufferTarget.CopyReadBuffer, source.ToInt32()); + GL.BindBuffer(BufferTarget.CopyWriteBuffer, destination.ToInt32()); GL.CopyBufferSubData( BufferTarget.CopyReadBuffer, @@ -29,9 +29,9 @@ namespace Ryujinx.Graphics.OpenGL (IntPtr)size); } - public byte[] GetData(int offset, int size) + public static byte[] GetData(BufferHandle buffer, int offset, int size) { - GL.BindBuffer(BufferTarget.CopyReadBuffer, Handle); + GL.BindBuffer(BufferTarget.CopyReadBuffer, buffer.ToInt32()); byte[] data = new byte[size]; @@ -40,22 +40,9 @@ namespace Ryujinx.Graphics.OpenGL return data; } - public void SetData(ReadOnlySpan data) + public static void SetData(BufferHandle buffer, int offset, ReadOnlySpan data) { - unsafe - { - GL.BindBuffer(BufferTarget.CopyWriteBuffer, Handle); - - fixed (byte* ptr = data) - { - GL.BufferData(BufferTarget.CopyWriteBuffer, data.Length, (IntPtr)ptr, BufferUsageHint.DynamicDraw); - } - } - } - - public void SetData(int offset, ReadOnlySpan data) - { - GL.BindBuffer(BufferTarget.CopyWriteBuffer, Handle); + GL.BindBuffer(BufferTarget.CopyWriteBuffer, buffer.ToInt32()); unsafe { @@ -66,9 +53,9 @@ namespace Ryujinx.Graphics.OpenGL } } - public void Dispose() + public static void Delete(BufferHandle buffer) { - GL.DeleteBuffer(Handle); + GL.DeleteBuffer(buffer.ToInt32()); } } } diff --git a/Ryujinx.Graphics.OpenGL/Constants.cs b/Ryujinx.Graphics.OpenGL/Constants.cs new file mode 100644 index 000000000..9775b240d --- /dev/null +++ b/Ryujinx.Graphics.OpenGL/Constants.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.Graphics.OpenGL +{ + static class Constants + { + public const int MaxRenderTargets = 8; + public const int MaxViewports = 16; + public const int MaxVertexAttribs = 16; + public const int MaxVertexBuffers = 16; + } +} diff --git a/Ryujinx.Graphics.OpenGL/Framebuffer.cs b/Ryujinx.Graphics.OpenGL/Framebuffer.cs index 23f015b18..e66dcaca8 100644 --- a/Ryujinx.Graphics.OpenGL/Framebuffer.cs +++ b/Ryujinx.Graphics.OpenGL/Framebuffer.cs @@ -1,5 +1,6 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.OpenGL.Image; using System; namespace Ryujinx.Graphics.OpenGL diff --git a/Ryujinx.Graphics.OpenGL/Handle.cs b/Ryujinx.Graphics.OpenGL/Handle.cs new file mode 100644 index 000000000..4b2f05e67 --- /dev/null +++ b/Ryujinx.Graphics.OpenGL/Handle.cs @@ -0,0 +1,23 @@ +using Ryujinx.Graphics.GAL; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace Ryujinx.Graphics.OpenGL +{ + static class Handle + { + public static T FromInt32(int handle) where T : unmanaged + { + Debug.Assert(Unsafe.SizeOf() == sizeof(ulong)); + + ulong handle64 = (uint)handle; + + return Unsafe.As(ref handle64); + } + + public static int ToInt32(this BufferHandle handle) + { + return (int)Unsafe.As(ref handle); + } + } +} diff --git a/Ryujinx.Graphics.OpenGL/Sampler.cs b/Ryujinx.Graphics.OpenGL/Image/Sampler.cs similarity index 98% rename from Ryujinx.Graphics.OpenGL/Sampler.cs rename to Ryujinx.Graphics.OpenGL/Image/Sampler.cs index 674fc7978..e13f0da3f 100644 --- a/Ryujinx.Graphics.OpenGL/Sampler.cs +++ b/Ryujinx.Graphics.OpenGL/Image/Sampler.cs @@ -1,7 +1,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Graphics.GAL; -namespace Ryujinx.Graphics.OpenGL +namespace Ryujinx.Graphics.OpenGL.Image { class Sampler : ISampler { diff --git a/Ryujinx.Graphics.OpenGL/TextureBase.cs b/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs similarity index 88% rename from Ryujinx.Graphics.OpenGL/TextureBase.cs rename to Ryujinx.Graphics.OpenGL/Image/TextureBase.cs index f4ab0bda4..a4209ea15 100644 --- a/Ryujinx.Graphics.OpenGL/TextureBase.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureBase.cs @@ -1,10 +1,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Graphics.GAL; -using System; -using System.Collections.Generic; -using System.Text; -namespace Ryujinx.Graphics.OpenGL +namespace Ryujinx.Graphics.OpenGL.Image { class TextureBase { diff --git a/Ryujinx.Graphics.OpenGL/TextureBuffer.cs b/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs similarity index 79% rename from Ryujinx.Graphics.OpenGL/TextureBuffer.cs rename to Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs index fb18c6ee7..2c69571c3 100644 --- a/Ryujinx.Graphics.OpenGL/TextureBuffer.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureBuffer.cs @@ -2,14 +2,14 @@ using Ryujinx.Graphics.GAL; using System; -namespace Ryujinx.Graphics.OpenGL +namespace Ryujinx.Graphics.OpenGL.Image { class TextureBuffer : TextureBase, ITexture { private int _bufferOffset; private int _bufferSize; - private Buffer _buffer; + private BufferHandle _buffer; public TextureBuffer(TextureCreateInfo info) : base(info) {} @@ -30,24 +30,24 @@ namespace Ryujinx.Graphics.OpenGL public byte[] GetData() { - return _buffer?.GetData(_bufferOffset, _bufferSize); + return Buffer.GetData(_buffer, _bufferOffset, _bufferSize); } public void SetData(ReadOnlySpan data) { - _buffer?.SetData(_bufferOffset, data.Slice(0, Math.Min(data.Length, _bufferSize))); + Buffer.SetData(_buffer, _bufferOffset, data.Slice(0, Math.Min(data.Length, _bufferSize))); } public void SetStorage(BufferRange buffer) { - if (buffer.Buffer == _buffer && + if (buffer.Handle == _buffer && buffer.Offset == _bufferOffset && buffer.Size == _bufferSize) { return; } - _buffer = (Buffer)buffer.Buffer; + _buffer = buffer.Handle; _bufferOffset = buffer.Offset; _bufferSize = buffer.Size; @@ -55,7 +55,7 @@ namespace Ryujinx.Graphics.OpenGL SizedInternalFormat format = (SizedInternalFormat)FormatTable.GetFormatInfo(Info.Format).PixelInternalFormat; - GL.TexBufferRange(TextureBufferTarget.TextureBuffer, format, _buffer.Handle, (IntPtr)buffer.Offset, buffer.Size); + GL.TexBufferRange(TextureBufferTarget.TextureBuffer, format, _buffer.ToInt32(), (IntPtr)buffer.Offset, buffer.Size); } public void Dispose() diff --git a/Ryujinx.Graphics.OpenGL/TextureCopy.cs b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs similarity index 99% rename from Ryujinx.Graphics.OpenGL/TextureCopy.cs rename to Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs index 59db94a47..1cef61a9e 100644 --- a/Ryujinx.Graphics.OpenGL/TextureCopy.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs @@ -2,7 +2,7 @@ using Ryujinx.Graphics.GAL; using OpenTK.Graphics.OpenGL; using System; -namespace Ryujinx.Graphics.OpenGL +namespace Ryujinx.Graphics.OpenGL.Image { class TextureCopy : IDisposable { diff --git a/Ryujinx.Graphics.OpenGL/TextureCopyUnscaled.cs b/Ryujinx.Graphics.OpenGL/Image/TextureCopyUnscaled.cs similarity index 98% rename from Ryujinx.Graphics.OpenGL/TextureCopyUnscaled.cs rename to Ryujinx.Graphics.OpenGL/Image/TextureCopyUnscaled.cs index 5ae75d9c0..284011385 100644 --- a/Ryujinx.Graphics.OpenGL/TextureCopyUnscaled.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureCopyUnscaled.cs @@ -3,7 +3,7 @@ using Ryujinx.Common; using Ryujinx.Graphics.GAL; using System; -namespace Ryujinx.Graphics.OpenGL +namespace Ryujinx.Graphics.OpenGL.Image { static class TextureCopyUnscaled { diff --git a/Ryujinx.Graphics.OpenGL/TextureStorage.cs b/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs similarity index 99% rename from Ryujinx.Graphics.OpenGL/TextureStorage.cs rename to Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs index b680f3a6b..baf8e65d0 100644 --- a/Ryujinx.Graphics.OpenGL/TextureStorage.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs @@ -2,7 +2,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; -namespace Ryujinx.Graphics.OpenGL +namespace Ryujinx.Graphics.OpenGL.Image { class TextureStorage { diff --git a/Ryujinx.Graphics.OpenGL/TextureView.cs b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs similarity index 99% rename from Ryujinx.Graphics.OpenGL/TextureView.cs rename to Ryujinx.Graphics.OpenGL/Image/TextureView.cs index 0ab59d425..0b24a2962 100644 --- a/Ryujinx.Graphics.OpenGL/TextureView.cs +++ b/Ryujinx.Graphics.OpenGL/Image/TextureView.cs @@ -2,7 +2,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Graphics.GAL; using System; -namespace Ryujinx.Graphics.OpenGL +namespace Ryujinx.Graphics.OpenGL.Image { class TextureView : TextureBase, ITexture { diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 80b071088..05383f5d7 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -1,6 +1,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.OpenGL.Image; using Ryujinx.Graphics.OpenGL.Queries; using Ryujinx.Graphics.Shader; using System; @@ -32,7 +33,7 @@ namespace Ryujinx.Graphics.OpenGL private ClipOrigin _clipOrigin; private ClipDepthMode _clipDepthMode; - private uint[] _componentMasks; + private readonly uint[] _componentMasks; private bool _scissor0Enable = false; @@ -43,6 +44,13 @@ namespace Ryujinx.Graphics.OpenGL _rasterizerDiscard = false; _clipOrigin = ClipOrigin.LowerLeft; _clipDepthMode = ClipDepthMode.NegativeOneToOne; + + _componentMasks = new uint[Constants.MaxRenderTargets]; + + for (int index = 0; index < Constants.MaxRenderTargets; index++) + { + _componentMasks[index] = 0xf; + } } public void Barrier() @@ -112,6 +120,11 @@ namespace Ryujinx.Graphics.OpenGL _framebuffer.SignalModified(); } + public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size) + { + Buffer.Copy(source, destination, srcOffset, dstOffset, size); + } + public void DispatchCompute(int groupsX, int groupsY, int groupsZ) { if (!_program.IsLinked) @@ -631,7 +644,7 @@ namespace Ryujinx.Graphics.OpenGL EnsureVertexArray(); - _vertexArray.SetIndexBuffer((Buffer)buffer.Buffer); + _vertexArray.SetIndexBuffer(buffer.Handle); } public void SetPointSize(float size) @@ -661,7 +674,6 @@ namespace Ryujinx.Graphics.OpenGL public void SetProgram(IProgram program) { _program = (Program)program; - _program.Bind(); } @@ -679,12 +691,12 @@ namespace Ryujinx.Graphics.OpenGL _rasterizerDiscard = discard; } - public void SetRenderTargetColorMasks(uint[] componentMasks) + public void SetRenderTargetColorMasks(ReadOnlySpan componentMasks) { - _componentMasks = (uint[])componentMasks.Clone(); - for (int index = 0; index < componentMasks.Length; index++) { + _componentMasks[index] = componentMasks[index]; + RestoreComponentMask(index); } } @@ -823,21 +835,21 @@ namespace Ryujinx.Graphics.OpenGL GL.Enable(EnableCap.ClipDistance0 + index); } - public void SetVertexAttribs(VertexAttribDescriptor[] vertexAttribs) + public void SetVertexAttribs(ReadOnlySpan vertexAttribs) { EnsureVertexArray(); _vertexArray.SetVertexAttributes(vertexAttribs); } - public void SetVertexBuffers(VertexBufferDescriptor[] vertexBuffers) + public void SetVertexBuffers(ReadOnlySpan vertexBuffers) { EnsureVertexArray(); _vertexArray.SetVertexBuffers(vertexBuffers); } - public void SetViewports(int first, Viewport[] viewports) + public void SetViewports(int first, ReadOnlySpan viewports) { bool flipY = false; @@ -906,18 +918,16 @@ namespace Ryujinx.Graphics.OpenGL ? BufferRangeTarget.ShaderStorageBuffer : BufferRangeTarget.UniformBuffer; - if (buffer.Buffer == null) + if (buffer.Handle == null) { GL.BindBufferRange(target, bindingPoint, 0, IntPtr.Zero, 0); return; } - int bufferHandle = ((Buffer)buffer.Buffer).Handle; - IntPtr bufferOffset = (IntPtr)buffer.Offset; - GL.BindBufferRange(target, bindingPoint, bufferHandle, bufferOffset, buffer.Size); + GL.BindBufferRange(target, bindingPoint, buffer.Handle.ToInt32(), bufferOffset, buffer.Size); } private void SetOrigin(ClipOrigin origin) @@ -997,15 +1007,12 @@ namespace Ryujinx.Graphics.OpenGL private void RestoreComponentMask(int index) { - if (_componentMasks != null) - { - GL.ColorMask( - index, - (_componentMasks[index] & 1u) != 0, - (_componentMasks[index] & 2u) != 0, - (_componentMasks[index] & 4u) != 0, - (_componentMasks[index] & 8u) != 0); - } + GL.ColorMask( + index, + (_componentMasks[index] & 1u) != 0, + (_componentMasks[index] & 2u) != 0, + (_componentMasks[index] & 4u) != 0, + (_componentMasks[index] & 8u) != 0); } public void RestoreScissor0Enable() diff --git a/Ryujinx.Graphics.OpenGL/Renderer.cs b/Ryujinx.Graphics.OpenGL/Renderer.cs index b3ae8c33d..15b223f59 100644 --- a/Ryujinx.Graphics.OpenGL/Renderer.cs +++ b/Ryujinx.Graphics.OpenGL/Renderer.cs @@ -1,6 +1,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.OpenGL.Image; using Ryujinx.Graphics.OpenGL.Queries; using Ryujinx.Graphics.Shader; using System; @@ -38,9 +39,9 @@ namespace Ryujinx.Graphics.OpenGL return new Shader(shader); } - public IBuffer CreateBuffer(int size) + public BufferHandle CreateBuffer(int size) { - return new Buffer(size); + return Buffer.Create(size); } public IProgram CreateProgram(IShader[] shaders) @@ -58,6 +59,16 @@ namespace Ryujinx.Graphics.OpenGL return info.Target == Target.TextureBuffer ? new TextureBuffer(info) : new TextureStorage(this, info).CreateDefaultView(); } + public void DeleteBuffer(BufferHandle buffer) + { + Buffer.Delete(buffer); + } + + public byte[] GetBufferData(BufferHandle buffer, int offset, int size) + { + return Buffer.GetData(buffer, offset, size); + } + public Capabilities GetCapabilities() { return new Capabilities( @@ -68,6 +79,11 @@ namespace Ryujinx.Graphics.OpenGL HwCapabilities.MaxSupportedAnisotropy); } + public void SetBufferData(BufferHandle buffer, int offset, ReadOnlySpan data) + { + Buffer.SetData(buffer, offset, data); + } + public void UpdateCounters() { _counters.Update(); diff --git a/Ryujinx.Graphics.OpenGL/VertexArray.cs b/Ryujinx.Graphics.OpenGL/VertexArray.cs index 43d200a40..cc352761d 100644 --- a/Ryujinx.Graphics.OpenGL/VertexArray.cs +++ b/Ryujinx.Graphics.OpenGL/VertexArray.cs @@ -10,12 +10,18 @@ namespace Ryujinx.Graphics.OpenGL private bool _needsAttribsUpdate; - private VertexBufferDescriptor[] _vertexBuffers; - private VertexAttribDescriptor[] _vertexAttribs; + private readonly VertexAttribDescriptor[] _vertexAttribs; + private readonly VertexBufferDescriptor[] _vertexBuffers; + + private int _vertexAttribsCount; + private int _vertexBuffersCount; public VertexArray() { Handle = GL.GenVertexArray(); + + _vertexAttribs = new VertexAttribDescriptor[Constants.MaxVertexAttribs]; + _vertexBuffers = new VertexBufferDescriptor[Constants.MaxVertexBuffers]; } public void Bind() @@ -23,17 +29,17 @@ namespace Ryujinx.Graphics.OpenGL GL.BindVertexArray(Handle); } - public void SetVertexBuffers(VertexBufferDescriptor[] vertexBuffers) + public void SetVertexBuffers(ReadOnlySpan vertexBuffers) { int bindingIndex = 0; - foreach (VertexBufferDescriptor vb in vertexBuffers) + for (int index = 0; index < vertexBuffers.Length; index++) { - if (vb.Buffer.Buffer != null) - { - int bufferHandle = ((Buffer)vb.Buffer.Buffer).Handle; + VertexBufferDescriptor vb = vertexBuffers[index]; - GL.BindVertexBuffer(bindingIndex, bufferHandle, (IntPtr)vb.Buffer.Offset, vb.Stride); + if (vb.Buffer.Handle != null) + { + GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride); GL.VertexBindingDivisor(bindingIndex, vb.Divisor); } @@ -42,31 +48,35 @@ namespace Ryujinx.Graphics.OpenGL GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0); } + _vertexBuffers[index] = vb; + bindingIndex++; } - _vertexBuffers = vertexBuffers; + _vertexBuffersCount = bindingIndex; _needsAttribsUpdate = true; } - public void SetVertexAttributes(VertexAttribDescriptor[] vertexAttribs) + public void SetVertexAttributes(ReadOnlySpan vertexAttribs) { - int attribIndex = 0; + int index = 0; - foreach (VertexAttribDescriptor attrib in vertexAttribs) + for (; index < vertexAttribs.Length; index++) { + VertexAttribDescriptor attrib = vertexAttribs[index]; + FormatInfo fmtInfo = FormatTable.GetFormatInfo(attrib.Format); if (attrib.IsZero) { // Disabling the attribute causes the shader to read a constant value. // The value is configurable, but by default is a vector of (0, 0, 0, 1). - GL.DisableVertexAttribArray(attribIndex); + GL.DisableVertexAttribArray(index); } else { - GL.EnableVertexAttribArray(attribIndex); + GL.EnableVertexAttribArray(index); } int offset = attrib.Offset; @@ -79,47 +89,47 @@ namespace Ryujinx.Graphics.OpenGL { VertexAttribType type = (VertexAttribType)fmtInfo.PixelType; - GL.VertexAttribFormat(attribIndex, size, type, fmtInfo.Normalized, offset); + GL.VertexAttribFormat(index, size, type, fmtInfo.Normalized, offset); } else { VertexAttribIntegerType type = (VertexAttribIntegerType)fmtInfo.PixelType; - GL.VertexAttribIFormat(attribIndex, size, type, offset); + GL.VertexAttribIFormat(index, size, type, offset); } - GL.VertexAttribBinding(attribIndex, attrib.BufferIndex); + GL.VertexAttribBinding(index, attrib.BufferIndex); - attribIndex++; + _vertexAttribs[index] = attrib; } - for (; attribIndex < 16; attribIndex++) + _vertexAttribsCount = index; + + for (; index < Constants.MaxVertexAttribs; index++) { - GL.DisableVertexAttribArray(attribIndex); + GL.DisableVertexAttribArray(index); } - - _vertexAttribs = vertexAttribs; } - public void SetIndexBuffer(Buffer indexBuffer) + public void SetIndexBuffer(BufferHandle buffer) { - GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer?.Handle ?? 0); + GL.BindBuffer(BufferTarget.ElementArrayBuffer, buffer.ToInt32()); } public void Validate() { - for (int attribIndex = 0; attribIndex < _vertexAttribs.Length; attribIndex++) + for (int attribIndex = 0; attribIndex < _vertexAttribsCount; attribIndex++) { VertexAttribDescriptor attrib = _vertexAttribs[attribIndex]; - if ((uint)attrib.BufferIndex >= _vertexBuffers.Length) + if ((uint)attrib.BufferIndex >= _vertexBuffersCount) { GL.DisableVertexAttribArray(attribIndex); continue; } - if (_vertexBuffers[attrib.BufferIndex].Buffer.Buffer == null) + if (_vertexBuffers[attrib.BufferIndex].Buffer.Handle == null) { GL.DisableVertexAttribArray(attribIndex); diff --git a/Ryujinx.Graphics.OpenGL/Window.cs b/Ryujinx.Graphics.OpenGL/Window.cs index 9f0007c4d..6e7ddbacb 100644 --- a/Ryujinx.Graphics.OpenGL/Window.cs +++ b/Ryujinx.Graphics.OpenGL/Window.cs @@ -1,5 +1,6 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.OpenGL.Image; using System; namespace Ryujinx.Graphics.OpenGL