Skip to content

Commit

Permalink
Merge pull request #6190 from smoogipoo/deferred-renderer-2
Browse files Browse the repository at this point in the history
Implement a "deferred" renderer
  • Loading branch information
bdach committed Mar 11, 2024
2 parents aaf3e8f + 7a9a521 commit cb0ac0e
Show file tree
Hide file tree
Showing 48 changed files with 2,666 additions and 15 deletions.
228 changes: 228 additions & 0 deletions osu.Framework.Benchmarks/BenchmarkEventList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
// 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 BenchmarkDotNet.Attributes;
using osu.Framework.Graphics.Rendering.Deferred;
using osu.Framework.Graphics.Rendering.Deferred.Allocation;
using osu.Framework.Graphics.Rendering.Deferred.Events;

namespace osu.Framework.Benchmarks
{
public class BenchmarkEventList
{
// Used for benchmark-local testing.
private ResourceAllocator localAllocator = null!;
private EventList 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];

[GlobalSetup]
public void GlobalSetup()
{
localAllocator = new ResourceAllocator();
localEventList = new EventList(localAllocator);

for (int i = 0; i < staticItems.Length; i++)
{
ResourceAllocator allocator = new ResourceAllocator();
staticItems[i] = (allocator, new EventList(allocator));
}

for (int i = 0; i < 10000; i++)
{
staticItems[0].list.Enqueue(new FlushEvent(RenderEventType.Flush, new ResourceReference(1), 10));
staticItems[1].list.Enqueue(new AddPrimitiveToBatchEvent(RenderEventType.AddPrimitiveToBatch, new ResourceReference(0), staticItems[1].allocator.AllocateRegion(1024)));

if (i % 2 == 0)
staticItems[2].list.Enqueue(new FlushEvent(RenderEventType.Flush, new ResourceReference(1), 10));
else
staticItems[2].list.Enqueue(new AddPrimitiveToBatchEvent(RenderEventType.AddPrimitiveToBatch, 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(new FlushEvent());
}

[Benchmark]
public void WriteWithData()
{
localEventList.NewFrame();
localAllocator.NewFrame();

for (int i = 0; i < 10000; i++)
localEventList.Enqueue(new AddPrimitiveToBatchEvent(RenderEventType.AddPrimitiveToBatch, new ResourceReference(0), localAllocator.AllocateRegion(1024)));
}

[Benchmark]
public int Read()
{
var enumerator = staticItems[0].list.CreateEnumerator();

int totalVertices = 0;

while (enumerator.Next())
{
switch (enumerator.CurrentType())
{
case RenderEventType.Flush:
ref FlushEvent e = ref enumerator.Current<FlushEvent>();
totalVertices += e.VertexCount;
break;
}
}

return totalVertices;
}

[Benchmark]
public int ReadWithData()
{
var enumerator = staticItems[1].list.CreateEnumerator();

int data = 0;

while (enumerator.Next())
{
switch (enumerator.CurrentType())
{
case RenderEventType.AddPrimitiveToBatch:
ref AddPrimitiveToBatchEvent e = ref enumerator.Current<AddPrimitiveToBatchEvent>();
foreach (byte b in staticItems[1].allocator.GetRegion(e.Memory))
data += b;
break;
}
}

return data;
}

[Benchmark]
public int ReadMixed()
{
var enumerator = staticItems[2].list.CreateEnumerator();

int data = 0;

while (enumerator.Next())
{
switch (enumerator.CurrentType())
{
case RenderEventType.Flush:
{
ref FlushEvent e = ref enumerator.Current<FlushEvent>();
data += e.VertexCount;
break;
}

case RenderEventType.AddPrimitiveToBatch:
{
ref AddPrimitiveToBatchEvent e = ref enumerator.Current<AddPrimitiveToBatchEvent>();
foreach (byte b in staticItems[2].allocator.GetRegion(e.Memory))
data += b;
break;
}
}
}

return data;
}

[Benchmark]
public int ReplaceSame()
{
localEventList.NewFrame();
localAllocator.NewFrame();

localEventList.Enqueue(new FlushEvent());
localEventList.Enqueue(new FlushEvent());
localEventList.Enqueue(new FlushEvent());

var enumerator = localEventList.CreateEnumerator();
enumerator.Next();
enumerator.Next();
enumerator.Replace(new FlushEvent());

int i = 0;
enumerator = localEventList.CreateEnumerator();

while (enumerator.Next())
{
enumerator.CurrentType();
i++;
}

localAllocator.NewFrame();

return i;
}

[Benchmark]
public int ReplaceSmaller()
{
localEventList.NewFrame();
localAllocator.NewFrame();

localEventList.Enqueue(new FlushEvent());
localEventList.Enqueue(new FlushEvent());
localEventList.Enqueue(new FlushEvent());

var enumerator = localEventList.CreateEnumerator();
enumerator.Next();
enumerator.Next();
enumerator.Replace(new SetScissorStateEvent());

int i = 0;
enumerator = localEventList.CreateEnumerator();

while (enumerator.Next())
{
enumerator.CurrentType();
i++;
}

localAllocator.NewFrame();

return i;
}

[Benchmark]
public int ReplaceBigger()
{
localEventList.NewFrame();
localAllocator.NewFrame();

localEventList.Enqueue(new FlushEvent());
localEventList.Enqueue(new FlushEvent());
localEventList.Enqueue(new FlushEvent());

var enumerator = localEventList.CreateEnumerator();
enumerator.Next();
enumerator.Next();
enumerator.Replace(new SetUniformBufferDataEvent());

int i = 0;
enumerator = localEventList.CreateEnumerator();

while (enumerator.Next())
{
enumerator.CurrentType();
i++;
}

localAllocator.NewFrame();

return i;
}
}
}
55 changes: 55 additions & 0 deletions osu.Framework.Tests/Graphics/EventListTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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 NUnit.Framework;
using osu.Framework.Development;
using osu.Framework.Graphics.Rendering.Deferred;
using osu.Framework.Graphics.Rendering.Deferred.Allocation;
using osu.Framework.Graphics.Rendering.Deferred.Events;

namespace osu.Framework.Tests.Graphics
{
[TestFixture]
public class EventListTest
{
private ResourceAllocator allocator = null!;
private EventList list = null!;

[SetUp]
public void Setup()
{
ThreadSafety.IsDrawThread = true;

allocator = new ResourceAllocator();
list = new EventList(allocator);
}

[TearDown]
public void TearDown()
{
allocator.NewFrame();

ThreadSafety.IsDrawThread = false;
}

[Test]
public void ReplaceWithSmallEvent()
{
list.Enqueue(new FlushEvent());

var enumerator = list.CreateEnumerator();
enumerator.Next();
enumerator.Replace(new FlushEvent());
}

[Test]
public void ReplaceWithLargeEvent()
{
list.Enqueue(new FlushEvent());

var enumerator = list.CreateEnumerator();
enumerator.Next();
enumerator.Replace(new SetUniformBufferDataEvent());
}
}
}
12 changes: 12 additions & 0 deletions osu.Framework/Configuration/RendererType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,17 @@ public enum RendererType
[Obsolete]
[Description("OpenGL (Legacy)")]
OpenGLLegacy,

[Description("Metal (Experimental)")]
Deferred_Metal = 32,

[Description("Vulkan (Experimental)")]
Deferred_Vulkan,

[Description("Direct3D 11 (Experimental)")]
Deferred_Direct3D11,

[Description("OpenGL (Experimental)")]
Deferred_OpenGL
}
}
3 changes: 3 additions & 0 deletions osu.Framework/FrameworkEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public static class FrameworkEnvironment
public static int? StagingBufferType { get; }
public static int? VertexBufferCount { get; }
public static bool NoStructuredBuffers { get; }
public static string? DeferredRendererEventsOutputPath { get; }

