Skip to content

Commit

Permalink
Merge pull request #6073 from smoogipoo/drawnode-subtree-draw-cleanup
Browse files Browse the repository at this point in the history
Cleanup `DrawNode` drawing methods
  • Loading branch information
bdach authored Dec 4, 2023
2 parents a025d23 + 8dd8b61 commit f7b43b5
Show file tree
Hide file tree
Showing 20 changed files with 94 additions and 114 deletions.
12 changes: 6 additions & 6 deletions osu.Framework.Tests/Visual/Containers/TestSceneFrontToBack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ protected override void Update()
if (drawNode != null)
{
labelDrawables.Text = $"boxes: {Cell(1).Children.Count * cell_count:N0}";
labelFrag.Text = $"samples ({nameof(DrawNode.Draw)}): {drawNode.DrawSamples:N0}";
labelFrag2.Text = $"samples ({nameof(DrawNode.DrawOpaqueInteriorSubTree)}): {drawNode.DrawOpaqueInteriorSubTreeSamples:N0}";
labelFrag.Text = $"samples (Draw): {drawNode.DrawSamples:N0}";
labelFrag2.Text = $"samples (DrawOpaqueInterior): {drawNode.DrawOpaqueInteriorSubTreeSamples:N0}";
}
}

Expand Down Expand Up @@ -151,16 +151,16 @@ public QueryingCompositeDrawableDrawNode(CompositeDrawable source)
{
}

internal override void DrawOpaqueInteriorSubTree(IRenderer renderer, DepthValue depthValue)
protected override void DrawOpaqueInterior(IRenderer renderer)
{
if (renderer is VeldridRenderer)
{
base.DrawOpaqueInteriorSubTree(renderer, depthValue);
base.DrawOpaqueInterior(renderer);
return;
}

startQuery();
base.DrawOpaqueInteriorSubTree(renderer, depthValue);
base.DrawOpaqueInterior(renderer);
DrawOpaqueInteriorSubTreeSamples = endQuery();
}

Expand All @@ -171,7 +171,7 @@ public override void ApplyState()
base.ApplyState();
}

public override void Draw(IRenderer renderer)
protected override void Draw(IRenderer renderer)
{
if (renderer is VeldridRenderer)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public override void ApplyState()
private IShaderStorageBufferObject<ColourData>? colourBuffer;
private IVertexBatch<ColourIndexedVertex>? vertices;

public override void Draw(IRenderer renderer)
protected override void Draw(IRenderer renderer)
{
base.Draw(renderer);

Expand Down Expand Up @@ -192,7 +192,7 @@ public override void ApplyState()
private ShaderStorageBufferObjectStack<ColourData>? colourBuffer;
private IVertexBatch<ColourIndexedVertex>? vertices;

public override void Draw(IRenderer renderer)
protected override void Draw(IRenderer renderer)
{
base.Draw(renderer);

Expand Down
6 changes: 3 additions & 3 deletions osu.Framework.Tests/Visual/Graphics/TestSceneStencil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public StencilDrawNode(IDrawable source)
{
}

public override void Draw(IRenderer renderer)
protected override void Draw(IRenderer renderer)
{
base.Draw(renderer);

Expand Down Expand Up @@ -164,7 +164,7 @@ private void drawStencil(IRenderer renderer, DrawNode drawNode)
DestinationAlpha = BlendingType.One,
});

drawNode.Draw(renderer);
DrawOther(drawNode, renderer);

renderer.PopStencilInfo();
renderer.SetBlend(DrawColourInfo.Blending);
Expand All @@ -182,7 +182,7 @@ private void drawBackground(IRenderer renderer, DrawNode drawNode)
passed: StencilOperation.Keep
));

drawNode.Draw(renderer);
DrawOther(drawNode, renderer);

renderer.PopStencilInfo();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public BoxWithFlushDrawNode(BoxWithFlush source)
{
}

