From 4496030ea9bd873d101628a8eb943b976ec7b07a Mon Sep 17 00:00:00 2001
From: Kelebek1 <eeeedddccc@hotmail.co.uk>
Date: Mon, 10 Oct 2022 20:32:38 +0100
Subject: [PATCH] Fix stencil func registers, make clip control equivalent to
 how it was before, but surely wrong.

---
 src/video_core/dirty_flags.cpp                |  2 +-
 src/video_core/engines/maxwell_3d.cpp         |  8 +++----
 src/video_core/engines/maxwell_3d.h           | 22 ++++++++++---------
 .../renderer_opengl/gl_rasterizer.cpp         | 17 +++++++++-----
 .../renderer_opengl/gl_state_tracker.cpp      | 14 +++++-------
 .../renderer_vulkan/fixed_pipeline_state.cpp  |  6 ++++-
 .../renderer_vulkan/vk_rasterizer.cpp         | 14 +++++-------
 .../renderer_vulkan/vk_state_tracker.cpp      | 12 +++++-----
 8 files changed, 51 insertions(+), 44 deletions(-)

diff --git a/src/video_core/dirty_flags.cpp b/src/video_core/dirty_flags.cpp
index 1039e036f..c2ecc12f5 100644
--- a/src/video_core/dirty_flags.cpp
+++ b/src/video_core/dirty_flags.cpp
@@ -61,7 +61,7 @@ void SetupDirtyRenderTargets(Maxwell3D::DirtyState::Tables& tables) {
 }
 
 void SetupDirtyShaders(Maxwell3D::DirtyState::Tables& tables) {
-    FillBlock(tables[0], OFF(pipelines), NUM(pipelines) * Maxwell3D::Regs::MaxShaderProgram,
+    FillBlock(tables[0], OFF(pipelines), NUM(pipelines[0]) * Maxwell3D::Regs::MaxShaderProgram,
               Shaders);
 }
 } // Anonymous namespace
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 84c1abf3d..89a9d1f5a 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -74,15 +74,15 @@ void Maxwell3D::InitializeRegisterDefaults() {
     regs.stencil_front_op.zfail = Regs::StencilOp::Op::Keep_D3D;
     regs.stencil_front_op.zpass = Regs::StencilOp::Op::Keep_D3D;
     regs.stencil_front_op.func = Regs::ComparisonOp::Always_GL;
-    regs.stencil_front_func.func_mask = 0xFFFFFFFF;
-    regs.stencil_front_func.mask = 0xFFFFFFFF;
+    regs.stencil_front_func_mask = 0xFFFFFFFF;
+    regs.stencil_front_mask = 0xFFFFFFFF;
     regs.stencil_two_side_enable = 1;
     regs.stencil_back_op.fail = Regs::StencilOp::Op::Keep_D3D;
     regs.stencil_back_op.zfail = Regs::StencilOp::Op::Keep_D3D;
     regs.stencil_back_op.zpass = Regs::StencilOp::Op::Keep_D3D;
     regs.stencil_back_op.func = Regs::ComparisonOp::Always_GL;
-    regs.stencil_back_func.func_mask = 0xFFFFFFFF;
-    regs.stencil_back_func.mask = 0xFFFFFFFF;
+    regs.stencil_back_func_mask = 0xFFFFFFFF;
+    regs.stencil_back_mask = 0xFFFFFFFF;
 
     regs.depth_test_func = Regs::ComparisonOp::Always_GL;
     regs.gl_front_face = Regs::FrontFace::CounterClockWise;
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index efe1073b0..12dbd9cc4 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -1795,12 +1795,6 @@ public:
             ComparisonOp func;
         };
 
