diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs index fc5cf483d..5b663823f 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 cc476654c..3175ebd2f 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 18720440d..509138014 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 de09f3e7d..4b81029c4 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 8631efcc1..e59a3aafb 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 0a720b2c4..a178c2f8c 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 3480cf82c..aef3383b1 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 ac9459d4a..59db94a47 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 c9b7daeb9..9f0007c4d 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()