diff options
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Pipeline.cs')
-rw-r--r-- | Ryujinx.Graphics.OpenGL/Pipeline.cs | 62 |
1 files changed, 45 insertions, 17 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index ff5af42d..c20ce8a3 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -53,7 +53,9 @@ namespace Ryujinx.Graphics.OpenGL private ClipOrigin _clipOrigin; private ClipDepthMode _clipDepthMode; - private readonly uint[] _componentMasks; + private uint _fragmentOutputMap; + private uint _componentMasks; + private uint _currentComponentMasks; private uint _scissorEnables; @@ -73,12 +75,8 @@ namespace Ryujinx.Graphics.OpenGL _clipOrigin = ClipOrigin.LowerLeft; _clipDepthMode = ClipDepthMode.NegativeOneToOne; - _componentMasks = new uint[Constants.MaxRenderTargets]; - - for (int index = 0; index < Constants.MaxRenderTargets; index++) - { - _componentMasks[index] = 0xf; - } + _fragmentOutputMap = uint.MaxValue; + _componentMasks = uint.MaxValue; var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f }; new Span<Vector4<float>>(_renderScale).Fill(defaultScale); @@ -1001,18 +999,30 @@ namespace Ryujinx.Graphics.OpenGL public void SetProgram(IProgram program) { - _program = (Program)program; + Program prg = (Program)program; if (_tfEnabled) { GL.EndTransformFeedback(); - _program.Bind(); + prg.Bind(); GL.BeginTransformFeedback(_tfTopology); } else { - _program.Bind(); + prg.Bind(); + } + + if (prg.HasFragmentShader && _fragmentOutputMap != (uint)prg.FragmentOutputMap) + { + _fragmentOutputMap = (uint)prg.FragmentOutputMap; + + for (int index = 0; index < Constants.MaxRenderTargets; index++) + { + RestoreComponentMask(index, force: false); + } } + + _program = prg; } public void SetRasterizerDiscard(bool discard) @@ -1037,11 +1047,13 @@ namespace Ryujinx.Graphics.OpenGL public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks) { + _componentMasks = 0; + for (int index = 0; index < componentMasks.Length; index++) { - _componentMasks[index] = componentMasks[index]; + _componentMasks |= componentMasks[index] << (index * 4); - RestoreComponentMask(index); + RestoreComponentMask(index, force: false); } } @@ -1436,18 +1448,34 @@ namespace Ryujinx.Graphics.OpenGL } } - public void RestoreComponentMask(int index) + public void RestoreComponentMask(int index, bool force = true) { // If the bound render target is bgra, swap the red and blue masks. uint redMask = _fpIsBgra[index].X == 0 ? 1u : 4u; uint blueMask = _fpIsBgra[index].X == 0 ? 4u : 1u; + int shift = index * 4; + uint componentMask = _componentMasks & _fragmentOutputMap; + uint checkMask = 0xfu << shift; + uint componentMaskAtIndex = componentMask & checkMask; + + if (!force && componentMaskAtIndex == (_currentComponentMasks & checkMask)) + { + return; + } + + componentMask >>= shift; + componentMask &= 0xfu; + GL.ColorMask( index, - (_componentMasks[index] & redMask) != 0, - (_componentMasks[index] & 2u) != 0, - (_componentMasks[index] & blueMask) != 0, - (_componentMasks[index] & 8u) != 0); + (componentMask & redMask) != 0, + (componentMask & 2u) != 0, + (componentMask & blueMask) != 0, + (componentMask & 8u) != 0); + + _currentComponentMasks &= ~checkMask; + _currentComponentMasks |= componentMaskAtIndex; } public void RestoreScissor0Enable() |