forked from Mirror/Ryujinx
Add support for bigger UBOs, fix sRGB regression, small improvement t… (#503)
* Add support for bigger UBOs, fix sRGB regression, small improvement to the 2D copy engine * Break into multiple lines * Read fractions for source/step values on the 2d copy engine aswell * Use fixed point math for more speed * Fix reinterpret when texture sizes are different
This commit is contained in:
parent
00579927e4
commit
59964f667c
6 changed files with 90 additions and 24 deletions
12
Ryujinx.Graphics/Gal/OpenGL/OGLLimit.cs
Normal file
12
Ryujinx.Graphics/Gal/OpenGL/OGLLimit.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using OpenTK.Graphics.OpenGL;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
{
|
||||||
|
static class OGLLimit
|
||||||
|
{
|
||||||
|
private static Lazy<int> s_MaxUboSize = new Lazy<int>(() => GL.GetInteger(GetPName.MaxUniformBlockSize));
|
||||||
|
|
||||||
|
public static int MaxUboSize => s_MaxUboSize.Value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,17 +77,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
private GalPipelineState Old;
|
private GalPipelineState Old;
|
||||||
|
|
||||||
private OGLConstBuffer Buffer;
|
private OGLConstBuffer Buffer;
|
||||||
private OGLRasterizer Rasterizer;
|
private OGLRenderTarget RenderTarget;
|
||||||
private OGLShader Shader;
|
private OGLRasterizer Rasterizer;
|
||||||
|
private OGLShader Shader;
|
||||||
|
|
||||||
private int VaoHandle;
|
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.Buffer = Buffer;
|
||||||
this.Rasterizer = Rasterizer;
|
this.RenderTarget = RenderTarget;
|
||||||
this.Shader = Shader;
|
this.Rasterizer = Rasterizer;
|
||||||
|
this.Shader = Shader;
|
||||||
|
|
||||||
//These values match OpenGL's defaults
|
//These values match OpenGL's defaults
|
||||||
Old = new GalPipelineState
|
Old = new GalPipelineState
|
||||||
|
@ -144,6 +150,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
if (New.FramebufferSrgb != Old.FramebufferSrgb)
|
if (New.FramebufferSrgb != Old.FramebufferSrgb)
|
||||||
{
|
{
|
||||||
Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb);
|
Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb);
|
||||||
|
|
||||||
|
RenderTarget.FramebufferSrgb = New.FramebufferSrgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (New.FlipX != Old.FlipX || New.FlipY != Old.FlipY || New.Instance != Old.Instance)
|
if (New.FlipX != Old.FlipX || New.FlipY != Old.FlipY || New.Instance != Old.Instance)
|
||||||
|
|
|
@ -90,6 +90,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
private int CopyPBO;
|
private int CopyPBO;
|
||||||
|
|
||||||
|
public bool FramebufferSrgb { get; set; }
|
||||||
|
|
||||||
public OGLRenderTarget(OGLTexture Texture)
|
public OGLRenderTarget(OGLTexture Texture)
|
||||||
{
|
{
|
||||||
Attachments = new FrameBufferAttachments();
|
Attachments = new FrameBufferAttachments();
|
||||||
|
@ -363,11 +365,24 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||||
|
|
||||||
|
GL.Disable(EnableCap.FramebufferSrgb);
|
||||||
|
|
||||||
GL.BlitFramebuffer(
|
GL.BlitFramebuffer(
|
||||||
SrcX0, SrcY0, SrcX1, SrcY1,
|
SrcX0,
|
||||||
DstX0, DstY0, DstX1, DstY1,
|
SrcY0,
|
||||||
|
SrcX1,
|
||||||
|
SrcY1,
|
||||||
|
DstX0,
|
||||||
|
DstY0,
|
||||||
|
DstX1,
|
||||||
|
DstY1,
|
||||||
ClearBufferMask.ColorBufferBit,
|
ClearBufferMask.ColorBufferBit,
|
||||||
BlitFramebufferFilter.Linear);
|
BlitFramebufferFilter.Linear);
|
||||||
|
|
||||||
|
if (FramebufferSrgb)
|
||||||
|
{
|
||||||
|
GL.Enable(EnableCap.FramebufferSrgb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Copy(
|
public void Copy(
|
||||||
|
@ -432,7 +447,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NewImage.Format == OldImage.Format)
|
if (NewImage.Format == OldImage.Format &&
|
||||||
|
NewImage.Width == OldImage.Width &&
|
||||||
|
NewImage.Height == OldImage.Height)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -444,7 +461,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.PixelPackBuffer, CopyPBO);
|
GL.BindBuffer(BufferTarget.PixelPackBuffer, CopyPBO);
|
||||||
|
|
||||||
GL.BufferData(BufferTarget.PixelPackBuffer, Math.Max(ImageUtils.GetSize(OldImage), ImageUtils.GetSize(NewImage)), IntPtr.Zero, BufferUsageHint.StreamCopy);
|
//The buffer should be large enough to hold the largest texture.
|
||||||
|
int BufferSize = Math.Max(ImageUtils.GetSize(OldImage),
|
||||||
|
ImageUtils.GetSize(NewImage));
|
||||||
|
|
||||||
|
GL.BufferData(BufferTarget.PixelPackBuffer, BufferSize, IntPtr.Zero, BufferUsageHint.StreamCopy);
|
||||||
|
|
||||||
if (!Texture.TryGetImageHandler(Key, out ImageHandler CachedImage))
|
if (!Texture.TryGetImageHandler(Key, out ImageHandler CachedImage))
|
||||||
{
|
{
|
||||||
|
@ -460,8 +481,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
|
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
|
||||||
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyPBO);
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyPBO);
|
||||||
|
|
||||||
|
GL.PixelStore(PixelStoreParameter.UnpackRowLength, OldImage.Width);
|
||||||
|
|
||||||
Texture.Create(Key, ImageUtils.GetSize(NewImage), NewImage);
|
Texture.Create(Key, ImageUtils.GetSize(NewImage), NewImage);
|
||||||
|
|
||||||
|
GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
Shader = new OGLShader(Buffer as OGLConstBuffer);
|
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<Action>();
|
ActionsQueue = new ConcurrentQueue<Action>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Ryujinx.Graphics.Gal.OpenGL;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -16,8 +17,6 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
public const int VertexIdAttr = 0x2fc;
|
public const int VertexIdAttr = 0x2fc;
|
||||||
public const int FaceAttr = 0x3fc;
|
public const int FaceAttr = 0x3fc;
|
||||||
|
|
||||||
public const int MaxUboSize = 1024;
|
|
||||||
|
|
||||||
public const int GlPositionVec4Index = 7;
|
public const int GlPositionVec4Index = 7;
|
||||||
|
|
||||||
public const int PositionOutAttrLocation = 15;
|
public const int PositionOutAttrLocation = 15;
|
||||||
|
@ -51,6 +50,8 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
public const string SsyStackName = "ssy_stack";
|
public const string SsyStackName = "ssy_stack";
|
||||||
public const string SsyCursorName = "ssy_cursor";
|
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[] StagePrefixes = new string[] { "vp", "tcp", "tep", "gp", "fp" };
|
||||||
|
|
||||||
private string StagePrefix;
|
private string StagePrefix;
|
||||||
|
@ -98,8 +99,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
m_Preds = new Dictionary<int, ShaderDeclInfo>();
|
m_Preds = new Dictionary<int, ShaderDeclInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public GlslDecl(ShaderIrBlock[] Blocks, GalShaderType ShaderType, ShaderHeader Header)
|
public GlslDecl(ShaderIrBlock[] Blocks, GalShaderType ShaderType, ShaderHeader Header) : this(ShaderType)
|
||||||
: this(ShaderType)
|
|
||||||
{
|
{
|
||||||
StagePrefix = StagePrefixes[(int)ShaderType] + "_";
|
StagePrefix = StagePrefixes[(int)ShaderType] + "_";
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,11 @@ namespace Ryujinx.Graphics
|
||||||
int DstBlitW = ReadRegister(NvGpuEngine2dReg.BlitDstW);
|
int DstBlitW = ReadRegister(NvGpuEngine2dReg.BlitDstW);
|
||||||
int DstBlitH = ReadRegister(NvGpuEngine2dReg.BlitDstH);
|
int DstBlitH = ReadRegister(NvGpuEngine2dReg.BlitDstH);
|
||||||
|
|
||||||
int SrcBlitX = ReadRegister(NvGpuEngine2dReg.BlitSrcXInt);
|
long BlitDuDx = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitDuDxFract);
|
||||||
int SrcBlitY = ReadRegister(NvGpuEngine2dReg.BlitSrcYInt);
|
long BlitDvDy = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitDvDyFract);
|
||||||
|
|
||||||
|
long SrcBlitX = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitSrcXFract);
|
||||||
|
long SrcBlitY = ReadRegisterFixed1_31_32(NvGpuEngine2dReg.BlitSrcYFract);
|
||||||
|
|
||||||
GalImageFormat SrcImgFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)SrcFormat);
|
GalImageFormat SrcImgFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)SrcFormat);
|
||||||
GalImageFormat DstImgFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)DstFormat);
|
GalImageFormat DstImgFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)DstFormat);
|
||||||
|
@ -99,13 +102,19 @@ namespace Ryujinx.Graphics
|
||||||
Gpu.ResourceManager.SendTexture(Vmm, SrcKey, SrcTexture);
|
Gpu.ResourceManager.SendTexture(Vmm, SrcKey, SrcTexture);
|
||||||
Gpu.ResourceManager.SendTexture(Vmm, DstKey, DstTexture);
|
Gpu.ResourceManager.SendTexture(Vmm, DstKey, DstTexture);
|
||||||
|
|
||||||
|
int SrcBlitX1 = (int)(SrcBlitX >> 32);
|
||||||
|
int SrcBlitY1 = (int)(SrcBlitY >> 32);
|
||||||
|
|
||||||
|
int SrcBlitX2 = (int)(SrcBlitX + DstBlitW * BlitDuDx >> 32);
|
||||||
|
int SrcBlitY2 = (int)(SrcBlitY + DstBlitH * BlitDvDy >> 32);
|
||||||
|
|
||||||
Gpu.Renderer.RenderTarget.Copy(
|
Gpu.Renderer.RenderTarget.Copy(
|
||||||
SrcKey,
|
SrcKey,
|
||||||
DstKey,
|
DstKey,
|
||||||
SrcBlitX,
|
SrcBlitX1,
|
||||||
SrcBlitY,
|
SrcBlitY1,
|
||||||
SrcBlitX + DstBlitW,
|
SrcBlitX2,
|
||||||
SrcBlitY + DstBlitH,
|
SrcBlitY2,
|
||||||
DstBlitX,
|
DstBlitX,
|
||||||
DstBlitY,
|
DstBlitY,
|
||||||
DstBlitX + DstBlitW,
|
DstBlitX + DstBlitW,
|
||||||
|
@ -121,8 +130,8 @@ namespace Ryujinx.Graphics
|
||||||
DstTexture,
|
DstTexture,
|
||||||
SrcAddress,
|
SrcAddress,
|
||||||
DstAddress,
|
DstAddress,
|
||||||
SrcBlitX,
|
SrcBlitX1,
|
||||||
SrcBlitY,
|
SrcBlitY1,
|
||||||
DstBlitX,
|
DstBlitX,
|
||||||
DstBlitY,
|
DstBlitY,
|
||||||
DstBlitW,
|
DstBlitW,
|
||||||
|
@ -150,6 +159,14 @@ namespace Ryujinx.Graphics
|
||||||
Registers[MethCall.Method] = MethCall.Argument;
|
Registers[MethCall.Method] = MethCall.Argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private long ReadRegisterFixed1_31_32(NvGpuEngine2dReg Reg)
|
||||||
|
{
|
||||||
|
long Low = (uint)ReadRegister(Reg + 0);
|
||||||
|
long High = (uint)ReadRegister(Reg + 1);
|
||||||
|
|
||||||
|
return Low | (High << 32);
|
||||||
|
}
|
||||||
|
|
||||||
private int ReadRegister(NvGpuEngine2dReg Reg)
|
private int ReadRegister(NvGpuEngine2dReg Reg)
|
||||||
{
|
{
|
||||||
return Registers[(int)Reg];
|
return Registers[(int)Reg];
|
||||||
|
|
Reference in a new issue