IndexBufferState.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. using Ryujinx.Graphics.GAL;
  2. using IndexType = Silk.NET.Vulkan.IndexType;
  3. namespace Ryujinx.Graphics.Vulkan
  4. {
  5. internal struct IndexBufferState
  6. {
  7. private const int IndexBufferMaxMirrorable = 0x20000;
  8. public static IndexBufferState Null => new(BufferHandle.Null, 0, 0);
  9. private readonly int _offset;
  10. private readonly int _size;
  11. private readonly IndexType _type;
  12. private readonly BufferHandle _handle;
  13. private Auto<DisposableBuffer> _buffer;
  14. public IndexBufferState(BufferHandle handle, int offset, int size, IndexType type)
  15. {
  16. _handle = handle;
  17. _offset = offset;
  18. _size = size;
  19. _type = type;
  20. _buffer = null;
  21. }
  22. public IndexBufferState(BufferHandle handle, int offset, int size)
  23. {
  24. _handle = handle;
  25. _offset = offset;
  26. _size = size;
  27. _type = IndexType.Uint16;
  28. _buffer = null;
  29. }
  30. public void BindIndexBuffer(VulkanRenderer gd, CommandBufferScoped cbs)
  31. {
  32. Auto<DisposableBuffer> autoBuffer;
  33. int offset, size;
  34. IndexType type = _type;
  35. bool mirrorable = false;
  36. if (_type == IndexType.Uint8Ext && !gd.Capabilities.SupportsIndexTypeUint8)
  37. {
  38. // Index type is not supported. Convert to I16.
  39. autoBuffer = gd.BufferManager.GetBufferI8ToI16(cbs, _handle, _offset, _size);
  40. type = IndexType.Uint16;
  41. offset = 0;
  42. size = _size * 2;
  43. }
  44. else
  45. {
  46. autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int bufferSize);
  47. if (_offset >= bufferSize)
  48. {
  49. autoBuffer = null;
  50. }
  51. mirrorable = _size < IndexBufferMaxMirrorable;
  52. offset = _offset;
  53. size = _size;
  54. }
  55. _buffer = autoBuffer;
  56. if (autoBuffer != null)
  57. {
  58. DisposableBuffer buffer = mirrorable ? autoBuffer.GetMirrorable(cbs, ref offset, size, out _) : autoBuffer.Get(cbs, offset, size);
  59. gd.Api.CmdBindIndexBuffer(cbs.CommandBuffer, buffer.Value, (ulong)offset, type);
  60. }
  61. }
  62. public void BindConvertedIndexBuffer(
  63. VulkanRenderer gd,
  64. CommandBufferScoped cbs,
  65. int firstIndex,
  66. int indexCount,
  67. int convertedCount,
  68. IndexBufferPattern pattern)
  69. {
  70. Auto<DisposableBuffer> autoBuffer;
  71. // Convert the index buffer using the given pattern.
  72. int indexSize = GetIndexSize();
  73. int firstIndexOffset = firstIndex * indexSize;
  74. autoBuffer = gd.BufferManager.GetBufferTopologyConversion(cbs, _handle, _offset + firstIndexOffset, indexCount * indexSize, pattern, indexSize);
  75. int size = convertedCount * 4;
  76. _buffer = autoBuffer;
  77. if (autoBuffer != null)
  78. {
  79. gd.Api.CmdBindIndexBuffer(cbs.CommandBuffer, autoBuffer.Get(cbs, 0, size).Value, 0, IndexType.Uint32);
  80. }
  81. }
  82. public Auto<DisposableBuffer> BindConvertedIndexBufferIndirect(
  83. VulkanRenderer gd,
  84. CommandBufferScoped cbs,
  85. BufferRange indirectBuffer,
  86. BufferRange drawCountBuffer,
  87. IndexBufferPattern pattern,
  88. bool hasDrawCount,
  89. int maxDrawCount,
  90. int indirectDataStride)
  91. {
  92. // Convert the index buffer using the given pattern.
  93. int indexSize = GetIndexSize();
  94. (var indexBufferAuto, var indirectBufferAuto) = gd.BufferManager.GetBufferTopologyConversionIndirect(
  95. gd,
  96. cbs,
  97. new BufferRange(_handle, _offset, _size),
  98. indirectBuffer,
  99. drawCountBuffer,
  100. pattern,
  101. indexSize,
  102. hasDrawCount,
  103. maxDrawCount,
  104. indirectDataStride);
  105. int convertedCount = pattern.GetConvertedCount(_size / indexSize);
  106. int size = convertedCount * 4;
  107. _buffer = indexBufferAuto;
  108. if (indexBufferAuto != null)
  109. {
  110. gd.Api.CmdBindIndexBuffer(cbs.CommandBuffer, indexBufferAuto.Get(cbs, 0, size).Value, 0, IndexType.Uint32);
  111. }
  112. return indirectBufferAuto;
  113. }
  114. private readonly int GetIndexSize()
  115. {
  116. return _type switch
  117. {
  118. IndexType.Uint32 => 4,
  119. IndexType.Uint16 => 2,
  120. _ => 1,
  121. };
  122. }
  123. public readonly bool BoundEquals(Auto<DisposableBuffer> buffer)
  124. {
  125. return _buffer == buffer;
  126. }
  127. public void Swap(Auto<DisposableBuffer> from, Auto<DisposableBuffer> to)
  128. {
  129. if (_buffer == from)
  130. {
  131. _buffer = to;
  132. }
  133. }
  134. public readonly bool Overlaps(Auto<DisposableBuffer> buffer, int offset, int size)
  135. {
  136. return buffer == _buffer && offset < _offset + _size && offset + size > _offset;
  137. }
  138. }
  139. }