From 42ebfdff7f2889be38a3415bf33aeb41df90bd98 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 14 Apr 2018 00:39:24 -0300 Subject: [PATCH] [GPU] Fix frame buffer being upside down in some cases --- Ryujinx.Core/LogClass.cs | 6 +--- Ryujinx.Graphics/Gal/GalConsts.cs | 7 ++++ Ryujinx.Graphics/Gal/IGalRenderer.cs | 4 +++ Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs | 36 +++++++++++++++++++ Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs | 9 +++++ Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs | 15 ++++++++ Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs | 7 ++++ Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs | 11 ++++++ Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs | 6 ++++ 9 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 Ryujinx.Graphics/Gal/GalConsts.cs diff --git a/Ryujinx.Core/LogClass.cs b/Ryujinx.Core/LogClass.cs index 67fd8559f..1a3fbb590 100644 --- a/Ryujinx.Core/LogClass.cs +++ b/Ryujinx.Core/LogClass.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Ryujinx.Core +namespace Ryujinx.Core { public enum LogClass { diff --git a/Ryujinx.Graphics/Gal/GalConsts.cs b/Ryujinx.Graphics/Gal/GalConsts.cs new file mode 100644 index 000000000..6c8857c6e --- /dev/null +++ b/Ryujinx.Graphics/Gal/GalConsts.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.Graphics.Gal +{ + public static class GalConsts + { + public const string FlipUniformName = "flip"; + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/IGalRenderer.cs b/Ryujinx.Graphics/Gal/IGalRenderer.cs index c30c79fb3..af88412a2 100644 --- a/Ryujinx.Graphics/Gal/IGalRenderer.cs +++ b/Ryujinx.Graphics/Gal/IGalRenderer.cs @@ -42,6 +42,8 @@ namespace Ryujinx.Graphics.Gal void SetFrameBufferTransform(float SX, float SY, float Rotate, float TX, float TY); + void SetViewport(int X, int Y, int Width, int Height); + //Rasterizer void ClearBuffers(int RtIndex, GalClearBufferFlags Flags); @@ -62,6 +64,8 @@ namespace Ryujinx.Graphics.Gal void SetUniform1(string UniformName, int Value); + void SetUniform2F(string UniformName, float X, float Y); + void BindShader(long Tag); void BindProgram(); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs index cca61e181..e0da9179a 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs @@ -7,6 +7,22 @@ namespace Ryujinx.Graphics.Gal.OpenGL { class OGLFrameBuffer { + private struct Rect + { + public int X { get; private set; } + public int Y { get; private set; } + public int Width { get; private set; } + public int Height { get; private set; } + + public Rect(int X, int Y, int Width, int Height) + { + this.X = X; + this.Y = Y; + this.Width = Width; + this.Height = Height; + } + } + private class FrameBuffer { public int Width { get; set; } @@ -38,6 +54,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL private ShaderProgram Shader; + private Rect Viewport; + private bool IsInitialized; private int RawFbTexWidth; @@ -178,6 +196,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.UseProgram(CurrentProgram); } + public void SetViewport(int X, int Y, int Width, int Height) + { + Viewport = new Rect(X, Y, Width, Height); + + //TODO + } + public void Render() { if (CurrTexHandle != 0) @@ -196,6 +221,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); + GL.Viewport(0, 0, 1280, 720); + GL.Clear( ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); @@ -218,6 +245,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL } } + private void SetViewport() + { + GL.Viewport( + Viewport.X, + Viewport.Y, + Viewport.Width, + Viewport.Height); + } + private void EnsureInitialized() { if (!IsInitialized) diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs index 6d6ac555d..fff6362b4 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLShader.cs @@ -158,6 +158,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.Uniform1(Location, Value); } + public void SetUniform2F(string UniformName, float X, float Y) + { + BindProgram(); + + int Location = GL.GetUniformLocation(CurrentProgramHandle, UniformName); + + GL.Uniform2(Location, X, Y); + } + public void Bind(long Tag) { if (Stages.TryGetValue(Tag, out ShaderStage Stage)) diff --git a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs index b3ccae5f8..5e066e3f1 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OpenGLRenderer.cs @@ -141,6 +141,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL ActionsQueue.Enqueue(() => FrameBuffer.SetTransform(Transform, Offs)); } + public void SetViewport(int X, int Y, int Width, int Height) + { + ActionsQueue.Enqueue(() => FrameBuffer.SetViewport(X, Y, Width, Height)); + } + public void ClearBuffers(int RtIndex, GalClearBufferFlags Flags) { ActionsQueue.Enqueue(() => Rasterizer.ClearBuffers(RtIndex, Flags)); @@ -218,6 +223,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL ActionsQueue.Enqueue(() => Shader.SetUniform1(UniformName, Value)); } + public void SetUniform2F(string UniformName, float X, float Y) + { + if (UniformName == null) + { + throw new ArgumentNullException(nameof(UniformName)); + } + + ActionsQueue.Enqueue(() => Shader.SetUniform2F(UniformName, X, Y)); + } + public IEnumerable GetTextureUsage(long Tag) { return Shader.GetTextureUsage(Tag); diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index 7d97ec334..457192dc2 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -115,6 +115,11 @@ namespace Ryujinx.Graphics.Gal.Shader private void PrintDeclUniforms() { + if (Decl.ShaderType == GalShaderType.Vertex) + { + SB.AppendLine("uniform vec2 " + GalConsts.FlipUniformName + ";"); + } + foreach (ShaderDeclInfo DeclInfo in Decl.Uniforms.Values.OrderBy(DeclKeySelector)) { SB.AppendLine($"uniform {GetDecl(DeclInfo)};"); @@ -270,6 +275,8 @@ namespace Ryujinx.Graphics.Gal.Shader //the shader ends here. if (Decl.ShaderType == GalShaderType.Vertex) { + SB.AppendLine(Identation + "gl_Position.xy *= flip;"); + SB.AppendLine(Identation + GlslDecl.PositionOutAttrName + " = gl_Position;"); } } diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs index fd13367c4..88ad76334 100644 --- a/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs +++ b/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs @@ -147,6 +147,17 @@ namespace Ryujinx.Graphics.Gpu Gpu.Renderer.BindShader(Tag); } + int RawSX = ReadRegister(NvGpuEngine3dReg.ViewportScaleX); + int RawSY = ReadRegister(NvGpuEngine3dReg.ViewportScaleY); + + float SX = BitConverter.Int32BitsToSingle(RawSX); + float SY = BitConverter.Int32BitsToSingle(RawSY); + + float SignX = MathF.Sign(SX); + float SignY = MathF.Sign(SY); + + Gpu.Renderer.SetUniform2F(GalConsts.FlipUniformName, SignX, SignY); + return Tags; } diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs index 4f1dce94b..605ca9dab 100644 --- a/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs +++ b/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs @@ -6,6 +6,12 @@ namespace Ryujinx.Graphics.Gpu FrameBufferNWidth = 0x202, FrameBufferNHeight = 0x203, FrameBufferNFormat = 0x204, + ViewportScaleX = 0x280, + ViewportScaleY = 0x281, + ViewportScaleZ = 0x282, + ViewportTranslateX = 0x283, + ViewportTranslateY = 0x284, + ViewportTranslateZ = 0x285, VertexAttribNFormat = 0x458, IBlendEnable = 0x4b9, BlendSeparateAlpha = 0x4cf,