Optimize terrain debug shape drawing by caching lines into a vertex buffer

#2841
This commit is contained in:
Wojtek Figat
2024-12-09 18:26:53 +01:00
parent 0cf31395b5
commit 3e344e789a
7 changed files with 141 additions and 34 deletions

View File

@@ -94,6 +94,13 @@ struct DebugLine
float TimeLeft;
};
struct DebugGeometryBuffer
{
GPUBuffer* Buffer;
float TimeLeft;
Matrix Transform;
};
struct DebugTriangle
{
Float3 V0;
@@ -122,12 +129,9 @@ struct DebugText3D
float TimeLeft;
};
PACK_STRUCT(struct Vertex {
Float3 Position;
Color32 Color;
});
typedef DebugDraw::Vertex Vertex;
GPU_CB_STRUCT(Data {
GPU_CB_STRUCT(ShaderData {
Matrix ViewProjection;
Float2 Padding;
float ClipPosZBias;
@@ -231,6 +235,7 @@ void TeleportList(const Float3& delta, Array<DebugText3D>& list)
struct DebugDrawData
{
Array<DebugGeometryBuffer> GeometryBuffers;
Array<DebugLine> DefaultLines;
Array<Vertex> OneFrameLines;
Array<DebugTriangle> DefaultTriangles;
@@ -244,7 +249,7 @@ struct DebugDrawData
inline int32 Count() const
{
return LinesCount() + TrianglesCount() + TextCount();
return LinesCount() + TrianglesCount() + TextCount() + GeometryBuffers.Count();
}
inline int32 LinesCount() const
@@ -280,6 +285,7 @@ struct DebugDrawData
inline void Update(float deltaTime)
{
UpdateList(deltaTime, GeometryBuffers);
UpdateList(deltaTime, DefaultLines);
UpdateList(deltaTime, DefaultTriangles);
UpdateList(deltaTime, DefaultWireTriangles);
@@ -784,7 +790,7 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe
// Update constant buffer
const auto cb = DebugDrawShader->GetShader()->GetCB(0);
Data data;
ShaderData data;
Matrix vp;
Matrix::Multiply(view.View, view.Projection, vp);
Matrix::Transpose(vp, data.ViewProjection);
@@ -830,6 +836,22 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe
context->Draw(depthTestTriangles.StartVertex, depthTestTriangles.VertexCount);
}
// Geometries
for (auto& geometry : Context->DebugDrawDepthTest.GeometryBuffers)
{
auto tmp = data;
Matrix mvp;
Matrix::Multiply(geometry.Transform, vp, mvp);
Matrix::Transpose(mvp, tmp.ViewProjection);
context->UpdateCB(cb, &tmp);
auto state = data.EnableDepthTest ? &DebugDrawPsLinesDepthTest : &DebugDrawPsLinesDefault;
context->SetState(state->Get(enableDepthWrite, true));
context->BindVB(ToSpan(&geometry.Buffer, 1));
context->Draw(0, geometry.Buffer->GetElementsCount());
}
if (Context->DebugDrawDepthTest.GeometryBuffers.HasItems())
context->UpdateCB(cb, &data);
if (data.EnableDepthTest)
context->UnBindSR(0);
}
@@ -862,6 +884,19 @@ void DebugDraw::Draw(RenderContext& renderContext, GPUTextureView* target, GPUTe
context->BindVB(ToSpan(&vb, 1));
context->Draw(defaultTriangles.StartVertex, defaultTriangles.VertexCount);
}
// Geometries
for (auto& geometry : Context->DebugDrawDefault.GeometryBuffers)
{
auto tmp = data;
Matrix mvp;
Matrix::Multiply(geometry.Transform, vp, mvp);
Matrix::Transpose(mvp, tmp.ViewProjection);
context->UpdateCB(cb, &tmp);
context->SetState(DebugDrawPsLinesDefault.Get(false, false));
context->BindVB(ToSpan(&geometry.Buffer, 1));
context->Draw(0, geometry.Buffer->GetElementsCount());
}
}
// Text
@@ -1088,6 +1123,24 @@ void DebugDraw::DrawLines(const Span<Float3>& lines, const Matrix& transform, co
}
}
void DebugDraw::DrawLines(GPUBuffer* lines, const Matrix& transform, float duration, bool depthTest)
{
if (lines == nullptr || lines->GetSize() == 0)
return;
if (lines->GetSize() % (sizeof(Vertex) * 2) != 0)
{
DebugLog::ThrowException("Cannot draw debug lines with uneven amount of items in array");
return;
}
// Draw lines
auto& debugDrawData = depthTest ? Context->DebugDrawDepthTest : Context->DebugDrawDefault;
auto& geometry = debugDrawData.GeometryBuffers.AddOne();
geometry.Buffer = lines;
geometry.TimeLeft = duration;
geometry.Transform = transform * Matrix::Translation(-Context->Origin);
}
void DebugDraw::DrawLines(const Array<Float3>& lines, const Matrix& transform, const Color& color, float duration, bool depthTest)
{
DrawLines(Span<Float3>(lines.Get(), lines.Count()), transform, color, duration, depthTest);
@@ -2147,6 +2200,7 @@ void DebugDraw::DrawText(const StringView& text, const Transform& transform, con
void DebugDraw::Clear(void* context)
{
DebugDraw::UpdateContext(context, MAX_float);
UpdateContext(context, MAX_float);
}
#endif

View File

@@ -6,6 +6,8 @@
#include "Engine/Scripting/ScriptingType.h"
#include "Engine/Core/Math/Color.h"
#include "Engine/Core/Math/Color32.h"
#include "Engine/Core/Math/Vector3.h"
#include "Engine/Core/Types/Span.h"
struct RenderView;
@@ -14,6 +16,7 @@ class Light;
struct RenderContext;
class GPUTextureView;
class GPUContext;
class GPUBuffer;
class RenderTask;
class SceneRenderTask;
class Actor;
@@ -26,6 +29,14 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
{
DECLARE_SCRIPTING_TYPE_NO_SPAWN(DebugDraw);
/// <summary>
/// Vertex data for debug shapes.
/// </summary>
PACK_STRUCT(struct Vertex {
Float3 Position;
Color32 Color;
});
#if USE_EDITOR
/// <summary>
/// Allocates the context for Debug Drawing. Can be use to redirect debug shapes collecting to a separate container (instead of global state).
@@ -175,6 +186,15 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawLines(const Span<Float3>& lines, const Matrix& transform, const Color& color = Color::White, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the lines using the provided vertex buffer that contains pairs of Vertex elements. Line positions are located one after another (e.g. l0.start, l0.end, l1.start, l1.end,...).
/// </summary>
/// <param name="lines">The GPU buffer with vertices for lines (must have multiple of 2 elements).</param>
/// <param name="transform">The custom matrix used to transform all line vertices.</param>
/// <param name="duration">The duration (in seconds). Use 0 to draw it only once.</param>
/// <param name="depthTest">If set to <c>true</c> depth test will be performed, otherwise depth will be ignored.</param>
API_FUNCTION() static void DrawLines(GPUBuffer* lines, const Matrix& transform, float duration = 0.0f, bool depthTest = true);
/// <summary>
/// Draws the lines. Line positions are located one after another (e.g. l0.start, l0.end, l1.start, l1.end,...).
/// </summary>
@@ -691,9 +711,9 @@ API_CLASS(Static) class FLAXENGINE_API DebugDraw
API_FUNCTION() static void DrawText(const StringView& text, const Transform& transform, const Color& color = Color::White, int32 size = 32, float duration = 0.0f);
/// <summary>
/// Clear all debug draw displayed on sceen.
/// Clears all debug shapes displayed on screen.
/// </summary>
/// <returns></returns>
/// <param name="context">The context.</param>
API_FUNCTION() static void Clear(void* context = nullptr);
};