Change over draw call propagation in the vertex generator.

This commit is contained in:
H. Utku Maden 2022-08-18 13:58:03 +03:00
parent 7c0c6d9a75
commit a0473d9e83
2 changed files with 47 additions and 45 deletions

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
namespace Quik.VertexGenerator namespace Quik.VertexGenerator
{ {
@ -75,6 +76,8 @@ namespace Quik.VertexGenerator
/// </summary> /// </summary>
public int ElementCount => _elementBufferPointer; public int ElementCount => _elementBufferPointer;
public List<QuikDrawCall> DrawCalls { get; } = new List<QuikDrawCall>();
public float CurveGranularity { get; set; } = 0.2f; public float CurveGranularity { get; set; } = 0.2f;
public QuikContext Context { get; } public QuikContext Context { get; }
@ -168,76 +171,69 @@ namespace Quik.VertexGenerator
_vertexBufferPointer = 0; _vertexBufferPointer = 0;
_elementBufferPointer = 0; _elementBufferPointer = 0;
DrawCalls.Clear();
} }
private QuikDrawCall _call; public QuikDrawCall CallTemplate;
public event VertexGeneratorCommandHandler HandleCommand; public event VertexGeneratorCommandHandler HandleCommand;
protected virtual void OnHandleCommand(QuikVertexGenerator generator, QuikCommand command, ref QuikDrawCall? call) protected virtual bool OnHandleCommand(QuikVertexGenerator generator, QuikCommand command)
{ {
HandleCommand?.Invoke(generator, command, ref call); bool anyCalls = false;
HandleCommand?.Invoke(generator, command, ref anyCalls);
return anyCalls;
} }
public QuikDrawCall? ConsumeCommand(QuikCommand command) public void ConsumeCommand(QuikCommand command)
{ {
_call.Target = _renderStencilMask ? QuikRenderTarget.Stencil : QuikRenderTarget.Color; CallTemplate.Target = _renderStencilMask ? QuikRenderTarget.Stencil : QuikRenderTarget.Color;
QuikDrawCall call = _call;
switch (command.Type) switch (command.Type)
{ {
case QuikCommandType.Mask: case QuikCommandType.Mask:
_call.Bounds = ((QuikCommandMask)command).Bounds; CallTemplate.Bounds = ((QuikCommandMask)command).Bounds;
break; break;
case QuikCommandType.StencilMaskClear: case QuikCommandType.StencilMaskClear:
_call.ClearStencil = true; CallTemplate.ClearStencil = true;
break; break;
case QuikCommandType.StencilMaskBegin: case QuikCommandType.StencilMaskBegin:
_renderStencilMask = true; _renderStencilMask = true;
_call.Target = QuikRenderTarget.Stencil; CallTemplate.Target = QuikRenderTarget.Stencil;
break; break;
case QuikCommandType.StencilMaskEnd: case QuikCommandType.StencilMaskEnd:
_renderStencilMask = false; _renderStencilMask = false;
_call.Target = QuikRenderTarget.Color; CallTemplate.Target = QuikRenderTarget.Color;
break; break;
case QuikCommandType.Line: case QuikCommandType.Line:
RenderLine(ref call, command as QuikCommandLine); RenderLine(command as QuikCommandLine);
goto exit_with_call; goto exit_with_call;
case QuikCommandType.Lines: case QuikCommandType.Lines:
RenderLine(ref call, command as QuikCommandLines); RenderLine(command as QuikCommandLines);
goto exit_with_call; goto exit_with_call;
case QuikCommandType.Bezier: case QuikCommandType.Bezier:
RenderBezier(ref _call, command as QuikCommandBezier); RenderBezier(command as QuikCommandBezier);
goto exit_with_call; goto exit_with_call;
case QuikCommandType.Rectangle: case QuikCommandType.Rectangle:
RenderRectangles(ref call, command as QuikCommandRectangle); RenderRectangles(command as QuikCommandRectangle);
goto exit_with_call; goto exit_with_call;
case QuikCommandType.Rectangles: case QuikCommandType.Rectangles:
RenderRectangles(ref call, command as QuikCommandRectangles); RenderRectangles(command as QuikCommandRectangles);
goto exit_with_call; goto exit_with_call;
default: default:
{ {
QuikDrawCall? subcall = null; QuikDrawCall? subcall = null;
OnHandleCommand(this, command, ref subcall); if (OnHandleCommand(this, command))
if (subcall.HasValue)
{
call = subcall.Value;
goto exit_with_call; goto exit_with_call;
} break;
else
{
goto exit_without_call;
} }
} }
} return;
exit_without_call:
return null;
exit_with_call: exit_with_call:
_call.ClearStencil = false; CallTemplate.ClearStencil = false;
return call;
} }
#region Lines & Beziers #region Lines & Beziers
@ -563,7 +559,7 @@ namespace Quik.VertexGenerator
/// </summary> /// </summary>
/// <param name="call">The draw call to generate.</param> /// <param name="call">The draw call to generate.</param>
/// <param name="line">The line to draw.</param> /// <param name="line">The line to draw.</param>
private void RenderLine(ref QuikDrawCall call, QuikCommandLine line) private void RenderLine(QuikCommandLine line)
{ {
// Skip over stipple patterns for now. // Skip over stipple patterns for now.
QuikStrokeStyle style = line.Style ?? Context.DefaultStroke; QuikStrokeStyle style = line.Style ?? Context.DefaultStroke;
@ -582,8 +578,10 @@ namespace Quik.VertexGenerator
GenerateEndCap(baseVertex, line.Line.End, normal, style.Width, endCapResolution, (short) (startOffset + 2),(short) GenerateEndCap(baseVertex, line.Line.End, normal, style.Width, endCapResolution, (short) (startOffset + 2),(short)
(startOffset + 3)); (startOffset + 3));
QuikDrawCall call = CallTemplate;
call.Offset = (short) (startOffset * 2); call.Offset = (short) (startOffset * 2);
call.Count = (short) (_elementBufferPointer - startOffset); call.Count = (short) (_elementBufferPointer - startOffset);
DrawCalls.Add(call);
} }
/// <summary> /// <summary>
@ -591,7 +589,7 @@ namespace Quik.VertexGenerator
/// </summary> /// </summary>
/// <param name="call">The draw call to generate.</param> /// <param name="call">The draw call to generate.</param>
/// <param name="lines">The lines command.</param> /// <param name="lines">The lines command.</param>
private void RenderLine(ref QuikDrawCall call, QuikCommandLines lines) private void RenderLine(QuikCommandLines lines)
{ {
// Skip over stipple patterns for now. // Skip over stipple patterns for now.
QuikStrokeStyle style = lines.Style ?? Context.DefaultStroke; QuikStrokeStyle style = lines.Style ?? Context.DefaultStroke;
@ -644,11 +642,13 @@ namespace Quik.VertexGenerator
lastStartIndex = lineStartIndex; lastStartIndex = lineStartIndex;
} }
QuikDrawCall call = CallTemplate;
call.Offset = (short) (startOffset * 2); call.Offset = (short) (startOffset * 2);
call.Count = (short) (_elementBufferPointer - startOffset); call.Count = (short) (_elementBufferPointer - startOffset);
DrawCalls.Add(call);
} }
private void RenderBezier(ref QuikDrawCall call, QuikCommandBezier bezier) private void RenderBezier(QuikCommandBezier bezier)
{ {
QuikStrokeStyle style = bezier.Style ?? Context.DefaultStroke; QuikStrokeStyle style = bezier.Style ?? Context.DefaultStroke;
QuikVertex baseVertex = new QuikVertex() { Color = style.Color }; QuikVertex baseVertex = new QuikVertex() { Color = style.Color };
@ -715,8 +715,10 @@ namespace Quik.VertexGenerator
lastEndNegative = endNegative; lastEndNegative = endNegative;
} }
QuikDrawCall call = CallTemplate;
call.Offset = (short) (startOffset * 2); call.Offset = (short) (startOffset * 2);
call.Count = (short) (_elementBufferPointer - startOffset); call.Count = (short) (_elementBufferPointer - startOffset);
DrawCalls.Add(call);
} }
private void GenerateBezierSegment( private void GenerateBezierSegment(
@ -780,7 +782,7 @@ namespace Quik.VertexGenerator
#region Rectangles #region Rectangles
private void RenderRectangles(ref QuikDrawCall call, QuikCommandRectangle rectangle) private void RenderRectangles(QuikCommandRectangle rectangle)
{ {
QuikStrokeStyle stroke = rectangle.StrokeStyle ?? Context.DefaultStroke; QuikStrokeStyle stroke = rectangle.StrokeStyle ?? Context.DefaultStroke;
QuikFillStyle fill = rectangle.FillStyle ?? Context.DefaultFill; QuikFillStyle fill = rectangle.FillStyle ?? Context.DefaultFill;
@ -789,8 +791,10 @@ namespace Quik.VertexGenerator
GenerateRectangle(rectangle.Rectangle, stroke, fill, rectangle.CornerRadius); GenerateRectangle(rectangle.Rectangle, stroke, fill, rectangle.CornerRadius);
QuikDrawCall call = CallTemplate;
call.Offset = (short) (start * 2); call.Offset = (short) (start * 2);
call.Count = (short) (_elementBufferPointer - start); call.Count = (short) (_elementBufferPointer - start);
DrawCalls.Add(call);
} }
private void GenerateRectangle(QuikRectangle rectangle, QuikStrokeStyle stroke, QuikFillStyle fill, float cornerRadius) private void GenerateRectangle(QuikRectangle rectangle, QuikStrokeStyle stroke, QuikFillStyle fill, float cornerRadius)
@ -1370,7 +1374,7 @@ namespace Quik.VertexGenerator
); );
} }
private void RenderRectangles(ref QuikDrawCall call, QuikCommandRectangles rectangles) private void RenderRectangles(QuikCommandRectangles rectangles)
{ {
QuikStrokeStyle stroke = rectangles.StrokeStyle ?? Context.DefaultStroke; QuikStrokeStyle stroke = rectangles.StrokeStyle ?? Context.DefaultStroke;
QuikFillStyle fill = rectangles.FillStyle ?? Context.DefaultFill; QuikFillStyle fill = rectangles.FillStyle ?? Context.DefaultFill;
@ -1382,14 +1386,16 @@ namespace Quik.VertexGenerator
GenerateRectangle(rectangles.Rectangles[i], stroke, fill, rectangles.CornerRadius); GenerateRectangle(rectangles.Rectangles[i], stroke, fill, rectangles.CornerRadius);
} }
QuikDrawCall call = CallTemplate;
call.Offset = (short) (start * 2); call.Offset = (short) (start * 2);
call.Count = (short) (_elementBufferPointer - start); call.Count = (short) (_elementBufferPointer - start);
DrawCalls.Add(call);
} }
#endregion #endregion
} }
public delegate void VertexGeneratorCommandHandler(QuikVertexGenerator generator, QuikCommand command, ref QuikDrawCall? call); public delegate void VertexGeneratorCommandHandler(QuikVertexGenerator generator, QuikCommand command, ref bool anyCalls);
public enum QuikRenderTarget public enum QuikRenderTarget
{ {

@ -114,7 +114,6 @@ void main()
loc = GL.GetUniformLocation(sp, "matrix"); loc = GL.GetUniformLocation(sp, "matrix");
List<QuikDrawCall> calls = new List<QuikDrawCall>();
int i = 0; int i = 0;
QuikStrokeStyle strokeBorder = new QuikStrokeStyle() QuikStrokeStyle strokeBorder = new QuikStrokeStyle()
@ -203,29 +202,26 @@ void main()
QuikCommand command; QuikCommand command;
while (context.Draw.Commands.TryDequeue(out command)) while (context.Draw.Commands.TryDequeue(out command))
{ {
QuikDrawCall? call = gen.ConsumeCommand(command); gen.ConsumeCommand(command);
if (call.HasValue) calls.Add(call.Value);
} }
GL.BufferData(BufferTarget.ArrayBuffer, gen.VertexCount * QuikVertex.Stride, ref gen.VertexBuffer[0], BufferUsageHint.StreamDraw); GL.BufferData(BufferTarget.ArrayBuffer, gen.VertexCount * QuikVertex.Stride, ref gen.VertexBuffer[0], BufferUsageHint.StreamDraw);
GL.BufferData(BufferTarget.ElementArrayBuffer, gen.ElementCount * 2, ref gen.ElementBuffer[0], BufferUsageHint.StreamDraw); GL.BufferData(BufferTarget.ElementArrayBuffer, gen.ElementCount * 2, ref gen.ElementBuffer[0], BufferUsageHint.StreamDraw);
foreach (QuikDrawCall call in calls) foreach (QuikDrawCall call in gen.DrawCalls)
{ {
GL.DrawElements(BeginMode.Triangles, call.Count, DrawElementsType.UnsignedShort, call.Offset); GL.DrawElements(BeginMode.Triangles, call.Count, DrawElementsType.UnsignedShort, call.Offset);
} }
int callCount = gen.DrawCalls.Count;
gen.Clear(); gen.Clear();
calls.Clear();
if (++i % 60 == 0) if (++i % 60 == 0)
{ {
Console.WriteLine("Vertex Usage: {0} ; Element Usage: {1}", gen.VertexUsage, gen.ElementUsage); Console.WriteLine("Vertex Usage: {0} ; Element Usage: {1} Calls: {2}", gen.VertexUsage, gen.ElementUsage, callCount);
} }
window.Context.SwapBuffers(); window.Context.SwapBuffers();
} }
} }
} }