Fix for render target and a shader compilation issue (#471)
* Fix render target using possibly deleted or wrong handles * Fix basic blocks with only a KIL instruction on the shader translator * Formatting fix
This commit is contained in:
parent
044b84b078
commit
9ace6b9285
4 changed files with 128 additions and 84 deletions
|
@ -6,6 +6,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
class OGLRenderTarget : IGalRenderTarget
|
class OGLRenderTarget : IGalRenderTarget
|
||||||
{
|
{
|
||||||
|
private const int NativeWidth = 1280;
|
||||||
|
private const int NativeHeight = 720;
|
||||||
|
|
||||||
|
private const int RenderTargetsCount = GalPipelineState.RenderTargetsCount;
|
||||||
|
|
||||||
private struct Rect
|
private struct Rect
|
||||||
{
|
{
|
||||||
public int X { get; private set; }
|
public int X { get; private set; }
|
||||||
|
@ -24,11 +29,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
private class FrameBufferAttachments
|
private class FrameBufferAttachments
|
||||||
{
|
{
|
||||||
public long[] Colors;
|
public int MapCount { get; set; }
|
||||||
public long Zeta;
|
|
||||||
|
|
||||||
public int MapCount;
|
public DrawBuffersEnum[] Map { get; private set; }
|
||||||
public DrawBuffersEnum[] Map;
|
|
||||||
|
public long[] Colors { get; private set; }
|
||||||
|
|
||||||
|
public long Zeta { get; set; }
|
||||||
|
|
||||||
public FrameBufferAttachments()
|
public FrameBufferAttachments()
|
||||||
{
|
{
|
||||||
|
@ -37,37 +44,31 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
Map = new DrawBuffersEnum[RenderTargetsCount];
|
Map = new DrawBuffersEnum[RenderTargetsCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAndClear(FrameBufferAttachments Source)
|
public void Update(FrameBufferAttachments Source)
|
||||||
{
|
{
|
||||||
Zeta = Source.Zeta;
|
for (int Index = 0; Index < RenderTargetsCount; Index++)
|
||||||
|
{
|
||||||
|
Map[Index] = Source.Map[Index];
|
||||||
|
|
||||||
|
Colors[Index] = Source.Colors[Index];
|
||||||
|
}
|
||||||
|
|
||||||
MapCount = Source.MapCount;
|
MapCount = Source.MapCount;
|
||||||
|
Zeta = Source.Zeta;
|
||||||
Source.Zeta = 0;
|
|
||||||
Source.MapCount = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < RenderTargetsCount; i++)
|
|
||||||
{
|
|
||||||
Colors[i] = Source.Colors[i];
|
|
||||||
Map[i] = Source.Map[i];
|
|
||||||
|
|
||||||
Source.Colors[i] = 0;
|
|
||||||
Source.Map[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const int NativeWidth = 1280;
|
private int[] ColorHandles;
|
||||||
private const int NativeHeight = 720;
|
private int ZetaHandle;
|
||||||
|
|
||||||
private const int RenderTargetsCount = GalPipelineState.RenderTargetsCount;
|
|
||||||
|
|
||||||
private OGLTexture Texture;
|
private OGLTexture Texture;
|
||||||
|
|
||||||
private ImageHandler ReadTex;
|
private ImageHandler ReadTex;
|
||||||
|
|
||||||
private float[] Viewports;
|
|
||||||
private Rect Window;
|
private Rect Window;
|
||||||
|
|
||||||
|
private float[] Viewports;
|
||||||
|
|
||||||
private bool FlipX;
|
private bool FlipX;
|
||||||
private bool FlipY;
|
private bool FlipY;
|
||||||
|
|
||||||
|
@ -95,9 +96,31 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
OldAttachments = new FrameBufferAttachments();
|
OldAttachments = new FrameBufferAttachments();
|
||||||
|
|
||||||
|
ColorHandles = new int[RenderTargetsCount];
|
||||||
|
|
||||||
Viewports = new float[RenderTargetsCount * 4];
|
Viewports = new float[RenderTargetsCount * 4];
|
||||||
|
|
||||||
this.Texture = Texture;
|
this.Texture = Texture;
|
||||||
|
|
||||||
|
Texture.TextureDeleted += TextureDeletionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TextureDeletionHandler(object Sender, int Handle)
|
||||||
|
{
|
||||||
|
//Texture was deleted, the handle is no longer valid, so
|
||||||
|
//reset all uses of this handle on a render target.
|
||||||
|
for (int Attachment = 0; Attachment < RenderTargetsCount; Attachment++)
|
||||||
|
{
|
||||||
|
if (ColorHandles[Attachment] == Handle)
|
||||||
|
{
|
||||||
|
ColorHandles[Attachment] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ZetaHandle == Handle)
|
||||||
|
{
|
||||||
|
ZetaHandle = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Bind()
|
public void Bind()
|
||||||
|
@ -115,11 +138,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
long Key = Attachments.Colors[Attachment];
|
long Key = Attachments.Colors[Attachment];
|
||||||
|
|
||||||
if (Key == OldAttachments.Colors[Attachment])
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Handle = 0;
|
int Handle = 0;
|
||||||
|
|
||||||
if (Key != 0 && Texture.TryGetImageHandler(Key, out CachedImage))
|
if (Key != 0 && Texture.TryGetImageHandler(Key, out CachedImage))
|
||||||
|
@ -127,16 +145,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
Handle = CachedImage.Handle;
|
Handle = CachedImage.Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Handle == ColorHandles[Attachment])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.DrawFramebuffer,
|
FramebufferTarget.DrawFramebuffer,
|
||||||
FramebufferAttachment.ColorAttachment0 + Attachment,
|
FramebufferAttachment.ColorAttachment0 + Attachment,
|
||||||
Handle,
|
Handle,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
|
ColorHandles[Attachment] = Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Attachments.Zeta != OldAttachments.Zeta)
|
|
||||||
{
|
|
||||||
if (Attachments.Zeta != 0 && Texture.TryGetImageHandler(Attachments.Zeta, out CachedImage))
|
if (Attachments.Zeta != 0 && Texture.TryGetImageHandler(Attachments.Zeta, out CachedImage))
|
||||||
|
{
|
||||||
|
if (CachedImage.Handle != ZetaHandle)
|
||||||
{
|
{
|
||||||
if (CachedImage.HasDepth && CachedImage.HasStencil)
|
if (CachedImage.HasDepth && CachedImage.HasStencil)
|
||||||
{
|
{
|
||||||
|
@ -162,17 +187,21 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new InvalidOperationException("Invalid image format \"" + CachedImage.Format + "\" used as Zeta!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ZetaHandle = CachedImage.Handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (ZetaHandle != 0)
|
||||||
{
|
{
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.DrawFramebuffer,
|
FramebufferTarget.DrawFramebuffer,
|
||||||
FramebufferAttachment.DepthStencilAttachment,
|
FramebufferAttachment.DepthStencilAttachment,
|
||||||
0,
|
0,
|
||||||
0);
|
0);
|
||||||
}
|
|
||||||
|
ZetaHandle = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OGLExtension.ViewportArray)
|
if (OGLExtension.ViewportArray)
|
||||||
|
@ -201,7 +230,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
GL.DrawBuffer(DrawBufferMode.None);
|
GL.DrawBuffer(DrawBufferMode.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
OldAttachments.SetAndClear(Attachments);
|
OldAttachments.Update(Attachments);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BindColor(long Key, int Attachment)
|
public void BindColor(long Key, int Attachment)
|
||||||
|
@ -431,7 +460,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
GL.GetTexImage(TextureTarget.Texture2D, 0, Format, Type, IntPtr.Zero);
|
GL.GetTexImage(TextureTarget.Texture2D, 0, Format, Type, IntPtr.Zero);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
|
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
|
||||||
|
|
||||||
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyPBO);
|
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyPBO);
|
||||||
|
|
||||||
Texture.Create(Key, ImageUtils.GetSize(NewImage), NewImage);
|
Texture.Create(Key, ImageUtils.GetSize(NewImage), NewImage);
|
||||||
|
|
|
@ -8,6 +8,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
private OGLCachedResource<ImageHandler> TextureCache;
|
private OGLCachedResource<ImageHandler> TextureCache;
|
||||||
|
|
||||||
|
public EventHandler<int> TextureDeleted { get; set; }
|
||||||
|
|
||||||
public OGLTexture()
|
public OGLTexture()
|
||||||
{
|
{
|
||||||
TextureCache = new OGLCachedResource<ImageHandler>(DeleteTexture);
|
TextureCache = new OGLCachedResource<ImageHandler>(DeleteTexture);
|
||||||
|
@ -23,8 +25,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
TextureCache.Unlock();
|
TextureCache.Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DeleteTexture(ImageHandler CachedImage)
|
private void DeleteTexture(ImageHandler CachedImage)
|
||||||
{
|
{
|
||||||
|
TextureDeleted?.Invoke(this, CachedImage.Handle);
|
||||||
|
|
||||||
GL.DeleteTexture(CachedImage.Handle);
|
GL.DeleteTexture(CachedImage.Handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -252,9 +252,8 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
SB.AppendLine(IdentationStr + "int " + GlslDecl.InstanceUniformName + ";");
|
SB.AppendLine(IdentationStr + "int " + GlslDecl.InstanceUniformName + ";");
|
||||||
|
|
||||||
SB.AppendLine("};");
|
SB.AppendLine("};");
|
||||||
}
|
|
||||||
|
|
||||||
SB.AppendLine();
|
SB.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
foreach (ShaderDeclInfo DeclInfo in Decl.Uniforms.Values.OrderBy(DeclKeySelector))
|
foreach (ShaderDeclInfo DeclInfo in Decl.Uniforms.Values.OrderBy(DeclKeySelector))
|
||||||
{
|
{
|
||||||
|
@ -312,17 +311,27 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
{
|
{
|
||||||
if (Decl.ShaderType == GalShaderType.Fragment)
|
if (Decl.ShaderType == GalShaderType.Fragment)
|
||||||
{
|
{
|
||||||
|
int Count = 0;
|
||||||
|
|
||||||
for (int Attachment = 0; Attachment < 8; Attachment++)
|
for (int Attachment = 0; Attachment < 8; Attachment++)
|
||||||
{
|
{
|
||||||
if (Header.OmapTargets[Attachment].Enabled)
|
if (Header.OmapTargets[Attachment].Enabled)
|
||||||
{
|
{
|
||||||
SB.AppendLine("layout (location = " + Attachment + ") out vec4 " + GlslDecl.FragmentOutputName + Attachment + ";");
|
SB.AppendLine("layout (location = " + Attachment + ") out vec4 " + GlslDecl.FragmentOutputName + Attachment + ";");
|
||||||
|
|
||||||
|
Count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Count > 0)
|
||||||
|
{
|
||||||
|
SB.AppendLine();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SB.AppendLine("layout (location = " + GlslDecl.PositionOutAttrLocation + ") out vec4 " + GlslDecl.PositionOutAttrName + ";");
|
SB.AppendLine("layout (location = " + GlslDecl.PositionOutAttrLocation + ") out vec4 " + GlslDecl.PositionOutAttrName + ";");
|
||||||
|
SB.AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintDeclAttributes(Decl.OutAttributes.Values, "out");
|
PrintDeclAttributes(Decl.OutAttributes.Values, "out");
|
||||||
|
@ -558,6 +567,49 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PrintNodes(ShaderIrBlock Block, ShaderIrNode[] Nodes)
|
||||||
|
{
|
||||||
|
foreach (ShaderIrNode Node in Nodes)
|
||||||
|
{
|
||||||
|
PrintNode(Block, Node, IdentationStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Nodes.Length == 0)
|
||||||
|
{
|
||||||
|
SB.AppendLine(IdentationStr + "return 0u;");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderIrNode Last = Nodes[Nodes.Length - 1];
|
||||||
|
|
||||||
|
bool UnconditionalFlowChange = false;
|
||||||
|
|
||||||
|
if (Last is ShaderIrOp Op)
|
||||||
|
{
|
||||||
|
switch (Op.Inst)
|
||||||
|
{
|
||||||
|
case ShaderIrInst.Bra:
|
||||||
|
case ShaderIrInst.Exit:
|
||||||
|
case ShaderIrInst.Sync:
|
||||||
|
UnconditionalFlowChange = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UnconditionalFlowChange)
|
||||||
|
{
|
||||||
|
if (Block.Next != null)
|
||||||
|
{
|
||||||
|
SB.AppendLine(IdentationStr + "return " + GetBlockPosition(Block.Next) + ";");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SB.AppendLine(IdentationStr + "return 0u;");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void PrintNode(ShaderIrBlock Block, ShaderIrNode Node, string Identation)
|
private void PrintNode(ShaderIrBlock Block, ShaderIrNode Node, string Identation)
|
||||||
{
|
{
|
||||||
if (Node is ShaderIrCond Cond)
|
if (Node is ShaderIrCond Cond)
|
||||||
|
@ -571,14 +623,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
|
||||||
SB.AppendLine(Identation + "if (" + IfExpr + ") {");
|
SB.AppendLine(Identation + "if (" + IfExpr + ") {");
|
||||||
|
|
||||||
if (Cond.Child is ShaderIrOp Op && Op.Inst == ShaderIrInst.Bra)
|
|
||||||
{
|
|
||||||
SB.AppendLine(Identation + IdentationStr + "return " + GetBlockPosition(Block.Branch) + ";");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PrintNode(Block, Cond.Child, Identation + IdentationStr);
|
PrintNode(Block, Cond.Child, Identation + IdentationStr);
|
||||||
}
|
|
||||||
|
|
||||||
SB.AppendLine(Identation + "}");
|
SB.AppendLine(Identation + "}");
|
||||||
}
|
}
|
||||||
|
@ -655,39 +700,6 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PrintNodes(ShaderIrBlock Block, ShaderIrNode[] Nodes)
|
|
||||||
{
|
|
||||||
foreach (ShaderIrNode Node in Nodes)
|
|
||||||
{
|
|
||||||
PrintNode(Block, Node, IdentationStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Nodes.Length > 0)
|
|
||||||
{
|
|
||||||
ShaderIrNode Last = Nodes[Nodes.Length - 1];
|
|
||||||
|
|
||||||
bool UnconditionalFlowChange = false;
|
|
||||||
|
|
||||||
if (Last is ShaderIrOp Op)
|
|
||||||
{
|
|
||||||
switch (Op.Inst)
|
|
||||||
{
|
|
||||||
case ShaderIrInst.Bra:
|
|
||||||
case ShaderIrInst.Exit:
|
|
||||||
case ShaderIrInst.Kil:
|
|
||||||
case ShaderIrInst.Sync:
|
|
||||||
UnconditionalFlowChange = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!UnconditionalFlowChange)
|
|
||||||
{
|
|
||||||
SB.AppendLine(IdentationStr + "return " + GetBlockPosition(Block.Next) + ";");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsValidOutOper(ShaderIrNode Node)
|
private bool IsValidOutOper(ShaderIrNode Node)
|
||||||
{
|
{
|
||||||
if (Node is ShaderIrOperGpr Gpr && Gpr.IsConst)
|
if (Node is ShaderIrOperGpr Gpr && Gpr.IsConst)
|
||||||
|
|
Loading…
Reference in a new issue