From 900a84ae0a90ae13c8c3f5158eff85c68a953362 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Wed, 27 Jun 2018 01:32:28 -0300
Subject: [PATCH] Fix vertex buffer size on the gpu when the draw vertex count
 is less than the buffer size, added a few more registers (currently not
 implemented)

---
 Ryujinx.Graphics/Gal/GalComparisonOp.cs       | 14 ++++++++++
 Ryujinx.Graphics/Gal/IGalRasterizer.cs        | 10 +++++++
 .../Gal/OpenGL/OGLEnumConverter.cs            | 11 ++++++++
 Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs  | 25 ++++++++++++++++++
 Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs      |  2 +-
 Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs      | 26 ++++++++++---------
 Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs   |  5 ++++
 7 files changed, 80 insertions(+), 13 deletions(-)
 create mode 100644 Ryujinx.Graphics/Gal/GalComparisonOp.cs

diff --git a/Ryujinx.Graphics/Gal/GalComparisonOp.cs b/Ryujinx.Graphics/Gal/GalComparisonOp.cs
new file mode 100644
index 0000000000..ddddecebb4
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/GalComparisonOp.cs
@@ -0,0 +1,14 @@
+namespace Ryujinx.Graphics.Gal
+{
+    public enum GalComparisonOp
+    {
+        Never    = 0x200,
+        Less     = 0x201,
+        Equal    = 0x202,
+        Lequal   = 0x203,
+        Greater  = 0x204,
+        NotEqual = 0x205,
+        Gequal   = 0x206,
+        Always   = 0x207
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalRasterizer.cs b/Ryujinx.Graphics/Gal/IGalRasterizer.cs
index 81c922befd..1323372a26 100644
--- a/Ryujinx.Graphics/Gal/IGalRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/IGalRasterizer.cs
@@ -8,6 +8,16 @@ namespace Ryujinx.Graphics.Gal
 
         bool IsIboCached(long Key, long DataSize);
 
+        void EnableCullFace();
+
+        void DisableCullFace();
+
+        void EnableDepthTest();
+
+        void DisableDepthTest();
+
+        void SetDepthFunction(GalComparisonOp Func);
+
         void CreateVbo(long Key, byte[] Buffer);
 
         void CreateIbo(long Key, byte[] Buffer);
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
index c2b0c40a72..cb2c1a0e8b 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
@@ -5,6 +5,17 @@ namespace Ryujinx.Graphics.Gal.OpenGL
 {
     static class OGLEnumConverter
     {
+        public static DepthFunction GetDepthFunc(GalComparisonOp Func)
+        {
+            if ((int)Func >= (int)DepthFunction.Never &&
+                (int)Func <= (int)DepthFunction.Always)
+            {
+                return (DepthFunction)Func;
+            }
+
+            throw new ArgumentException(nameof(Func));
+        }
+
         public static DrawElementsType GetDrawElementsType(GalIndexFormat Format)
         {
             switch (Format)
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
index bdf22b9c11..0525069690 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
@@ -106,6 +106,31 @@ namespace Ryujinx.Graphics.Gal.OpenGL
             return IboCache.TryGetSize(Key, out long Size) && Size == DataSize;
         }
 
+        public void EnableCullFace()
+        {
+            GL.Enable(EnableCap.CullFace);
+        }
+
+        public void DisableCullFace()
+        {
+            GL.Disable(EnableCap.CullFace);
+        }
+
+        public void EnableDepthTest()
+        {
+            GL.Enable(EnableCap.DepthTest);
+        }
+
+        public void DisableDepthTest()
+        {
+            GL.Disable(EnableCap.DepthTest);
+        }
+
+        public void SetDepthFunction(GalComparisonOp Func)
+        {
+            GL.DepthFunc(OGLEnumConverter.GetDepthFunc(Func));
+        }
+
         public void CreateVbo(long Key, byte[] Buffer)
         {
             int Handle = GL.GenBuffer();
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
index 28fa8728ef..da2762d6c8 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs
@@ -283,7 +283,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
 
                 return FreeBinding;
             }
-            
+
             BindUniformBuffersIfNotNull(Current.Vertex);
             BindUniformBuffersIfNotNull(Current.TessControl);
             BindUniformBuffersIfNotNull(Current.TessEvaluation);
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
index 02461d5dda..1663d4c59b 100644
--- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
+++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
@@ -79,6 +79,8 @@ namespace Ryujinx.HLE.Gpu.Engines
 
             Gpu.Renderer.Shader.BindProgram();
 
+            SetCullFace();
+            SetDepth();
             SetAlphaBlending();
 
             UploadTextures(Vmm, Keys);
@@ -98,8 +100,7 @@ namespace Ryujinx.HLE.Gpu.Engines
 
             SetFrameBuffer(Vmm, 0);
 
-            //TODO: Enable this once the frame buffer problems are fixed.
-            //Gpu.Renderer.ClearBuffers(Layer, Flags);
+            Gpu.Renderer.Rasterizer.ClearBuffers(Layer, Flags);
         }
 
         private void SetFrameBuffer(NvGpuVmm Vmm, int FbIndex)
@@ -177,6 +178,16 @@ namespace Ryujinx.HLE.Gpu.Engines
             throw new ArgumentOutOfRangeException(nameof(Program));
         }
 
+        private void SetCullFace()
+        {
+            //TODO.
+        }
+
+        private void SetDepth()
+        {
+            //TODO.
+        }
+
         private void SetAlphaBlending()
         {
             //TODO: Support independent blend properly.
@@ -434,16 +445,7 @@ namespace Ryujinx.HLE.Gpu.Engines
 
                 int Stride = Control & 0xfff;
 
-                long VbSize = 0;
-
-                if (IndexCount != 0)
-                {
-                    VbSize = (VertexEndPos - VertexPosition) + 1;
-                }
-                else
-                {
-                    VbSize = VertexCount * Stride;
-                }
+                long VbSize = (VertexEndPos - VertexPosition) + 1;
 
                 bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VertexPosition, VbSize);
 
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs
index de2b2eef27..64866ce9aa 100644
--- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs
+++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs
@@ -15,7 +15,9 @@ namespace Ryujinx.HLE.Gpu.Engines
         VertexArrayFirst     = 0x35d,
         VertexArrayCount     = 0x35e,
         VertexAttribNFormat  = 0x458,
+        DepthTestEnable      = 0x4b3,
         IBlendEnable         = 0x4b9,
+        DepthTestFunction    = 0x4c3,
         BlendSeparateAlpha   = 0x4cf,
         BlendEquationRgb     = 0x4d0,
         BlendFuncSrcRgb      = 0x4d1,
@@ -35,6 +37,9 @@ namespace Ryujinx.HLE.Gpu.Engines
         IndexArrayFormat     = 0x5f6,
         IndexBatchFirst      = 0x5f7,
         IndexBatchCount      = 0x5f8,
+        CullFaceEnable       = 0x646,
+        FrontFace            = 0x647,
+        CullFace             = 0x648,
         QueryAddress         = 0x6c0,
         QuerySequence        = 0x6c2,
         QueryControl         = 0x6c3,