Use structures for GLSL input and output attributes

* Better end-of-line styling
This commit is contained in:
ReinUsesLisp 2018-06-27 01:07:35 -03:00
parent af5f059d4e
commit f6ebea82ca
2 changed files with 113 additions and 15 deletions

View file

@ -14,6 +14,9 @@ namespace Ryujinx.Graphics.Gal.Shader
private const int AttrStartIndex = 8; private const int AttrStartIndex = 8;
private const int TexStartIndex = 8; private const int TexStartIndex = 8;
public const string StageAFunctionName = "StageA";
public const string StageBFunctionName = "StageB";
public const string PositionOutAttrName = "position"; public const string PositionOutAttrName = "position";
private const string InAttrName = "in_attr"; private const string InAttrName = "in_attr";

View file

@ -114,14 +114,25 @@ namespace Ryujinx.Graphics.Gal.Shader
SB.AppendLine("#version 410 core"); SB.AppendLine("#version 410 core");
//TODO: Decide if Stage B has to be called
SB.AppendLine("#define HAS_STAGE_B 0" + Environment.NewLine);
PrintDeclTextures(); PrintDeclTextures();
PrintDeclUniforms(); PrintDeclUniforms();
PrintDeclInAttributes(); PrintDeclInAttributes();
PrintDeclOutAttributes(); PrintDeclOutAttributes();
PrintDeclInStruct();
PrintDeclOutStruct();
PrintDeclGprs(); PrintDeclGprs();
PrintDeclPreds(); PrintDeclPreds();
PrintBlockScope(Blocks[0], null, null, "void main()", IdentationStr); //TODO: Build Stage B here
string StageAFunc = "void " + GlslDecl.StageAFunctionName + "(in Input IN, out Output OUT)";
PrintBlockScope(Blocks[0], null, null, StageAFunc, IdentationStr);
PrintMain();
string GlslCode = SB.ToString(); string GlslCode = SB.ToString();
@ -196,6 +207,40 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
private void PrintDeclInStruct()
{
SB.AppendLine("struct Input {");
PrintDeclStructAttributes(Decl.InAttributes.Values);
SB.AppendLine("};" + Environment.NewLine);
}
private void PrintDeclOutStruct()
{
SB.AppendLine("struct Output {");
PrintDeclStructAttributes(Decl.OutAttributes.Values);
SB.AppendLine("};" + Environment.NewLine);
}
private void PrintDeclStructAttributes(IEnumerable<ShaderDeclInfo> Decls)
{
if (Decls.Count() > 0)
{
foreach (ShaderDeclInfo DeclInfo in Decls.OrderBy(DeclKeySelector))
{
SB.AppendLine(IdentationStr + GetDecl(DeclInfo) + ";");
}
}
else
{
//Looks like GLSL doesn't like empty structs
SB.AppendLine(IdentationStr + "float dummy;");
}
}
private void PrintDeclGprs() private void PrintDeclGprs()
{ {
PrintDecls(Decl.Gprs); PrintDecls(Decl.Gprs);
@ -244,6 +289,63 @@ namespace Ryujinx.Graphics.Gal.Shader
return ElemTypes[DeclInfo.Size - 1] + " " + DeclInfo.Name; return ElemTypes[DeclInfo.Size - 1] + " " + DeclInfo.Name;
} }
private void PrintMain()
{
SB.AppendLine("void main() {");
//Build host input attributes
SB.AppendLine(IdentationStr + "Input in_B;");
foreach (ShaderDeclInfo DeclInfo in Decl.InAttributes.Values.OrderBy(DeclKeySelector))
{
SB.AppendLine(IdentationStr + "in_B." + DeclInfo.Name + " = " + DeclInfo.Name + ";");
}
SB.AppendLine();
//Build Stage A input (IN)
SB.AppendLine(IdentationStr + "Input in_A;");
SB.AppendLine("#if HAS_STAGE_B");
SB.AppendLine(IdentationStr + GlslDecl.StageBFunctionName + "(in_B, in_A);");
SB.AppendLine("#else");
SB.AppendLine(IdentationStr + "in_A = in_B;");
SB.AppendLine("#endif" + Environment.NewLine);
//Call Stage A
SB.AppendLine(IdentationStr + "Output out_host;");
SB.AppendLine(IdentationStr + GlslDecl.StageAFunctionName + "(in_A, out_host);");
//Write host output attributes
if (Decl.OutAttributes.Count > 0)
{
SB.AppendLine();
foreach (ShaderDeclInfo DeclInfo in Decl.OutAttributes.Values.OrderBy(DeclKeySelector))
{
SB.AppendLine(IdentationStr + DeclInfo.Name + " = out_host." + DeclInfo.Name + ";");
}
}
//Do end-of-vertex stuff (host specific)
if (Decl.ShaderType == GalShaderType.Vertex)
{
SB.AppendLine();
SB.AppendLine(IdentationStr + "gl_Position.xy *= " + GlslDecl.FlipUniformName + ";");
SB.AppendLine(IdentationStr + GlslDecl.PositionOutAttrName + " = out_host.gl_Position;");
SB.AppendLine(IdentationStr + GlslDecl.PositionOutAttrName + ".w = 1;");
}
SB.AppendLine("}");
}
private void PrintBlockScope( private void PrintBlockScope(
ShaderIrBlock Block, ShaderIrBlock Block,
ShaderIrBlock EndBlock, ShaderIrBlock EndBlock,
@ -278,6 +380,11 @@ namespace Ryujinx.Graphics.Gal.Shader
{ {
SB.AppendLine(UpIdent + "}"); SB.AppendLine(UpIdent + "}");
} }
if (EndBlock == null)
{
SB.AppendLine();
}
} }
private ShaderIrBlock PrintNodes( private ShaderIrBlock PrintNodes(
@ -383,18 +490,6 @@ namespace Ryujinx.Graphics.Gal.Shader
continue; continue;
} }
else if (Op.Inst == ShaderIrInst.Exit)
{
//Do everything that needs to be done before
//the shader ends here.
if (Decl.ShaderType == GalShaderType.Vertex)
{
SB.AppendLine(Identation + "gl_Position.xy *= flip;");
SB.AppendLine(Identation + GlslDecl.PositionOutAttrName + " = gl_Position;");
SB.AppendLine(Identation + GlslDecl.PositionOutAttrName + ".w = 1;");
}
}
SB.AppendLine(Identation + GetSrcExpr(Op, true) + ";"); SB.AppendLine(Identation + GetSrcExpr(Op, true) + ";");
} }
@ -546,7 +641,7 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetOutAbufName(ShaderIrOperAbuf Abuf) private string GetOutAbufName(ShaderIrOperAbuf Abuf)
{ {
return GetName(Decl.OutAttributes, Abuf); return "OUT." + GetName(Decl.OutAttributes, Abuf);
} }
private string GetName(ShaderIrOperAbuf Abuf) private string GetName(ShaderIrOperAbuf Abuf)
@ -569,7 +664,7 @@ namespace Ryujinx.Graphics.Gal.Shader
} }
} }
return GetName(Decl.InAttributes, Abuf); return "IN." + GetName(Decl.InAttributes, Abuf);
} }
private string GetName(IReadOnlyDictionary<int, ShaderDeclInfo> Dict, ShaderIrOperAbuf Abuf) private string GetName(IReadOnlyDictionary<int, ShaderDeclInfo> Dict, ShaderIrOperAbuf Abuf)