IbStreamer.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. using Ryujinx.Common;
  2. using Ryujinx.Graphics.GAL;
  3. using System;
  4. using System.Runtime.InteropServices;
  5. namespace Ryujinx.Graphics.Gpu.Engine.Threed
  6. {
  7. /// <summary>
  8. /// Holds inline index buffer state.
  9. /// The inline index buffer data is sent to the GPU through the command buffer.
  10. /// </summary>
  11. struct IbStreamer
  12. {
  13. private BufferHandle _inlineIndexBuffer;
  14. private int _inlineIndexBufferSize;
  15. private int _inlineIndexCount;
  16. /// <summary>
  17. /// Indicates if any index buffer data has been pushed.
  18. /// </summary>
  19. public bool HasInlineIndexData => _inlineIndexCount != 0;
  20. /// <summary>
  21. /// Total numbers of indices that have been pushed.
  22. /// </summary>
  23. public int InlineIndexCount => _inlineIndexCount;
  24. /// <summary>
  25. /// Gets the handle for the host buffer currently holding the inline index buffer data.
  26. /// </summary>
  27. /// <returns>Host buffer handle</returns>
  28. public BufferHandle GetInlineIndexBuffer()
  29. {
  30. return _inlineIndexBuffer;
  31. }
  32. /// <summary>
  33. /// Gets the number of elements on the current inline index buffer,
  34. /// while also reseting it to zero for the next draw.
  35. /// </summary>
  36. /// <returns>Inline index bufffer count</returns>
  37. public int GetAndResetInlineIndexCount()
  38. {
  39. int temp = _inlineIndexCount;
  40. _inlineIndexCount = 0;
  41. return temp;
  42. }
  43. /// <summary>
  44. /// Pushes four 8-bit index buffer elements.
  45. /// </summary>
  46. /// <param name="renderer">Host renderer</param>
  47. /// <param name="argument">Method call argument</param>
  48. public void VbElementU8(IRenderer renderer, int argument)
  49. {
  50. byte i0 = (byte)argument;
  51. byte i1 = (byte)(argument >> 8);
  52. byte i2 = (byte)(argument >> 16);
  53. byte i3 = (byte)(argument >> 24);
  54. Span<uint> data = stackalloc uint[4];
  55. data[0] = i0;
  56. data[1] = i1;
  57. data[2] = i2;
  58. data[3] = i3;
  59. int offset = _inlineIndexCount * 4;
  60. renderer.SetBufferData(GetInlineIndexBuffer(renderer, offset), offset, MemoryMarshal.Cast<uint, byte>(data));
  61. _inlineIndexCount += 4;
  62. }
  63. /// <summary>
  64. /// Pushes two 16-bit index buffer elements.
  65. /// </summary>
  66. /// <param name="renderer">Host renderer</param>
  67. /// <param name="argument">Method call argument</param>
  68. public void VbElementU16(IRenderer renderer, int argument)
  69. {
  70. ushort i0 = (ushort)argument;
  71. ushort i1 = (ushort)(argument >> 16);
  72. Span<uint> data = stackalloc uint[2];
  73. data[0] = i0;
  74. data[1] = i1;
  75. int offset = _inlineIndexCount * 4;
  76. renderer.SetBufferData(GetInlineIndexBuffer(renderer, offset), offset, MemoryMarshal.Cast<uint, byte>(data));
  77. _inlineIndexCount += 2;
  78. }
  79. /// <summary>
  80. /// Pushes one 32-bit index buffer element.
  81. /// </summary>
  82. /// <param name="renderer">Host renderer</param>
  83. /// <param name="argument">Method call argument</param>
  84. public void VbElementU32(IRenderer renderer, int argument)
  85. {
  86. uint i0 = (uint)argument;
  87. Span<uint> data = stackalloc uint[1];
  88. data[0] = i0;
  89. int offset = _inlineIndexCount++ * 4;
  90. renderer.SetBufferData(GetInlineIndexBuffer(renderer, offset), offset, MemoryMarshal.Cast<uint, byte>(data));
  91. }
  92. /// <summary>
  93. /// Gets the handle of a buffer large enough to hold the data that will be written to <paramref name="offset"/>.
  94. /// </summary>
  95. /// <param name="renderer">Host renderer</param>
  96. /// <param name="offset">Offset where the data will be written</param>
  97. /// <returns>Buffer handle</returns>
  98. private BufferHandle GetInlineIndexBuffer(IRenderer renderer, int offset)
  99. {
  100. // Calculate a reasonable size for the buffer that can fit all the data,
  101. // and that also won't require frequent resizes if we need to push more data.
  102. int size = BitUtils.AlignUp(offset + 0x10, 0x200);
  103. if (_inlineIndexBuffer == BufferHandle.Null)
  104. {
  105. _inlineIndexBuffer = renderer.CreateBuffer(size);
  106. _inlineIndexBufferSize = size;
  107. }
  108. else if (_inlineIndexBufferSize < size)
  109. {
  110. BufferHandle oldBuffer = _inlineIndexBuffer;
  111. int oldSize = _inlineIndexBufferSize;
  112. _inlineIndexBuffer = renderer.CreateBuffer(size);
  113. _inlineIndexBufferSize = size;
  114. renderer.Pipeline.CopyBuffer(oldBuffer, _inlineIndexBuffer, 0, 0, oldSize);
  115. renderer.DeleteBuffer(oldBuffer);
  116. }
  117. return _inlineIndexBuffer;
  118. }
  119. }
  120. }