Remove EventList as a concept

This commit is contained in:
Dan Balasescu
2024-03-09 20:24:55 +09:00
parent 9346cf7719
commit f2b5b694fe
4 changed files with 56 additions and 233 deletions

View File

@@ -1,8 +1,8 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using osu.Framework.Graphics.Rendering.Deferred;
using osu.Framework.Graphics.Rendering.Deferred.Allocation;
using osu.Framework.Graphics.Rendering.Deferred.Events;
@@ -12,71 +12,65 @@ namespace osu.Framework.Benchmarks
{
// Used for benchmark-local testing.
private ResourceAllocator localAllocator = null!;
private EventList localEventList = null!;
private List<RenderEvent> localEventList = null!;
// Used for benchmark-static testing.
// 0: Basic events
// 1: Events with data
// 2: Mixed events
private readonly (ResourceAllocator allocator, EventList list)[] staticItems = new (ResourceAllocator allocator, EventList list)[3];
private readonly (ResourceAllocator allocator, List<RenderEvent> list)[] staticItems = new (ResourceAllocator allocator, List<RenderEvent> list)[3];
[GlobalSetup]
public void GlobalSetup()
{
localAllocator = new ResourceAllocator();
localEventList = new EventList();
localEventList = new List<RenderEvent>();
for (int i = 0; i < staticItems.Length; i++)
{
ResourceAllocator allocator = new ResourceAllocator();
staticItems[i] = (allocator, new EventList());
staticItems[i] = (allocator, new List<RenderEvent>());
}
for (int i = 0; i < 10000; i++)
{
staticItems[0].list.Enqueue(RenderEvent.Init(new FlushEvent(new ResourceReference(1), 10)));
staticItems[1].list.Enqueue(RenderEvent.Init(new AddPrimitiveToBatchEvent(new ResourceReference(0), staticItems[1].allocator.AllocateRegion(1024))));
if (i % 2 == 0)
staticItems[2].list.Enqueue(RenderEvent.Init(new FlushEvent(new ResourceReference(1), 10)));
else
staticItems[2].list.Enqueue(RenderEvent.Init(new AddPrimitiveToBatchEvent(new ResourceReference(0), staticItems[2].allocator.AllocateRegion(1024))));
staticItems[0].list.Add(RenderEvent.Init(new FlushEvent(new ResourceReference(1), 10)));
staticItems[1].list.Add(RenderEvent.Init(new AddPrimitiveToBatchEvent(new ResourceReference(0), staticItems[1].allocator.AllocateRegion(1024))));
staticItems[2].list.Add(i % 2 == 0
? RenderEvent.Init(new FlushEvent(new ResourceReference(1), 10))
: RenderEvent.Init(new AddPrimitiveToBatchEvent(new ResourceReference(0), staticItems[2].allocator.AllocateRegion(1024))));
}
}
[Benchmark]
public void Write()
{
localEventList.NewFrame();
localAllocator.NewFrame();
for (int i = 0; i < 10000; i++)
localEventList.Enqueue(RenderEvent.Init(new FlushEvent()));
localEventList.Add(RenderEvent.Init(new FlushEvent()));
}
[Benchmark]
public void WriteWithData()
{
localEventList.NewFrame();
localAllocator.NewFrame();
for (int i = 0; i < 10000; i++)
localEventList.Enqueue(RenderEvent.Init(new AddPrimitiveToBatchEvent(new ResourceReference(0), localAllocator.AllocateRegion(1024))));
localEventList.Add(RenderEvent.Init(new AddPrimitiveToBatchEvent(new ResourceReference(0), localAllocator.AllocateRegion(1024))));
}
[Benchmark]
public int Read()
{
var enumerator = staticItems[0].list.CreateEnumerator();
int totalVertices = 0;
while (enumerator.Next())
foreach (var renderEvent in staticItems[0].list)
{
switch (enumerator.Current().Type)
switch (renderEvent.Type)
{
case RenderEventType.Flush:
enumerator.Current().Decompose(out FlushEvent e);
renderEvent.Decompose(out FlushEvent e);
totalVertices += e.VertexCount;
break;
}
@@ -88,16 +82,14 @@ namespace osu.Framework.Benchmarks
[Benchmark]
public int ReadWithData()
{
var enumerator = staticItems[1].list.CreateEnumerator();
int data = 0;
while (enumerator.Next())
foreach (var renderEvent in staticItems[1].list)
{
switch (enumerator.Current().Type)
switch (renderEvent.Type)
{
case RenderEventType.AddPrimitiveToBatch:
enumerator.Current().Decompose(out AddPrimitiveToBatchEvent e);
renderEvent.Decompose(out AddPrimitiveToBatchEvent e);
foreach (byte b in staticItems[1].allocator.GetRegion(e.Memory))
data += b;
break;
@@ -110,24 +102,22 @@ namespace osu.Framework.Benchmarks
[Benchmark]
public int ReadMixed()
{
var enumerator = staticItems[2].list.CreateEnumerator();
int data = 0;
while (enumerator.Next())
foreach (var renderEvent in staticItems[2].list)
{
switch (enumerator.Current().Type)
switch (renderEvent.Type)
{
case RenderEventType.Flush:
{
enumerator.Current().Decompose(out FlushEvent e);
renderEvent.Decompose(out FlushEvent e);
data += e.VertexCount;
break;
}
case RenderEventType.AddPrimitiveToBatch:
{
enumerator.Current().Decompose(out AddPrimitiveToBatchEvent e);
renderEvent.Decompose(out AddPrimitiveToBatchEvent e);
foreach (byte b in staticItems[2].allocator.GetRegion(e.Memory))
data += b;
break;
@@ -137,92 +127,5 @@ namespace osu.Framework.Benchmarks
return data;
}
[Benchmark]
public int ReplaceSame()
{
localEventList.NewFrame();
localAllocator.NewFrame();
localEventList.Enqueue(RenderEvent.Init(new FlushEvent()));
localEventList.Enqueue(RenderEvent.Init(new FlushEvent()));
localEventList.Enqueue(RenderEvent.Init(new FlushEvent()));
var enumerator = localEventList.CreateEnumerator();
enumerator.Next();
enumerator.Next();
enumerator.Replace(RenderEvent.Init(new FlushEvent()));
int i = 0;
enumerator = localEventList.CreateEnumerator();
while (enumerator.Next())
{
enumerator.Current();
i++;
}
localAllocator.NewFrame();
return i;
}
[Benchmark]
public int ReplaceSmaller()
{
localEventList.NewFrame();
localAllocator.NewFrame();
localEventList.Enqueue(RenderEvent.Init(new FlushEvent()));
localEventList.Enqueue(RenderEvent.Init(new FlushEvent()));
localEventList.Enqueue(RenderEvent.Init(new FlushEvent()));
var enumerator = localEventList.CreateEnumerator();
enumerator.Next();
enumerator.Next();
enumerator.Replace(RenderEvent.Init(new SetScissorStateEvent()));
int i = 0;
enumerator = localEventList.CreateEnumerator();
while (enumerator.Next())
{
enumerator.Current();
i++;
}
localAllocator.NewFrame();
return i;
}
[Benchmark]
public int ReplaceBigger()
{
localEventList.NewFrame();
localAllocator.NewFrame();
localEventList.Enqueue(RenderEvent.Init(new FlushEvent()));
localEventList.Enqueue(RenderEvent.Init(new FlushEvent()));
localEventList.Enqueue(RenderEvent.Init(new FlushEvent()));
var enumerator = localEventList.CreateEnumerator();
enumerator.Next();
enumerator.Next();
enumerator.Replace(RenderEvent.Init(new SetUniformBufferDataEvent()));
int i = 0;
enumerator = localEventList.CreateEnumerator();
while (enumerator.Next())
{
enumerator.Current();
i++;
}
localAllocator.NewFrame();
return i;
}
}
}

View File

@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using osu.Framework.Graphics.Rendering.Deferred.Allocation;
using osu.Framework.Graphics.Rendering.Deferred.Events;
using osu.Framework.Graphics.Veldrid.Pipelines;
@@ -17,9 +18,10 @@ namespace osu.Framework.Graphics.Rendering.Deferred
public GraphicsPipeline Graphics
=> Renderer.Graphics;
public readonly List<RenderEvent> RenderEvents = new List<RenderEvent>();
public readonly DeferredRenderer Renderer;
public readonly ResourceAllocator Allocator;
public readonly EventList RenderEvents;
public readonly UniformBufferManager UniformBufferManager;
public readonly VertexManager VertexManager;
@@ -27,15 +29,14 @@ namespace osu.Framework.Graphics.Rendering.Deferred
{
Renderer = renderer;
Allocator = new ResourceAllocator();
RenderEvents = new EventList();
UniformBufferManager = new UniformBufferManager(this);
VertexManager = new VertexManager(this);
}
public void NewFrame()
{
RenderEvents.Clear();
Allocator.NewFrame();
RenderEvents.NewFrame();
UniformBufferManager.NewFrame();
VertexManager.Reset();
}
@@ -101,6 +102,6 @@ namespace osu.Framework.Graphics.Rendering.Deferred
/// </summary>
/// <param name="renderEvent">The render event.</param>
public void EnqueueEvent(in RenderEvent renderEvent)
=> RenderEvents.Enqueue(renderEvent);
=> RenderEvents.Add(renderEvent);
}
}

View File

@@ -1,77 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Framework.Graphics.Rendering.Deferred.Events;
namespace osu.Framework.Graphics.Rendering.Deferred
{
internal class EventList
{
private readonly List<RenderEvent> events = new List<RenderEvent>();
/// <summary>
/// Prepares this <see cref="EventList"/> for a new frame.
/// </summary>
public void NewFrame()
=> events.Clear();
/// <summary>
/// Enqueues a render event to the list.
/// </summary>
/// <param name="renderEvent">The render event.</param>
public void Enqueue(RenderEvent renderEvent)
=> events.Add(renderEvent);
/// <summary>
/// Creates a reader of this <see cref="EventList"/>.
/// </summary>
/// <returns>The <see cref="Enumerator"/>.</returns>
public Enumerator CreateEnumerator()
=> new Enumerator(this);
/// <summary>
/// Reads an <see cref="EventList"/>. Semantically, this is very similar to <see cref="IEnumerator{T}"/>.
/// </summary>
internal ref struct Enumerator
{
private readonly EventList list;
private int eventIndex;
private RenderEvent currentEvent;
public Enumerator(EventList list)
{
this.list = list;
eventIndex = 0;
}
/// <summary>
/// Advances to the next (or first) event in the list.
/// </summary>
/// <returns>Whether an event can be read.</returns>
public bool Next()
{
if (eventIndex < list.events.Count)
{
currentEvent = list.events[eventIndex];
eventIndex++;
return true;
}
return false;
}
public RenderEvent Current() => currentEvent;
/// <summary>
/// Replaces the current event with a new one.
/// </summary>
/// <param name="newEvent">The new render event.</param>
public void Replace(RenderEvent newEvent)
{
list.events[eventIndex - 1] = newEvent;
}
}
}
}

View File

@@ -38,21 +38,19 @@ namespace osu.Framework.Graphics.Rendering.Deferred
if (string.IsNullOrEmpty(FrameworkEnvironment.DeferredRendererEventsOutputPath))
return;
EventList.Enumerator enumerator = context.RenderEvents.CreateEnumerator();
StringBuilder builder = new StringBuilder();
int indent = 0;
while (enumerator.Next())
foreach (var renderEvent in context.RenderEvents)
{
string info;
int indentChange = 0;
switch (enumerator.Current().Type)
switch (renderEvent.Type)
{
case RenderEventType.DrawNodeAction:
{
enumerator.Current().Decompose(out DrawNodeActionEvent e);
renderEvent.Decompose(out DrawNodeActionEvent e);
info = $"DrawNode.{e.Action} ({context.Dereference<DrawNode>(e.DrawNode)})";
@@ -72,7 +70,7 @@ namespace osu.Framework.Graphics.Rendering.Deferred
default:
{
info = $"{enumerator.Current().Type.ToString()}";
info = $"{renderEvent.Type.ToString()}";
break;
}
}
@@ -87,15 +85,15 @@ namespace osu.Framework.Graphics.Rendering.Deferred
private void processUploads()
{
EventList.Enumerator enumerator = context.RenderEvents.CreateEnumerator();
while (enumerator.Next())
for (int i = 0; i < context.RenderEvents.Count; i++)
{
switch (enumerator.Current().Type)
var renderEvent = context.RenderEvents[i];
switch (renderEvent.Type)
{
case RenderEventType.AddPrimitiveToBatch:
{
enumerator.Current().Decompose(out AddPrimitiveToBatchEvent e);
renderEvent.Decompose(out AddPrimitiveToBatchEvent e);
IDeferredVertexBatch batch = context.Dereference<IDeferredVertexBatch>(e.VertexBatch);
batch.Write(e.Memory);
break;
@@ -103,16 +101,16 @@ namespace osu.Framework.Graphics.Rendering.Deferred
case RenderEventType.SetUniformBufferData:
{
enumerator.Current().Decompose(out SetUniformBufferDataEvent e);
renderEvent.Decompose(out SetUniformBufferDataEvent e);
IDeferredUniformBuffer buffer = context.Dereference<IDeferredUniformBuffer>(e.Buffer);
UniformBufferReference range = buffer.Write(e.Data.Memory);
enumerator.Replace(RenderEvent.Init(e with { Data = new UniformBufferData(range) }));
context.RenderEvents[i] = RenderEvent.Init(e with { Data = new UniformBufferData(range) });
break;
}
case RenderEventType.SetShaderStorageBufferObjectData:
{
enumerator.Current().Decompose(out SetShaderStorageBufferObjectDataEvent e);
renderEvent.Decompose(out SetShaderStorageBufferObjectDataEvent e);
IDeferredShaderStorageBufferObject buffer = context.Dereference<IDeferredShaderStorageBufferObject>(e.Buffer);
buffer.Write(e.Index, e.Memory);
break;
@@ -126,113 +124,111 @@ namespace osu.Framework.Graphics.Rendering.Deferred
private void processEvents()
{
EventList.Enumerator enumerator = context.RenderEvents.CreateEnumerator();
while (enumerator.Next())
foreach (var renderEvent in context.RenderEvents)
{
switch (enumerator.Current().Type)
switch (renderEvent.Type)
{
case RenderEventType.SetFrameBuffer:
{
enumerator.Current().Decompose(out SetFrameBufferEvent e);
renderEvent.Decompose(out SetFrameBufferEvent e);
processEvent(e);
break;
}
case RenderEventType.ResizeFrameBuffer:
{
enumerator.Current().Decompose(out ResizeFrameBufferEvent e);
renderEvent.Decompose(out ResizeFrameBufferEvent e);
processEvent(e);
break;
}
case RenderEventType.SetShader:
{
enumerator.Current().Decompose(out SetShaderEvent e);
renderEvent.Decompose(out SetShaderEvent e);
processEvent(e);
break;
}
case RenderEventType.SetTexture:
{
enumerator.Current().Decompose(out SetTextureEvent e);
renderEvent.Decompose(out SetTextureEvent e);
processEvent(e);
break;
}
case RenderEventType.SetUniformBuffer:
{
enumerator.Current().Decompose(out SetUniformBufferEvent e);
renderEvent.Decompose(out SetUniformBufferEvent e);
processEvent(e);
break;
}
case RenderEventType.Clear:
{
enumerator.Current().Decompose(out ClearEvent e);
renderEvent.Decompose(out ClearEvent e);
processEvent(e);
break;
}
case RenderEventType.SetDepthInfo:
{
enumerator.Current().Decompose(out SetDepthInfoEvent e);
renderEvent.Decompose(out SetDepthInfoEvent e);
processEvent(e);
break;
}
case RenderEventType.SetScissor:
{
enumerator.Current().Decompose(out SetScissorEvent e);
renderEvent.Decompose(out SetScissorEvent e);
processEvent(e);
break;
}
case RenderEventType.SetScissorState:
{
enumerator.Current().Decompose(out SetScissorStateEvent e);
renderEvent.Decompose(out SetScissorStateEvent e);
processEvent(e);
break;
}
case RenderEventType.SetStencilInfo:
{
enumerator.Current().Decompose(out SetStencilInfoEvent e);
renderEvent.Decompose(out SetStencilInfoEvent e);
processEvent(e);
break;
}
case RenderEventType.SetViewport:
{
enumerator.Current().Decompose(out SetViewportEvent e);
renderEvent.Decompose(out SetViewportEvent e);
processEvent(e);
break;
}
case RenderEventType.SetBlend:
{
enumerator.Current().Decompose(out SetBlendEvent e);
renderEvent.Decompose(out SetBlendEvent e);
processEvent(e);
break;
}
case RenderEventType.SetBlendMask:
{
enumerator.Current().Decompose(out SetBlendMaskEvent e);
renderEvent.Decompose(out SetBlendMaskEvent e);
processEvent(e);
break;
}
case RenderEventType.Flush:
{
enumerator.Current().Decompose(out FlushEvent e);
renderEvent.Decompose(out FlushEvent e);
processEvent(e);
break;
}
case RenderEventType.SetUniformBufferData:
{
enumerator.Current().Decompose(out SetUniformBufferDataEvent e);
renderEvent.Decompose(out SetUniformBufferDataEvent e);
processEvent(e);
break;
}