NvGpuEngineM2mf.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. using Ryujinx.Graphics.Memory;
  2. using Ryujinx.Graphics.Texture;
  3. using System.Collections.Generic;
  4. namespace Ryujinx.Graphics
  5. {
  6. class NvGpuEngineM2mf : INvGpuEngine
  7. {
  8. public int[] Registers { get; private set; }
  9. private NvGpu Gpu;
  10. private Dictionary<int, NvGpuMethod> Methods;
  11. public NvGpuEngineM2mf(NvGpu Gpu)
  12. {
  13. this.Gpu = Gpu;
  14. Registers = new int[0x1d6];
  15. Methods = new Dictionary<int, NvGpuMethod>();
  16. void AddMethod(int Meth, int Count, int Stride, NvGpuMethod Method)
  17. {
  18. while (Count-- > 0)
  19. {
  20. Methods.Add(Meth, Method);
  21. Meth += Stride;
  22. }
  23. }
  24. AddMethod(0xc0, 1, 1, Execute);
  25. }
  26. public void CallMethod(NvGpuVmm Vmm, GpuMethodCall MethCall)
  27. {
  28. if (Methods.TryGetValue(MethCall.Method, out NvGpuMethod Method))
  29. {
  30. Method(Vmm, MethCall);
  31. }
  32. else
  33. {
  34. WriteRegister(MethCall);
  35. }
  36. }
  37. private void Execute(NvGpuVmm Vmm, GpuMethodCall MethCall)
  38. {
  39. //TODO: Some registers and copy modes are still not implemented.
  40. int Control = MethCall.Argument;
  41. bool SrcLinear = ((Control >> 7) & 1) != 0;
  42. bool DstLinear = ((Control >> 8) & 1) != 0;
  43. bool Copy2d = ((Control >> 9) & 1) != 0;
  44. long SrcAddress = MakeInt64From2xInt32(NvGpuEngineM2mfReg.SrcAddress);
  45. long DstAddress = MakeInt64From2xInt32(NvGpuEngineM2mfReg.DstAddress);
  46. int SrcPitch = ReadRegister(NvGpuEngineM2mfReg.SrcPitch);
  47. int DstPitch = ReadRegister(NvGpuEngineM2mfReg.DstPitch);
  48. int XCount = ReadRegister(NvGpuEngineM2mfReg.XCount);
  49. int YCount = ReadRegister(NvGpuEngineM2mfReg.YCount);
  50. int Swizzle = ReadRegister(NvGpuEngineM2mfReg.Swizzle);
  51. int DstBlkDim = ReadRegister(NvGpuEngineM2mfReg.DstBlkDim);
  52. int DstSizeX = ReadRegister(NvGpuEngineM2mfReg.DstSizeX);
  53. int DstSizeY = ReadRegister(NvGpuEngineM2mfReg.DstSizeY);
  54. int DstSizeZ = ReadRegister(NvGpuEngineM2mfReg.DstSizeZ);
  55. int DstPosXY = ReadRegister(NvGpuEngineM2mfReg.DstPosXY);
  56. int DstPosZ = ReadRegister(NvGpuEngineM2mfReg.DstPosZ);
  57. int SrcBlkDim = ReadRegister(NvGpuEngineM2mfReg.SrcBlkDim);
  58. int SrcSizeX = ReadRegister(NvGpuEngineM2mfReg.SrcSizeX);
  59. int SrcSizeY = ReadRegister(NvGpuEngineM2mfReg.SrcSizeY);
  60. int SrcSizeZ = ReadRegister(NvGpuEngineM2mfReg.SrcSizeZ);
  61. int SrcPosXY = ReadRegister(NvGpuEngineM2mfReg.SrcPosXY);
  62. int SrcPosZ = ReadRegister(NvGpuEngineM2mfReg.SrcPosZ);
  63. int SrcCpp = ((Swizzle >> 20) & 7) + 1;
  64. int DstCpp = ((Swizzle >> 24) & 7) + 1;
  65. int DstPosX = (DstPosXY >> 0) & 0xffff;
  66. int DstPosY = (DstPosXY >> 16) & 0xffff;
  67. int SrcPosX = (SrcPosXY >> 0) & 0xffff;
  68. int SrcPosY = (SrcPosXY >> 16) & 0xffff;
  69. int SrcBlockHeight = 1 << ((SrcBlkDim >> 4) & 0xf);
  70. int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);
  71. long SrcPA = Vmm.GetPhysicalAddress(SrcAddress);
  72. long DstPA = Vmm.GetPhysicalAddress(DstAddress);
  73. if (Copy2d)
  74. {
  75. if (SrcLinear)
  76. {
  77. SrcPosX = SrcPosY = SrcPosZ = 0;
  78. }
  79. if (DstLinear)
  80. {
  81. DstPosX = DstPosY = DstPosZ = 0;
  82. }
  83. if (SrcLinear && DstLinear)
  84. {
  85. for (int Y = 0; Y < YCount; Y++)
  86. {
  87. int SrcOffset = (SrcPosY + Y) * SrcPitch + SrcPosX * SrcCpp;
  88. int DstOffset = (DstPosY + Y) * DstPitch + DstPosX * DstCpp;
  89. long Src = SrcPA + (uint)SrcOffset;
  90. long Dst = DstPA + (uint)DstOffset;
  91. Vmm.Memory.CopyBytes(Src, Dst, XCount * SrcCpp);
  92. }
  93. }
  94. else
  95. {
  96. ISwizzle SrcSwizzle;
  97. if (SrcLinear)
  98. {
  99. SrcSwizzle = new LinearSwizzle(SrcPitch, SrcCpp);
  100. }
  101. else
  102. {
  103. SrcSwizzle = new BlockLinearSwizzle(SrcSizeX, SrcCpp, SrcBlockHeight);
  104. }
  105. ISwizzle DstSwizzle;
  106. if (DstLinear)
  107. {
  108. DstSwizzle = new LinearSwizzle(DstPitch, DstCpp);
  109. }
  110. else
  111. {
  112. DstSwizzle = new BlockLinearSwizzle(DstSizeX, DstCpp, DstBlockHeight);
  113. }
  114. for (int Y = 0; Y < YCount; Y++)
  115. for (int X = 0; X < XCount; X++)
  116. {
  117. int SrcOffset = SrcSwizzle.GetSwizzleOffset(SrcPosX + X, SrcPosY + Y);
  118. int DstOffset = DstSwizzle.GetSwizzleOffset(DstPosX + X, DstPosY + Y);
  119. long Src = SrcPA + (uint)SrcOffset;
  120. long Dst = DstPA + (uint)DstOffset;
  121. Vmm.Memory.CopyBytes(Src, Dst, SrcCpp);
  122. }
  123. }
  124. }
  125. else
  126. {
  127. Vmm.Memory.CopyBytes(SrcPA, DstPA, XCount);
  128. }
  129. }
  130. private long MakeInt64From2xInt32(NvGpuEngineM2mfReg Reg)
  131. {
  132. return
  133. (long)Registers[(int)Reg + 0] << 32 |
  134. (uint)Registers[(int)Reg + 1];
  135. }
  136. private void WriteRegister(GpuMethodCall MethCall)
  137. {
  138. Registers[MethCall.Method] = MethCall.Argument;
  139. }
  140. private int ReadRegister(NvGpuEngineM2mfReg Reg)
  141. {
  142. return Registers[(int)Reg];
  143. }
  144. private void WriteRegister(NvGpuEngineM2mfReg Reg, int Value)
  145. {
  146. Registers[(int)Reg] = Value;
  147. }
  148. }
  149. }