diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs index 5b663823..4c892bea 100644 --- a/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/Ryujinx.Graphics.GAL/IPipeline.cs @@ -29,6 +29,7 @@ namespace Ryujinx.Graphics.GAL void SetBlendColor(ColorF color); void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp); + void SetDepthClamp(bool clampNear, bool clampFar); void SetDepthMode(DepthMode mode); void SetDepthTest(DepthTestDescriptor depthTest); diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index 50913801..b7f4e1d9 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs @@ -127,6 +127,11 @@ namespace Ryujinx.Graphics.Gpu.Engine UpdateScissorState(state); } + if (state.QueryModified(MethodOffset.ViewVolumeClipControl)) + { + UpdateDepthClampState(state); + } + if (state.QueryModified(MethodOffset.DepthTestEnable, MethodOffset.DepthWriteEnable, MethodOffset.DepthTestFunc)) @@ -134,7 +139,9 @@ namespace Ryujinx.Graphics.Gpu.Engine UpdateDepthTestState(state); } - if (state.QueryModified(MethodOffset.DepthMode, MethodOffset.ViewportTransform, MethodOffset.ViewportExtents)) + if (state.QueryModified(MethodOffset.DepthMode, + MethodOffset.ViewportTransform, + MethodOffset.ViewportExtents)) { UpdateViewportTransform(state); } @@ -362,6 +369,17 @@ namespace Ryujinx.Graphics.Gpu.Engine } } + /// + /// Updates host depth clamp state based on current GPU state. + /// + /// Current GPU state + private void UpdateDepthClampState(GpuState state) + { + ViewVolumeClipControl clip = state.Get(MethodOffset.ViewVolumeClipControl); + _context.Renderer.Pipeline.SetDepthClamp((clip & ViewVolumeClipControl.DepthClampNear) != 0, + (clip & ViewVolumeClipControl.DepthClampFar) != 0); + } + /// /// Updates host depth test state based on current GPU state. /// @@ -384,8 +402,7 @@ namespace Ryujinx.Graphics.Gpu.Engine _context.Renderer.Pipeline.SetDepthMode(depthMode); - bool flipY = (state.Get(MethodOffset.YControl) & 1) != 0; - + bool flipY = (state.Get(MethodOffset.YControl) & YControl.NegateY) != 0; float yFlip = flipY ? -1 : 1; Viewport[] viewports = new Viewport[Constants.TotalViewports]; diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs index a178c2f8..b8ee7e91 100644 --- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs +++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs @@ -75,6 +75,7 @@ namespace Ryujinx.Graphics.Gpu.State VertexBufferInstanced = 0x620, FaceState = 0x646, ViewportTransformEnable = 0x64b, + ViewVolumeClipControl = 0x64f, Clear = 0x674, RtColorMask = 0x680, ReportState = 0x6c0, diff --git a/Ryujinx.Graphics.Gpu/State/ViewVolumeClipControl.cs b/Ryujinx.Graphics.Gpu/State/ViewVolumeClipControl.cs new file mode 100644 index 00000000..4e12c424 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/State/ViewVolumeClipControl.cs @@ -0,0 +1,12 @@ +using System; + +namespace Ryujinx.Graphics.Gpu.State +{ + [Flags] + enum ViewVolumeClipControl + { + ForceDepthRangeZeroToOne = 1 << 0, + DepthClampNear = 1 << 3, + DepthClampFar = 1 << 4, + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.Gpu/State/YControl.cs b/Ryujinx.Graphics.Gpu/State/YControl.cs new file mode 100644 index 00000000..58e000d9 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/State/YControl.cs @@ -0,0 +1,11 @@ +using System; + +namespace Ryujinx.Graphics.Gpu.State +{ + [Flags] + enum YControl + { + NegateY = 1 << 0, + TriangleRastFlip = 1 << 4 + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index aef3383b..e32b5b85 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs @@ -546,6 +546,21 @@ namespace Ryujinx.Graphics.OpenGL // GL.PolygonOffsetClamp(factor, units, clamp); } + public void SetDepthClamp(bool clampNear, bool clampFar) + { + // TODO: Use GL_AMD_depth_clamp_separate or similar if available? + // Currently enables clamping if either is set. + bool clamp = clampNear || clampFar; + + if (!clamp) + { + GL.Disable(EnableCap.DepthClamp); + return; + } + + GL.Enable(EnableCap.DepthClamp); + } + public void SetDepthMode(DepthMode mode) { ClipDepthMode depthMode = mode.Convert();