DmaPusher.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. using Ryujinx.Graphics.Memory;
  2. using System.Collections.Concurrent;
  3. using System.Threading;
  4. namespace Ryujinx.Graphics
  5. {
  6. public class DmaPusher
  7. {
  8. private ConcurrentQueue<(NvGpuVmm, long)> IbBuffer;
  9. private long DmaPut;
  10. private long DmaGet;
  11. private struct DmaState
  12. {
  13. public int Method;
  14. public int SubChannel;
  15. public int MethodCount;
  16. public bool NonIncrementing;
  17. public bool IncrementOnce;
  18. public int LengthPending;
  19. }
  20. private DmaState State;
  21. private bool SliEnable;
  22. private bool SliActive;
  23. private bool IbEnable;
  24. private bool NonMain;
  25. private long DmaMGet;
  26. private NvGpuVmm Vmm;
  27. private NvGpu Gpu;
  28. private AutoResetEvent Event;
  29. public DmaPusher(NvGpu Gpu)
  30. {
  31. this.Gpu = Gpu;
  32. IbBuffer = new ConcurrentQueue<(NvGpuVmm, long)>();
  33. IbEnable = true;
  34. Event = new AutoResetEvent(false);
  35. }
  36. public void Push(NvGpuVmm Vmm, long Entry)
  37. {
  38. IbBuffer.Enqueue((Vmm, Entry));
  39. Event.Set();
  40. }
  41. public bool WaitForCommands()
  42. {
  43. return Event.WaitOne(8);
  44. }
  45. public void DispatchCalls()
  46. {
  47. while (Step());
  48. }
  49. private bool Step()
  50. {
  51. if (DmaGet != DmaPut)
  52. {
  53. int Word = Vmm.ReadInt32(DmaGet);
  54. DmaGet += 4;
  55. if (!NonMain)
  56. {
  57. DmaMGet = DmaGet;
  58. }
  59. if (State.LengthPending != 0)
  60. {
  61. State.LengthPending = 0;
  62. State.MethodCount = Word & 0xffffff;
  63. }
  64. else if (State.MethodCount != 0)
  65. {
  66. if (!SliEnable || SliActive)
  67. {
  68. CallMethod(Word);
  69. }
  70. if (!State.NonIncrementing)
  71. {
  72. State.Method++;
  73. }
  74. if (State.IncrementOnce)
  75. {
  76. State.NonIncrementing = true;
  77. }
  78. State.MethodCount--;
  79. }
  80. else
  81. {
  82. int SumissionMode = (Word >> 29) & 7;
  83. switch (SumissionMode)
  84. {
  85. case 1:
  86. //Incrementing.
  87. SetNonImmediateState(Word);
  88. State.NonIncrementing = false;
  89. State.IncrementOnce = false;
  90. break;
  91. case 3:
  92. //Non-incrementing.
  93. SetNonImmediateState(Word);
  94. State.NonIncrementing = true;
  95. State.IncrementOnce = false;
  96. break;
  97. case 4:
  98. //Immediate.
  99. State.Method = (Word >> 0) & 0x1fff;
  100. State.SubChannel = (Word >> 13) & 7;
  101. State.NonIncrementing = true;
  102. State.IncrementOnce = false;
  103. CallMethod((Word >> 16) & 0x1fff);
  104. break;
  105. case 5:
  106. //Increment-once.
  107. SetNonImmediateState(Word);
  108. State.NonIncrementing = false;
  109. State.IncrementOnce = true;
  110. break;
  111. }
  112. }
  113. }
  114. else if (IbEnable && IbBuffer.TryDequeue(out (NvGpuVmm Vmm, long Entry) Tuple))
  115. {
  116. this.Vmm = Tuple.Vmm;
  117. long Entry = Tuple.Entry;
  118. int Length = (int)(Entry >> 42) & 0x1fffff;
  119. DmaGet = Entry & 0xfffffffffc;
  120. DmaPut = DmaGet + Length * 4;
  121. NonMain = (Entry & (1L << 41)) != 0;
  122. Gpu.ResourceManager.ClearPbCache();
  123. }
  124. else
  125. {
  126. return false;
  127. }
  128. return true;
  129. }
  130. private void SetNonImmediateState(int Word)
  131. {
  132. State.Method = (Word >> 0) & 0x1fff;
  133. State.SubChannel = (Word >> 13) & 7;
  134. State.MethodCount = (Word >> 16) & 0x1fff;
  135. }
  136. private void CallMethod(int Argument)
  137. {
  138. Gpu.Fifo.CallMethod(Vmm, new GpuMethodCall(
  139. State.Method,
  140. Argument,
  141. State.SubChannel,
  142. State.MethodCount));
  143. }
  144. }
  145. }