Avoid some redundant GL calls (#1958)

This commit is contained in:
gdkchan 2021-01-26 18:44:07 -03:00 committed by GitHub
parent d6bd0470fb
commit caf049ed15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 115 additions and 51 deletions

View file

@ -68,8 +68,7 @@ namespace Ryujinx.Graphics.GAL
void SetSampler(int binding, ISampler sampler); void SetSampler(int binding, ISampler sampler);
void SetScissorEnable(int index, bool enable); void SetScissor(int index, bool enable, int x, int y, int width, int height);
void SetScissor(int index, int x, int y, int width, int height);
void SetStencilTest(StencilTestDescriptor stencilTest); void SetStencilTest(StencilTestDescriptor stencilTest);

View file

@ -1,6 +1,8 @@
using System;
namespace Ryujinx.Graphics.GAL namespace Ryujinx.Graphics.GAL
{ {
public struct VertexAttribDescriptor public struct VertexAttribDescriptor : IEquatable<VertexAttribDescriptor>
{ {
public int BufferIndex { get; } public int BufferIndex { get; }
public int Offset { get; } public int Offset { get; }
@ -16,5 +18,23 @@ namespace Ryujinx.Graphics.GAL
IsZero = isZero; IsZero = isZero;
Format = format; 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);
}
} }
} }

View file

@ -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); bool enable = scissor.Enable && (scissor.X1 != 0 || scissor.Y1 != 0 || scissor.X2 != 0xffff || scissor.Y2 != 0xffff);
_context.Renderer.Pipeline.SetScissorEnable(index, enable);
if (enable) if (enable)
{ {
int x = scissor.X1; int x = scissor.X1;
@ -454,7 +452,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
height = (int)Math.Ceiling(height * scale); 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);
} }
} }
} }

View file

@ -2,6 +2,7 @@ using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image; using Ryujinx.Graphics.OpenGL.Image;
using System; using System;
using System.Runtime.CompilerServices;
namespace Ryujinx.Graphics.OpenGL namespace Ryujinx.Graphics.OpenGL
{ {
@ -29,21 +30,27 @@ namespace Ryujinx.Graphics.OpenGL
return Handle; return Handle;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AttachColor(int index, TextureView color) public void AttachColor(int index, TextureView color)
{ {
if (_colors[index] == color)
{
return;
}
FramebufferAttachment attachment = FramebufferAttachment.ColorAttachment0 + index; FramebufferAttachment attachment = FramebufferAttachment.ColorAttachment0 + index;
if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Amd || if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Amd ||
HwCapabilities.Vendor == HwCapabilities.GpuVendor.Intel) HwCapabilities.Vendor == HwCapabilities.GpuVendor.Intel)
{ {
GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.GetIncompatibleFormatViewHandle() ?? 0, 0); GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.GetIncompatibleFormatViewHandle() ?? 0, 0);
_colors[index] = color;
} }
else else
{ {
GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.Handle ?? 0, 0); GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.Handle ?? 0, 0);
} }
_colors[index] = color;
} }
public void AttachDepthStencil(TextureView depthStencil) public void AttachDepthStencil(TextureView depthStencil)

View file

@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.OpenGL
private readonly uint[] _componentMasks; private readonly uint[] _componentMasks;
private bool _scissor0Enable = false; private uint _scissorEnables;
private bool _tfEnabled; private bool _tfEnabled;
private TransformFeedbackPrimitiveType _tfTopology; private TransformFeedbackPrimitiveType _tfTopology;
@ -883,25 +883,27 @@ namespace Ryujinx.Graphics.OpenGL
((Sampler)sampler).Bind(binding); ((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); 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); GL.ScissorIndexed(index, x, y, width, height);
} }
@ -1241,7 +1243,7 @@ namespace Ryujinx.Graphics.OpenGL
public void RestoreScissor0Enable() public void RestoreScissor0Enable()
{ {
if (_scissor0Enable) if ((_scissorEnables & 1u) != 0)
{ {
GL.Enable(IndexedEnableCap.ScissorTest, 0); GL.Enable(IndexedEnableCap.ScissorTest, 0);
} }

View file

@ -1,6 +1,7 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System; using System;
using System.Runtime.CompilerServices;
namespace Ryujinx.Graphics.OpenGL namespace Ryujinx.Graphics.OpenGL
{ {
@ -16,6 +17,9 @@ namespace Ryujinx.Graphics.OpenGL
private int _vertexAttribsCount; private int _vertexAttribsCount;
private int _vertexBuffersCount; private int _vertexBuffersCount;
private uint _vertexAttribsInUse;
private uint _vertexBuffersInUse;
public VertexArray() public VertexArray()
{ {
Handle = GL.GenVertexArray(); Handle = GL.GenVertexArray();
@ -31,30 +35,30 @@ namespace Ryujinx.Graphics.OpenGL
public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers) public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
{ {
int bindingIndex = 0; int bindingIndex;
for (bindingIndex = 0; bindingIndex < vertexBuffers.Length; bindingIndex++)
for (int index = 0; index < vertexBuffers.Length; index++)
{ {
VertexBufferDescriptor vb = vertexBuffers[index]; VertexBufferDescriptor vb = vertexBuffers[bindingIndex];
if (vb.Buffer.Handle != BufferHandle.Null) if (vb.Buffer.Handle != BufferHandle.Null)
{ {
GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride); GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
GL.VertexBindingDivisor(bindingIndex, vb.Divisor); GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
_vertexBuffersInUse |= 1u << bindingIndex;
} }
else 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; _vertexBuffers[bindingIndex] = vb;
bindingIndex++;
} }
_vertexBuffersCount = bindingIndex; _vertexBuffersCount = bindingIndex;
_needsAttribsUpdate = true; _needsAttribsUpdate = true;
} }
@ -66,17 +70,22 @@ namespace Ryujinx.Graphics.OpenGL
{ {
VertexAttribDescriptor attrib = vertexAttribs[index]; VertexAttribDescriptor attrib = vertexAttribs[index];
if (attrib.Equals(_vertexAttribs[index]))
{
continue;
}
FormatInfo fmtInfo = FormatTable.GetFormatInfo(attrib.Format); FormatInfo fmtInfo = FormatTable.GetFormatInfo(attrib.Format);
if (attrib.IsZero) if (attrib.IsZero)
{ {
// Disabling the attribute causes the shader to read a constant value. // 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). // The value is configurable, but by default is a vector of (0, 0, 0, 1).
GL.DisableVertexAttribArray(index); DisableVertexAttrib(index);
} }
else else
{ {
GL.EnableVertexAttribArray(index); EnableVertexAttrib(index);
} }
int offset = attrib.Offset; int offset = attrib.Offset;
@ -107,7 +116,7 @@ namespace Ryujinx.Graphics.OpenGL
for (; index < Constants.MaxVertexAttribs; index++) for (; index < Constants.MaxVertexAttribs; index++)
{ {
GL.DisableVertexAttribArray(index); DisableVertexAttrib(index);
} }
} }
@ -122,29 +131,54 @@ namespace Ryujinx.Graphics.OpenGL
{ {
VertexAttribDescriptor attrib = _vertexAttribs[attribIndex]; 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) if (_needsAttribsUpdate)
{ {
GL.DisableVertexAttribArray(attribIndex); EnableVertexAttrib(attribIndex);
}
continue;
}
if (_needsAttribsUpdate && !attrib.IsZero)
{
GL.EnableVertexAttribArray(attribIndex);
} }
} }
_needsAttribsUpdate = false; _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() public void Dispose()
{ {
if (Handle != 0) if (Handle != 0)