NvGpuFifo.cs 4.7 KB

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