public override void Draw(IRenderer renderer)
protected override void Draw(IRenderer renderer)
{
base.Draw(renderer);
renderer.FlushCurrentBatch(null);
Expand Down
2 changes: 1 addition & 1 deletion osu.Framework/Graphics/Audio/WaveformGraph.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ public override void ApplyState()

private IVertexBatch<TexturedVertex2D>? vertexBatch;

public override void Draw(IRenderer renderer)
protected override void Draw(IRenderer renderer)
{
base.Draw(renderer);

Expand Down
4 changes: 2 additions & 2 deletions osu.Framework/Graphics/BufferedDrawNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public override void ApplyState()
/// <returns>A version representing this <see cref="DrawNode"/>'s state.</returns>
protected virtual long GetDrawVersion() => InvalidationID;

public sealed override void Draw(IRenderer renderer)
protected sealed override void Draw(IRenderer renderer)
{
if (!SharedData.IsInitialised)
SharedData.Initialise(renderer);
Expand All @@ -101,7 +101,7 @@ public sealed override void Draw(IRenderer renderer)
renderer.PushOrtho(screenSpaceDrawRectangle);
renderer.Clear(new ClearInfo(backgroundColour));

Child.Draw(renderer);
DrawOther(Child, renderer);

renderer.PopOrtho();
}
Expand Down
26 changes: 9 additions & 17 deletions osu.Framework/Graphics/Containers/CompositeDrawable_DrawNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using osuTK;
using osu.Framework.Graphics.Colour;
using System;
using System.Runtime.CompilerServices;
using osu.Framework.Graphics.Effects;
using osu.Framework.Graphics.Rendering;
using osu.Framework.Graphics.Rendering.Vertices;
Expand Down Expand Up @@ -177,7 +176,7 @@ private void updateQuadBatch(IRenderer renderer)
quadBatch = renderer.CreateQuadBatch<TexturedVertex2D>(100, 1000);
}

public override void Draw(IRenderer renderer)
protected override void Draw(IRenderer renderer)
{
updateQuadBatch(renderer);

Expand All @@ -201,7 +200,7 @@ public override void Draw(IRenderer renderer)
if (Children != null)
{
for (int i = 0; i < Children.Count; i++)
Children[i].Draw(renderer);
DrawOther(Children[i], renderer);
}

if (maskingInfo != null)
Expand All @@ -211,21 +210,11 @@ public override void Draw(IRenderer renderer)
renderer.PopQuadBatch();
}

internal override void DrawOpaqueInteriorSubTree(IRenderer renderer, DepthValue depthValue)
protected override void DrawOpaqueInterior(IRenderer renderer)
{
DrawChildrenOpaqueInteriors(renderer, depthValue);
base.DrawOpaqueInteriorSubTree(renderer, depthValue);
}
base.DrawOpaqueInterior(renderer);

/// <summary>
/// Performs <see cref="DrawOpaqueInteriorSubTree"/> on all children of this <see cref="CompositeDrawableDrawNode"/>.
/// </summary>
/// <param name="renderer">The renderer to draw with.</param>
/// <param name="depthValue">The previous depth value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected virtual void DrawChildrenOpaqueInteriors(IRenderer renderer, DepthValue depthValue)
{
bool canIncrement = depthValue.CanIncrement;
bool canIncrement = renderer.BackbufferDepth.CanIncrement;

// Assume that if we can't increment the depth value, no child can, thus nothing will be drawn.
if (canIncrement)
Expand All @@ -244,7 +233,7 @@ protected virtual void DrawChildrenOpaqueInteriors(IRenderer renderer, DepthValu
if (Children != null)
{
for (int i = Children.Count - 1; i >= 0; i--)
Children[i].DrawOpaqueInteriorSubTree(renderer, depthValue);
DrawOtherOpaqueInterior(Children[i], renderer);
}

// Assume that if we can't increment the depth value, no child can, thus nothing will be drawn.
Expand All @@ -258,6 +247,9 @@ protected virtual void DrawChildrenOpaqueInteriors(IRenderer renderer, DepthValu
}
}

protected internal override bool CanDrawOpaqueInterior => true;
protected override bool HasOwnOpaqueInterior => false;

protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
Expand Down
71 changes: 31 additions & 40 deletions osu.Framework/Graphics/DrawNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ public class DrawNode : IDisposable
private long referenceCount;

/// <summary>
/// The depth at which drawing should take place.
/// This is written to from the front-to-back pass and used in both passes.
/// The depth at which this <see cref="DrawNode"/> is to be drawn.
/// Only used if front-to-back is enabled.
/// </summary>
private float drawDepth;

Expand Down Expand Up @@ -74,60 +74,45 @@ public virtual void ApplyState()
/// Subclasses must invoke <code>base.Draw()</code> prior to drawing vertices.
/// </remarks>
/// <param name="renderer">The renderer to draw with.</param>
public virtual void Draw(IRenderer renderer)
protected virtual void Draw(IRenderer renderer)
{
renderer.SetBlend(DrawColourInfo.Blending);

// This is the back-to-front (BTF) pass. The back-buffer depth test function used is GL_LESS.
// The depth test will fail for samples that overlap the opaque interior of this <see cref="DrawNode"/> and any <see cref="DrawNode"/>s above this one.
renderer.SetDrawDepth(drawDepth);
renderer.BackbufferDepth.Set(drawDepth);
}

/// <summary>
/// Draws the opaque interior of this <see cref="DrawNode"/> and all <see cref="DrawNode"/>s further down the scene graph, invoking <see cref="DrawOpaqueInterior"/> if <see cref="CanDrawOpaqueInterior"/>
/// indicates that an opaque interior can be drawn for each relevant <see cref="DrawNode"/>.
/// Draws the opaque interior of this <see cref="DrawNode"/> to the screen, if <see cref="CanDrawOpaqueInterior"/> indicates that an opaque interior can be drawn.
/// The opaque interior must be a fully-opaque, non-blended area of this <see cref="DrawNode"/>, clipped to the current masking area via <code>DrawClipped()</code>.
/// See <see cref="Sprites.SpriteDrawNode"/> for an example implementation.
/// </summary>
/// <remarks>
/// This is the front-to-back pass. The back-buffer depth test function used is GL_LESS.<br />
/// During this pass, the opaque interior is drawn BELOW ourselves. For this to occur, <see cref="drawDepth"/> is temporarily incremented and then decremented after drawing is complete.
/// Other <see cref="DrawNode"/>s behind ourselves receive the incremented depth value before doing the same themselves, allowing early-z to take place during this pass.
/// Subclasses must invoke <code>base.DrawOpaqueInterior()</code> prior to drawing vertices.
/// </remarks>
/// <param name="renderer">The renderer to draw with.</param>
/// <param name="depthValue">The previous depth value.</param>
internal virtual void DrawOpaqueInteriorSubTree(IRenderer renderer, DepthValue depthValue)
protected virtual void DrawOpaqueInterior(IRenderer renderer)
{
if (!depthValue.CanIncrement || !CanDrawOpaqueInterior)
{
// The back-to-front pass requires the depth value.
drawDepth = depthValue;
return;
}

// For an incoming depth value D, the opaque interior is drawn at depth D+e and the content is drawn at depth D.
// As such, when the GL_LESS test function is applied, the content will always pass the depth test for the same DrawNode (D < D+e).

// Increment the depth.
float previousDepthValue = depthValue;
drawDepth = depthValue.Increment();

DrawOpaqueInterior(renderer);
if (HasOwnOpaqueInterior)
renderer.BackbufferDepth.Increment();
}

// Decrement the depth.
drawDepth = previousDepthValue;
protected internal static void DrawOther(DrawNode node, IRenderer renderer)
{
node.Draw(renderer);
}

/// <summary>
/// Draws the opaque interior of this <see cref="DrawNode"/> to the screen.
/// The opaque interior must be a fully-opaque, non-blended area of this <see cref="DrawNode"/>, clipped to the current masking area via <code>DrawClipped()</code>.
/// See <see cref="Sprites.SpriteDrawNode"/> for an example implementation.
/// Draws the opaque interior of a <see cref="DrawNode"/>.
/// </summary>
/// <remarks>
/// Subclasses must invoke <code>base.DrawOpaqueInterior()</code> prior to drawing vertices.
/// </remarks>
/// <param name="renderer">The renderer to draw with.</param>
protected virtual void DrawOpaqueInterior(IRenderer renderer)
protected internal static void DrawOtherOpaqueInterior(DrawNode node, IRenderer renderer)
{
renderer.SetDrawDepth(drawDepth);
// For an incoming depth value D, the content is to be drawn at depth D and the opaque interior is to be drawn at depth D+e.
// When the GL_LESS test function is applied, the content will therefore always pass the depth test for the same DrawNode (D < D+e)
node.drawDepth = renderer.BackbufferDepth;

if (!renderer.BackbufferDepth.CanIncrement || !node.CanDrawOpaqueInterior)
return;

node.DrawOpaqueInterior(renderer);
}

/// <summary>
Expand All @@ -136,6 +121,12 @@ protected virtual void DrawOpaqueInterior(IRenderer renderer)
/// </summary>
protected internal virtual bool CanDrawOpaqueInterior => false;

/// <summary>
/// Whether this <see cref="DrawNode"/> has its own opaque interior.
/// If <c>false</c>, a child of the <see cref="DrawNode"/> may be the source of the opaque interior.
/// </summary>
protected virtual bool HasOwnOpaqueInterior => CanDrawOpaqueInterior;

/// <summary>
/// Increments the reference count of this <see cref="DrawNode"/>, blocking <see cref="Dispose()"/> until the count reaches 0.
/// Invoke <see cref="Dispose()"/> to remove the reference.
Expand Down
14 changes: 10 additions & 4 deletions osu.Framework/Graphics/Drawable_ProxyDrawable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,17 @@ public ProxyDrawNode(ProxyDrawable proxyDrawable)
{
}

internal override void DrawOpaqueInteriorSubTree(IRenderer renderer, DepthValue depthValue)
=> getCurrentFrameSource()?.DrawOpaqueInteriorSubTree(renderer, depthValue);
protected override void DrawOpaqueInterior(IRenderer renderer)
{
if (getCurrentFrameSource() != null)
DrawOtherOpaqueInterior(getCurrentFrameSource(), renderer);
}

public override void Draw(IRenderer renderer)
=> getCurrentFrameSource()?.Draw(renderer);
protected override void Draw(IRenderer renderer)
{
if (getCurrentFrameSource() != null)
DrawOther(getCurrentFrameSource(), renderer);
}

protected internal override bool CanDrawOpaqueInterior => getCurrentFrameSource()?.CanDrawOpaqueInterior ?? false;

Expand Down
2 changes: 1 addition & 1 deletion osu.Framework/Graphics/Lines/Path_DrawNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public override void ApplyState()
pathShader = Source.pathShader;
}

public override void Draw(IRenderer renderer)
protected override void Draw(IRenderer renderer)
{
base.Draw(renderer);

Expand Down
10 changes: 10 additions & 0 deletions osu.Framework/Graphics/Rendering/DepthValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ internal void Reset()
count = 0;
}

/// <summary>
/// Sets the depth to a given value. After this, the depth value can no longer be incremented.
/// </summary>
/// <param name="value">The new depth value.</param>
public void Set(float value)
{
count = max_count;
depth = value;
}

/// <summary>
/// Whether the depth value can be incremented.
/// </summary>
Expand Down
6 changes: 1 addition & 5 deletions osu.Framework/Graphics/Rendering/Dummy/DummyRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ public sealed class DummyRenderer : IRenderer
public WrapMode CurrentWrapModeS => WrapMode.None;
public WrapMode CurrentWrapModeT => WrapMode.None;
public bool IsMaskingActive => false;
public float BackbufferDrawDepth => 0;
public bool UsingBackbuffer => false;
public Texture WhitePixel { get; }
DepthValue IRenderer.BackbufferDepth { get; } = new DepthValue();

public bool IsInitialised { get; private set; }

Expand Down Expand Up @@ -220,10 +220,6 @@ void IRenderer.SetUniform<T>(IUniformWithValue<T> uniform)
{
}

void IRenderer.SetDrawDepth(float drawDepth)
{
}

IVertexBatch<TexturedVertex2D> IRenderer.DefaultQuadBatch => new DummyVertexBatch<TexturedVertex2D>();

void IRenderer.PushQuadBatch(IVertexBatch<TexturedVertex2D> quadBatch)
Expand Down
Loading

0 comments on commit f7b43b5

Please sign in to comment.