From 468d8f841ffcbebf4130371eb64ab04165bce3e9 Mon Sep 17 00:00:00 2001 From: mageven <62494521+mageven@users.noreply.github.com> Date: Tue, 7 Apr 2020 14:49:45 +0530 Subject: [PATCH] Simple GPU fixes (#1093) * Implement RasterizeEnable * Match viewport count to hardware * Simplify ScissorTest tracking around Blits * Disable RasterizerDiscard around Blits and track its state * Read RasterizeEnable reg as bool and add doc --- Ryujinx.Graphics.GAL/IPipeline.cs | 2 + Ryujinx.Graphics.Gpu/Constants.cs | 2 +- Ryujinx.Graphics.Gpu/Engine/Methods.cs | 15 +++++++ Ryujinx.Graphics.Gpu/State/GpuState.cs | 3 ++ Ryujinx.Graphics.Gpu/State/GpuStateTable.cs | 6 +-- Ryujinx.Graphics.Gpu/State/MethodOffset.cs | 1 + Ryujinx.Graphics.OpenGL/Pipeline.cs | 43 ++++++++++++++++----- Ryujinx.Graphics.OpenGL/TextureCopy.cs | 6 ++- Ryujinx.Graphics.OpenGL/Window.cs | 6 ++- 9 files changed, 66 insertions(+), 18 deletions(-) diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs index fc5cf483db..5b663823f5 100644 --- a/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/Ryujinx.Graphics.GAL/IPipeline.cs @@ -48,6 +48,8 @@ namespace Ryujinx.Graphics.GAL void SetProgram(IProgram program); + void SetRasterizerDiscard(bool discard); + void SetRenderTargetColorMasks(uint[] componentMask); void SetRenderTargets(ITexture[] colors, ITexture depthStencil); diff --git a/Ryujinx.Graphics.Gpu/Constants.cs b/Ryujinx.Graphics.Gpu/Constants.cs index cc476654ce..3175ebd2fa 100644 --- a/Ryujinx.Graphics.Gpu/Constants.cs +++ b/Ryujinx.Graphics.Gpu/Constants.cs @@ -53,6 +53,6 @@ namespace Ryujinx.Graphics.Gpu /// /// Maximum number of viewports. /// - public const int TotalViewports = 8; + public const int TotalViewports = 16; } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index 18720440da..5091380143 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -108,6 +108,11 @@ namespace Ryujinx.Graphics.Gpu.Engine UpdateShaderState(state); } + if (state.QueryModified(MethodOffset.RasterizeEnable)) + { + UpdateRasterizerState(state); + } + if (state.QueryModified(MethodOffset.RtColorState, MethodOffset.RtDepthStencilState, MethodOffset.RtControl, @@ -211,6 +216,16 @@ namespace Ryujinx.Graphics.Gpu.Engine CommitBindings(); } + /// + /// Updates Rasterizer primitive discard state based on guest gpu state. + /// + /// Current GPU state + private void UpdateRasterizerState(GpuState state) + { + Boolean32 enable = state.Get(MethodOffset.RasterizeEnable); + _context.Renderer.Pipeline.SetRasterizerDiscard(!enable); + } + /// /// Ensures that the bindings are visible to the host GPU. /// Note: this actually performs the binding using the host graphics API. diff --git a/Ryujinx.Graphics.Gpu/State/GpuState.cs b/Ryujinx.Graphics.Gpu/State/GpuState.cs index de09f3e7da..4b81029c43 100644 --- a/Ryujinx.Graphics.Gpu/State/GpuState.cs +++ b/Ryujinx.Graphics.Gpu/State/GpuState.cs @@ -117,6 +117,9 @@ namespace Ryujinx.Graphics.Gpu.State /// private void InitializeDefaultState() { + // Enable Rasterizer + _backingMemory[(int)MethodOffset.RasterizeEnable] = 1; + // Depth ranges. for (int index = 0; index < 8; index++) { diff --git a/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs b/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs index 8631efcc1f..e59a3aafbf 100644 --- a/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs +++ b/Ryujinx.Graphics.Gpu/State/GpuStateTable.cs @@ -53,11 +53,11 @@ namespace Ryujinx.Graphics.Gpu.State public static TableItem[] Table = new TableItem[] { new TableItem(MethodOffset.RtColorState, typeof(RtColorState), 8), - new TableItem(MethodOffset.ViewportTransform, typeof(ViewportTransform), 8), - new TableItem(MethodOffset.ViewportExtents, typeof(ViewportExtents), 8), + new TableItem(MethodOffset.ViewportTransform, typeof(ViewportTransform), Constants.TotalViewports), + new TableItem(MethodOffset.ViewportExtents, typeof(ViewportExtents), Constants.TotalViewports), new TableItem(MethodOffset.VertexBufferDrawState, typeof(VertexBufferDrawState), 1), new TableItem(MethodOffset.DepthBiasState, typeof(DepthBiasState), 1), - new TableItem(MethodOffset.ScissorState, typeof(ScissorState), 8), + new TableItem(MethodOffset.ScissorState, typeof(ScissorState), Constants.TotalViewports), new TableItem(MethodOffset.StencilBackMasks, typeof(StencilBackMasks), 1), new TableItem(MethodOffset.RtDepthStencilState, typeof(RtDepthStencilState), 1), new TableItem(MethodOffset.VertexAttribState, typeof(VertexAttribState), 16), diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs index 0a720b2c48..a178c2f8c3 100644 --- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs +++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs @@ -16,6 +16,7 @@ namespace Ryujinx.Graphics.Gpu.State DispatchParamsAddress = 0xad, Dispatch = 0xaf, CopyBuffer = 0xc0, + RasterizeEnable = 0xdf, CopyBufferParams = 0x100, CopyBufferSwizzle = 0x1c2, CopyBufferDstTexture = 0x1c3, diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 3480cf82cc..aef3383b16 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -10,6 +10,8 @@ namespace Ryujinx.Graphics.OpenGL { private Program _program; + private bool _rasterizerDiscard; + private VertexArray _vertexArray; private Framebuffer _framebuffer; @@ -31,14 +33,13 @@ namespace Ryujinx.Graphics.OpenGL private uint[] _componentMasks; - private readonly bool[] _scissorEnable; + private bool _scissor0Enable = false; internal Pipeline() { + _rasterizerDiscard = false; _clipOrigin = ClipOrigin.LowerLeft; _clipDepthMode = ClipDepthMode.NegativeOneToOne; - - _scissorEnable = new bool[8]; } public void Barrier() @@ -644,6 +645,20 @@ namespace Ryujinx.Graphics.OpenGL _program.Bind(); } + public void SetRasterizerDiscard(bool discard) + { + if (discard) + { + GL.Enable(EnableCap.RasterizerDiscard); + } + else + { + GL.Disable(EnableCap.RasterizerDiscard); + } + + _rasterizerDiscard = discard; + } + public void SetRenderTargetColorMasks(uint[] componentMasks) { _componentMasks = (uint[])componentMasks.Clone(); @@ -697,7 +712,10 @@ namespace Ryujinx.Graphics.OpenGL GL.Disable(IndexedEnableCap.ScissorTest, index); } - _scissorEnable[index] = enable; + if (index == 0) + { + _scissor0Enable = enable; + } } public void SetScissor(int index, int x, int y, int width, int height) @@ -959,14 +977,19 @@ namespace Ryujinx.Graphics.OpenGL } } - public void RestoreScissorEnable() + public void RestoreScissor0Enable() { - for (int index = 0; index < 8; index++) + if (_scissor0Enable) { - if (_scissorEnable[index]) - { - GL.Enable(IndexedEnableCap.ScissorTest, index); - } + GL.Enable(IndexedEnableCap.ScissorTest, 0); + } + } + + public void RestoreRasterizerDiscard() + { + if (_rasterizerDiscard) + { + GL.Enable(EnableCap.RasterizerDiscard); } } diff --git a/Ryujinx.Graphics.OpenGL/TextureCopy.cs b/Ryujinx.Graphics.OpenGL/TextureCopy.cs index ac9459d4aa..59db94a47c 100644 --- a/Ryujinx.Graphics.OpenGL/TextureCopy.cs +++ b/Ryujinx.Graphics.OpenGL/TextureCopy.cs @@ -41,7 +41,8 @@ namespace Ryujinx.Graphics.OpenGL GL.ReadBuffer(ReadBufferMode.ColorAttachment0); GL.DrawBuffer(DrawBufferMode.ColorAttachment0); - GL.Disable(EnableCap.ScissorTest); + GL.Disable(EnableCap.RasterizerDiscard); + GL.Disable(IndexedEnableCap.ScissorTest, 0); GL.BlitFramebuffer( srcRegion.X1, @@ -58,7 +59,8 @@ namespace Ryujinx.Graphics.OpenGL GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle); GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle); - ((Pipeline)_renderer.Pipeline).RestoreScissorEnable(); + ((Pipeline)_renderer.Pipeline).RestoreScissor0Enable(); + ((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard(); } private static void Attach(FramebufferTarget target, Format format, int handle) diff --git a/Ryujinx.Graphics.OpenGL/Window.cs b/Ryujinx.Graphics.OpenGL/Window.cs index c9b7daeb95..9f0007c4d8 100644 --- a/Ryujinx.Graphics.OpenGL/Window.cs +++ b/Ryujinx.Graphics.OpenGL/Window.cs @@ -59,7 +59,8 @@ namespace Ryujinx.Graphics.OpenGL GL.ReadBuffer(ReadBufferMode.ColorAttachment0); - GL.Disable(EnableCap.ScissorTest); + GL.Disable(EnableCap.RasterizerDiscard); + GL.Disable(IndexedEnableCap.ScissorTest, 0); GL.Clear(ClearBufferMask.ColorBufferBit); @@ -126,7 +127,8 @@ namespace Ryujinx.Graphics.OpenGL GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, oldReadFramebufferHandle); GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, oldDrawFramebufferHandle); - ((Pipeline)_renderer.Pipeline).RestoreScissorEnable(); + ((Pipeline)_renderer.Pipeline).RestoreScissor0Enable(); + ((Pipeline)_renderer.Pipeline).RestoreRasterizerDiscard(); } private int GetCopyFramebufferHandleLazy()