GlslGenerator.cs 4.9 KB

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