Преглед изворни кода

Implement Depth Clamping (#1120)

* Implement Depth Clamping and add misc enums

* Fix formatting
mageven пре 6 година
родитељ
комит
4960ab85f8

+ 1 - 0
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);
 

+ 20 - 3
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
             }
         }
 
+        /// <summary>
+        /// Updates host depth clamp state based on current GPU state.
+        /// </summary>
+        /// <param name="state">Current GPU state</param>
+        private void UpdateDepthClampState(GpuState state)
+        {
+            ViewVolumeClipControl clip = state.Get<ViewVolumeClipControl>(MethodOffset.ViewVolumeClipControl);
+            _context.Renderer.Pipeline.SetDepthClamp((clip & ViewVolumeClipControl.DepthClampNear) != 0,
+                                                     (clip & ViewVolumeClipControl.DepthClampFar) != 0);
+        }
+
         /// <summary>
         /// Updates host depth test state based on current GPU state.
         /// </summary>
@@ -384,8 +402,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
 
             _context.Renderer.Pipeline.SetDepthMode(depthMode);
 
-            bool flipY = (state.Get<int>(MethodOffset.YControl) & 1) != 0;
-
+            bool flipY = (state.Get<YControl>(MethodOffset.YControl) & YControl.NegateY) != 0;
             float yFlip = flipY ? -1 : 1;
 
             Viewport[] viewports = new Viewport[Constants.TotalViewports];

+ 1 - 0
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,

+ 12 - 0
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,
+    }
+}

+ 11 - 0
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
+    }
+}

+ 15 - 0
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();