IndexBufferPattern.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. using Ryujinx.Graphics.GAL;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Runtime.InteropServices;
  5. namespace Ryujinx.Graphics.Vulkan
  6. {
  7. internal class IndexBufferPattern : IDisposable
  8. {
  9. public int PrimitiveVertices { get; }
  10. public int PrimitiveVerticesOut { get; }
  11. public int BaseIndex { get; }
  12. public int[] OffsetIndex { get; }
  13. public int IndexStride { get; }
  14. public bool RepeatStart { get; }
  15. private VulkanRenderer _gd;
  16. private int _currentSize;
  17. private BufferHandle _repeatingBuffer;
  18. public IndexBufferPattern(VulkanRenderer gd,
  19. int primitiveVertices,
  20. int primitiveVerticesOut,
  21. int baseIndex,
  22. int[] offsetIndex,
  23. int indexStride,
  24. bool repeatStart)
  25. {
  26. PrimitiveVertices = primitiveVertices;
  27. PrimitiveVerticesOut = primitiveVerticesOut;
  28. BaseIndex = baseIndex;
  29. OffsetIndex = offsetIndex;
  30. IndexStride = indexStride;
  31. RepeatStart = repeatStart;
  32. _gd = gd;
  33. }
  34. public int GetPrimitiveCount(int vertexCount)
  35. {
  36. return Math.Max(0, (vertexCount - BaseIndex) / IndexStride);
  37. }
  38. public int GetConvertedCount(int indexCount)
  39. {
  40. int primitiveCount = GetPrimitiveCount(indexCount);
  41. return primitiveCount * OffsetIndex.Length;
  42. }
  43. public IEnumerable<int> GetIndexMapping(int indexCount)
  44. {
  45. int primitiveCount = GetPrimitiveCount(indexCount);
  46. int index = BaseIndex;
  47. for (int i = 0; i < primitiveCount; i++)
  48. {
  49. if (RepeatStart)
  50. {
  51. // Used for triangle fan
  52. yield return 0;
  53. }
  54. for (int j = RepeatStart ? 1 : 0; j < OffsetIndex.Length; j++)
  55. {
  56. yield return index + OffsetIndex[j];
  57. }
  58. index += IndexStride;
  59. }
  60. }
  61. public BufferHandle GetRepeatingBuffer(int vertexCount, out int indexCount)
  62. {
  63. int primitiveCount = GetPrimitiveCount(vertexCount);
  64. indexCount = primitiveCount * PrimitiveVerticesOut;
  65. int expectedSize = primitiveCount * OffsetIndex.Length;
  66. if (expectedSize <= _currentSize && _repeatingBuffer != BufferHandle.Null)
  67. {
  68. return _repeatingBuffer;
  69. }
  70. // Expand the repeating pattern to the number of requested primitives.
  71. BufferHandle newBuffer = _gd.CreateBuffer(expectedSize * sizeof(int));
  72. // Copy the old data to the new one.
  73. if (_repeatingBuffer != BufferHandle.Null)
  74. {
  75. _gd.Pipeline.CopyBuffer(_repeatingBuffer, newBuffer, 0, 0, _currentSize * sizeof(int));
  76. _gd.DeleteBuffer(_repeatingBuffer);
  77. }
  78. _repeatingBuffer = newBuffer;
  79. // Add the additional repeats on top.
  80. int newPrimitives = primitiveCount;
  81. int oldPrimitives = (_currentSize) / OffsetIndex.Length;
  82. int[] newData;
  83. newPrimitives -= oldPrimitives;
  84. newData = new int[expectedSize - _currentSize];
  85. int outOffset = 0;
  86. int index = oldPrimitives * IndexStride + BaseIndex;
  87. for (int i = 0; i < newPrimitives; i++)
  88. {
  89. if (RepeatStart)
  90. {
  91. // Used for triangle fan
  92. newData[outOffset++] = 0;
  93. }
  94. for (int j = RepeatStart ? 1 : 0; j < OffsetIndex.Length; j++)
  95. {
  96. newData[outOffset++] = index + OffsetIndex[j];
  97. }
  98. index += IndexStride;
  99. }
  100. _gd.SetBufferData(newBuffer, _currentSize * sizeof(int), MemoryMarshal.Cast<int, byte>(newData));
  101. _currentSize = expectedSize;
  102. return newBuffer;
  103. }
  104. public void Dispose()
  105. {
  106. if (_repeatingBuffer != BufferHandle.Null)
  107. {
  108. _gd.DeleteBuffer(_repeatingBuffer);
  109. _repeatingBuffer = BufferHandle.Null;
  110. }
  111. }
  112. }
  113. }