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 }