/ src / Ryujinx.Graphics.Gpu / Engine / Threed / ComputeDraw / VertexInfoBufferUpdater.cs
VertexInfoBufferUpdater.cs
  1  using Ryujinx.Graphics.GAL;
  2  using Ryujinx.Graphics.Gpu.Memory;
  3  using Ryujinx.Graphics.Shader;
  4  using System.Runtime.CompilerServices;
  5  using System.Runtime.InteropServices;
  6  
  7  namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
  8  {
  9      /// <summary>
 10      /// Vertex info buffer data updater.
 11      /// </summary>
 12      class VertexInfoBufferUpdater : BufferUpdater
 13      {
 14          private VertexInfoBuffer _data;
 15  
 16          /// <summary>
 17          /// Creates a new instance of the vertex info buffer updater.
 18          /// </summary>
 19          /// <param name="renderer">Renderer that the vertex info buffer will be used with</param>
 20          public VertexInfoBufferUpdater(IRenderer renderer) : base(renderer)
 21          {
 22          }
 23  
 24          /// <summary>
 25          /// Sets vertex data related counts.
 26          /// </summary>
 27          /// <param name="vertexCount">Number of vertices used on the draw</param>
 28          /// <param name="instanceCount">Number of draw instances</param>
 29          /// <param name="firstVertex">Index of the first vertex on the vertex buffer</param>
 30          /// <param name="firstInstance">Index of the first instanced vertex on the vertex buffer</param>
 31          public void SetVertexCounts(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
 32          {
 33              if (_data.VertexCounts.X != vertexCount)
 34              {
 35                  _data.VertexCounts.X = vertexCount;
 36                  MarkDirty(VertexInfoBuffer.VertexCountsOffset, sizeof(int));
 37              }
 38  
 39              if (_data.VertexCounts.Y != instanceCount)
 40              {
 41                  _data.VertexCounts.Y = instanceCount;
 42                  MarkDirty(VertexInfoBuffer.VertexCountsOffset + sizeof(int), sizeof(int));
 43              }
 44  
 45              if (_data.VertexCounts.Z != firstVertex)
 46              {
 47                  _data.VertexCounts.Z = firstVertex;
 48                  MarkDirty(VertexInfoBuffer.VertexCountsOffset + sizeof(int) * 2, sizeof(int));
 49              }
 50  
 51              if (_data.VertexCounts.W != firstInstance)
 52              {
 53                  _data.VertexCounts.W = firstInstance;
 54                  MarkDirty(VertexInfoBuffer.VertexCountsOffset + sizeof(int) * 3, sizeof(int));
 55              }
 56          }
 57  
 58          /// <summary>
 59          /// Sets vertex data related counts.
 60          /// </summary>
 61          /// <param name="primitivesCount">Number of primitives consumed by the geometry shader</param>
 62          public void SetGeometryCounts(int primitivesCount)
 63          {
 64              if (_data.GeometryCounts.X != primitivesCount)
 65              {
 66                  _data.GeometryCounts.X = primitivesCount;
 67                  MarkDirty(VertexInfoBuffer.GeometryCountsOffset, sizeof(int));
 68              }
 69          }
 70  
 71          /// <summary>
 72          /// Sets a vertex stride and related data.
 73          /// </summary>
 74          /// <param name="index">Index of the vertex stride to be updated</param>
 75          /// <param name="stride">Stride divided by the component or format size</param>
 76          /// <param name="componentCount">Number of components that the format has</param>
 77          public void SetVertexStride(int index, int stride, int componentCount)
 78          {
 79              if (_data.VertexStrides[index].X != stride)
 80              {
 81                  _data.VertexStrides[index].X = stride;
 82                  MarkDirty(VertexInfoBuffer.VertexStridesOffset + index * Unsafe.SizeOf<Vector4<int>>(), sizeof(int));
 83              }
 84  
 85              for (int c = 1; c < 4; c++)
 86              {
 87                  int value = c < componentCount ? 1 : 0;
 88  
 89                  ref int currentValue = ref GetElementRef(ref _data.VertexStrides[index], c);
 90  
 91                  if (currentValue != value)
 92                  {
 93                      currentValue = value;
 94                      MarkDirty(VertexInfoBuffer.VertexStridesOffset + index * Unsafe.SizeOf<Vector4<int>>() + c * sizeof(int), sizeof(int));
 95                  }
 96              }
 97          }
 98  
 99          /// <summary>
100          /// Sets a vertex offset and related data.
101          /// </summary>
102          /// <param name="index">Index of the vertex offset to be updated</param>
103          /// <param name="offset">Offset divided by the component or format size</param>
104          /// <param name="divisor">If the draw is instanced, should have the vertex divisor value, otherwise should be zero</param>
105          public void SetVertexOffset(int index, int offset, int divisor)
106          {
107              if (_data.VertexOffsets[index].X != offset)
108              {
109                  _data.VertexOffsets[index].X = offset;
110                  MarkDirty(VertexInfoBuffer.VertexOffsetsOffset + index * Unsafe.SizeOf<Vector4<int>>(), sizeof(int));
111              }
112  
113              if (_data.VertexOffsets[index].Y != divisor)
114              {
115                  _data.VertexOffsets[index].Y = divisor;
116                  MarkDirty(VertexInfoBuffer.VertexOffsetsOffset + index * Unsafe.SizeOf<Vector4<int>>() + sizeof(int), sizeof(int));
117              }
118          }
119  
120          /// <summary>
121          /// Sets the offset of the index buffer.
122          /// </summary>
123          /// <param name="offset">Offset divided by the component size</param>
124          public void SetIndexBufferOffset(int offset)
125          {
126              if (_data.GeometryCounts.W != offset)
127              {
128                  _data.GeometryCounts.W = offset;
129                  MarkDirty(VertexInfoBuffer.GeometryCountsOffset + sizeof(int) * 3, sizeof(int));
130              }
131          }
132  
133          /// <summary>
134          /// Submits all pending buffer updates to the GPU.
135          /// </summary>
136          public void Commit()
137          {
138              Commit(MemoryMarshal.Cast<VertexInfoBuffer, byte>(MemoryMarshal.CreateSpan(ref _data, 1)));
139          }
140      }
141  }