VertexArray.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using OpenTK.Graphics.OpenGL;
  2. using Ryujinx.Graphics.GAL;
  3. using System;
  4. namespace Ryujinx.Graphics.OpenGL
  5. {
  6. class VertexArray : IDisposable
  7. {
  8. public int Handle { get; private set; }
  9. private bool _needsAttribsUpdate;
  10. private VertexBufferDescriptor[] _vertexBuffers;
  11. private VertexAttribDescriptor[] _vertexAttribs;
  12. public VertexArray()
  13. {
  14. Handle = GL.GenVertexArray();
  15. }
  16. public void Bind()
  17. {
  18. GL.BindVertexArray(Handle);
  19. }
  20. public void SetVertexBuffers(VertexBufferDescriptor[] vertexBuffers)
  21. {
  22. int bindingIndex = 0;
  23. foreach (VertexBufferDescriptor vb in vertexBuffers)
  24. {
  25. if (vb.Buffer.Buffer != null)
  26. {
  27. int bufferHandle = ((Buffer)vb.Buffer.Buffer).Handle;
  28. GL.BindVertexBuffer(bindingIndex, bufferHandle, (IntPtr)vb.Buffer.Offset, vb.Stride);
  29. GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
  30. }
  31. else
  32. {
  33. GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0);
  34. }
  35. bindingIndex++;
  36. }
  37. _vertexBuffers = vertexBuffers;
  38. _needsAttribsUpdate = true;
  39. }
  40. public void SetVertexAttributes(VertexAttribDescriptor[] vertexAttribs)
  41. {
  42. int attribIndex = 0;
  43. foreach (VertexAttribDescriptor attrib in vertexAttribs)
  44. {
  45. FormatInfo fmtInfo = FormatTable.GetFormatInfo(attrib.Format);
  46. if (attrib.IsZero)
  47. {
  48. // Disabling the attribute causes the shader to read a constant value.
  49. // The value is configurable, but by default is a vector of (0, 0, 0, 1).
  50. GL.DisableVertexAttribArray(attribIndex);
  51. }
  52. else
  53. {
  54. GL.EnableVertexAttribArray(attribIndex);
  55. }
  56. int offset = attrib.Offset;
  57. int size = fmtInfo.Components;
  58. bool isFloat = fmtInfo.PixelType == PixelType.Float ||
  59. fmtInfo.PixelType == PixelType.HalfFloat;
  60. if (isFloat || fmtInfo.Normalized || fmtInfo.Scaled)
  61. {
  62. VertexAttribType type = (VertexAttribType)fmtInfo.PixelType;
  63. GL.VertexAttribFormat(attribIndex, size, type, fmtInfo.Normalized, offset);
  64. }
  65. else
  66. {
  67. VertexAttribIntegerType type = (VertexAttribIntegerType)fmtInfo.PixelType;
  68. GL.VertexAttribIFormat(attribIndex, size, type, offset);
  69. }
  70. GL.VertexAttribBinding(attribIndex, attrib.BufferIndex);
  71. attribIndex++;
  72. }
  73. for (; attribIndex < 16; attribIndex++)
  74. {
  75. GL.DisableVertexAttribArray(attribIndex);
  76. }
  77. _vertexAttribs = vertexAttribs;
  78. }
  79. public void SetIndexBuffer(Buffer indexBuffer)
  80. {
  81. GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer?.Handle ?? 0);
  82. }
  83. public void Validate()
  84. {
  85. for (int attribIndex = 0; attribIndex < _vertexAttribs.Length; attribIndex++)
  86. {
  87. VertexAttribDescriptor attrib = _vertexAttribs[attribIndex];
  88. if ((uint)attrib.BufferIndex >= _vertexBuffers.Length)
  89. {
  90. GL.DisableVertexAttribArray(attribIndex);
  91. continue;
  92. }
  93. if (_vertexBuffers[attrib.BufferIndex].Buffer.Buffer == null)
  94. {
  95. GL.DisableVertexAttribArray(attribIndex);
  96. continue;
  97. }
  98. if (_needsAttribsUpdate && !attrib.IsZero)
  99. {
  100. GL.EnableVertexAttribArray(attribIndex);
  101. }
  102. }
  103. _needsAttribsUpdate = false;
  104. }
  105. public void Dispose()
  106. {
  107. if (Handle != 0)
  108. {
  109. GL.DeleteVertexArray(Handle);
  110. Handle = 0;
  111. }
  112. }
  113. }
  114. }