Add new draw call recorder class.
This commit is contained in:
		
							parent
							
								
									57620f5d5c
								
							
						
					
					
						commit
						afa6ed4f4c
					
				| @ -1,3 +1,4 @@ | ||||
| using System.Diagnostics.Contracts; | ||||
| using System.Runtime.CompilerServices; | ||||
| using System.Runtime.InteropServices; | ||||
| using OpenTK.Graphics.OpenGL; | ||||
| @ -224,4 +225,243 @@ namespace Dashboard.Drawing.OpenGL | ||||
|             public int CmdIndex; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /// <summary> | ||||
|     /// A customizable immediate mode draw call queue, for the modern OpenGL user. | ||||
|     /// </summary> | ||||
|     /// <typeparam name="TCall">The call info type.</typeparam> | ||||
|     /// <typeparam name="TVertex">The vertex structure.</typeparam> | ||||
|     public abstract class DrawCallRecorder<TCall, TVertex> : IGLDisposable, IInitializer | ||||
|         where TVertex : unmanaged | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// The vertex array for this queue. | ||||
|         /// </summary> | ||||
|         public int Vao { get; private set; } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The vertex buffer for this queue. | ||||
|         /// </summary> | ||||
|         public int Vbo { get; private set; } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Number of calls recorded in this queue. | ||||
|         /// </summary> | ||||
|         public int CallCount => Calls.Count; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The number of total vertices recorded. | ||||
|         /// </summary> | ||||
|         public int TotalVertices => Vertices.Count; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The latest draw call info. | ||||
|         /// </summary> | ||||
|         public ref TCall CurrentCall => ref _currentCall; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The latest vertex emitted. | ||||
|         /// </summary> | ||||
|         public ref TVertex CurrentVertex => ref _currentVertex; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// True if currently recording a draw call. | ||||
|         /// </summary> | ||||
|         public bool InCall => _primitiveMode != 0; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Size of one vertex. | ||||
|         /// </summary> | ||||
|         protected int VertexSize => Unsafe.SizeOf<TVertex>(); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The list of draw calls. | ||||
|         /// </summary> | ||||
|         protected List<DrawCall> Calls { get; } = new List<DrawCall>(); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The list of all vertices. | ||||
|         /// </summary> | ||||
|         protected List<TVertex> Vertices { get; } = new List<TVertex>(); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The value to write for the draw call info at the start of a call. | ||||
|         /// </summary> | ||||
|         [Pure] protected virtual TCall DefaultCall => default(TCall); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// The value to write for last vertex at the start of a call. | ||||
|         /// </summary> | ||||
|         [Pure] protected virtual TVertex DefaultVertex => default; | ||||
| 
 | ||||
|         private int _start = 0; | ||||
|         private int _count = 0; | ||||
|         private int _primitiveMode = 0; | ||||
|         private TCall _currentCall; | ||||
|         private TVertex _currentVertex; | ||||
| 
 | ||||
