From d4b960d34807f818d2af6899f87137bef353c82e Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 4 Apr 2022 18:43:24 -0300 Subject: [PATCH] Implement primitive restart draw arrays properly on OpenGL (#3256) --- .../Engine/Threed/StateUpdater.cs | 21 ++++++++++++++++--- .../Engine/Threed/ThreedClassState.cs | 4 +++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index a65fc9085..f44089598 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -20,6 +20,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed public const int RasterizerStateIndex = 1; public const int ScissorStateIndex = 2; public const int VertexBufferStateIndex = 3; + public const int PrimitiveRestartStateIndex = 4; private readonly GpuContext _context; private readonly GpuChannel _channel; @@ -75,6 +76,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed nameof(ThreedClassState.VertexBufferState), nameof(ThreedClassState.VertexBufferEndAddress)), + new StateUpdateCallbackEntry(UpdatePrimitiveRestartState, + nameof(ThreedClassState.PrimitiveRestartDrawArrays), + nameof(ThreedClassState.PrimitiveRestartState)), + new StateUpdateCallbackEntry(UpdateTessellationState, nameof(ThreedClassState.TessOuterLevel), nameof(ThreedClassState.TessInnerLevel), @@ -140,8 +145,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed nameof(ThreedClassState.PointSpriteEnable), nameof(ThreedClassState.PointCoordReplace)), - new StateUpdateCallbackEntry(UpdatePrimitiveRestartState, nameof(ThreedClassState.PrimitiveRestartState)), - new StateUpdateCallbackEntry(UpdateIndexBufferState, nameof(ThreedClassState.IndexBufferState), nameof(ThreedClassState.IndexBufferCount)), @@ -197,6 +200,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed if (_drawState.DrawIndexed != _prevDrawIndexed) { _updateTracker.ForceDirty(VertexBufferStateIndex); + + // If PrimitiveRestartDrawArrays is false and this is a non-indexed draw, we need to ensure primitive restart is disabled. + // If PrimitiveRestartDrawArrays is false and this is a indexed draw, we need to ensure primitive restart enable matches GPU state. + // If PrimitiveRestartDrawArrays is true, then primitive restart enable should always match GPU state. + // That is because "PrimitiveRestartDrawArrays" is not configurable on the backend, it is always + // true on OpenGL and always false on Vulkan. + if (!_state.State.PrimitiveRestartDrawArrays && _state.State.PrimitiveRestartState.Enable) + { + _updateTracker.ForceDirty(PrimitiveRestartStateIndex); + } + _prevDrawIndexed = _drawState.DrawIndexed; } @@ -816,8 +830,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed private void UpdatePrimitiveRestartState() { PrimitiveRestartState primitiveRestart = _state.State.PrimitiveRestartState; + bool enable = primitiveRestart.Enable && (_drawState.DrawIndexed || _state.State.PrimitiveRestartDrawArrays); - _context.Renderer.Pipeline.SetPrimitiveRestart(primitiveRestart.Enable, primitiveRestart.Index); + _context.Renderer.Pipeline.SetPrimitiveRestart(enable, primitiveRestart.Index); } /// diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs index a6a5a2ab9..81a228315 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Threed/ThreedClassState.cs @@ -730,7 +730,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed public int PatchVertices; public fixed uint ReservedDD0[4]; public uint TextureBarrier; - public fixed uint ReservedDE4[7]; + public uint WatchdogTimer; + public Boolean32 PrimitiveRestartDrawArrays; + public fixed uint ReservedDEC[5]; public Array16 ScissorState; public fixed uint ReservedF00[21]; public StencilBackMasks StencilBackMasks;