diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs index c5cf975097..b74912d90c 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs @@ -6,6 +6,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL { class OglRenderTarget : IGalRenderTarget { + private const int NativeWidth = 1280; + private const int NativeHeight = 720; + + private const int RenderTargetsCount = GalPipelineState.RenderTargetsCount; + private struct Rect { public int X { get; private set; } @@ -24,11 +29,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL private class FrameBufferAttachments { - public long[] Colors; - public long Zeta; + public int MapCount { get; set; } - public int MapCount; - public DrawBuffersEnum[] Map; + public DrawBuffersEnum[] Map { get; private set; } + + public long[] Colors { get; private set; } + + public long Zeta { get; set; } public FrameBufferAttachments() { @@ -36,30 +43,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL Map = new DrawBuffersEnum[RenderTargetsCount]; } - - public void SetAndClear(FrameBufferAttachments source) + + public void Update(FrameBufferAttachments source) { - Zeta = source.Zeta; - MapCount = source.MapCount; - - source.Zeta = 0; - source.MapCount = 0; - - for (int i = 0; i < RenderTargetsCount; i++) + for (int index = 0; index < RenderTargetsCount; index++) { - Colors[i] = source.Colors[i]; - Map[i] = source.Map[i]; + Map[index] = Source.Map[index]; - source.Colors[i] = 0; - source.Map[i] = 0; + Colors[index] = Source.Colors[index]; } + + MapCount = source.MapCount; + Zeta = source.Zeta; } } - private const int NativeWidth = 1280; - private const int NativeHeight = 720; - - private const int RenderTargetsCount = GalPipelineState.RenderTargetsCount; + private int[] _colorHandles; + private int _zetaHandle; private OglTexture _texture; @@ -71,6 +71,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL private bool _flipX; private bool _flipY; + private int _cropTop; private int _cropLeft; private int _cropRight; @@ -95,9 +96,29 @@ namespace Ryujinx.Graphics.Gal.OpenGL _oldAttachments = new FrameBufferAttachments(); + _colorHandles = new int[RenderTargetsCount]; _viewports = new float[RenderTargetsCount * 4]; - this._texture = texture; + _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() @@ -127,16 +148,25 @@ namespace Ryujinx.Graphics.Gal.OpenGL handle = cachedImage.Handle; } + if (handle == _colorHandles[attachment]) + { + continue; + } + GL.FramebufferTexture( FramebufferTarget.DrawFramebuffer, FramebufferAttachment.ColorAttachment0 + attachment, handle, 0); + + _colorHandles[attachment] = handle; } - if (_attachments.Zeta != _oldAttachments.Zeta) + // 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) { @@ -162,17 +192,21 @@ namespace Ryujinx.Graphics.Gal.OpenGL } else { - throw new NotImplementedException(); + throw new InvalidOperationException("Invalid image format \"" + CachedImage.Format + "\" used as Zeta!"); } + + _zetaHandle = CachedImage.Handle; } - else - { - GL.FramebufferTexture( - FramebufferTarget.DrawFramebuffer, - FramebufferAttachment.DepthStencilAttachment, - 0, - 0); - } + } + else if (_zetaHandle != 0) + { + GL.FramebufferTexture( + FramebufferTarget.DrawFramebuffer, + FramebufferAttachment.DepthStencilAttachment, + 0, + 0); + + ZetaHandle = 0; } if (OglExtension.ViewportArray) @@ -431,7 +465,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL GL.GetTexImage(TextureTarget.Texture2D, 0, format, type, IntPtr.Zero); GL.BindBuffer(BufferTarget.PixelPackBuffer, 0); - + GL.BindBuffer(BufferTarget.PixelUnpackBuffer, _copyPbo); _texture.Create(key, ImageUtils.GetSize(newImage), newImage); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs index 175ef82ee3..d9ed4bc59d 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs @@ -7,7 +7,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL class OglTexture : IGalTexture { private OglCachedResource _textureCache; - + public EventHandler TextureDeleted { get; set; } + public OglTexture() { _textureCache = new OglCachedResource(DeleteTexture); @@ -26,6 +27,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL private static void DeleteTexture(ImageHandler cachedImage) { GL.DeleteTexture(cachedImage.Handle); + TextureDeleted?.Invoke(this, cachedImage.Handle); } public void Create(long key, int size, GalImage image) diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index ecc32ed812..bfbd408321 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -252,10 +252,9 @@ namespace Ryujinx.Graphics.Gal.Shader _sb.AppendLine(IdentationStr + "int " + GlslDecl.InstanceUniformName + ";"); _sb.AppendLine("};"); + _sb.AppendLine(); } - _sb.AppendLine(); - foreach (ShaderDeclInfo declInfo in _decl.Uniforms.Values.OrderBy(DeclKeySelector)) { _sb.AppendLine($"layout (std140) uniform {declInfo.Name} {{"); @@ -312,17 +311,27 @@ namespace Ryujinx.Graphics.Gal.Shader { if (_decl.ShaderType == GalShaderType.Fragment) { + int count = 0; + for (int attachment = 0; attachment < 8; attachment++) { if (_header.OmapTargets[attachment].Enabled) { _sb.AppendLine("layout (location = " + attachment + ") out vec4 " + GlslDecl.FragmentOutputName + attachment + ";"); + + count++; } } + + if (count > 0) + { + _sb.AppendLine(); + } } else { _sb.AppendLine("layout (location = " + GlslDecl.PositionOutAttrLocation + ") out vec4 " + GlslDecl.PositionOutAttrName + ";"); + _sb.AppendLine(); } PrintDeclAttributes(_decl.OutAttributes.Values, "out"); @@ -558,6 +567,39 @@ 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 void PrintNode(ShaderIrBlock block, ShaderIrNode node, string identation) { if (node is ShaderIrCond cond) @@ -655,39 +697,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) { if (node is ShaderIrOperGpr gpr && gpr.IsConst)