NsGpuPGraph.cs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. using ChocolArm64.Memory;
  2. using Ryujinx.Graphics.Gal;
  3. using System.Collections.Generic;
  4. namespace Ryujinx.Graphics.Gpu
  5. {
  6. class NsGpuPGraph
  7. {
  8. private NsGpu Gpu;
  9. private uint[] Registers;
  10. public NsGpuEngine[] SubChannels;
  11. private Dictionary<long, int> CurrentVertexBuffers;
  12. public NsGpuPGraph(NsGpu Gpu)
  13. {
  14. this.Gpu = Gpu;
  15. Registers = new uint[0x1000];
  16. SubChannels = new NsGpuEngine[8];
  17. CurrentVertexBuffers = new Dictionary<long, int>();
  18. }
  19. public void ProcessPushBuffer(NsGpuPBEntry[] PushBuffer, AMemory Memory)
  20. {
  21. bool HasQuery = false;
  22. foreach (NsGpuPBEntry Entry in PushBuffer)
  23. {
  24. if (Entry.Arguments.Count == 1)
  25. {
  26. SetRegister(Entry.Register, (uint)Entry.Arguments[0]);
  27. }
  28. switch (Entry.Register)
  29. {
  30. case NsGpuRegister.BindChannel:
  31. if (Entry.Arguments.Count > 0)
  32. {
  33. SubChannels[Entry.SubChannel] = (NsGpuEngine)Entry.Arguments[0];
  34. }
  35. break;
  36. case NsGpuRegister._3dVertexArray0Fetch:
  37. SendVertexBuffers(Memory);
  38. break;
  39. case NsGpuRegister._3dCbData0:
  40. if (GetRegister(NsGpuRegister._3dCbPos) == 0x20)
  41. {
  42. SendTexture(Memory);
  43. }
  44. break;
  45. case NsGpuRegister._3dQueryAddressHigh:
  46. case NsGpuRegister._3dQueryAddressLow:
  47. case NsGpuRegister._3dQuerySequence:
  48. case NsGpuRegister._3dQueryGet:
  49. HasQuery = true;
  50. break;
  51. case NsGpuRegister._3dSetShader:
  52. uint ShaderPrg = (uint)Entry.Arguments[0];
  53. uint ShaderId = (uint)Entry.Arguments[1];
  54. uint CodeAddr = (uint)Entry.Arguments[2];
  55. uint ShaderType = (uint)Entry.Arguments[3];
  56. uint CodeEnd = (uint)Entry.Arguments[4];
  57. SendShader(
  58. Memory,
  59. ShaderPrg,
  60. ShaderId,
  61. CodeAddr,
  62. ShaderType,
  63. CodeEnd);
  64. break;
  65. }
  66. }
  67. if (HasQuery)
  68. {
  69. long Position =
  70. (long)GetRegister(NsGpuRegister._3dQueryAddressHigh) << 32 |
  71. (long)GetRegister(NsGpuRegister._3dQueryAddressLow) << 0;
  72. uint Seq = GetRegister(NsGpuRegister._3dQuerySequence);
  73. uint Get = GetRegister(NsGpuRegister._3dQueryGet);
  74. uint Mode = Get & 3;
  75. if (Mode == 0)
  76. {
  77. //Write
  78. Position = Gpu.MemoryMgr.GetCpuAddr(Position);
  79. if (Position != -1)
  80. {
  81. Gpu.Renderer.QueueAction(delegate()
  82. {
  83. Memory.WriteUInt32(Position, Seq);
  84. });
  85. }
  86. }
  87. }
  88. }
  89. private void SendVertexBuffers(AMemory Memory)
  90. {
  91. long Position =
  92. (long)GetRegister(NsGpuRegister._3dVertexArray0StartHigh) << 32 |
  93. (long)GetRegister(NsGpuRegister._3dVertexArray0StartLow) << 0;
  94. long Limit =
  95. (long)GetRegister(NsGpuRegister._3dVertexArray0LimitHigh) << 32 |
  96. (long)GetRegister(NsGpuRegister._3dVertexArray0LimitLow) << 0;
  97. int VbIndex = CurrentVertexBuffers.Count;
  98. if (!CurrentVertexBuffers.TryAdd(Position, VbIndex))
  99. {
  100. VbIndex = CurrentVertexBuffers[Position];
  101. }
  102. if (Limit != 0)
  103. {
  104. long Size = (Limit - Position) + 1;
  105. Position = Gpu.MemoryMgr.GetCpuAddr(Position);
  106. if (Position != -1)
  107. {
  108. byte[] Buffer = AMemoryHelper.ReadBytes(Memory, Position, Size);
  109. int Stride = (int)GetRegister(NsGpuRegister._3dVertexArray0Fetch) & 0xfff;
  110. List<GalVertexAttrib> Attribs = new List<GalVertexAttrib>();
  111. for (int Attr = 0; Attr < 16; Attr++)
  112. {
  113. int Packed = (int)GetRegister(NsGpuRegister._3dVertexAttrib0Format + Attr * 4);
  114. GalVertexAttrib Attrib = new GalVertexAttrib(Attr,
  115. (Packed >> 0) & 0x1f,
  116. ((Packed >> 6) & 0x1) != 0,
  117. (Packed >> 7) & 0x3fff,
  118. (GalVertexAttribSize)((Packed >> 21) & 0x3f),
  119. (GalVertexAttribType)((Packed >> 27) & 0x7),
  120. ((Packed >> 31) & 0x1) != 0);
  121. if (Attrib.Offset < Stride)
  122. {
  123. Attribs.Add(Attrib);
  124. }
  125. }
  126. Gpu.Renderer.QueueAction(delegate()
  127. {
  128. Gpu.Renderer.SendVertexBuffer(VbIndex, Buffer, Stride, Attribs.ToArray());
  129. });
  130. }
  131. }
  132. }
  133. private void SendTexture(AMemory Memory)
  134. {
  135. long TicPos = (long)GetRegister(NsGpuRegister._3dTicAddressHigh) << 32 |
  136. (long)GetRegister(NsGpuRegister._3dTicAddressLow) << 0;
  137. uint CbData = GetRegister(NsGpuRegister._3dCbData0);
  138. uint TicIndex = (CbData >> 0) & 0xfffff;
  139. uint TscIndex = (CbData >> 20) & 0xfff; //I guess?
  140. TicPos = Gpu.MemoryMgr.GetCpuAddr(TicPos + TicIndex * 0x20);
  141. if (TicPos != -1)
  142. {
  143. int Word0 = Memory.ReadInt32(TicPos + 0x0);
  144. int Word1 = Memory.ReadInt32(TicPos + 0x4);
  145. int Word2 = Memory.ReadInt32(TicPos + 0x8);
  146. int Word3 = Memory.ReadInt32(TicPos + 0xc);
  147. int Word4 = Memory.ReadInt32(TicPos + 0x10);
  148. int Word5 = Memory.ReadInt32(TicPos + 0x14);
  149. int Word6 = Memory.ReadInt32(TicPos + 0x18);
  150. int Word7 = Memory.ReadInt32(TicPos + 0x1c);
  151. long TexAddress = Word1;
  152. TexAddress |= (long)(Word2 & 0xff) << 32;
  153. TexAddress = Gpu.MemoryMgr.GetCpuAddr(TexAddress);
  154. if (TexAddress != -1)
  155. {
  156. NsGpuTextureFormat Format = (NsGpuTextureFormat)(Word0 & 0x7f);
  157. int Width = (Word4 & 0xffff) + 1;
  158. int Height = (Word5 & 0xffff) + 1;
  159. byte[] Buffer = GetDecodedTexture(Memory, Format, TexAddress, Width, Height);
  160. if (Buffer != null)
  161. {
  162. Gpu.Renderer.QueueAction(delegate()
  163. {
  164. Gpu.Renderer.SendR8G8B8A8Texture(0, Buffer, Width, Height);
  165. });
  166. }
  167. }
  168. }
  169. }
  170. private void SendShader(
  171. AMemory Memory,
  172. uint ShaderPrg,
  173. uint ShaderId,
  174. uint CodeAddr,
  175. uint ShaderType,
  176. uint CodeEnd)
  177. {
  178. long CodePos = Gpu.MemoryMgr.GetCpuAddr(CodeAddr);
  179. byte[] Data = AMemoryHelper.ReadBytes(Memory, CodePos, 0x300);
  180. }
  181. private static byte[] GetDecodedTexture(
  182. AMemory Memory,
  183. NsGpuTextureFormat Format,
  184. long Position,
  185. int Width,
  186. int Height)
  187. {
  188. byte[] Data = null;
  189. switch (Format)
  190. {
  191. case NsGpuTextureFormat.BC1:
  192. {
  193. int Size = (Width * Height) >> 1;
  194. Data = AMemoryHelper.ReadBytes(Memory, Position, Size);
  195. Data = BCn.DecodeBC1(new NsGpuTexture()
  196. {
  197. Width = Width,
  198. Height = Height,
  199. Data = Data
  200. }, 0);
  201. break;
  202. }
  203. case NsGpuTextureFormat.BC2:
  204. {
  205. int Size = Width * Height;
  206. Data = AMemoryHelper.ReadBytes(Memory, Position, Size);
  207. Data = BCn.DecodeBC2(new NsGpuTexture()
  208. {
  209. Width = Width,
  210. Height = Height,
  211. Data = Data
  212. }, 0);
  213. break;
  214. }
  215. case NsGpuTextureFormat.BC3:
  216. {
  217. int Size = Width * Height;
  218. Data = AMemoryHelper.ReadBytes(Memory, Position, Size);
  219. Data = BCn.DecodeBC3(new NsGpuTexture()
  220. {
  221. Width = Width,
  222. Height = Height,
  223. Data = Data
  224. }, 0);
  225. break;
  226. }
  227. //default: throw new NotImplementedException(Format.ToString());
  228. }
  229. return Data;
  230. }
  231. public uint GetRegister(NsGpuRegister Register)
  232. {
  233. return Registers[((int)Register >> 2) & 0xfff];
  234. }
  235. public void SetRegister(NsGpuRegister Register, uint Value)
  236. {
  237. Registers[((int)Register >> 2) & 0xfff] = Value;
  238. }
  239. }
  240. }