Macro.cs 3.3 KB

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