From caf049ed15f1c22d55aacfab79019538b2587e11 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Tue, 26 Jan 2021 18:44:07 -0300 Subject: [PATCH] Avoid some redundant GL calls (#1958) --- Ryujinx.Graphics.GAL/IPipeline.cs | 3 +- .../VertexAttribDescriptor.cs | 22 ++++- Ryujinx.Graphics.Gpu/Engine/Methods.cs | 8 +- Ryujinx.Graphics.OpenGL/Framebuffer.cs | 11 ++- Ryujinx.Graphics.OpenGL/Pipeline.cs | 34 +++---- Ryujinx.Graphics.OpenGL/VertexArray.cs | 88 +++++++++++++------ 6 files changed, 115 insertions(+), 51 deletions(-) diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs index 96ccfb2859..bb3a8dcac9 100644 --- a/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/Ryujinx.Graphics.GAL/IPipeline.cs @@ -68,8 +68,7 @@ namespace Ryujinx.Graphics.GAL void SetSampler(int binding, ISampler sampler); - void SetScissorEnable(int index, bool enable); - void SetScissor(int index, int x, int y, int width, int height); + void SetScissor(int index, bool enable, int x, int y, int width, int height); void SetStencilTest(StencilTestDescriptor stencilTest); diff --git a/Ryujinx.Graphics.GAL/VertexAttribDescriptor.cs b/Ryujinx.Graphics.GAL/VertexAttribDescriptor.cs index 1547658e47..b3248b621f 100644 --- a/Ryujinx.Graphics.GAL/VertexAttribDescriptor.cs +++ b/Ryujinx.Graphics.GAL/VertexAttribDescriptor.cs @@ -1,6 +1,8 @@ +using System; + namespace Ryujinx.Graphics.GAL { - public struct VertexAttribDescriptor + public struct VertexAttribDescriptor : IEquatable { public int BufferIndex { get; } public int Offset { get; } @@ -16,5 +18,23 @@ namespace Ryujinx.Graphics.GAL IsZero = isZero; Format = format; } + + public override bool Equals(object obj) + { + return obj is VertexAttribDescriptor other && Equals(other); + } + + public bool Equals(VertexAttribDescriptor other) + { + return BufferIndex == other.BufferIndex && + Offset == other.Offset && + IsZero == other.IsZero && + Format == other.Format; + } + + public override int GetHashCode() + { + return HashCode.Combine(BufferIndex, Offset, IsZero, Format); + } } } diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index d6bd51106c..a41fd5414d 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -436,8 +436,6 @@ namespace Ryujinx.Graphics.Gpu.Engine bool enable = scissor.Enable && (scissor.X1 != 0 || scissor.Y1 != 0 || scissor.X2 != 0xffff || scissor.Y2 != 0xffff); - _context.Renderer.Pipeline.SetScissorEnable(index, enable); - if (enable) { int x = scissor.X1; @@ -454,7 +452,11 @@ namespace Ryujinx.Graphics.Gpu.Engine height = (int)Math.Ceiling(height * scale); } - _context.Renderer.Pipeline.SetScissor(index, x, y, width, height); + _context.Renderer.Pipeline.SetScissor(index, true, x, y, width, height); + } + else + { + _context.Renderer.Pipeline.SetScissor(index, false, 0, 0, 0, 0); } } } diff --git a/Ryujinx.Graphics.OpenGL/Framebuffer.cs b/Ryujinx.Graphics.OpenGL/Framebuffer.cs index 015b0ec0ae..66bf892b31 100644 --- a/Ryujinx.Graphics.OpenGL/Framebuffer.cs +++ b/Ryujinx.Graphics.OpenGL/Framebuffer.cs @@ -2,6 +2,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.OpenGL.Image; using System; +using System.Runtime.CompilerServices; namespace Ryujinx.Graphics.OpenGL { @@ -29,21 +30,27 @@ namespace Ryujinx.Graphics.OpenGL return Handle; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AttachColor(int index, TextureView color) { + if (_colors[index] == color) + { + return; + } + FramebufferAttachment attachment = FramebufferAttachment.ColorAttachment0 + index; if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Amd || HwCapabilities.Vendor == HwCapabilities.GpuVendor.Intel) { GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.GetIncompatibleFormatViewHandle() ?? 0, 0); - - _colors[index] = color; } else { GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.Handle ?? 0, 0); } + + _colors[index] = color; } public void AttachDepthStencil(TextureView depthStencil) diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index b6a34e9cb8..f42187bdf7 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.OpenGL private readonly uint[] _componentMasks; - private bool _scissor0Enable = false; + private uint _scissorEnables; private bool _tfEnabled; private TransformFeedbackPrimitiveType _tfTopology; @@ -883,25 +883,27 @@ namespace Ryujinx.Graphics.OpenGL ((Sampler)sampler).Bind(binding); } - public void SetScissorEnable(int index, bool enable) + public void SetScissor(int index, bool enable, int x, int y, int width, int height) { - if (enable) + uint mask = 1u << index; + + if (!enable) { + if ((_scissorEnables & mask) != 0) + { + _scissorEnables &= ~mask; + GL.Disable(IndexedEnableCap.ScissorTest, index); + } + + return; + } + + if ((_scissorEnables & mask) == 0) + { + _scissorEnables |= mask; GL.Enable(IndexedEnableCap.ScissorTest, index); } - else - { - GL.Disable(IndexedEnableCap.ScissorTest, index); - } - if (index == 0) - { - _scissor0Enable = enable; - } - } - - public void SetScissor(int index, int x, int y, int width, int height) - { GL.ScissorIndexed(index, x, y, width, height); } @@ -1241,7 +1243,7 @@ namespace Ryujinx.Graphics.OpenGL public void RestoreScissor0Enable() { - if (_scissor0Enable) + if ((_scissorEnables & 1u) != 0) { GL.Enable(IndexedEnableCap.ScissorTest, 0); } diff --git a/Ryujinx.Graphics.OpenGL/VertexArray.cs b/Ryujinx.Graphics.OpenGL/VertexArray.cs index 64c6a82198..17703cd129 100644 --- a/Ryujinx.Graphics.OpenGL/VertexArray.cs +++ b/Ryujinx.Graphics.OpenGL/VertexArray.cs @@ -1,6 +1,7 @@ using OpenTK.Graphics.OpenGL; using Ryujinx.Graphics.GAL; using System; +using System.Runtime.CompilerServices; namespace Ryujinx.Graphics.OpenGL { @@ -16,6 +17,9 @@ namespace Ryujinx.Graphics.OpenGL private int _vertexAttribsCount; private int _vertexBuffersCount; + private uint _vertexAttribsInUse; + private uint _vertexBuffersInUse; + public VertexArray() { Handle = GL.GenVertexArray(); @@ -31,30 +35,30 @@ namespace Ryujinx.Graphics.OpenGL public void SetVertexBuffers(ReadOnlySpan vertexBuffers) { - int bindingIndex = 0; - - for (int index = 0; index < vertexBuffers.Length; index++) + int bindingIndex; + for (bindingIndex = 0; bindingIndex < vertexBuffers.Length; bindingIndex++) { - VertexBufferDescriptor vb = vertexBuffers[index]; + VertexBufferDescriptor vb = vertexBuffers[bindingIndex]; if (vb.Buffer.Handle != BufferHandle.Null) { GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride); - GL.VertexBindingDivisor(bindingIndex, vb.Divisor); + _vertexBuffersInUse |= 1u << bindingIndex; } else { - GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0); + if ((_vertexBuffersInUse & (1u << bindingIndex)) != 0) + { + GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0); + _vertexBuffersInUse &= ~(1u << bindingIndex); + } } - _vertexBuffers[index] = vb; - - bindingIndex++; + _vertexBuffers[bindingIndex] = vb; } _vertexBuffersCount = bindingIndex; - _needsAttribsUpdate = true; } @@ -66,17 +70,22 @@ namespace Ryujinx.Graphics.OpenGL { VertexAttribDescriptor attrib = vertexAttribs[index]; + if (attrib.Equals(_vertexAttribs[index])) + { + continue; + } + 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(index); + DisableVertexAttrib(index); } else { - GL.EnableVertexAttribArray(index); + EnableVertexAttrib(index); } int offset = attrib.Offset; @@ -107,7 +116,7 @@ namespace Ryujinx.Graphics.OpenGL for (; index < Constants.MaxVertexAttribs; index++) { - GL.DisableVertexAttribArray(index); + DisableVertexAttrib(index); } } @@ -122,29 +131,54 @@ namespace Ryujinx.Graphics.OpenGL { VertexAttribDescriptor attrib = _vertexAttribs[attribIndex]; - if ((uint)attrib.BufferIndex >= _vertexBuffersCount) + if (!attrib.IsZero) { - GL.DisableVertexAttribArray(attribIndex); + if ((uint)attrib.BufferIndex >= _vertexBuffersCount) + { + DisableVertexAttrib(attribIndex); + continue; + } - continue; - } + if (_vertexBuffers[attrib.BufferIndex].Buffer.Handle == BufferHandle.Null) + { + DisableVertexAttrib(attribIndex); + continue; + } - if (_vertexBuffers[attrib.BufferIndex].Buffer.Handle == BufferHandle.Null) - { - GL.DisableVertexAttribArray(attribIndex); - - continue; - } - - if (_needsAttribsUpdate && !attrib.IsZero) - { - GL.EnableVertexAttribArray(attribIndex); + if (_needsAttribsUpdate) + { + EnableVertexAttrib(attribIndex); + } } } _needsAttribsUpdate = false; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void EnableVertexAttrib(int index) + { + uint mask = 1u << index; + + if ((_vertexAttribsInUse & mask) == 0) + { + _vertexAttribsInUse |= mask; + GL.EnableVertexAttribArray(index); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void DisableVertexAttrib(int index) + { + uint mask = 1u << index; + + if ((_vertexAttribsInUse & mask) != 0) + { + _vertexAttribsInUse &= ~mask; + GL.DisableVertexAttribArray(index); + } + } + public void Dispose() { if (Handle != 0)