GlslGenerator.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions;
  2. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  3. using Ryujinx.Graphics.Shader.StructuredIr;
  4. using System;
  5. using static Ryujinx.Graphics.Shader.CodeGen.Glsl.TypeConversion;
  6. namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
  7. {
  8. static class GlslGenerator
  9. {
  10. public static GlslProgram Generate(StructuredProgramInfo info, ShaderConfig config)
  11. {
  12. CodeGenContext context = new CodeGenContext(config);
  13. Declarations.Declare(context, info);
  14. PrintMainBlock(context, info);
  15. return new GlslProgram(
  16. context.CBufferDescriptors.ToArray(),
  17. context.SBufferDescriptors.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. // Ensure that unused attributes are set, otherwise the downstream
  27. // compiler may eliminate them.
  28. // (Not needed for fragment shader as it is the last stage).
  29. if (context.Config.Stage != ShaderStage.Compute &&
  30. context.Config.Stage != ShaderStage.Fragment)
  31. {
  32. for (int attr = 0; attr < Declarations.MaxAttributes; attr++)
  33. {
  34. if (info.OAttributes.Contains(attr))
  35. {
  36. continue;
  37. }
  38. context.AppendLine($"{DefaultNames.OAttributePrefix}{attr} = vec4(0);");
  39. }
  40. }
  41. PrintBlock(context, info.MainBlock);
  42. context.LeaveScope();
  43. }
  44. private static void PrintBlock(CodeGenContext context, AstBlock block)
  45. {
  46. AstBlockVisitor visitor = new AstBlockVisitor(block);
  47. visitor.BlockEntered += (sender, e) =>
  48. {
  49. switch (e.Block.Type)
  50. {
  51. case AstBlockType.DoWhile:
  52. context.AppendLine("do");
  53. break;
  54. case AstBlockType.Else:
  55. context.AppendLine("else");
  56. break;
  57. case AstBlockType.ElseIf:
  58. context.AppendLine($"else if ({GetCondExpr(context, e.Block.Condition)})");
  59. break;
  60. case AstBlockType.If:
  61. context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})");
  62. break;
  63. default: throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\".");
  64. }
  65. context.EnterScope();
  66. };
  67. visitor.BlockLeft += (sender, e) =>
  68. {
  69. context.LeaveScope();
  70. if (e.Block.Type == AstBlockType.DoWhile)
  71. {
  72. context.AppendLine($"while ({GetCondExpr(context, e.Block.Condition)});");
  73. }
  74. };
  75. foreach (IAstNode node in visitor.Visit())
  76. {
  77. if (node is AstOperation operation)
  78. {
  79. context.AppendLine(InstGen.GetExpression(context, operation) + ";");
  80. }
  81. else if (node is AstAssignment assignment)
  82. {
  83. VariableType srcType = OperandManager.GetNodeDestType(assignment.Source);
  84. VariableType dstType = OperandManager.GetNodeDestType(assignment.Destination);
  85. string dest;
  86. if (assignment.Destination is AstOperand operand && operand.Type == OperandType.Attribute)
  87. {
  88. dest = OperandManager.GetOutAttributeName(operand, context.Config.Stage);
  89. }
  90. else
  91. {
  92. dest = InstGen.GetExpression(context, assignment.Destination);
  93. }
  94. string src = ReinterpretCast(context, assignment.Source, srcType, dstType);
  95. context.AppendLine(dest + " = " + src + ";");
  96. }
  97. else if (node is AstComment comment)
  98. {
  99. context.AppendLine("// " + comment.Comment);
  100. }
  101. else
  102. {
  103. throw new InvalidOperationException($"Found unexpected node type \"{node?.GetType().Name ?? "null"}\".");
  104. }
  105. }
  106. }
  107. private static string GetCondExpr(CodeGenContext context, IAstNode cond)
  108. {
  109. VariableType srcType = OperandManager.GetNodeDestType(cond);
  110. return ReinterpretCast(context, cond, srcType, VariableType.Bool);
  111. }
  112. }
  113. }