NvGpuEngineM2mf.cs 6.5 KB

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