static FrameworkEnvironment()
{
Expand All @@ -34,6 +35,8 @@ static FrameworkEnvironment()
StagingBufferType = stagingBufferImplementation;

NoStructuredBuffers = parseBool(Environment.GetEnvironmentVariable("OSU_GRAPHICS_NO_SSBO")) ?? false;

DeferredRendererEventsOutputPath = Environment.GetEnvironmentVariable("DEFERRED_RENDERER_EVENTS_OUTPUT");
}

private static bool? parseBool(string? value)
Expand Down
4 changes: 4 additions & 0 deletions osu.Framework/Graphics/DrawNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ protected virtual void DrawOpaqueInterior(IRenderer renderer)

protected internal static void DrawOther(DrawNode node, IRenderer renderer)
{
renderer.EnterDrawNode(node);
node.Draw(renderer);
renderer.ExitDrawNode();
}

/// <summary>
Expand Down Expand Up @@ -136,6 +138,8 @@ protected internal static void DrawOtherOpaqueInterior(DrawNode node, IRenderer
/// </remarks>
internal void Reference() => Interlocked.Increment(ref referenceCount);

public override string ToString() => Source.ToString();

protected internal bool IsDisposed { get; private set; }

public void Dispose()
Expand Down

0 comments on commit cb0ac0e

Please sign in to comment.