diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLLimit.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLLimit.cs new file mode 100644 index 0000000000..6c385bc4a2 --- /dev/null +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLLimit.cs @@ -0,0 +1,12 @@ +using OpenTK.Graphics.OpenGL; +using System; + +namespace Ryujinx.Graphics.Gal.OpenGL +{ + static class OGLLimit + { + private static Lazy s_MaxUboSize = new Lazy(() => GL.GetInteger(GetPName.MaxUniformBlockSize)); + + public static int MaxUboSize => s_MaxUboSize.Value; + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs index e81cf8a384..35411d7faf 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs @@ -77,17 +77,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL private GalPipelineState Old; - private OGLConstBuffer Buffer; - private OGLRasterizer Rasterizer; - private OGLShader Shader; + private OGLConstBuffer Buffer; + private OGLRenderTarget RenderTarget; + private OGLRasterizer Rasterizer; + private OGLShader Shader; private int VaoHandle; - public OGLPipeline(OGLConstBuffer Buffer, OGLRasterizer Rasterizer, OGLShader Shader) + public OGLPipeline( + OGLConstBuffer Buffer, + OGLRenderTarget RenderTarget, + OGLRasterizer Rasterizer, + OGLShader Shader) { - this.Buffer = Buffer; - this.Rasterizer = Rasterizer; - this.Shader = Shader; + this.Buffer = Buffer; + this.RenderTarget = RenderTarget; + this.Rasterizer = Rasterizer; + this.Shader = Shader; //These values match OpenGL's defaults Old = new GalPipelineState @@ -144,6 +150,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL if (New.FramebufferSrgb != Old.FramebufferSrgb) { Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb); + + RenderTarget.FramebufferSrgb = New.FramebufferSrgb; } if (New.FlipX != Old.FlipX || New.FlipY != Old.FlipY || New.Instance != Old.Instance) diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs index 8d04f1aae7..9c00ae9af6 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs @@ -90,6 +90,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL private int CopyPBO; + public bool FramebufferSrgb { get; set; } + public OGLRenderTarget(OGLTexture Texture) { Attachments = new FrameBufferAttachments(); @@ -363,11 +365,24 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.Clear(ClearBufferMask.ColorBufferBit); + GL.Disable(EnableCap.FramebufferSrgb); + GL.BlitFramebuffer( - SrcX0, SrcY0, SrcX1, SrcY1, - DstX0, DstY0, DstX1, DstY1, + SrcX0, + SrcY0, + SrcX1, + SrcY1, + DstX0, + DstY0, + DstX1, + DstY1, ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Linear); + + if (FramebufferSrgb) + { + GL.Enable(EnableCap.FramebufferSrgb); + } } public void Copy( diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs index a23541f3dd..5610317471 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs @@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL Shader = new OGLShader(Buffer as OGLConstBuffer); - Pipeline = new OGLPipeline(Buffer as OGLConstBuffer, Rasterizer as OGLRasterizer, Shader as OGLShader); + Pipeline = new OGLPipeline(Buffer as OGLConstBuffer, RenderTarget as OGLRenderTarget, Rasterizer as OGLRasterizer, Shader as OGLShader); ActionsQueue = new ConcurrentQueue(); } diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs index c837632ec2..f1b63a8da3 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs @@ -1,3 +1,4 @@ +using Ryujinx.Graphics.Gal.OpenGL; using System; using System.Collections.Generic; @@ -16,8 +17,6 @@ namespace Ryujinx.Graphics.Gal.Shader public const int VertexIdAttr = 0x2fc; public const int FaceAttr = 0x3fc; - public const int MaxUboSize = 1024; - public const int GlPositionVec4Index = 7; public const int PositionOutAttrLocation = 15; @@ -51,6 +50,8 @@ namespace Ryujinx.Graphics.Gal.Shader public const string SsyStackName = "ssy_stack"; public const string SsyCursorName = "ssy_cursor"; + public static int MaxUboSize => OGLLimit.MaxUboSize / 16; + private string[] StagePrefixes = new string[] { "vp", "tcp", "tep", "gp", "fp" }; private string StagePrefix; @@ -98,8 +99,7 @@ namespace Ryujinx.Graphics.Gal.Shader m_Preds = new Dictionary(); } - public GlslDecl(ShaderIrBlock[] Blocks, GalShaderType ShaderType, ShaderHeader Header) - : this(ShaderType) + public GlslDecl(ShaderIrBlock[] Blocks, GalShaderType ShaderType, ShaderHeader Header) : this(ShaderType) { StagePrefix = StagePrefixes[(int)ShaderType] + "_"; diff --git a/Ryujinx.Graphics/NvGpuEngine2d.cs b/Ryujinx.Graphics/NvGpuEngine2d.cs index f20f8d6eeb..5de4143f25 100644 --- a/Ryujinx.Graphics/NvGpuEngine2d.cs +++ b/Ryujinx.Graphics/NvGpuEngine2d.cs @@ -61,6 +61,9 @@ namespace Ryujinx.Graphics int DstBlitW = ReadRegister(NvGpuEngine2dReg.BlitDstW); int DstBlitH = ReadRegister(NvGpuEngine2dReg.BlitDstH); + int BlitDuDx = ReadRegister(NvGpuEngine2dReg.BlitDuDxInt); + int BlitDvDy = ReadRegister(NvGpuEngine2dReg.BlitDvDyInt); + int SrcBlitX = ReadRegister(NvGpuEngine2dReg.BlitSrcXInt); int SrcBlitY = ReadRegister(NvGpuEngine2dReg.BlitSrcYInt); @@ -99,13 +102,16 @@ namespace Ryujinx.Graphics Gpu.ResourceManager.SendTexture(Vmm, SrcKey, SrcTexture); Gpu.ResourceManager.SendTexture(Vmm, DstKey, DstTexture); + int SrcBlitX2 = SrcBlitX + DstBlitW * BlitDuDx; + int SrcBlitY2 = SrcBlitY + DstBlitH * BlitDvDy; + Gpu.Renderer.RenderTarget.Copy( SrcKey, DstKey, SrcBlitX, SrcBlitY, - SrcBlitX + DstBlitW, - SrcBlitY + DstBlitH, + SrcBlitX2, + SrcBlitY2, DstBlitX, DstBlitY, DstBlitX + DstBlitW,