|         protected DrawCallRecorder() | ||||
|         { | ||||
|             _currentCall = DefaultCall; | ||||
|             _currentVertex = DefaultVertex; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Record a draw call directly. | ||||
|         /// </summary> | ||||
|         /// <param name="type">The primitive type to use.</param> | ||||
|         /// <param name="callInfo">The call info structure to use</param> | ||||
|         /// <param name="vertices">The list of vertices to use.</param> | ||||
|         /// <exception cref="InvalidOperationException">You attempted to use this function during another draw call.</exception> | ||||
|         public void DrawArrays(PrimitiveType type, in TCall callInfo, ReadOnlySpan<TVertex> vertices) | ||||
|         { | ||||
|             if (InCall) | ||||
|                 throw new InvalidOperationException("Cannot use draw arrays in the middle of an ongoing immediate-mode call."); | ||||
| 
 | ||||
|             DrawCall call = new DrawCall() | ||||
|             { | ||||
|                 Type = type, | ||||
|                 Start = Vertices.Count, | ||||
|                 Count = vertices.Length, | ||||
|                 CallInfo = callInfo, | ||||
|             }; | ||||
| 
 | ||||
|             Vertices.AddRange(vertices); | ||||
|             Calls.Add(call); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Start a draw call. | ||||
|         /// </summary> | ||||
|         /// <param name="type">The primitive type for the call.</param> | ||||
|         public void Begin(PrimitiveType type) => Begin(type, DefaultCall); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Start a draw call. | ||||
|         /// </summary> | ||||
|         /// <param name="type">The primitive type for the call.</param> | ||||
|         /// <param name="callInfo">The call info.</param> | ||||
|         /// <exception cref="InvalidOperationException">You attempted to create a draw call within a draw call.</exception> | ||||
|         public void Begin(PrimitiveType type, TCall callInfo) | ||||
|         { | ||||
|             if (InCall) | ||||
|                 throw new InvalidOperationException("Attempt to begin new draw call before finishing previous one."); | ||||
| 
 | ||||
|             _primitiveMode = (int)type; | ||||
|             _start = Vertices.Count; | ||||
|             _count = 0; | ||||
|             CurrentCall = callInfo; | ||||
|             CurrentVertex = DefaultVertex; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Emit the latest or modified vertex. | ||||
|         /// </summary> | ||||
|         public void Vertex() | ||||
|         { | ||||
|             Vertex(CurrentVertex); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Emit a vertex. | ||||
|         /// </summary> | ||||
|         /// <param name="vertex">The vertex to emit.</param> | ||||
|         public void Vertex(in TVertex vertex) | ||||
|         { | ||||
|             Vertices.Add(CurrentVertex = vertex); | ||||
|             _count++; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// End the current call. | ||||
|         /// </summary> | ||||
|         /// <exception cref="InvalidOperationException">You tried to end a call that you didn't begin recording.</exception> | ||||
|         public void End() | ||||
|         { | ||||
|             if (!InCall) | ||||
|                 throw new InvalidOperationException("Attempt to end draw call before starting one."); | ||||
| 
 | ||||
|             Calls.Add(new DrawCall() | ||||
|             { | ||||
|                 Start = _start, | ||||
|                 Count = _count, | ||||
|                 Type = (PrimitiveType)_primitiveMode, | ||||
|                 CallInfo = CurrentCall, | ||||
|             }); | ||||
| 
 | ||||
|             _primitiveMode = 0; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Called by the execution engine before a draw call is executed. | ||||
|         /// </summary> | ||||
|         /// <param name="call">The call to prepare.</param> | ||||
|         protected abstract void PrepareCall(in TCall call); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Set the vertex format for the <see cref="Vao"/> and <see cref="Vbo"/> created by the recorder. | ||||
|         /// </summary> | ||||
|         protected abstract void SetVertexFormat(); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Execute all the recorded draw calls. | ||||
|         /// </summary> | ||||
|         public void Execute() | ||||
|         { | ||||
|             GL.BindVertexArray(Vao); | ||||
|             GL.BindBuffer(BufferTarget.ArrayBuffer, Vbo); | ||||
| 
 | ||||
|             ReadOnlySpan<TVertex> vertices = CollectionsMarshal.AsSpan(Vertices); | ||||
|             GL.BufferData(BufferTarget.ArrayBuffer, Vertices.Count * VertexSize, vertices, BufferUsage.DynamicDraw); | ||||
| 
 | ||||
|             foreach (DrawCall call in Calls) | ||||
|             { | ||||
|                 PrepareCall(call.CallInfo); | ||||
|                 GL.DrawArrays(call.Type, call.Start, call.Count); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Clear the draw call queue. | ||||
|         /// </summary> | ||||
|         public void Clear() | ||||
|         { | ||||
|             Vertices.Clear(); | ||||
|             Calls.Clear(); | ||||
|         } | ||||
| 
 | ||||
|         public void Dispose() | ||||
|         { | ||||
|             throw new NotImplementedException(); | ||||
|         } | ||||
| 
 | ||||
|         public void Dispose(bool safeExit) | ||||
|         { | ||||
|             throw new NotImplementedException(); | ||||
|         } | ||||
| 
 | ||||
|         public bool IsInitialized { get; private set; } | ||||
|         public void Initialize() | ||||
|         { | ||||
|             if (IsInitialized) | ||||
|                 return; | ||||
|             IsInitialized = true; | ||||
| 
 | ||||
|             Vao = GL.CreateVertexArray(); | ||||
|             Vbo = GL.CreateBuffer(); | ||||
| 
 | ||||
|             GL.BindVertexArray(Vao); | ||||
|             GL.BindBuffer(BufferTarget.ArrayBuffer, Vbo); | ||||
| 
 | ||||
|             SetVertexFormat(); | ||||
|         } | ||||
| 
 | ||||
|         protected struct DrawCall | ||||
|         { | ||||
|             public PrimitiveType Type; | ||||
|             public int Start; | ||||
|             public int Count; | ||||
|             public TCall CallInfo; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user