From 53369e79bdc34440a48e932e7024bab92f30f957 Mon Sep 17 00:00:00 2001 From: mageven <62494521+mageven@users.noreply.github.com> Date: Mon, 4 May 2020 07:34:49 +0530 Subject: [PATCH] Implement user-defined clipping on GL state pipeline (#1118) --- Ryujinx.Graphics.GAL/IPipeline.cs | 2 ++ Ryujinx.Graphics.Gpu/Constants.cs | 5 +++++ Ryujinx.Graphics.Gpu/Engine/Methods.cs | 19 +++++++++++++++++++ Ryujinx.Graphics.Gpu/State/MethodOffset.cs | 1 + Ryujinx.Graphics.OpenGL/Pipeline.cs | 11 +++++++++++ 5 files changed, 38 insertions(+) diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs index 51b8d91ab..290462fa8 100644 --- a/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/Ryujinx.Graphics.GAL/IPipeline.cs @@ -66,6 +66,8 @@ namespace Ryujinx.Graphics.GAL void SetUniformBuffer(int index, ShaderStage stage, BufferRange buffer); + void SetUserClipDistance(int index, bool enableClip); + void SetVertexAttribs(VertexAttribDescriptor[] vertexAttribs); void SetVertexBuffers(VertexBufferDescriptor[] vertexBuffers); diff --git a/Ryujinx.Graphics.Gpu/Constants.cs b/Ryujinx.Graphics.Gpu/Constants.cs index 3175ebd2f..1ae902731 100644 --- a/Ryujinx.Graphics.Gpu/Constants.cs +++ b/Ryujinx.Graphics.Gpu/Constants.cs @@ -54,5 +54,10 @@ namespace Ryujinx.Graphics.Gpu /// Maximum number of viewports. /// public const int TotalViewports = 16; + + /// + /// Maximum size of gl_ClipDistance array in shaders. + /// + public const int TotalClipDistances = 8; } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index a517ae05d..59678be59 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -125,6 +125,11 @@ namespace Ryujinx.Graphics.Gpu.Engine UpdateShaderState(state); } + if (state.QueryModified(MethodOffset.ClipDistanceEnable)) + { + UpdateUserClipState(state); + } + if (state.QueryModified(MethodOffset.RasterizeEnable)) { UpdateRasterizerState(state); @@ -902,6 +907,20 @@ namespace Ryujinx.Graphics.Gpu.Engine _context.Renderer.Pipeline.SetProgram(gs.HostProgram); } + /// + /// Updates user-defined clipping based on the guest GPU state. + /// + /// Current GPU state + private void UpdateUserClipState(GpuState state) + { + int clipMask = state.Get(MethodOffset.ClipDistanceEnable); + + for (int i = 0; i < Constants.TotalClipDistances; ++i) + { + _context.Renderer.Pipeline.SetUserClipDistance(i, (clipMask & (1 << i)) != 0); + } + } + /// /// Gets texture target from a sampler type. /// diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs index 077b09c27..b39ff9b5e 100644 --- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs +++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs @@ -66,6 +66,7 @@ namespace Ryujinx.Graphics.Gpu.State YControl = 0x4eb, FirstVertex = 0x50d, FirstInstance = 0x50e, + ClipDistanceEnable = 0x544, PointSize = 0x546, ResetCounter = 0x54c, RtDepthStencilEnable = 0x54e, diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 604d0ba30..dc04805da 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -811,6 +811,17 @@ namespace Ryujinx.Graphics.OpenGL SetBuffer(index, stage, buffer, isStorage: false); } + public void SetUserClipDistance(int index, bool enableClip) + { + if (!enableClip) + { + GL.Disable(EnableCap.ClipDistance0 + index); + return; + } + + GL.Enable(EnableCap.ClipDistance0 + index); + } + public void SetVertexAttribs(VertexAttribDescriptor[] vertexAttribs) { EnsureVertexArray();