ShaderHeader.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. using Ryujinx.Graphics.Shader.Decoders;
  2. using System;
  3. namespace Ryujinx.Graphics.Shader.Translation
  4. {
  5. enum PixelImap
  6. {
  7. Unused = 0,
  8. Constant = 1,
  9. Perspective = 2,
  10. ScreenLinear = 3
  11. }
  12. struct ImapPixelType
  13. {
  14. public PixelImap X { get; }
  15. public PixelImap Y { get; }
  16. public PixelImap Z { get; }
  17. public PixelImap W { get; }
  18. public ImapPixelType(PixelImap x, PixelImap y, PixelImap z, PixelImap w)
  19. {
  20. X = x;
  21. Y = y;
  22. Z = z;
  23. W = w;
  24. }
  25. public PixelImap GetFirstUsedType()
  26. {
  27. if (X != PixelImap.Unused) return X;
  28. if (Y != PixelImap.Unused) return Y;
  29. if (Z != PixelImap.Unused) return Z;
  30. return W;
  31. }
  32. }
  33. struct OmapTarget
  34. {
  35. public bool Red { get; }
  36. public bool Green { get; }
  37. public bool Blue { get; }
  38. public bool Alpha { get; }
  39. public bool Enabled => Red || Green || Blue || Alpha;
  40. public OmapTarget(bool red, bool green, bool blue, bool alpha)
  41. {
  42. Red = red;
  43. Green = green;
  44. Blue = blue;
  45. Alpha = alpha;
  46. }
  47. public bool ComponentEnabled(int component)
  48. {
  49. switch (component)
  50. {
  51. case 0: return Red;
  52. case 1: return Green;
  53. case 2: return Blue;
  54. case 3: return Alpha;
  55. }
  56. throw new ArgumentOutOfRangeException(nameof(component));
  57. }
  58. }
  59. class ShaderHeader
  60. {
  61. public int SphType { get; }
  62. public int Version { get; }
  63. public ShaderStage Stage { get; }
  64. public bool MrtEnable { get; }
  65. public bool KillsPixels { get; }
  66. public bool DoesGlobalStore { get; }
  67. public int SassVersion { get; }
  68. public bool GpPassthrough { get; }
  69. public bool DoesLoadOrStore { get; }
  70. public bool DoesFp64 { get; }
  71. public int StreamOutMask { get; }
  72. public int ShaderLocalMemoryLowSize { get; }
  73. public int PerPatchAttributeCount { get; }
  74. public int ShaderLocalMemoryHighSize { get; }
  75. public int ThreadsPerInputPrimitive { get; }
  76. public int ShaderLocalMemoryCrsSize { get; }
  77. public OutputTopology OutputTopology { get; }
  78. public int MaxOutputVertexCount { get; }
  79. public int StoreReqStart { get; }
  80. public int StoreReqEnd { get; }
  81. public ImapPixelType[] ImapTypes { get; }
  82. public OmapTarget[] OmapTargets { get; }
  83. public bool OmapSampleMask { get; }
  84. public bool OmapDepth { get; }
  85. public ShaderHeader(IGpuAccessor gpuAccessor, ulong address)
  86. {
  87. int commonWord0 = gpuAccessor.MemoryRead<int>(address + 0);
  88. int commonWord1 = gpuAccessor.MemoryRead<int>(address + 4);
  89. int commonWord2 = gpuAccessor.MemoryRead<int>(address + 8);
  90. int commonWord3 = gpuAccessor.MemoryRead<int>(address + 12);
  91. int commonWord4 = gpuAccessor.MemoryRead<int>(address + 16);
  92. SphType = commonWord0.Extract(0, 5);
  93. Version = commonWord0.Extract(5, 5);
  94. Stage = (ShaderStage)commonWord0.Extract(10, 4);
  95. // Invalid.
  96. if (Stage == ShaderStage.Compute)
  97. {
  98. Stage = ShaderStage.Vertex;
  99. }
  100. MrtEnable = commonWord0.Extract(14);
  101. KillsPixels = commonWord0.Extract(15);
  102. DoesGlobalStore = commonWord0.Extract(16);
  103. SassVersion = commonWord0.Extract(17, 4);
  104. GpPassthrough = commonWord0.Extract(24);
  105. DoesLoadOrStore = commonWord0.Extract(26);
  106. DoesFp64 = commonWord0.Extract(27);
  107. StreamOutMask = commonWord0.Extract(28, 4);
  108. ShaderLocalMemoryLowSize = commonWord1.Extract(0, 24);
  109. PerPatchAttributeCount = commonWord1.Extract(24, 8);
  110. ShaderLocalMemoryHighSize = commonWord2.Extract(0, 24);
  111. ThreadsPerInputPrimitive = commonWord2.Extract(24, 8);
  112. ShaderLocalMemoryCrsSize = commonWord3.Extract(0, 24);
  113. OutputTopology = (OutputTopology)commonWord3.Extract(24, 4);
  114. MaxOutputVertexCount = commonWord4.Extract(0, 12);
  115. StoreReqStart = commonWord4.Extract(12, 8);
  116. StoreReqEnd = commonWord4.Extract(24, 8);
  117. ImapTypes = new ImapPixelType[32];
  118. for (ulong i = 0; i < 32; i++)
  119. {
  120. byte imap = gpuAccessor.MemoryRead<byte>(address + 0x18 + i);
  121. ImapTypes[i] = new ImapPixelType(
  122. (PixelImap)((imap >> 0) & 3),
  123. (PixelImap)((imap >> 2) & 3),
  124. (PixelImap)((imap >> 4) & 3),
  125. (PixelImap)((imap >> 6) & 3));
  126. }
  127. int type2OmapTarget = gpuAccessor.MemoryRead<int>(address + 0x48);
  128. int type2Omap = gpuAccessor.MemoryRead<int>(address + 0x4c);
  129. OmapTargets = new OmapTarget[8];
  130. for (int offset = 0; offset < OmapTargets.Length * 4; offset += 4)
  131. {
  132. OmapTargets[offset >> 2] = new OmapTarget(
  133. type2OmapTarget.Extract(offset + 0),
  134. type2OmapTarget.Extract(offset + 1),
  135. type2OmapTarget.Extract(offset + 2),
  136. type2OmapTarget.Extract(offset + 3));
  137. }
  138. OmapSampleMask = type2Omap.Extract(0);
  139. OmapDepth = type2Omap.Extract(1);
  140. }
  141. }
  142. }