瀏覽代碼

GL: Implement more Point parameters (#1399)

* Fix GL_INVALID_VALUE on glPointSize calls

* Implement more of Point primitive state

* Use existing Origin enum
mageven 5 年之前
父節點
當前提交
723ae240dc

+ 1 - 1
Ryujinx.Graphics.GAL/IPipeline.cs

@@ -50,7 +50,7 @@ namespace Ryujinx.Graphics.GAL
 
         void SetOrigin(Origin origin);
 
-        void SetPointSize(float size);
+        void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin);
 
         void SetPrimitiveRestart(bool enable, int index);
 

+ 12 - 4
Ryujinx.Graphics.Gpu/Engine/Methods.cs

@@ -224,9 +224,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
                 UpdateVertexAttribState(state);
             }
 
-            if (state.QueryModified(MethodOffset.PointSize))
+            if (state.QueryModified(MethodOffset.PointSize,
+                                    MethodOffset.VertexProgramPointSize,
+                                    MethodOffset.PointSpriteEnable,
+                                    MethodOffset.PointCoordReplace))
             {
-                UpdatePointSizeState(state);
+                UpdatePointState(state);
             }
 
             if (state.QueryModified(MethodOffset.PrimitiveRestartState))
@@ -703,11 +706,16 @@ namespace Ryujinx.Graphics.Gpu.Engine
         /// Updates host point size based on guest GPU state.
         /// </summary>
         /// <param name="state">Current GPU state</param>
-        private void UpdatePointSizeState(GpuState state)
+        private void UpdatePointState(GpuState state)
         {
             float size = state.Get<float>(MethodOffset.PointSize);
+            bool isProgramPointSize = state.Get<Boolean32>(MethodOffset.VertexProgramPointSize);
+            bool enablePointSprite = state.Get<Boolean32>(MethodOffset.PointSpriteEnable);
+            
+            // TODO: Need to figure out a way to map PointCoordReplace enable bit.
+            Origin origin = (state.Get<int>(MethodOffset.PointCoordReplace) & 4) == 0 ? Origin.LowerLeft : Origin.UpperLeft;
 
-            _context.Renderer.Pipeline.SetPointSize(size);
+            _context.Renderer.Pipeline.SetPointParameters(size, isProgramPointSize, enablePointSprite, origin);
         }
 
         /// <summary>

+ 5 - 0
Ryujinx.Graphics.Gpu/State/GpuState.cs

@@ -173,6 +173,11 @@ namespace Ryujinx.Graphics.Gpu.State
             {
                 Set(MethodOffset.BlendState, index, BlendState.Default);
             }
+
+            // Default Point Parameters
+            memory[(int)MethodOffset.PointSpriteEnable] = 1;
+            memory[(int)MethodOffset.PointSize] = 0x3F800000; // 1.0f
+            memory[(int)MethodOffset.PointCoordReplace] = 0x8; // Enable
         }
 
         /// <summary>

+ 3 - 0
Ryujinx.Graphics.Gpu/State/MethodOffset.cs

@@ -73,6 +73,7 @@ namespace Ryujinx.Graphics.Gpu.State
         FirstInstance                   = 0x50e,
         ClipDistanceEnable              = 0x544,
         PointSize                       = 0x546,
+        PointSpriteEnable               = 0x548,
         ResetCounter                    = 0x54c,
         RtDepthStencilEnable            = 0x54e,
         ConditionState                  = 0x554,
@@ -84,6 +85,7 @@ namespace Ryujinx.Graphics.Gpu.State
         RtMsaaMode                      = 0x574,
         VbElementU32                    = 0x57a,
         VbElementU16                    = 0x57c,
+        PointCoordReplace               = 0x581,
         ShaderBaseAddress               = 0x582,
         DrawEnd                         = 0x585,
         DrawBegin                       = 0x586,
@@ -92,6 +94,7 @@ namespace Ryujinx.Graphics.Gpu.State
         IndexBufferCount                = 0x5f8,
         DepthBiasClamp                  = 0x61f,
         VertexBufferInstanced           = 0x620,
+        VertexProgramPointSize          = 0x644,
         FaceState                       = 0x646,
         ViewportTransformEnable         = 0x64b,
         ViewVolumeClipControl           = 0x64f,

+ 28 - 2
Ryujinx.Graphics.OpenGL/Pipeline.cs

@@ -700,9 +700,35 @@ namespace Ryujinx.Graphics.OpenGL
             SetOrigin(clipOrigin);
         }
 
-        public void SetPointSize(float size)
+        public void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin)
         {
-            GL.PointSize(size);
+            // GL_POINT_SPRITE was deprecated in core profile 3.2+ and causes GL_INVALID_ENUM when set.
+            // As we don't know if the current context is core or compat, it's safer to keep this code.
+            if (enablePointSprite)
+            {
+                GL.Enable(EnableCap.PointSprite);
+            }
+            else
+            {
+                GL.Disable(EnableCap.PointSprite);
+            }
+
+            if (isProgramPointSize)
+            {
+                GL.Enable(EnableCap.ProgramPointSize);
+            }
+            else
+            {
+                GL.Disable(EnableCap.ProgramPointSize);
+            }
+
+            GL.PointParameter(origin == Origin.LowerLeft 
+                ? PointSpriteCoordOriginParameter.LowerLeft 
+                : PointSpriteCoordOriginParameter.UpperLeft);
+
+            // Games seem to set point size to 0 which generates a GL_INVALID_VALUE
+            // From the spec, GL_INVALID_VALUE is generated if size is less than or equal to 0. 
+            GL.PointSize(Math.Max(float.Epsilon, size));
         }
 
         public void SetPrimitiveRestart(bool enable, int index)