Procházet zdrojové kódy

[GPU] Fix frame buffer being upside down in some cases

gdkchan před 8 roky
rodič
revize
42ebfdff7f

+ 1 - 5
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
     {

+ 7 - 0
Ryujinx.Graphics/Gal/GalConsts.cs

@@ -0,0 +1,7 @@
+namespace Ryujinx.Graphics.Gal
+{
+    public static class GalConsts
+    {
+        public const string FlipUniformName = "flip";
+    }
+}

+ 4 - 0
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();

+ 36 - 0
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)

+ 9 - 0
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))

+ 15 - 0
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<ShaderDeclInfo> GetTextureUsage(long Tag)
         {
             return Shader.GetTextureUsage(Tag);

+ 7 - 0
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;");
                         }
                     }

+ 11 - 0
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;
         }
 

+ 6 - 0
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,