From 73ad195699579577330cc0ded451f7467bfc9ed9 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 27 Jun 2018 23:16:16 -0300 Subject: [PATCH] Handle possible case where VPB uses an output attribute written by VPA but not available on the vbo --- Ryujinx.Graphics/Gal/Shader/GlslDecl.cs | 70 ++++++++++++++++--- Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs | 10 ++- 2 files changed, 66 insertions(+), 14 deletions(-) diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs index c1fd16eb86..5c7dd794e3 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs @@ -64,14 +64,11 @@ namespace Ryujinx.Graphics.Gal.Shader public GalShaderType ShaderType { get; private set; } - public GlslDecl(GalShaderType ShaderType) + private GlslDecl(GalShaderType ShaderType) { this.ShaderType = ShaderType; - StagePrefix = StagePrefixes[(int)ShaderType] + "_"; - m_Uniforms = new Dictionary(); - m_Textures = new Dictionary(); m_Attributes = new Dictionary(); @@ -80,15 +77,17 @@ namespace Ryujinx.Graphics.Gal.Shader m_Gprs = new Dictionary(); m_Preds = new Dictionary(); + } + + public GlslDecl(ShaderIrBlock[] Blocks, GalShaderType ShaderType) : this(ShaderType) + { + StagePrefix = StagePrefixes[(int)ShaderType] + "_"; if (ShaderType == GalShaderType.Fragment) { m_Gprs.Add(0, new ShaderDeclInfo(FragmentOutputName, 0, 0, 4)); } - } - public void Add(ShaderIrBlock[] Blocks) - { foreach (ShaderIrBlock Block in Blocks) { foreach (ShaderIrNode Node in Block.GetNodes()) @@ -97,6 +96,58 @@ namespace Ryujinx.Graphics.Gal.Shader } } } + + public static GlslDecl Merge(GlslDecl VpA, GlslDecl VpB) + { + GlslDecl Combined = new GlslDecl(GalShaderType.Vertex); + + Merge(Combined.m_Textures, VpA.m_Textures, VpB.m_Textures); + Merge(Combined.m_Uniforms, VpA.m_Uniforms, VpB.m_Uniforms); + + Merge(Combined.m_Attributes, VpA.m_Attributes, VpB.m_Attributes); + Merge(Combined.m_OutAttributes, VpA.m_OutAttributes, VpB.m_OutAttributes); + + Merge(Combined.m_Gprs, VpA.m_Gprs, VpB.m_Gprs); + Merge(Combined.m_Preds, VpA.m_Preds, VpB.m_Preds); + + //Merge input attributes. + foreach (KeyValuePair KV in VpA.m_InAttributes) + { + Combined.m_InAttributes.TryAdd(KV.Key, KV.Value); + } + + foreach (KeyValuePair KV in VpB.m_InAttributes) + { + //If Vertex Program A already writes to this attribute, + //then we don't need to add it as an input attribute since + //Vertex Program A will already have written to it anyway, + //and there's no guarantee that there is an input attribute + //for this slot. + if (!VpA.m_OutAttributes.ContainsKey(KV.Key)) + { + Combined.m_InAttributes.TryAdd(KV.Key, KV.Value); + } + } + + return Combined; + } + + private static void Merge( + Dictionary C, + Dictionary A, + Dictionary B) + { + foreach (KeyValuePair KV in A) + { + C.TryAdd(KV.Key, KV.Value); + } + + foreach (KeyValuePair KV in B) + { + C.TryAdd(KV.Key, KV.Value); + } + } + private void Traverse(ShaderIrNode Parent, ShaderIrNode Node) { switch (Node) @@ -228,7 +279,10 @@ namespace Ryujinx.Graphics.Gal.Shader private bool HasName(Dictionary Decls, int Index) { - int VecIndex = Index >> 2; + //This is used to check if the dictionary already contains + //a entry for a vector at a given index position. + //Used to enable turning gprs into vectors. + int VecIndex = Index & ~3; if (Decls.TryGetValue(VecIndex, out ShaderDeclInfo DeclInfo)) { diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index ee8321fa6b..a3517f08df 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -113,10 +113,10 @@ namespace Ryujinx.Graphics.Gal.Shader Blocks = ShaderDecoder.Decode(Memory, VpAPosition); BlocksB = ShaderDecoder.Decode(Memory, VpBPosition); - Decl = new GlslDecl(ShaderType); + GlslDecl DeclVpA = new GlslDecl(Blocks, ShaderType); + GlslDecl DeclVpB = new GlslDecl(BlocksB, ShaderType); - Decl.Add(Blocks); - Decl.Add(BlocksB); + Decl = GlslDecl.Merge(DeclVpA, DeclVpB); return Decompile(); } @@ -126,9 +126,7 @@ namespace Ryujinx.Graphics.Gal.Shader Blocks = ShaderDecoder.Decode(Memory, Position); BlocksB = null; - Decl = new GlslDecl(ShaderType); - - Decl.Add(Blocks); + Decl = new GlslDecl(Blocks, ShaderType); return Decompile(); }