TranslatorContext.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. using Ryujinx.Graphics.Shader.Decoders;
  2. using Ryujinx.Graphics.Shader.IntermediateRepresentation;
  3. using System.Collections.Generic;
  4. using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
  5. using static Ryujinx.Graphics.Shader.Translation.Translator;
  6. namespace Ryujinx.Graphics.Shader.Translation
  7. {
  8. public class TranslatorContext
  9. {
  10. private readonly Block[][] _cfg;
  11. private readonly Block[][] _cfgA;
  12. private ShaderConfig _config;
  13. private ShaderConfig _configA;
  14. public ulong Address { get; }
  15. public ulong AddressA { get; }
  16. public ShaderStage Stage => _config.Stage;
  17. public int Size => _config.Size;
  18. public int SizeA => _configA != null ? _configA.Size : 0;
  19. public HashSet<int> TextureHandlesForCache => _config.TextureHandlesForCache;
  20. public IGpuAccessor GpuAccessor => _config.GpuAccessor;
  21. internal TranslatorContext(ulong address, Block[][] cfg, ShaderConfig config)
  22. {
  23. Address = address;
  24. AddressA = 0;
  25. _config = config;
  26. _configA = null;
  27. _cfg = cfg;
  28. _cfgA = null;
  29. }
  30. internal TranslatorContext(ulong addressA, ulong addressB, Block[][] cfgA, Block[][] cfgB, ShaderConfig configA, ShaderConfig configB)
  31. {
  32. Address = addressB;
  33. AddressA = addressA;
  34. _config = configB;
  35. _configA = configA;
  36. _cfg = cfgB;
  37. _cfgA = cfgA;
  38. }
  39. private static bool IsUserAttribute(Operand operand)
  40. {
  41. return operand != null &&
  42. operand.Type == OperandType.Attribute &&
  43. operand.Value >= AttributeConsts.UserAttributeBase &&
  44. operand.Value < AttributeConsts.UserAttributeEnd;
  45. }
  46. private static FunctionCode[] Combine(FunctionCode[] a, FunctionCode[] b)
  47. {
  48. // Here we combine two shaders.
  49. // For shader A:
  50. // - All user attribute stores on shader A are turned into copies to a
  51. // temporary variable. It's assumed that shader B will consume them.
  52. // - All return instructions are turned into branch instructions, the
  53. // branch target being the start of the shader B code.
  54. // For shader B:
  55. // - All user attribute loads on shader B are turned into copies from a
  56. // temporary variable, as long that attribute is written by shader A.
  57. FunctionCode[] output = new FunctionCode[a.Length + b.Length - 1];
  58. List<Operation> ops = new List<Operation>(a.Length + b.Length);
  59. Operand[] temps = new Operand[AttributeConsts.UserAttributesCount * 4];
  60. Operand lblB = Label();
  61. for (int index = 0; index < a[0].Code.Length; index++)
  62. {
  63. Operation operation = a[0].Code[index];
  64. if (IsUserAttribute(operation.Dest))
  65. {
  66. int tIndex = (operation.Dest.Value - AttributeConsts.UserAttributeBase) / 4;
  67. Operand temp = temps[tIndex];
  68. if (temp == null)
  69. {
  70. temp = Local();
  71. temps[tIndex] = temp;
  72. }
  73. operation.Dest = temp;
  74. }
  75. if (operation.Inst == Instruction.Return)
  76. {
  77. ops.Add(new Operation(Instruction.Branch, lblB));
  78. }
  79. else
  80. {
  81. ops.Add(operation);
  82. }
  83. }
  84. ops.Add(new Operation(Instruction.MarkLabel, lblB));
  85. for (int index = 0; index < b[0].Code.Length; index++)
  86. {
  87. Operation operation = b[0].Code[index];
  88. for (int srcIndex = 0; srcIndex < operation.SourcesCount; srcIndex++)
  89. {
  90. Operand src = operation.GetSource(srcIndex);
  91. if (IsUserAttribute(src))
  92. {
  93. Operand temp = temps[(src.Value - AttributeConsts.UserAttributeBase) / 4];
  94. if (temp != null)
  95. {
  96. operation.SetSource(srcIndex, temp);
  97. }
  98. }
  99. }
  100. ops.Add(operation);
  101. }
  102. output[0] = new FunctionCode(ops.ToArray());
  103. for (int i = 1; i < a.Length; i++)
  104. {
  105. output[i] = a[i];
  106. }
  107. for (int i = 1; i < b.Length; i++)
  108. {
  109. output[a.Length + i - 1] = b[i];
  110. }
  111. return output;
  112. }
  113. public ShaderProgram Translate(out ShaderProgramInfo shaderProgramInfo)
  114. {
  115. FunctionCode[] code = EmitShader(_cfg, _config);
  116. if (_configA != null)
  117. {
  118. FunctionCode[] codeA = EmitShader(_cfgA, _configA);
  119. _config.SetUsedFeature(_configA.UsedFeatures);
  120. code = Combine(codeA, code);
  121. }
  122. return Translator.Translate(code, _config, out shaderProgramInfo, SizeA);
  123. }
  124. }
  125. }