NvGpuEngineDma.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. using System.Collections.Generic;
  2. namespace Ryujinx.HLE.Gpu
  3. {
  4. class NvGpuEngineDma : INvGpuEngine
  5. {
  6. public int[] Registers { get; private set; }
  7. private NvGpu Gpu;
  8. private Dictionary<int, NvGpuMethod> Methods;
  9. public NvGpuEngineDma(NvGpu Gpu)
  10. {
  11. this.Gpu = Gpu;
  12. Registers = new int[0x1d6];
  13. Methods = new Dictionary<int, NvGpuMethod>();
  14. void AddMethod(int Meth, int Count, int Stride, NvGpuMethod Method)
  15. {
  16. while (Count-- > 0)
  17. {
  18. Methods.Add(Meth, Method);
  19. Meth += Stride;
  20. }
  21. }
  22. AddMethod(0xc0, 1, 1, Execute);
  23. }
  24. public void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
  25. {
  26. if (Methods.TryGetValue(PBEntry.Method, out NvGpuMethod Method))
  27. {
  28. Method(Vmm, PBEntry);
  29. }
  30. else
  31. {
  32. WriteRegister(PBEntry);
  33. }
  34. }
  35. private void Execute(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
  36. {
  37. int Control = PBEntry.Arguments[0];
  38. bool SrcLinear = ((Control >> 7) & 1) != 0;
  39. bool DstLinear = ((Control >> 8) & 1) != 0;
  40. long SrcAddress = MakeInt64From2xInt32(NvGpuEngineDmaReg.SrcAddress);
  41. long DstAddress = MakeInt64From2xInt32(NvGpuEngineDmaReg.DstAddress);
  42. int SrcPitch = ReadRegister(NvGpuEngineDmaReg.SrcPitch);
  43. int DstPitch = ReadRegister(NvGpuEngineDmaReg.DstPitch);
  44. int DstBlkDim = ReadRegister(NvGpuEngineDmaReg.DstBlkDim);
  45. int DstSizeX = ReadRegister(NvGpuEngineDmaReg.DstSizeX);
  46. int DstSizeY = ReadRegister(NvGpuEngineDmaReg.DstSizeY);
  47. int DstSizeZ = ReadRegister(NvGpuEngineDmaReg.DstSizeZ);
  48. int DstPosXY = ReadRegister(NvGpuEngineDmaReg.DstPosXY);
  49. int DstPosZ = ReadRegister(NvGpuEngineDmaReg.DstPosZ);
  50. int SrcBlkDim = ReadRegister(NvGpuEngineDmaReg.SrcBlkDim);
  51. int SrcSizeX = ReadRegister(NvGpuEngineDmaReg.SrcSizeX);
  52. int SrcSizeY = ReadRegister(NvGpuEngineDmaReg.SrcSizeY);
  53. int SrcSizeZ = ReadRegister(NvGpuEngineDmaReg.SrcSizeZ);
  54. int SrcPosXY = ReadRegister(NvGpuEngineDmaReg.SrcPosXY);
  55. int SrcPosZ = ReadRegister(NvGpuEngineDmaReg.SrcPosZ);
  56. int DstPosX = (DstPosXY >> 0) & 0xffff;
  57. int DstPosY = (DstPosXY >> 16) & 0xffff;
  58. int SrcPosX = (SrcPosXY >> 0) & 0xffff;
  59. int SrcPosY = (SrcPosXY >> 16) & 0xffff;
  60. int SrcBlockHeight = 1 << ((SrcBlkDim >> 4) & 0xf);
  61. int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);
  62. ISwizzle SrcSwizzle;
  63. if (SrcLinear)
  64. {
  65. SrcSwizzle = new LinearSwizzle(SrcPitch, 1);
  66. }
  67. else
  68. {
  69. SrcSwizzle = new BlockLinearSwizzle(SrcSizeX, 1, SrcBlockHeight);
  70. }
  71. ISwizzle DstSwizzle;
  72. if (DstLinear)
  73. {
  74. DstSwizzle = new LinearSwizzle(DstPitch, 1);
  75. }
  76. else
  77. {
  78. DstSwizzle = new BlockLinearSwizzle(DstSizeX, 1, DstBlockHeight);
  79. }
  80. for (int Y = 0; Y < DstSizeY; Y++)
  81. for (int X = 0; X < DstSizeX; X++)
  82. {
  83. long SrcOffset = SrcAddress + (uint)SrcSwizzle.GetSwizzleOffset(X, Y);
  84. long DstOffset = DstAddress + (uint)DstSwizzle.GetSwizzleOffset(X, Y);
  85. Vmm.WriteByte(DstOffset, Vmm.ReadByte(SrcOffset));
  86. }
  87. }
  88. private long MakeInt64From2xInt32(NvGpuEngineDmaReg Reg)
  89. {
  90. return
  91. (long)Registers[(int)Reg + 0] << 32 |
  92. (uint)Registers[(int)Reg + 1];
  93. }
  94. private void WriteRegister(NvGpuPBEntry PBEntry)
  95. {
  96. int ArgsCount = PBEntry.Arguments.Count;
  97. if (ArgsCount > 0)
  98. {
  99. Registers[PBEntry.Method] = PBEntry.Arguments[ArgsCount - 1];
  100. }
  101. }
  102. private int ReadRegister(NvGpuEngineDmaReg Reg)
  103. {
  104. return Registers[(int)Reg];
  105. }
  106. private void WriteRegister(NvGpuEngineDmaReg Reg, int Value)
  107. {
  108. Registers[(int)Reg] = Value;
  109. }
  110. }
  111. }