Macro.cs 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. using Ryujinx.Graphics.Device;
  2. using Ryujinx.Graphics.Gpu.Engine.GPFifo;
  3. using Ryujinx.Graphics.Gpu.Memory;
  4. using System;
  5. namespace Ryujinx.Graphics.Gpu.Engine.MME
  6. {
  7. /// <summary>
  8. /// GPU macro program.
  9. /// </summary>
  10. struct Macro
  11. {
  12. /// <summary>
  13. /// Word offset of the code on the code memory.
  14. /// </summary>
  15. public int Position { get; }
  16. private IMacroEE _executionEngine;
  17. private bool _executionPending;
  18. private int _argument;
  19. private MacroHLEFunctionName _hleFunction;
  20. /// <summary>
  21. /// Creates a new instance of the GPU cached macro program.
  22. /// </summary>
  23. /// <param name="position">Macro code start position</param>
  24. public Macro(int position)
  25. {
  26. Position = position;
  27. _executionEngine = null;
  28. _executionPending = false;
  29. _argument = 0;
  30. _hleFunction = MacroHLEFunctionName.None;
  31. }
  32. /// <summary>
  33. /// Sets the first argument for the macro call.
  34. /// </summary>
  35. /// <param name="context">GPU context where the macro code is being executed</param>
  36. /// <param name="processor">GPU GP FIFO command processor</param>
  37. /// <param name="code">Code to be executed</param>
  38. /// <param name="argument">First argument</param>
  39. public void StartExecution(GpuContext context, GPFifoProcessor processor, ReadOnlySpan<int> code, int argument)
  40. {
  41. _argument = argument;
  42. _executionPending = true;
  43. if (_executionEngine == null)
  44. {
  45. if (GraphicsConfig.EnableMacroHLE && MacroHLETable.TryGetMacroHLEFunction(code.Slice(Position), context.Capabilities, out _hleFunction))
  46. {
  47. _executionEngine = new MacroHLE(processor, _hleFunction);
  48. }
  49. else if (GraphicsConfig.EnableMacroJit)
  50. {
  51. _executionEngine = new MacroJit();
  52. }
  53. else
  54. {
  55. _executionEngine = new MacroInterpreter();
  56. }
  57. }
  58. if (_hleFunction == MacroHLEFunctionName.MultiDrawElementsIndirectCount)
  59. {
  60. // We don't consume the parameter buffer value, so we don't need to flush it.
  61. // Doing so improves performance if the value was written by a GPU shader.
  62. context.GPFifo.SetFlushSkips(2);
  63. }
  64. }
  65. /// <summary>
  66. /// Starts executing the macro program code.
  67. /// </summary>
  68. /// <param name="code">Program code</param>
  69. /// <param name="state">Current GPU state</param>
  70. public void Execute(ReadOnlySpan<int> code, IDeviceState state)
  71. {
  72. if (_executionPending)
  73. {
  74. _executionPending = false;
  75. _executionEngine?.Execute(code.Slice(Position), state, _argument);
  76. }
  77. }
  78. /// <summary>
  79. /// Pushes an argument to the macro call argument FIFO.
  80. /// </summary>
  81. /// <param name="gpuVa">GPU virtual address where the command word is located</param>
  82. /// <param name="argument">Argument to be pushed</param>
  83. public void PushArgument(ulong gpuVa, int argument)
  84. {
  85. _executionEngine?.Fifo.Enqueue(new FifoWord(gpuVa, argument));
  86. }
  87. }
  88. }