From 0953469aa1325a20db3131e7be6be86c3ab35439 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Wed, 27 Jun 2018 21:51:20 -0300 Subject: [PATCH] Add separate subroutines for program A/B, and copy attributes to a temp --- Ryujinx.Graphics/Gal/Shader/GlslDecl.cs | 58 +++++------ Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs | 98 +++++++++++++++---- Ryujinx.Graphics/Gal/ShaderDeclInfo.cs | 8 -- 3 files changed, 109 insertions(+), 55 deletions(-) diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs index 5531aa46f7..c1fd16eb86 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs @@ -11,24 +11,32 @@ namespace Ryujinx.Graphics.Gal.Shader public const int VertexIdAttr = 0x2fc; public const int GlPositionWAttr = 0x7c; + public const int MaxUboSize = 1024; + + public const int GlPositionVec4Index = 7; + private const int AttrStartIndex = 8; private const int TexStartIndex = 8; public const string PositionOutAttrName = "position"; - private const string InAttrName = "in_attr"; - private const string OutAttrName = "out_attr"; + private const string TextureName = "tex"; private const string UniformName = "c"; - private const string GprName = "gpr"; - private const string PredName = "pred"; - private const string TextureName = "tex"; + private const string AttrName = "attr"; + private const string InAttrName = "in_" + AttrName; + private const string OutAttrName = "out_" + AttrName; + + private const string GprName = "gpr"; + private const string PredName = "pred"; public const string FragmentOutputName = "FragColor"; public const string FlipUniformName = "flip"; - public const string StageProgramBName = "program_b"; + public const string ProgramName = "program"; + public const string ProgramAName = ProgramName + "_a"; + public const string ProgramBName = ProgramName + "_b"; private string[] StagePrefixes = new string[] { "vp", "tcp", "tep", "gp", "fp" }; @@ -37,6 +45,7 @@ namespace Ryujinx.Graphics.Gal.Shader private Dictionary m_Textures; private Dictionary m_Uniforms; + private Dictionary m_Attributes; private Dictionary m_InAttributes; private Dictionary m_OutAttributes; @@ -46,6 +55,7 @@ namespace Ryujinx.Graphics.Gal.Shader public IReadOnlyDictionary Textures => m_Textures; public IReadOnlyDictionary Uniforms => m_Uniforms; + public IReadOnlyDictionary Attributes => m_Attributes; public IReadOnlyDictionary InAttributes => m_InAttributes; public IReadOnlyDictionary OutAttributes => m_OutAttributes; @@ -64,6 +74,7 @@ namespace Ryujinx.Graphics.Gal.Shader m_Textures = new Dictionary(); + m_Attributes = new Dictionary(); m_InAttributes = new Dictionary(); m_OutAttributes = new Dictionary(); @@ -73,12 +84,6 @@ namespace Ryujinx.Graphics.Gal.Shader if (ShaderType == GalShaderType.Fragment) { m_Gprs.Add(0, new ShaderDeclInfo(FragmentOutputName, 0, 0, 4)); - - m_InAttributes.Add(7, new ShaderDeclInfo(PositionOutAttrName, -1, 0, 4)); - } - else - { - m_OutAttributes.Add(7, new ShaderDeclInfo("gl_Position", -1, 0, 4)); } } @@ -135,28 +140,14 @@ namespace Ryujinx.Graphics.Gal.Shader case ShaderIrOperCbuf Cbuf: { - if (m_Uniforms.TryGetValue(Cbuf.Index, out ShaderDeclInfo DeclInfo)) - { - DeclInfo.SetCbufOffs(Cbuf.Pos); - } - else + if (!m_Uniforms.ContainsKey(Cbuf.Index)) { string Name = StagePrefix + UniformName + Cbuf.Index; - DeclInfo = new ShaderDeclInfo(Name, Cbuf.Pos, Cbuf.Index); + ShaderDeclInfo DeclInfo = new ShaderDeclInfo(Name, Cbuf.Pos, Cbuf.Index); m_Uniforms.Add(Cbuf.Index, DeclInfo); } - - if (Cbuf.Offs != null) - { - //The constant buffer is being accessed as an array, - //we have no way to know the max element it may access in this case. - //Here, we just assume the array size with arbitrary values. - //TODO: Find a better solution for this. - DeclInfo.SetCbufOffs(Cbuf.Pos + 15); - } - break; } @@ -174,6 +165,11 @@ namespace Ryujinx.Graphics.Gal.Shader int GlslIndex = Index - AttrStartIndex; + if (GlslIndex < 0) + { + return; + } + ShaderDeclInfo DeclInfo; if (Parent is ShaderIrAsg Asg && Asg.Dst == Node) @@ -197,6 +193,12 @@ namespace Ryujinx.Graphics.Gal.Shader DeclInfo.Enlarge(Elem + 1); + if (!m_Attributes.ContainsKey(Index)) + { + DeclInfo = new ShaderDeclInfo(AttrName + GlslIndex, GlslIndex, 0, 4); + + m_Attributes.Add(Index, DeclInfo); + } break; } diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs index 5389c0843d..b58025d617 100644 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs @@ -29,8 +29,6 @@ namespace Ryujinx.Graphics.Gal.Shader private StringBuilder SB; - private bool NeedsProgramBCall; - public GlslDecompiler() { InstsExpr = new Dictionary() @@ -143,6 +141,7 @@ namespace Ryujinx.Graphics.Gal.Shader PrintDeclTextures(); PrintDeclUniforms(); + PrintDeclAttributes(); PrintDeclInAttributes(); PrintDeclOutAttributes(); PrintDeclGprs(); @@ -150,18 +149,20 @@ namespace Ryujinx.Graphics.Gal.Shader if (BlocksB != null) { - string SubName = "void " + GlslDecl.StageProgramBName + "()"; - - PrintBlockScope(BlocksB[0], null, null, SubName, IdentationStr); + PrintBlockScope(Blocks[0], null, null, "void " + GlslDecl.ProgramAName + "()", IdentationStr); SB.AppendLine(); - NeedsProgramBCall = true; + PrintBlockScope(BlocksB[0], null, null, "void " + GlslDecl.ProgramBName + "()", IdentationStr); + } + else + { + PrintBlockScope(Blocks[0], null, null, "void " + GlslDecl.ProgramName + "()", IdentationStr); } - PrintBlockScope(Blocks[0], null, null, "void main()", IdentationStr); + SB.AppendLine(); - NeedsProgramBCall = false; + PrintMain(); string GlslCode = SB.ToString(); @@ -187,7 +188,7 @@ namespace Ryujinx.Graphics.Gal.Shader { SB.AppendLine($"layout (std140) uniform {DeclInfo.Name} {{"); - SB.AppendLine($"{IdentationStr}vec4 {DeclInfo.Name}_data[{DeclInfo.Index / 4 + 1}];"); + SB.AppendLine($"{IdentationStr}vec4 {DeclInfo.Name}_data[{GlslDecl.MaxUboSize}];"); SB.AppendLine("};"); } @@ -198,6 +199,11 @@ namespace Ryujinx.Graphics.Gal.Shader } } + private void PrintDeclAttributes() + { + PrintDecls(Decl.Attributes); + } + private void PrintDeclInAttributes() { if (Decl.ShaderType == GalShaderType.Fragment) @@ -286,6 +292,51 @@ namespace Ryujinx.Graphics.Gal.Shader return ElemTypes[DeclInfo.Size - 1] + " " + DeclInfo.Name; } + private void PrintMain() + { + SB.AppendLine("void main() {"); + + foreach (KeyValuePair KV in Decl.InAttributes) + { + if (!Decl.Attributes.TryGetValue(KV.Key, out ShaderDeclInfo Attr)) + { + continue; + } + + ShaderDeclInfo DeclInfo = KV.Value; + + string Swizzle = ".xyzw".Substring(0, DeclInfo.Size + 1); + + SB.AppendLine(IdentationStr + Attr.Name + Swizzle + " = " + DeclInfo.Name + ";"); + } + + if (BlocksB != null) + { + SB.AppendLine(IdentationStr + GlslDecl.ProgramAName + "();"); + SB.AppendLine(IdentationStr + GlslDecl.ProgramBName + "();"); + } + else + { + SB.AppendLine(IdentationStr + GlslDecl.ProgramName + "();"); + } + + foreach (KeyValuePair KV in Decl.OutAttributes) + { + if (!Decl.Attributes.TryGetValue(KV.Key, out ShaderDeclInfo Attr)) + { + continue; + } + + ShaderDeclInfo DeclInfo = KV.Value; + + string Swizzle = ".xyzw".Substring(0, DeclInfo.Size + 1); + + SB.AppendLine(IdentationStr + DeclInfo.Name + " = " + Attr.Name + Swizzle + ";"); + } + + SB.AppendLine("}"); + } + private void PrintBlockScope( ShaderIrBlock Block, ShaderIrBlock EndBlock, @@ -431,11 +482,6 @@ namespace Ryujinx.Graphics.Gal.Shader //the shader ends here. if (Decl.ShaderType == GalShaderType.Vertex) { - if (NeedsProgramBCall) - { - SB.AppendLine(Identation + GlslDecl.StageProgramBName + "();"); - } - SB.AppendLine(Identation + "gl_Position.xy *= flip;"); SB.AppendLine(Identation + GlslDecl.PositionOutAttrName + " = gl_Position;"); @@ -593,11 +639,12 @@ namespace Ryujinx.Graphics.Gal.Shader private string GetOutAbufName(ShaderIrOperAbuf Abuf) { - return GetName(Decl.OutAttributes, Abuf); + return GetAttrTempName(Abuf); } private string GetName(ShaderIrOperAbuf Abuf) { + //Handle special scalar read-only attributes here. if (Decl.ShaderType == GalShaderType.Vertex) { switch (Abuf.Offs) @@ -616,20 +663,33 @@ namespace Ryujinx.Graphics.Gal.Shader } } - return GetName(Decl.InAttributes, Abuf); + return GetAttrTempName(Abuf); } - private string GetName(IReadOnlyDictionary Dict, ShaderIrOperAbuf Abuf) + private string GetAttrTempName(ShaderIrOperAbuf Abuf) { int Index = Abuf.Offs >> 4; int Elem = (Abuf.Offs >> 2) & 3; - if (!Dict.TryGetValue(Index, out ShaderDeclInfo DeclInfo)) + string Swizzle = "." + GetAttrSwizzle(Elem); + + if (!Decl.Attributes.TryGetValue(Index, out ShaderDeclInfo DeclInfo)) { + //Handle special vec4 attributes here + //(for example, index 7 is aways gl_Position). + if (Index == GlslDecl.GlPositionVec4Index) + { + string Name = + Decl.ShaderType != GalShaderType.Vertex && + Decl.ShaderType != GalShaderType.Geometry ? GlslDecl.PositionOutAttrName : "gl_Position"; + + return Name + Swizzle; + } + throw new InvalidOperationException(); } - return DeclInfo.Size > 1 ? DeclInfo.Name + "." + GetAttrSwizzle(Elem) : DeclInfo.Name; + return DeclInfo.Name + Swizzle; } private string GetName(ShaderIrOperGpr Gpr) diff --git a/Ryujinx.Graphics/Gal/ShaderDeclInfo.cs b/Ryujinx.Graphics/Gal/ShaderDeclInfo.cs index e5ecee9506..d400850c86 100644 --- a/Ryujinx.Graphics/Gal/ShaderDeclInfo.cs +++ b/Ryujinx.Graphics/Gal/ShaderDeclInfo.cs @@ -23,13 +23,5 @@ namespace Ryujinx.Graphics.Gal Size = NewSize; } } - - internal void SetCbufOffs(int Offs) - { - if (Index < Offs) - { - Index = Offs; - } - } } } \ No newline at end of file