diff --git a/Ryujinx.Core/LogClass.cs b/Ryujinx.Core/LogClass.cs index 67fd8559ff..1a3fbb5903 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 0000000000..6c8857c6ed --- /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 c30c79fb38..af88412a29 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 cca61e1810..e0da9179a3 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 6d6ac555d6..fff6362b41 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 b3ccae5f87..5e066e3f19 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 7d97ec3342..457192dc2a 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 fd13367c41..88ad763349 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 4f1dce94b3..605ca9dab5 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,