diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs index 7c67a1720..83ccfc3de 100644 --- a/Ryujinx.Graphics.GAL/IPipeline.cs +++ b/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); diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs index 093f90488..df0e713df 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs +++ b/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. /// /// Current GPU state - private void UpdatePointSizeState(GpuState state) + private void UpdatePointState(GpuState state) { float size = state.Get(MethodOffset.PointSize); + bool isProgramPointSize = state.Get(MethodOffset.VertexProgramPointSize); + bool enablePointSprite = state.Get(MethodOffset.PointSpriteEnable); + + // TODO: Need to figure out a way to map PointCoordReplace enable bit. + Origin origin = (state.Get(MethodOffset.PointCoordReplace) & 4) == 0 ? Origin.LowerLeft : Origin.UpperLeft; - _context.Renderer.Pipeline.SetPointSize(size); + _context.Renderer.Pipeline.SetPointParameters(size, isProgramPointSize, enablePointSprite, origin); } /// diff --git a/Ryujinx.Graphics.Gpu/State/GpuState.cs b/Ryujinx.Graphics.Gpu/State/GpuState.cs index 9e7d9492a..67bcb291e 100644 --- a/Ryujinx.Graphics.Gpu/State/GpuState.cs +++ b/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 } /// diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs index b0eb6f328..d9e2ce930 100644 --- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs +++ b/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, diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs index 7537b44fa..2016d8524 100644 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ b/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)