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 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()