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
This commit is contained in:
parent
b5b7e23fc4
commit
0f6ec446ea
13 changed files with 269 additions and 226 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
|
||||
for (int index = 0; index < textureCount + imageCount; index++)
|
||||
{
|
||||
if (_renderScale[1 + index].X != scales[index])
|
||||
{
|
||||
_renderScale[1 + index].X = scales[index];
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
SetSupportBufferData<Vector4<float>>(SupportBuffer.FragmentRenderScaleOffset, _renderScale, 1 + textureCount + imageCount);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateRenderScale(ShaderStage stage, float[] scales, int textureCount, int imageCount)
|
||||
private void SetSupportBufferData<T>(int offset, ReadOnlySpan<T> data, int count) where T : unmanaged
|
||||
{
|
||||
if (_program != null)
|
||||
if (_supportBuffer == BufferHandle.Null)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
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;
|
||||
}
|
||||
_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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue