VertexBufferState.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. using BufferHandle = Ryujinx.Graphics.GAL.BufferHandle;
  2. namespace Ryujinx.Graphics.Vulkan
  3. {
  4. internal struct VertexBufferState
  5. {
  6. public static VertexBufferState Null => new VertexBufferState(null, 0, 0, 0);
  7. private readonly int _offset;
  8. private readonly int _size;
  9. private readonly int _stride;
  10. private readonly BufferHandle _handle;
  11. private Auto<DisposableBuffer> _buffer;
  12. internal readonly int DescriptorIndex;
  13. internal int AttributeScalarAlignment;
  14. public VertexBufferState(Auto<DisposableBuffer> buffer, int descriptorIndex, int offset, int size, int stride = 0)
  15. {
  16. _buffer = buffer;
  17. _handle = BufferHandle.Null;
  18. _offset = offset;
  19. _size = size;
  20. _stride = stride;
  21. DescriptorIndex = descriptorIndex;
  22. AttributeScalarAlignment = 1;
  23. buffer?.IncrementReferenceCount();
  24. }
  25. public VertexBufferState(BufferHandle handle, int descriptorIndex, int offset, int size, int stride = 0)
  26. {
  27. // This buffer state may be rewritten at bind time, so it must be retrieved on bind.
  28. _buffer = null;
  29. _handle = handle;
  30. _offset = offset;
  31. _size = size;
  32. _stride = stride;
  33. DescriptorIndex = descriptorIndex;
  34. AttributeScalarAlignment = 1;
  35. }
  36. public void BindVertexBuffer(VulkanRenderer gd, CommandBufferScoped cbs, uint binding, ref PipelineState state)
  37. {
  38. var autoBuffer = _buffer;
  39. if (_handle != BufferHandle.Null)
  40. {
  41. // May need to restride the vertex buffer.
  42. if (gd.NeedsVertexBufferAlignment(AttributeScalarAlignment, out int alignment) && (_stride % alignment) != 0)
  43. {
  44. autoBuffer = gd.BufferManager.GetAlignedVertexBuffer(cbs, _handle, _offset, _size, _stride, alignment);
  45. if (autoBuffer != null)
  46. {
  47. int stride = (_stride + (alignment - 1)) & -alignment;
  48. int newSize = (_size / _stride) * stride;
  49. var buffer = autoBuffer.Get(cbs, 0, newSize).Value;
  50. if (gd.Capabilities.SupportsExtendedDynamicState)
  51. {
  52. gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2(
  53. cbs.CommandBuffer,
  54. binding,
  55. 1,
  56. buffer,
  57. 0,
  58. (ulong)newSize,
  59. (ulong)stride);
  60. }
  61. else
  62. {
  63. gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, binding, 1, buffer, 0);
  64. }
  65. _buffer = autoBuffer;
  66. state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)stride;
  67. }
  68. return;
  69. }
  70. else
  71. {
  72. autoBuffer = gd.BufferManager.GetBuffer(cbs.CommandBuffer, _handle, false, out int size);
  73. // The original stride must be reapplied in case it was rewritten.
  74. state.Internal.VertexBindingDescriptions[DescriptorIndex].Stride = (uint)_stride;
  75. if (_offset >= size)
  76. {
  77. autoBuffer = null;
  78. }
  79. }
  80. }
  81. if (autoBuffer != null)
  82. {
  83. var buffer = autoBuffer.Get(cbs, _offset, _size).Value;
  84. if (gd.Capabilities.SupportsExtendedDynamicState)
  85. {
  86. gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2(
  87. cbs.CommandBuffer,
  88. binding,
  89. 1,
  90. buffer,
  91. (ulong)_offset,
  92. (ulong)_size,
  93. (ulong)_stride);
  94. }
  95. else
  96. {
  97. gd.Api.CmdBindVertexBuffers(cbs.CommandBuffer, binding, 1, buffer, (ulong)_offset);
  98. }
  99. }
  100. }
  101. public bool BoundEquals(Auto<DisposableBuffer> buffer)
  102. {
  103. return _buffer == buffer;
  104. }
  105. public void Dispose()
  106. {
  107. // Only dispose if this buffer is not refetched on each bind.
  108. if (_handle == BufferHandle.Null)
  109. {
  110. _buffer?.DecrementReferenceCount();
  111. }
  112. }
  113. }
  114. }