0
0
Fork 0

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:
gdkchan 2018-10-23 17:59:52 -03:00 committed by GitHub
parent 044b84b078
commit 9ace6b9285
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 128 additions and 84 deletions

View file

@ -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);

View file

@ -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);
} }

View file

@ -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)