NvGpuEngineP2mf.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using Ryujinx.Graphics.Memory;
  2. using Ryujinx.Graphics.Texture;
  3. using System.Collections.Generic;
  4. namespace Ryujinx.Graphics.Graphics3d
  5. {
  6. class NvGpuEngineP2mf : INvGpuEngine
  7. {
  8. public int[] Registers { get; private set; }
  9. private NvGpu _gpu;
  10. private Dictionary<int, NvGpuMethod> _methods;
  11. private int _copyStartX;
  12. private int _copyStartY;
  13. private int _copyWidth;
  14. private int _copyHeight;
  15. private int _copyGobBlockHeight;
  16. private long _copyAddress;
  17. private int _copyOffset;
  18. private int _copySize;
  19. private bool _copyLinear;
  20. private byte[] _buffer;
  21. public NvGpuEngineP2mf(NvGpu gpu)
  22. {
  23. _gpu = gpu;
  24. Registers = new int[0x80];
  25. _methods = new Dictionary<int, NvGpuMethod>();
  26. void AddMethod(int meth, int count, int stride, NvGpuMethod method)
  27. {
  28. while (count-- > 0)
  29. {
  30. _methods.Add(meth, method);
  31. meth += stride;
  32. }
  33. }
  34. AddMethod(0x6c, 1, 1, Execute);
  35. AddMethod(0x6d, 1, 1, PushData);
  36. }
  37. public void CallMethod(NvGpuVmm vmm, GpuMethodCall methCall)
  38. {
  39. if (_methods.TryGetValue(methCall.Method, out NvGpuMethod method))
  40. {
  41. method(vmm, methCall);
  42. }
  43. else
  44. {
  45. WriteRegister(methCall);
  46. }
  47. }
  48. private void Execute(NvGpuVmm vmm, GpuMethodCall methCall)
  49. {
  50. //TODO: Some registers and copy modes are still not implemented.
  51. int control = methCall.Argument;
  52. long dstAddress = MakeInt64From2xInt32(NvGpuEngineP2mfReg.DstAddress);
  53. int dstPitch = ReadRegister(NvGpuEngineP2mfReg.DstPitch);
  54. int dstBlkDim = ReadRegister(NvGpuEngineP2mfReg.DstBlockDim);
  55. int dstX = ReadRegister(NvGpuEngineP2mfReg.DstX);
  56. int dstY = ReadRegister(NvGpuEngineP2mfReg.DstY);
  57. int dstWidth = ReadRegister(NvGpuEngineP2mfReg.DstWidth);
  58. int dstHeight = ReadRegister(NvGpuEngineP2mfReg.DstHeight);
  59. int lineLengthIn = ReadRegister(NvGpuEngineP2mfReg.LineLengthIn);
  60. int lineCount = ReadRegister(NvGpuEngineP2mfReg.LineCount);
  61. _copyLinear = (control & 1) != 0;
  62. _copyGobBlockHeight = 1 << ((dstBlkDim >> 4) & 0xf);
  63. _copyStartX = dstX;
  64. _copyStartY = dstY;
  65. _copyWidth = dstWidth;
  66. _copyHeight = dstHeight;
  67. _copyAddress = dstAddress;
  68. _copyOffset = 0;
  69. _copySize = lineLengthIn * lineCount;
  70. _buffer = new byte[_copySize];
  71. }
  72. private void PushData(NvGpuVmm vmm, GpuMethodCall methCall)
  73. {
  74. if (_buffer == null)
  75. {
  76. return;
  77. }
  78. for (int shift = 0; shift < 32 && _copyOffset < _copySize; shift += 8, _copyOffset++)
  79. {
  80. _buffer[_copyOffset] = (byte)(methCall.Argument >> shift);
  81. }
  82. if (methCall.IsLastCall)
  83. {
  84. if (_copyLinear)
  85. {
  86. vmm.WriteBytes(_copyAddress, _buffer);
  87. }
  88. else
  89. {
  90. BlockLinearSwizzle swizzle = new BlockLinearSwizzle(
  91. _copyWidth,
  92. _copyHeight, 1,
  93. _copyGobBlockHeight, 1, 1);
  94. int srcOffset = 0;
  95. for (int y = _copyStartY; y < _copyHeight && srcOffset < _copySize; y++)
  96. for (int x = _copyStartX; x < _copyWidth && srcOffset < _copySize; x++)
  97. {
  98. int dstOffset = swizzle.GetSwizzleOffset(x, y, 0);
  99. vmm.WriteByte(_copyAddress + dstOffset, _buffer[srcOffset++]);
  100. }
  101. }
  102. _buffer = null;
  103. }
  104. }
  105. private long MakeInt64From2xInt32(NvGpuEngineP2mfReg reg)
  106. {
  107. return
  108. (long)Registers[(int)reg + 0] << 32 |
  109. (uint)Registers[(int)reg + 1];
  110. }
  111. private void WriteRegister(GpuMethodCall methCall)
  112. {
  113. Registers[methCall.Method] = methCall.Argument;
  114. }
  115. private int ReadRegister(NvGpuEngineP2mfReg reg)
  116. {
  117. return Registers[(int)reg];
  118. }
  119. private void WriteRegister(NvGpuEngineP2mfReg reg, int value)
  120. {
  121. Registers[(int)reg] = value;
  122. }
  123. }
  124. }