NvGpuPushBuffer.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using System.Collections.Generic;
  2. using System.IO;
  3. namespace Ryujinx.Graphics.Memory
  4. {
  5. public static class NvGpuPushBuffer
  6. {
  7. private enum SubmissionMode
  8. {
  9. Incrementing = 1,
  10. NonIncrementing = 3,
  11. Immediate = 4,
  12. IncrementOnce = 5
  13. }
  14. public static NvGpuPBEntry[] Decode(byte[] Data)
  15. {
  16. using (MemoryStream MS = new MemoryStream(Data))
  17. {
  18. BinaryReader Reader = new BinaryReader(MS);
  19. List<NvGpuPBEntry> PushBuffer = new List<NvGpuPBEntry>();
  20. bool CanRead() => MS.Position + 4 <= MS.Length;
  21. while (CanRead())
  22. {
  23. int Packed = Reader.ReadInt32();
  24. int Meth = (Packed >> 0) & 0x1fff;
  25. int SubC = (Packed >> 13) & 7;
  26. int Args = (Packed >> 16) & 0x1fff;
  27. int Mode = (Packed >> 29) & 7;
  28. switch ((SubmissionMode)Mode)
  29. {
  30. case SubmissionMode.Incrementing:
  31. {
  32. for (int Index = 0; Index < Args && CanRead(); Index++, Meth++)
  33. {
  34. PushBuffer.Add(new NvGpuPBEntry(Meth, SubC, Reader.ReadInt32()));
  35. }
  36. break;
  37. }
  38. case SubmissionMode.NonIncrementing:
  39. {
  40. int[] Arguments = new int[Args];
  41. for (int Index = 0; Index < Arguments.Length; Index++)
  42. {
  43. if (!CanRead())
  44. {
  45. break;
  46. }
  47. Arguments[Index] = Reader.ReadInt32();
  48. }
  49. PushBuffer.Add(new NvGpuPBEntry(Meth, SubC, Arguments));
  50. break;
  51. }
  52. case SubmissionMode.Immediate:
  53. {
  54. PushBuffer.Add(new NvGpuPBEntry(Meth, SubC, Args));
  55. break;
  56. }
  57. case SubmissionMode.IncrementOnce:
  58. {
  59. if (CanRead())
  60. {
  61. PushBuffer.Add(new NvGpuPBEntry(Meth, SubC, Reader.ReadInt32()));
  62. }
  63. if (CanRead() && Args > 1)
  64. {
  65. int[] Arguments = new int[Args - 1];
  66. for (int Index = 0; Index < Arguments.Length && CanRead(); Index++)
  67. {
  68. Arguments[Index] = Reader.ReadInt32();
  69. }
  70. PushBuffer.Add(new NvGpuPBEntry(Meth + 1, SubC, Arguments));
  71. }
  72. break;
  73. }
  74. }
  75. }
  76. return PushBuffer.ToArray();
  77. }
  78. }
  79. }
  80. }