GlslGenerator.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. using Ryujinx.Graphics.Gal;
  2. using Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions;
  3. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  4. using Ryujinx.Graphics.Shader.StructuredIr;
  5. using System;
  6. using static Ryujinx.Graphics.Shader.CodeGen.Glsl.TypeConversion;
  7. namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
  8. {
  9. static class GlslGenerator
  10. {
  11. public static GlslProgram Generate(StructuredProgramInfo info, ShaderConfig config)
  12. {
  13. CodeGenContext context = new CodeGenContext(config);
  14. Declarations.Declare(context, info);
  15. PrintMainBlock(context, info);
  16. return new GlslProgram(
  17. context.CBufferDescriptors.ToArray(),
  18. context.TextureDescriptors.ToArray(),
  19. context.GetCode());
  20. }
  21. private static void PrintMainBlock(CodeGenContext context, StructuredProgramInfo info)
  22. {
  23. context.AppendLine("void main()");
  24. context.EnterScope();
  25. Declarations.DeclareLocals(context, info);
  26. PrintBlock(context, info.MainBlock);
  27. context.LeaveScope();
  28. }
  29. private static void PrintBlock(CodeGenContext context, AstBlock block)
  30. {
  31. AstBlockVisitor visitor = new AstBlockVisitor(block);
  32. visitor.BlockEntered += (sender, e) =>
  33. {
  34. switch (e.Block.Type)
  35. {
  36. case AstBlockType.DoWhile:
  37. context.AppendLine("do");
  38. break;
  39. case AstBlockType.Else:
  40. context.AppendLine("else");
  41. break;
  42. case AstBlockType.ElseIf:
  43. context.AppendLine($"else if ({GetCondExpr(context, e.Block.Condition)})");
  44. break;
  45. case AstBlockType.If:
  46. context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})");
  47. break;
  48. default: throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\".");
  49. }
  50. context.EnterScope();
  51. };
  52. visitor.BlockLeft += (sender, e) =>
  53. {
  54. context.LeaveScope();
  55. if (e.Block.Type == AstBlockType.DoWhile)
  56. {
  57. context.AppendLine($"while ({GetCondExpr(context, e.Block.Condition)});");
  58. }
  59. };
  60. foreach (IAstNode node in visitor.Visit())
  61. {
  62. if (node is AstOperation operation)
  63. {
  64. if (operation.Inst == Instruction.Return)
  65. {
  66. PrepareForReturn(context);
  67. }
  68. context.AppendLine(InstGen.GetExpression(context, operation) + ";");
  69. }
  70. else if (node is AstAssignment assignment)
  71. {
  72. VariableType srcType = OperandManager.GetNodeDestType(assignment.Source);
  73. VariableType dstType = OperandManager.GetNodeDestType(assignment.Destination);
  74. string dest;
  75. if (assignment.Destination is AstOperand operand && operand.Type == OperandType.Attribute)
  76. {
  77. dest = OperandManager.GetOutAttributeName(operand, context.Config.Type);
  78. }
  79. else
  80. {
  81. dest = InstGen.GetExpression(context, assignment.Destination);
  82. }
  83. string src = ReinterpretCast(context, assignment.Source, srcType, dstType);
  84. context.AppendLine(dest + " = " + src + ";");
  85. }
  86. else
  87. {
  88. throw new InvalidOperationException($"Found unexpected node type \"{node?.GetType().Name ?? "null"}\".");
  89. }
  90. }
  91. }
  92. private static string GetCondExpr(CodeGenContext context, IAstNode cond)
  93. {
  94. VariableType srcType = OperandManager.GetNodeDestType(cond);
  95. return ReinterpretCast(context, cond, srcType, VariableType.Bool);
  96. }
  97. private static void PrepareForReturn(CodeGenContext context)
  98. {
  99. if (context.Config.Type == GalShaderType.Vertex)
  100. {
  101. context.AppendLine("gl_Position.xy *= flip;");
  102. }
  103. }
  104. }
  105. }