NvGpuFifo.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using ChocolArm64.Memory;
  2. using System.Collections.Concurrent;
  3. namespace Ryujinx.Graphics.Gpu
  4. {
  5. public class NvGpuFifo
  6. {
  7. private const int MacrosCount = 0x80;
  8. private const int MacroIndexMask = MacrosCount - 1;
  9. private NsGpu Gpu;
  10. private ConcurrentQueue<(AMemory, NsGpuPBEntry)> BufferQueue;
  11. private NvGpuEngine[] SubChannels;
  12. private struct CachedMacro
  13. {
  14. public long Position { get; private set; }
  15. private MacroInterpreter Interpreter;
  16. public CachedMacro(NvGpuFifo PFifo, INvGpuEngine Engine, long Position)
  17. {
  18. this.Position = Position;
  19. Interpreter = new MacroInterpreter(PFifo, Engine);
  20. }
  21. public void PushParam(int Param)
  22. {
  23. Interpreter?.Fifo.Enqueue(Param);
  24. }
  25. public void Execute(AMemory Memory, int Param)
  26. {
  27. Interpreter?.Execute(Memory, Position, Param);
  28. }
  29. }
  30. private long CurrMacroPosition;
  31. private int CurrMacroBindIndex;
  32. private CachedMacro[] Macros;
  33. public NvGpuFifo(NsGpu Gpu)
  34. {
  35. this.Gpu = Gpu;
  36. BufferQueue = new ConcurrentQueue<(AMemory, NsGpuPBEntry)>();
  37. SubChannels = new NvGpuEngine[8];
  38. Macros = new CachedMacro[MacrosCount];
  39. }
  40. public void PushBuffer(AMemory Memory, NsGpuPBEntry[] Buffer)
  41. {
  42. foreach (NsGpuPBEntry PBEntry in Buffer)
  43. {
  44. BufferQueue.Enqueue((Memory, PBEntry));
  45. }
  46. }
  47. public void DispatchCalls()
  48. {
  49. while (Step());
  50. }
  51. public bool Step()
  52. {
  53. if (BufferQueue.TryDequeue(out (AMemory Memory, NsGpuPBEntry PBEntry) Tuple))
  54. {
  55. CallMethod(Tuple.Memory, Tuple.PBEntry);
  56. return true;
  57. }
  58. return false;
  59. }
  60. private void CallMethod(AMemory Memory, NsGpuPBEntry PBEntry)
  61. {
  62. if (PBEntry.Method < 0x80)
  63. {
  64. switch ((NvGpuFifoMeth)PBEntry.Method)
  65. {
  66. case NvGpuFifoMeth.BindChannel:
  67. {
  68. NvGpuEngine Engine = (NvGpuEngine)PBEntry.Arguments[0];
  69. SubChannels[PBEntry.SubChannel] = Engine;
  70. break;
  71. }
  72. case NvGpuFifoMeth.SetMacroUploadAddress:
  73. {
  74. CurrMacroPosition = (long)((ulong)PBEntry.Arguments[0] << 2);
  75. break;
  76. }
  77. case NvGpuFifoMeth.SendMacroCodeData:
  78. {
  79. long Position = Gpu.GetCpuAddr(CurrMacroPosition);
  80. foreach (int Arg in PBEntry.Arguments)
  81. {
  82. Memory.WriteInt32(Position, Arg);
  83. CurrMacroPosition += 4;
  84. Position += 4;
  85. }
  86. break;
  87. }
  88. case NvGpuFifoMeth.SetMacroBindingIndex:
  89. {
  90. CurrMacroBindIndex = PBEntry.Arguments[0];
  91. break;
  92. }
  93. case NvGpuFifoMeth.BindMacro:
  94. {
  95. long Position = (long)((ulong)PBEntry.Arguments[0] << 2);
  96. Position = Gpu.GetCpuAddr(Position);
  97. Macros[CurrMacroBindIndex] = new CachedMacro(this, Gpu.Engine3d, Position);
  98. break;
  99. }
  100. }
  101. }
  102. else
  103. {
  104. switch (SubChannels[PBEntry.SubChannel])
  105. {
  106. case NvGpuEngine._2d: Call2dMethod(Memory, PBEntry); break;
  107. case NvGpuEngine._3d: Call3dMethod(Memory, PBEntry); break;
  108. }
  109. }
  110. }
  111. private void Call2dMethod(AMemory Memory, NsGpuPBEntry PBEntry)
  112. {
  113. Gpu.Engine2d.CallMethod(Memory, PBEntry);
  114. }
  115. private void Call3dMethod(AMemory Memory, NsGpuPBEntry PBEntry)
  116. {
  117. if (PBEntry.Method < 0xe00)
  118. {
  119. Gpu.Engine3d.CallMethod(Memory, PBEntry);
  120. }
  121. else
  122. {
  123. int MacroIndex = (PBEntry.Method >> 1) & MacroIndexMask;
  124. if ((PBEntry.Method & 1) != 0)
  125. {
  126. foreach (int Arg in PBEntry.Arguments)
  127. {
  128. Macros[MacroIndex].PushParam(Arg);
  129. }
  130. }
  131. else
  132. {
  133. Macros[MacroIndex].Execute(Memory, PBEntry.Arguments[0]);
  134. }
  135. }
  136. }
  137. }
  138. }