-        struct StencilFunc {
-            s32 ref;
-            u32 func_mask;
-            u32 mask;
-        };
-
         struct PsSaturate {
             // Opposite of DepthMode
             enum class Depth : u32 {
@@ -2737,7 +2731,9 @@ public:
                 u32 post_z_pixel_imask;                                                ///< 0x0F1C
                 INSERT_PADDING_BYTES_NOINIT(0x20);
                 ConstantColorRendering const_color_rendering;                          ///< 0x0F40
-                StencilFunc stencil_back_func;                                         ///< 0x0F54
+                s32 stencil_back_ref;                                                  ///< 0x0F54
+                u32 stencil_back_mask;                                                 ///< 0x0F58
+                u32 stencil_back_func_mask;                                            ///< 0x0F5C
                 INSERT_PADDING_BYTES_NOINIT(0x24);
                 VertexStreamSubstitute vertex_stream_substitute;                       ///< 0x0F84
                 u32 line_mode_clip_generated_edge_do_not_draw;                         ///< 0x0F8C
@@ -2855,7 +2851,9 @@ public:
                 Blend blend;                                                           ///< 0x133C
                 u32 stencil_enable;                                                    ///< 0x1380
                 StencilOp stencil_front_op;                                            ///< 0x1384
-                StencilFunc stencil_front_func;                                        ///< 0x1394
+                s32 stencil_front_ref;                                                 ///< 0x1394
+                s32 stencil_front_func_mask;                                           ///< 0x1398
+                s32 stencil_front_mask;                                                ///< 0x139C
                 INSERT_PADDING_BYTES_NOINIT(0x4);
                 u32 draw_auto_start_byte_count;                                        ///< 0x13A4
                 PsSaturate frag_color_clamp;                                           ///< 0x13A8
@@ -3311,7 +3309,9 @@ ASSERT_REG_POSITION(vpc_perf, 0x0F14);
 ASSERT_REG_POSITION(pm_local_trigger, 0x0F18);
 ASSERT_REG_POSITION(post_z_pixel_imask, 0x0F1C);
 ASSERT_REG_POSITION(const_color_rendering, 0x0F40);
-ASSERT_REG_POSITION(stencil_back_func, 0x0F54);
+ASSERT_REG_POSITION(stencil_back_ref, 0x0F54);
+ASSERT_REG_POSITION(stencil_back_mask, 0x0F58);
+ASSERT_REG_POSITION(stencil_back_func_mask, 0x0F5C);
 ASSERT_REG_POSITION(vertex_stream_substitute, 0x0F84);
 ASSERT_REG_POSITION(line_mode_clip_generated_edge_do_not_draw, 0x0F8C);
 ASSERT_REG_POSITION(color_mask_common, 0x0F90);
@@ -3416,7 +3416,9 @@ ASSERT_REG_POSITION(invalidate_texture_data_cache_lines, 0x1338);
 ASSERT_REG_POSITION(blend, 0x133C);
 ASSERT_REG_POSITION(stencil_enable, 0x1380);
 ASSERT_REG_POSITION(stencil_front_op, 0x1384);
-ASSERT_REG_POSITION(stencil_front_func, 0x1394);
+ASSERT_REG_POSITION(stencil_front_ref, 0x1394);
+ASSERT_REG_POSITION(stencil_front_func_mask, 0x1398);
+ASSERT_REG_POSITION(stencil_front_mask, 0x139C);
 ASSERT_REG_POSITION(draw_auto_start_byte_count, 0x13A4);
 ASSERT_REG_POSITION(frag_color_clamp, 0x13A8);
 ASSERT_REG_POSITION(window_origin, 0x13AC);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index cce00cea8..e5c09a969 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -658,8 +658,13 @@ void RasterizerOpenGL::SyncDepthClamp() {
     }
     flags[Dirty::DepthClampEnabled] = false;
 
-    oglEnable(GL_DEPTH_CLAMP, maxwell3d->regs.viewport_clip_control.geometry_clip !=
-                                  Maxwell::ViewportClipControl::GeometryClip::Passthrough);
+    bool depth_clamp_disabled{maxwell3d->regs.viewport_clip_control.geometry_clip ==
+                                  Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
+                              maxwell3d->regs.viewport_clip_control.geometry_clip ==
+                                  Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
+                              maxwell3d->regs.viewport_clip_control.geometry_clip ==
+                                  Maxwell::ViewportClipControl::GeometryClip::FrustumZ};
+    oglEnable(GL_DEPTH_CLAMP, !depth_clamp_disabled);
 }
 
 void RasterizerOpenGL::SyncClipEnabled(u32 clip_mask) {
@@ -746,19 +751,19 @@ void RasterizerOpenGL::SyncStencilTestState() {
     oglEnable(GL_STENCIL_TEST, regs.stencil_enable);
 
     glStencilFuncSeparate(GL_FRONT, MaxwellToGL::ComparisonOp(regs.stencil_front_op.func),
-                          regs.stencil_front_func.ref, regs.stencil_front_func.func_mask);
+                          regs.stencil_front_ref, regs.stencil_front_func_mask);
     glStencilOpSeparate(GL_FRONT, MaxwellToGL::StencilOp(regs.stencil_front_op.fail),
                         MaxwellToGL::StencilOp(regs.stencil_front_op.zfail),
                         MaxwellToGL::StencilOp(regs.stencil_front_op.zpass));
-    glStencilMaskSeparate(GL_FRONT, regs.stencil_front_func.mask);
+    glStencilMaskSeparate(GL_FRONT, regs.stencil_front_mask);
 
     if (regs.stencil_two_side_enable) {
         glStencilFuncSeparate(GL_BACK, MaxwellToGL::ComparisonOp(regs.stencil_back_op.func),
-                              regs.stencil_back_func.ref, regs.stencil_back_func.mask);
+                              regs.stencil_back_ref, regs.stencil_back_mask);
         glStencilOpSeparate(GL_BACK, MaxwellToGL::StencilOp(regs.stencil_back_op.fail),
                             MaxwellToGL::StencilOp(regs.stencil_back_op.zfail),
                             MaxwellToGL::StencilOp(regs.stencil_back_op.zpass));
-        glStencilMaskSeparate(GL_BACK, regs.stencil_back_func.mask);
+        glStencilMaskSeparate(GL_BACK, regs.stencil_back_mask);
     } else {
         glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 0xFFFFFFFF);
         glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_KEEP);
diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp
index e2c709aac..a359f96f1 100644
--- a/src/video_core/renderer_opengl/gl_state_tracker.cpp
+++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp
@@ -100,14 +100,12 @@ void SetupDirtyDepthTest(Tables& tables) {
 
 void SetupDirtyStencilTest(Tables& tables) {
     static constexpr std::array offsets = {
-        OFF(stencil_enable),          OFF(stencil_front_op.func),
-        OFF(stencil_front_func.ref),  OFF(stencil_front_func.func_mask),
-        OFF(stencil_front_op.fail),   OFF(stencil_front_op.zfail),
-        OFF(stencil_front_op.zpass),  OFF(stencil_front_func.mask),
-        OFF(stencil_two_side_enable), OFF(stencil_back_op.func),
-        OFF(stencil_back_func.ref),   OFF(stencil_back_func.func_mask),
-        OFF(stencil_back_op.fail),    OFF(stencil_back_op.zfail),
-        OFF(stencil_back_op.zpass),   OFF(stencil_back_func.mask)};
+        OFF(stencil_enable),          OFF(stencil_front_op.func), OFF(stencil_front_ref),
+        OFF(stencil_front_func_mask), OFF(stencil_front_op.fail), OFF(stencil_front_op.zfail),
+        OFF(stencil_front_op.zpass),  OFF(stencil_front_mask),    OFF(stencil_two_side_enable),
+        OFF(stencil_back_op.func),    OFF(stencil_back_ref),      OFF(stencil_back_func_mask),
+        OFF(stencil_back_op.fail),    OFF(stencil_back_op.zfail), OFF(stencil_back_op.zpass),
+        OFF(stencil_back_mask)};
     for (const auto offset : offsets) {
         tables[0][offset] = StencilTest;
     }
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
index eb7c22fd5..eab1b8f93 100644
--- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
+++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp
@@ -63,7 +63,11 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d,
     primitive_restart_enable.Assign(regs.primitive_restart.enabled != 0 ? 1 : 0);
     depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0);
     depth_clamp_disabled.Assign(regs.viewport_clip_control.geometry_clip ==
-                                Maxwell::ViewportClipControl::GeometryClip::Passthrough);
+                                    Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
+                                regs.viewport_clip_control.geometry_clip ==
+                                    Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
+                                regs.viewport_clip_control.geometry_clip ==
+                                    Maxwell::ViewportClipControl::GeometryClip::FrustumZ);
     ndc_minus_one_to_one.Assign(regs.depth_mode == Maxwell::DepthMode::MinusOneToOne ? 1 : 0);
     polygon_mode.Assign(PackPolygonMode(regs.polygon_mode_front));
     patch_control_points_minus_one.Assign(regs.patch_vertices - 1);
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 892cd94a3..47dfb45a1 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -772,11 +772,10 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs)
     if (regs.stencil_two_side_enable) {
         // Separate values per face
         scheduler.Record(
-            [front_ref = regs.stencil_front_func.ref,
-             front_write_mask = regs.stencil_front_func.mask,
-             front_test_mask = regs.stencil_front_func.func_mask,
-             back_ref = regs.stencil_back_func.ref, back_write_mask = regs.stencil_back_func.mask,
-             back_test_mask = regs.stencil_back_func.func_mask](vk::CommandBuffer cmdbuf) {
+            [front_ref = regs.stencil_front_ref, front_write_mask = regs.stencil_front_mask,
+             front_test_mask = regs.stencil_front_func_mask, back_ref = regs.stencil_back_ref,
+             back_write_mask = regs.stencil_back_mask,
+             back_test_mask = regs.stencil_back_func_mask](vk::CommandBuffer cmdbuf) {
                 // Front face
                 cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_BIT, front_ref);
                 cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_BIT, front_write_mask);
@@ -789,9 +788,8 @@ void RasterizerVulkan::UpdateStencilFaces(Tegra::Engines::Maxwell3D::Regs& regs)
             });
     } else {
         // Front face defines both faces
-        scheduler.Record([ref = regs.stencil_front_func.ref,
-                          write_mask = regs.stencil_front_func.mask,
-                          test_mask = regs.stencil_front_func.func_mask](vk::CommandBuffer cmdbuf) {
+        scheduler.Record([ref = regs.stencil_front_ref, write_mask = regs.stencil_front_mask,
+                          test_mask = regs.stencil_front_func_mask](vk::CommandBuffer cmdbuf) {
             cmdbuf.SetStencilReference(VK_STENCIL_FACE_FRONT_AND_BACK, ref);
             cmdbuf.SetStencilWriteMask(VK_STENCIL_FACE_FRONT_AND_BACK, write_mask);
             cmdbuf.SetStencilCompareMask(VK_STENCIL_FACE_FRONT_AND_BACK, test_mask);
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index ed98c8370..b87c3be66 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -77,12 +77,12 @@ void SetupDirtyDepthBounds(Tables& tables) {
 void SetupDirtyStencilProperties(Tables& tables) {
     auto& table = tables[0];
     table[OFF(stencil_two_side_enable)] = StencilProperties;
-    table[OFF(stencil_front_func.ref)] = StencilProperties;
-    table[OFF(stencil_front_func.mask)] = StencilProperties;
-    table[OFF(stencil_front_func.func_mask)] = StencilProperties;
-    table[OFF(stencil_back_func.ref)] = StencilProperties;
-    table[OFF(stencil_back_func.mask)] = StencilProperties;
-    table[OFF(stencil_back_func.func_mask)] = StencilProperties;
+    table[OFF(stencil_front_ref)] = StencilProperties;
+    table[OFF(stencil_front_mask)] = StencilProperties;
+    table[OFF(stencil_front_func_mask)] = StencilProperties;
+    table[OFF(stencil_back_ref)] = StencilProperties;
+    table[OFF(stencil_back_mask)] = StencilProperties;
+    table[OFF(stencil_back_func_mask)] = StencilProperties;
 }
 
 void SetupDirtyLineWidth(Tables& tables) {