diff options
Diffstat (limited to 'Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs')
| -rw-r--r-- | Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs b/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs new file mode 100644 index 00000000..4edbda8b --- /dev/null +++ b/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs @@ -0,0 +1,133 @@ +using Ryujinx.Graphics.Gal; +using Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions; +using Ryujinx.Graphics.Shader.IntermediateRepresentation; +using Ryujinx.Graphics.Shader.StructuredIr; +using System; + +using static Ryujinx.Graphics.Shader.CodeGen.Glsl.TypeConversion; + +namespace Ryujinx.Graphics.Shader.CodeGen.Glsl +{ + static class GlslGenerator + { + public static GlslProgram Generate(StructuredProgramInfo info, ShaderConfig config) + { + CodeGenContext context = new CodeGenContext(config); + + Declarations.Declare(context, info); + + PrintMainBlock(context, info); + + return new GlslProgram( + context.CBufferDescriptors.ToArray(), + context.TextureDescriptors.ToArray(), + context.GetCode()); + } + + private static void PrintMainBlock(CodeGenContext context, StructuredProgramInfo info) + { + context.AppendLine("void main()"); + + context.EnterScope(); + + Declarations.DeclareLocals(context, info); + + PrintBlock(context, info.MainBlock); + + context.LeaveScope(); + } + + private static void PrintBlock(CodeGenContext context, AstBlock block) + { + AstBlockVisitor visitor = new AstBlockVisitor(block); + + visitor.BlockEntered += (sender, e) => + { + switch (e.Block.Type) + { + case AstBlockType.DoWhile: + context.AppendLine("do"); + break; + + case AstBlockType.Else: + context.AppendLine("else"); + break; + + case AstBlockType.ElseIf: + context.AppendLine($"else if ({GetCondExpr(context, e.Block.Condition)})"); + break; + + case AstBlockType.If: + context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})"); + break; + + default: throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\"."); + } + + context.EnterScope(); + }; + + visitor.BlockLeft += (sender, e) => + { + context.LeaveScope(); + + if (e.Block.Type == AstBlockType.DoWhile) + { + context.AppendLine($"while ({GetCondExpr(context, e.Block.Condition)});"); + } + }; + + foreach (IAstNode node in visitor.Visit()) + { + if (node is AstOperation operation) + { + if (operation.Inst == Instruction.Return) + { + PrepareForReturn(context); + } + + context.AppendLine(InstGen.GetExpression(context, operation) + ";"); + } + else if (node is AstAssignment assignment) + { + VariableType srcType = OperandManager.GetNodeDestType(assignment.Source); + VariableType dstType = OperandManager.GetNodeDestType(assignment.Destination); + + string dest; + + if (assignment.Destination is AstOperand operand && operand.Type == OperandType.Attribute) + { + dest = OperandManager.GetOutAttributeName(operand, context.Config.Type); + } + else + { + dest = InstGen.GetExpression(context, assignment.Destination); + } + + string src = ReinterpretCast(context, assignment.Source, srcType, dstType); + + context.AppendLine(dest + " = " + src + ";"); + } + else + { + throw new InvalidOperationException($"Found unexpected node type \"{node?.GetType().Name ?? "null"}\"."); + } + } + } + + private static string GetCondExpr(CodeGenContext context, IAstNode cond) + { + VariableType srcType = OperandManager.GetNodeDestType(cond); + + return ReinterpretCast(context, cond, srcType, VariableType.Bool); + } + + private static void PrepareForReturn(CodeGenContext context) + { + if (context.Config.Type == GalShaderType.Vertex) + { + context.AppendLine("gl_Position.xy *= flip;"); + } + } + } +}
\ No newline at end of file |
