aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.OpenGL/Pipeline.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2021-08-11 16:33:43 -0300
committerGitHub <noreply@github.com>2021-08-11 21:33:43 +0200
commit0f6ec446ea3be41b1c22aa5c3870bd7a6c595d1f (patch)
treee441560dbdd560e9a020bb4b7606d3cd0698da02 /Ryujinx.Graphics.OpenGL/Pipeline.cs
parentb5b7e23fc41e7045f9e803d6926e98ec7d049f0c (diff)
Replace BGRA and scale uniforms with a uniform block (#2496)
* Replace BGRA and scale uniforms with a uniform block * Setting the data again on program change is no longer needed * Optimize and resolve some warnings * Avoid redundant support buffer updates * Some optimizations to BindBuffers (now inlined) * Unify render scale arrays
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Pipeline.cs')
-rw-r--r--Ryujinx.Graphics.OpenGL/Pipeline.cs122
1 files changed, 66 insertions, 56 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs
index 948a8b89..9c39f719 100644
--- a/Ryujinx.Graphics.OpenGL/Pipeline.cs
+++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs
@@ -5,6 +5,8 @@ using Ryujinx.Graphics.OpenGL.Image;
using Ryujinx.Graphics.OpenGL.Queries;
using Ryujinx.Graphics.Shader;
using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.OpenGL
{
@@ -31,9 +33,16 @@ namespace Ryujinx.Graphics.OpenGL
private int _boundDrawFramebuffer;
private int _boundReadFramebuffer;
- private int[] _fpIsBgra = new int[8];
- private float[] _fpRenderScale = new float[65];
- private float[] _cpRenderScale = new float[64];
+ private struct Vector4<T>
+ {
+ public T X;
+ public T Y;
+ public T Z;
+ public T W;
+ }
+
+ private Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount];
+ private Vector4<float>[] _renderScale = new Vector4<float>[65];
private TextureBase _unit0Texture;
@@ -48,6 +57,7 @@ namespace Ryujinx.Graphics.OpenGL
private bool _tfEnabled;
private TransformFeedbackPrimitiveType _tfTopology;
+ private BufferHandle _supportBuffer;
private readonly BufferHandle[] _tfbs;
private readonly BufferRange[] _tfbTargets;
@@ -66,15 +76,8 @@ namespace Ryujinx.Graphics.OpenGL
_componentMasks[index] = 0xf;
}
- for (int index = 0; index < _fpRenderScale.Length; index++)
- {
- _fpRenderScale[index] = 1f;
- }
-
- for (int index = 0; index < _cpRenderScale.Length; index++)
- {
- _cpRenderScale[index] = 1f;
- }
+ var v4Zero = new Vector4<float> { X = 0f, Y = 0f, Z = 0f, W = 0f };
+ new Span<Vector4<float>>(_renderScale).Fill(v4Zero);
_tfbs = new BufferHandle[Constants.MaxTransformFeedbackBuffers];
_tfbTargets = new BufferRange[Constants.MaxTransformFeedbackBuffers];
@@ -823,9 +826,6 @@ namespace Ryujinx.Graphics.OpenGL
{
_program.Bind();
}
-
- UpdateFpIsBgra();
- SetRenderTargetScale(_fpRenderScale[0]);
}
public void SetRasterizerDiscard(bool discard)
@@ -844,12 +844,8 @@ namespace Ryujinx.Graphics.OpenGL
public void SetRenderTargetScale(float scale)
{
- _fpRenderScale[0] = scale;
-
- if (_program != null && _program.FragmentRenderScaleUniform != -1)
- {
- GL.Uniform1(_program.FragmentRenderScaleUniform, 1, _fpRenderScale); // Just the first element.
- }
+ _renderScale[0].X = scale;
+ SetSupportBufferData<Vector4<float>>(SupportBuffer.FragmentRenderScaleOffset, _renderScale, 1); // Just the first element.
}
public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks)
@@ -866,6 +862,8 @@ namespace Ryujinx.Graphics.OpenGL
{
EnsureFramebuffer();
+ bool isBgraChanged = false;
+
for (int index = 0; index < colors.Length; index++)
{
TextureView color = (TextureView)colors[index];
@@ -874,15 +872,19 @@ namespace Ryujinx.Graphics.OpenGL
int isBgra = color != null && color.Format.IsBgra8() ? 1 : 0;
- if (_fpIsBgra[index] != isBgra)
+ if (_fpIsBgra[index].X != isBgra)
{
- _fpIsBgra[index] = isBgra;
+ _fpIsBgra[index].X = isBgra;
+ isBgraChanged = true;
RestoreComponentMask(index);
}
}
- UpdateFpIsBgra();
+ if (isBgraChanged)
+ {
+ SetSupportBufferData<Vector4<int>>(SupportBuffer.FragmentIsBgraOffset, _fpIsBgra, SupportBuffer.FragmentIsBgraCount);
+ }
TextureView depthStencilView = (TextureView)depthStencil;
@@ -965,9 +967,9 @@ namespace Ryujinx.Graphics.OpenGL
_stencilFrontMask = stencilTest.FrontMask;
}
- public void SetStorageBuffers(ReadOnlySpan<BufferRange> buffers)
+ public void SetStorageBuffers(int first, ReadOnlySpan<BufferRange> buffers)
{
- SetBuffers(buffers, isStorage: true);
+ SetBuffers(first, buffers, isStorage: true);
}
public void SetTexture(int binding, ITexture texture)
@@ -1023,9 +1025,9 @@ namespace Ryujinx.Graphics.OpenGL
}
}
- public void SetUniformBuffers(ReadOnlySpan<BufferRange> buffers)
+ public void SetUniformBuffers(int first, ReadOnlySpan<BufferRange> buffers)
{
- SetBuffers(buffers, isStorage: false);
+ SetBuffers(first, buffers, isStorage: false);
}
public void SetUserClipDistance(int index, bool enableClip)
@@ -1103,7 +1105,7 @@ namespace Ryujinx.Graphics.OpenGL
GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit);
}
- private void SetBuffers(ReadOnlySpan<BufferRange> buffers, bool isStorage)
+ private void SetBuffers(int first, ReadOnlySpan<BufferRange> buffers, bool isStorage)
{
BufferRangeTarget target = isStorage ? BufferRangeTarget.ShaderStorageBuffer : BufferRangeTarget.UniformBuffer;
@@ -1113,11 +1115,11 @@ namespace Ryujinx.Graphics.OpenGL
if (buffer.Handle == BufferHandle.Null)
{
- GL.BindBufferRange(target, index, 0, IntPtr.Zero, 0);
+ GL.BindBufferRange(target, first + index, 0, IntPtr.Zero, 0);
continue;
}
- GL.BindBufferRange(target, index, buffer.Handle.ToInt32(), (IntPtr)buffer.Offset, buffer.Size);
+ GL.BindBufferRange(target, first + index, buffer.Handle.ToInt32(), (IntPtr)buffer.Offset, buffer.Size);
}
}
@@ -1179,37 +1181,39 @@ namespace Ryujinx.Graphics.OpenGL
return (_boundDrawFramebuffer, _boundReadFramebuffer);
}
- private void UpdateFpIsBgra()
+ public void UpdateRenderScale(ShaderStage stage, float[] scales, int textureCount, int imageCount)
{
- if (_program != null)
+ if (stage != ShaderStage.Compute && stage != ShaderStage.Fragment)
{
- GL.Uniform1(_program.FragmentIsBgraUniform, 8, _fpIsBgra);
+ return;
}
- }
- public void UpdateRenderScale(ShaderStage stage, float[] scales, int textureCount, int imageCount)
- {
- if (_program != null)
+ bool changed = false;
+
+ for (int index = 0; index < textureCount + imageCount; index++)
{
- switch (stage)
+ if (_renderScale[1 + index].X != scales[index])
{
- case ShaderStage.Fragment:
- if (_program.FragmentRenderScaleUniform != -1)
- {
- Array.Copy(scales, 0, _fpRenderScale, 1, textureCount + imageCount);
- GL.Uniform1(_program.FragmentRenderScaleUniform, 1 + textureCount + imageCount, _fpRenderScale);
- }
- break;
-
- case ShaderStage.Compute:
- if (_program.ComputeRenderScaleUniform != -1)
- {
- Array.Copy(scales, 0, _cpRenderScale, 0, textureCount + imageCount);
- GL.Uniform1(_program.ComputeRenderScaleUniform, textureCount + imageCount, _cpRenderScale);
- }
- break;
+ _renderScale[1 + index].X = scales[index];
+ changed = true;
}
}
+
+ if (changed)
+ {
+ SetSupportBufferData<Vector4<float>>(SupportBuffer.FragmentRenderScaleOffset, _renderScale, 1 + textureCount + imageCount);
+ }
+ }
+
+ private void SetSupportBufferData<T>(int offset, ReadOnlySpan<T> data, int count) where T : unmanaged
+ {
+ if (_supportBuffer == BufferHandle.Null)
+ {
+ _supportBuffer = Buffer.Create(SupportBuffer.RequiredSize);
+ GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, Unsafe.As<BufferHandle, int>(ref _supportBuffer));
+ }
+
+ Buffer.SetData(_supportBuffer, offset, MemoryMarshal.Cast<T, byte>(data.Slice(0, count)));
}
private void PrepareForDispatch()
@@ -1249,8 +1253,8 @@ namespace Ryujinx.Graphics.OpenGL
public void RestoreComponentMask(int index)
{
// If the bound render target is bgra, swap the red and blue masks.
- uint redMask = _fpIsBgra[index] == 0 ? 1u : 4u;
- uint blueMask = _fpIsBgra[index] == 0 ? 4u : 1u;
+ uint redMask = _fpIsBgra[index].X == 0 ? 1u : 4u;
+ uint blueMask = _fpIsBgra[index].X == 0 ? 4u : 1u;
GL.ColorMask(
index,
@@ -1322,6 +1326,12 @@ namespace Ryujinx.Graphics.OpenGL
public void Dispose()
{
+ if (_supportBuffer != BufferHandle.Null)
+ {
+ Buffer.Delete(_supportBuffer);
+ _supportBuffer = BufferHandle.Null;
+ }
+
for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++)
{
if (_tfbs[i] != BufferHandle.Null)