ShaderHeader.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. using Ryujinx.Graphics.Gal;
  2. using Ryujinx.Graphics.Shader.Decoders;
  3. using System;
  4. namespace Ryujinx.Graphics.Shader
  5. {
  6. struct OutputMapTarget
  7. {
  8. public bool Red { get; }
  9. public bool Green { get; }
  10. public bool Blue { get; }
  11. public bool Alpha { get; }
  12. public bool Enabled => Red || Green || Blue || Alpha;
  13. public OutputMapTarget(bool red, bool green, bool blue, bool alpha)
  14. {
  15. Red = red;
  16. Green = green;
  17. Blue = blue;
  18. Alpha = alpha;
  19. }
  20. public bool ComponentEnabled(int component)
  21. {
  22. switch (component)
  23. {
  24. case 0: return Red;
  25. case 1: return Green;
  26. case 2: return Blue;
  27. case 3: return Alpha;
  28. }
  29. throw new ArgumentOutOfRangeException(nameof(component));
  30. }
  31. }
  32. class ShaderHeader
  33. {
  34. public int SphType { get; }
  35. public int Version { get; }
  36. public int ShaderType { get; }
  37. public bool MrtEnable { get; }
  38. public bool KillsPixels { get; }
  39. public bool DoesGlobalStore { get; }
  40. public int SassVersion { get; }
  41. public bool DoesLoadOrStore { get; }
  42. public bool DoesFp64 { get; }
  43. public int StreamOutMask{ get; }
  44. public int ShaderLocalMemoryLowSize { get; }
  45. public int PerPatchAttributeCount { get; }
  46. public int ShaderLocalMemoryHighSize { get; }
  47. public int ThreadsPerInputPrimitive { get; }
  48. public int ShaderLocalMemoryCrsSize { get; }
  49. public int OutputTopology { get; }
  50. public int MaxOutputVertexCount { get; }
  51. public int StoreReqStart { get; }
  52. public int StoreReqEnd { get; }
  53. public OutputMapTarget[] OmapTargets { get; }
  54. public bool OmapSampleMask { get; }
  55. public bool OmapDepth { get; }
  56. public ShaderHeader(IGalMemory memory, ulong address)
  57. {
  58. int commonWord0 = memory.ReadInt32((long)address + 0);
  59. int commonWord1 = memory.ReadInt32((long)address + 4);
  60. int commonWord2 = memory.ReadInt32((long)address + 8);
  61. int commonWord3 = memory.ReadInt32((long)address + 12);
  62. int commonWord4 = memory.ReadInt32((long)address + 16);
  63. SphType = commonWord0.Extract(0, 5);
  64. Version = commonWord0.Extract(5, 5);
  65. ShaderType = commonWord0.Extract(10, 4);
  66. MrtEnable = commonWord0.Extract(14);
  67. KillsPixels = commonWord0.Extract(15);
  68. DoesGlobalStore = commonWord0.Extract(16);
  69. SassVersion = commonWord0.Extract(17, 4);
  70. DoesLoadOrStore = commonWord0.Extract(26);
  71. DoesFp64 = commonWord0.Extract(27);
  72. StreamOutMask = commonWord0.Extract(28, 4);
  73. ShaderLocalMemoryLowSize = commonWord1.Extract(0, 24);
  74. PerPatchAttributeCount = commonWord1.Extract(24, 8);
  75. ShaderLocalMemoryHighSize = commonWord2.Extract(0, 24);
  76. ThreadsPerInputPrimitive = commonWord2.Extract(24, 8);
  77. ShaderLocalMemoryCrsSize = commonWord3.Extract(0, 24);
  78. OutputTopology = commonWord3.Extract(24, 4);
  79. MaxOutputVertexCount = commonWord4.Extract(0, 12);
  80. StoreReqStart = commonWord4.Extract(12, 8);
  81. StoreReqEnd = commonWord4.Extract(24, 8);
  82. int type2OmapTarget = memory.ReadInt32((long)address + 72);
  83. int type2Omap = memory.ReadInt32((long)address + 76);
  84. OmapTargets = new OutputMapTarget[8];
  85. for (int offset = 0; offset < OmapTargets.Length * 4; offset += 4)
  86. {
  87. OmapTargets[offset >> 2] = new OutputMapTarget(
  88. type2OmapTarget.Extract(offset + 0),
  89. type2OmapTarget.Extract(offset + 1),
  90. type2OmapTarget.Extract(offset + 2),
  91. type2OmapTarget.Extract(offset + 3));
  92. }
  93. OmapSampleMask = type2Omap.Extract(0);
  94. OmapDepth = type2Omap.Extract(1);
  95. }
  96. public int DepthRegister
  97. {
  98. get
  99. {
  100. int count = 0;
  101. for (int index = 0; index < OmapTargets.Length; index++)
  102. {
  103. for (int component = 0; component < 4; component++)
  104. {
  105. if (OmapTargets[index].ComponentEnabled(component))
  106. {
  107. count++;
  108. }
  109. }
  110. }
  111. // Depth register is always two registers after the last color output.
  112. return count + 1;
  113. }
  114. }
  115. }
  116. }