From 98d5769558afb18f30b98cdc5c75d14ae99cea83 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 28 Sep 2023 10:59:09 +0200 Subject: [PATCH] Fix performance bug in Development/Release builds due to incorrect draw calls batching (uninitialized memory) --- Source/Engine/Graphics/Models/Mesh.cpp | 12 ------------ Source/Engine/Graphics/Models/SkinnedMesh.cpp | 11 ----------- Source/Engine/Level/Actors/Skybox.cpp | 1 - Source/Engine/Renderer/DrawCall.h | 5 +++-- Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp | 1 - Source/Engine/Renderer/RenderList.cpp | 8 ++++---- Source/Engine/UI/TextRender.cpp | 3 --- 7 files changed, 7 insertions(+), 34 deletions(-) diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index c288a0ef8..f03c013c6 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -401,10 +401,6 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons drawCall.Geometry.VertexBuffers[0] = _vertexBuffers[0]; drawCall.Geometry.VertexBuffers[1] = _vertexBuffers[1]; drawCall.Geometry.VertexBuffers[2] = _vertexBuffers[2]; - drawCall.Geometry.VertexBuffersOffsets[0] = 0; - drawCall.Geometry.VertexBuffersOffsets[1] = 0; - drawCall.Geometry.VertexBuffersOffsets[2] = 0; - drawCall.Draw.StartIndex = 0; drawCall.Draw.IndicesCount = _triangles * 3; drawCall.InstanceCount = 1; drawCall.Material = material; @@ -459,9 +455,6 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float drawCall.Geometry.VertexBuffers[0] = _vertexBuffers[0]; drawCall.Geometry.VertexBuffers[1] = _vertexBuffers[1]; drawCall.Geometry.VertexBuffers[2] = _vertexBuffers[2]; - drawCall.Geometry.VertexBuffersOffsets[0] = 0; - drawCall.Geometry.VertexBuffersOffsets[1] = 0; - drawCall.Geometry.VertexBuffersOffsets[2] = 0; if (info.Deformation) { info.Deformation->RunDeformers(this, MeshBufferType::Vertex0, drawCall.Geometry.VertexBuffers[0]); @@ -476,7 +469,6 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float drawCall.Geometry.VertexBuffers[2] = info.VertexColors[_lodIndex]; drawCall.Geometry.VertexBuffersOffsets[2] = vertexOffset * sizeof(VB2ElementType); } - drawCall.Draw.StartIndex = 0; drawCall.Draw.IndicesCount = _triangles * 3; drawCall.InstanceCount = 1; drawCall.Material = material; @@ -525,9 +517,6 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in drawCall.Geometry.VertexBuffers[0] = _vertexBuffers[0]; drawCall.Geometry.VertexBuffers[1] = _vertexBuffers[1]; drawCall.Geometry.VertexBuffers[2] = _vertexBuffers[2]; - drawCall.Geometry.VertexBuffersOffsets[0] = 0; - drawCall.Geometry.VertexBuffersOffsets[1] = 0; - drawCall.Geometry.VertexBuffersOffsets[2] = 0; if (info.Deformation) { info.Deformation->RunDeformers(this, MeshBufferType::Vertex0, drawCall.Geometry.VertexBuffers[0]); @@ -542,7 +531,6 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in drawCall.Geometry.VertexBuffers[2] = info.VertexColors[_lodIndex]; drawCall.Geometry.VertexBuffersOffsets[2] = vertexOffset * sizeof(VB2ElementType); } - drawCall.Draw.StartIndex = 0; drawCall.Draw.IndicesCount = _triangles * 3; drawCall.InstanceCount = 1; drawCall.Material = material; diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp index 5c5ef4f34..48ff53549 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp @@ -175,11 +175,6 @@ void SkinnedMesh::Draw(const RenderContext& renderContext, const DrawInfo& info, DrawCall drawCall; drawCall.Geometry.IndexBuffer = _indexBuffer; drawCall.Geometry.VertexBuffers[0] = _vertexBuffer; - drawCall.Geometry.VertexBuffers[1] = nullptr; - drawCall.Geometry.VertexBuffers[2] = nullptr; - drawCall.Geometry.VertexBuffersOffsets[0] = 0; - drawCall.Geometry.VertexBuffersOffsets[1] = 0; - drawCall.Geometry.VertexBuffersOffsets[2] = 0; if (info.Deformation) info.Deformation->RunDeformers(this, MeshBufferType::Vertex0, drawCall.Geometry.VertexBuffers[0]); drawCall.Draw.StartIndex = 0; @@ -224,14 +219,8 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI DrawCall drawCall; drawCall.Geometry.IndexBuffer = _indexBuffer; drawCall.Geometry.VertexBuffers[0] = _vertexBuffer; - drawCall.Geometry.VertexBuffers[1] = nullptr; - drawCall.Geometry.VertexBuffers[2] = nullptr; - drawCall.Geometry.VertexBuffersOffsets[0] = 0; - drawCall.Geometry.VertexBuffersOffsets[1] = 0; - drawCall.Geometry.VertexBuffersOffsets[2] = 0; if (info.Deformation) info.Deformation->RunDeformers(this, MeshBufferType::Vertex0, drawCall.Geometry.VertexBuffers[0]); - drawCall.Draw.StartIndex = 0; drawCall.Draw.IndicesCount = _triangles * 3; drawCall.InstanceCount = 1; drawCall.Material = material; diff --git a/Source/Engine/Level/Actors/Skybox.cpp b/Source/Engine/Level/Actors/Skybox.cpp index 455c229c0..1b00b86d1 100644 --- a/Source/Engine/Level/Actors/Skybox.cpp +++ b/Source/Engine/Level/Actors/Skybox.cpp @@ -97,7 +97,6 @@ void Skybox::ApplySky(GPUContext* context, RenderContext& renderContext, const M { // Prepare mock draw call data DrawCall drawCall; - Platform::MemoryClear(&drawCall, sizeof(DrawCall)); drawCall.World = world; drawCall.ObjectPosition = drawCall.World.GetTranslation(); drawCall.ObjectRadius = _sphere.Radius; diff --git a/Source/Engine/Renderer/DrawCall.h b/Source/Engine/Renderer/DrawCall.h index d51102166..bde88ab80 100644 --- a/Source/Engine/Renderer/DrawCall.h +++ b/Source/Engine/Renderer/DrawCall.h @@ -279,10 +279,11 @@ struct DrawCall uint64 SortKey; /// - /// Does nothing. + /// Zero-init. /// - DrawCall() + FORCE_INLINE DrawCall() { + Platform::MemoryClear(this, sizeof(DrawCall)); } }; diff --git a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp index 319bc4924..f8572534b 100644 --- a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp +++ b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp @@ -49,7 +49,6 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context, context->BindUA(1, overdrawTexture->View()); context->BindUA(2, liveCountTexture->View()); DrawCall drawCall; - Platform::MemoryClear(&drawCall, sizeof(DrawCall)); drawCall.PerInstanceRandom = 1.0f; MaterialBase::BindParameters bindParams(context, renderContext, drawCall); bindParams.BindViewData(); diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp index f24f25128..7570fa71e 100644 --- a/Source/Engine/Renderer/RenderList.cpp +++ b/Source/Engine/Renderer/RenderList.cpp @@ -13,6 +13,7 @@ #include "Engine/Graphics/PostProcessEffect.h" #include "Engine/Profiler/Profiler.h" #include "Engine/Content/Assets/CubeTexture.h" +#include "Engine/Core/Log.h" #include "Engine/Level/Scene/Lightmap.h" #include "Engine/Level/Actors/PostFxVolume.h" @@ -434,11 +435,11 @@ FORCE_INLINE void CalculateSortKey(const RenderContext& renderContext, DrawCall& const float distance = Float3::Dot(planeNormal, drawCall.ObjectPosition) - planePoint; PackedSortKey key; key.DistanceKey = RenderTools::ComputeDistanceSortKey(distance); - uint32 batchKey = GetHash(drawCall.Geometry.IndexBuffer); + uint32 batchKey = GetHash(drawCall.Material); batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[0]); batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[1]); batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[2]); - batchKey = (batchKey * 397) ^ GetHash(drawCall.Material); + batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.IndexBuffer); IMaterial::InstancingHandler handler; if (drawCall.Material->CanUseInstancing(handler)) handler.GetHash(drawCall, batchKey); @@ -557,7 +558,7 @@ namespace a.InstanceCount != 0 && b.InstanceCount != 0 && handler.CanBatch(a, b) && - a.WorldDeterminantSign == b.WorldDeterminantSign; + a.WorldDeterminantSign * b.WorldDeterminantSign > 0; } } @@ -618,7 +619,6 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD const DrawCall& other = drawCallsData[listData[j]]; if (!CanBatchWith(drawCall, other)) break; - batchSize++; instanceCount += other.InstanceCount; } diff --git a/Source/Engine/UI/TextRender.cpp b/Source/Engine/UI/TextRender.cpp index d161db0ee..aa49dac45 100644 --- a/Source/Engine/UI/TextRender.cpp +++ b/Source/Engine/UI/TextRender.cpp @@ -379,9 +379,6 @@ void TextRender::Draw(RenderContext& renderContext) drawCall.Geometry.VertexBuffers[0] = _vb0.GetBuffer(); drawCall.Geometry.VertexBuffers[1] = _vb1.GetBuffer(); drawCall.Geometry.VertexBuffers[2] = _vb2.GetBuffer(); - drawCall.Geometry.VertexBuffersOffsets[0] = 0; - drawCall.Geometry.VertexBuffersOffsets[1] = 0; - drawCall.Geometry.VertexBuffersOffsets[2] = 0; drawCall.InstanceCount = 1; // Submit draw calls