Optimize foliage rendering with less cache misses
This commit is contained in:
@@ -130,26 +130,25 @@ void Foliage::AddToCluster(ChunkedArray<FoliageCluster, FOLIAGE_CLUSTER_CHUNKS_S
|
|||||||
|
|
||||||
#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
|
#if !FOLIAGE_USE_SINGLE_QUAD_TREE && FOLIAGE_USE_DRAW_CALLS_BATCHING
|
||||||
|
|
||||||
void Foliage::DrawInstance(DrawContext& context, FoliageInstance& instance, Model* model, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const
|
void Foliage::DrawInstance(DrawContext& context, FoliageInstance& instance, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const
|
||||||
{
|
{
|
||||||
const auto& meshes = model->LODs.Get()[lod].Meshes;
|
const auto& drawCalls = drawCallsLists[lod];
|
||||||
for (int32 meshIndex = 0; meshIndex < meshes.Count(); meshIndex++)
|
const auto* drawCallsPtr = drawCalls.Get();
|
||||||
|
for (int32 i = 0; i < drawCalls.Count(); i++)
|
||||||
{
|
{
|
||||||
auto& drawCall = drawCallsLists[lod][meshIndex];
|
auto& drawCall = drawCallsPtr[i];
|
||||||
if (!drawCall.Material)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
DrawKey key;
|
DrawKey key;
|
||||||
key.Mat = drawCall.Material;
|
key.Mat = drawCall.Material;
|
||||||
key.Geo = &meshes.Get()[meshIndex];
|
key.Geo = (Mesh*)(void*)drawCall.Geometry.IndexBuffer; // Hack to pass this over Foliage::DrawType
|
||||||
key.Lightmap = instance.LightmapTextureIndex;
|
key.Lightmap = instance.LightmapTextureIndex;
|
||||||
auto* e = result.TryGet(key);
|
auto* e = result.TryGet(key);
|
||||||
if (!e)
|
if (!e)
|
||||||
{
|
{
|
||||||
e = &result.Add(key, BatchedDrawCall(context.RenderContext.List))->Value;
|
e = &result.Add(key, BatchedDrawCall(context.RenderContext.List))->Value;
|
||||||
e->DrawCall.Material = key.Mat;
|
e->DrawCall.Material = key.Mat;
|
||||||
e->DrawCall.Surface.Lightmap = EnumHasAnyFlags(_staticFlags, StaticFlags::Lightmap) && _scene ? _scene->LightmapsData.GetReadyLightmap(key.Lightmap) : nullptr;
|
e->DrawCall.Surface.Lightmap = key.Lightmap != -1 && EnumHasAnyFlags(_staticFlags, StaticFlags::Lightmap) && _scene ? _scene->LightmapsData.GetReadyLightmap(key.Lightmap) : nullptr;
|
||||||
e->DrawCall.Surface.GeometrySize = key.Geo->GetBox().GetSize();
|
e->DrawCall.Surface.GeometrySize = drawCall.Surface.GeometrySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add instance to the draw batch
|
// Add instance to the draw batch
|
||||||
@@ -231,14 +230,14 @@ void Foliage::DrawCluster(DrawContext& context, FoliageCluster* cluster, DrawCal
|
|||||||
{
|
{
|
||||||
const auto prevLOD = model->ClampLODIndex(instance.DrawStatePrevLOD);
|
const auto prevLOD = model->ClampLODIndex(instance.DrawStatePrevLOD);
|
||||||
const float normalizedProgress = static_cast<float>(instance.DrawStateLODTransition) * (1.0f / 255.0f);
|
const float normalizedProgress = static_cast<float>(instance.DrawStateLODTransition) * (1.0f / 255.0f);
|
||||||
DrawInstance(context, instance, model, prevLOD, normalizedProgress, drawCallsLists, result);
|
DrawInstance(context, instance, prevLOD, normalizedProgress, drawCallsLists, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (instance.DrawStateLODTransition < 255)
|
else if (instance.DrawStateLODTransition < 255)
|
||||||
{
|
{
|
||||||
const auto prevLOD = model->ClampLODIndex(instance.DrawStatePrevLOD);
|
const auto prevLOD = model->ClampLODIndex(instance.DrawStatePrevLOD);
|
||||||
const float normalizedProgress = static_cast<float>(instance.DrawStateLODTransition) * (1.0f / 255.0f);
|
const float normalizedProgress = static_cast<float>(instance.DrawStateLODTransition) * (1.0f / 255.0f);
|
||||||
DrawInstance(context, instance, model, prevLOD, normalizedProgress, drawCallsLists, result);
|
DrawInstance(context, instance, prevLOD, normalizedProgress, drawCallsLists, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
instance.DrawStatePrevFrame = frame;
|
instance.DrawStatePrevFrame = frame;
|
||||||
@@ -278,19 +277,19 @@ void Foliage::DrawCluster(DrawContext& context, FoliageCluster* cluster, DrawCal
|
|||||||
// Draw
|
// Draw
|
||||||
if (instance.DrawStatePrevLOD == lodIndex)
|
if (instance.DrawStatePrevLOD == lodIndex)
|
||||||
{
|
{
|
||||||
DrawInstance(context, instance, model, lodIndex, 0.0f, drawCallsLists, result);
|
DrawInstance(context, instance, lodIndex, 0.0f, drawCallsLists, result);
|
||||||
}
|
}
|
||||||
else if (instance.DrawStatePrevLOD == -1)
|
else if (instance.DrawStatePrevLOD == -1)
|
||||||
{
|
{
|
||||||
const float normalizedProgress = static_cast<float>(instance.DrawStateLODTransition) * (1.0f / 255.0f);
|
const float normalizedProgress = static_cast<float>(instance.DrawStateLODTransition) * (1.0f / 255.0f);
|
||||||
DrawInstance(context, instance, model, lodIndex, 1.0f - normalizedProgress, drawCallsLists, result);
|
DrawInstance(context, instance, lodIndex, 1.0f - normalizedProgress, drawCallsLists, result);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto prevLOD = model->ClampLODIndex(instance.DrawStatePrevLOD);
|
const auto prevLOD = model->ClampLODIndex(instance.DrawStatePrevLOD);
|
||||||
const float normalizedProgress = static_cast<float>(instance.DrawStateLODTransition) * (1.0f / 255.0f);
|
const float normalizedProgress = static_cast<float>(instance.DrawStateLODTransition) * (1.0f / 255.0f);
|
||||||
DrawInstance(context, instance, model, prevLOD, normalizedProgress, drawCallsLists, result);
|
DrawInstance(context, instance, prevLOD, normalizedProgress, drawCallsLists, result);
|
||||||
DrawInstance(context, instance, model, lodIndex, normalizedProgress - 1.0f, drawCallsLists, result);
|
DrawInstance(context, instance, lodIndex, normalizedProgress - 1.0f, drawCallsLists, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
//DebugDraw::DrawSphere(instance.Bounds, Color::YellowGreen);
|
//DebugDraw::DrawSphere(instance.Bounds, Color::YellowGreen);
|
||||||
@@ -493,12 +492,10 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Me
|
|||||||
auto& modelLod = type.Model->LODs[lod];
|
auto& modelLod = type.Model->LODs[lod];
|
||||||
DrawCallsList& drawCallsList = drawCallsLists[lod];
|
DrawCallsList& drawCallsList = drawCallsLists[lod];
|
||||||
const auto& meshes = modelLod.Meshes;
|
const auto& meshes = modelLod.Meshes;
|
||||||
drawCallsList.Resize(meshes.Count());
|
drawCallsList.EnsureCapacity(meshes.Count());
|
||||||
for (int32 meshIndex = 0; meshIndex < meshes.Count(); meshIndex++)
|
for (int32 meshIndex = 0; meshIndex < meshes.Count(); meshIndex++)
|
||||||
{
|
{
|
||||||
const auto& mesh = meshes.Get()[meshIndex];
|
const auto& mesh = meshes.Get()[meshIndex];
|
||||||
auto& drawCall = drawCallsList.Get()[meshIndex];
|
|
||||||
drawCall.Material = nullptr; // DrawInstance skips draw calls from meshes with unset material
|
|
||||||
|
|
||||||
// Check entry visibility
|
// Check entry visibility
|
||||||
const auto& entry = type.Entries[mesh.GetMaterialSlotIndex()];
|
const auto& entry = type.Entries[mesh.GetMaterialSlotIndex()];
|
||||||
@@ -523,7 +520,10 @@ void Foliage::DrawType(RenderContext& renderContext, const FoliageType& type, Me
|
|||||||
if (drawModes == DrawPass::None)
|
if (drawModes == DrawPass::None)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Add mesh to drawing
|
||||||
|
auto& drawCall = drawCallsList.AddOne();
|
||||||
drawCall.Material = material;
|
drawCall.Material = material;
|
||||||
|
drawCall.Geometry.IndexBuffer = (GPUBuffer*)(void*)&mesh; // Wrap pointer to mesh for DrawKey::Geo
|
||||||
drawCall.Surface.GeometrySize = mesh.GetBox().GetSize();
|
drawCall.Surface.GeometrySize = mesh.GetBox().GetSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ private:
|
|||||||
|
|
||||||
typedef Array<struct DrawCall, InlinedAllocation<8>> DrawCallsList;
|
typedef Array<struct DrawCall, InlinedAllocation<8>> DrawCallsList;
|
||||||
typedef Dictionary<DrawKey, struct BatchedDrawCall, ConcurrentArenaAllocation> BatchedDrawCalls;
|
typedef Dictionary<DrawKey, struct BatchedDrawCall, ConcurrentArenaAllocation> BatchedDrawCalls;
|
||||||
void DrawInstance(DrawContext& context, FoliageInstance& instance, Model* model, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
|
void DrawInstance(DrawContext& context, FoliageInstance& instance, int32 lod, float lodDitherFactor, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
|
||||||
void DrawCluster(DrawContext& context, FoliageCluster* cluster, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
|
void DrawCluster(DrawContext& context, FoliageCluster* cluster, DrawCallsList* drawCallsLists, BatchedDrawCalls& result) const;
|
||||||
void DrawType(RenderContext& renderContext, const FoliageType& type, DrawCallsList* drawCallsLists);
|
void DrawType(RenderContext& renderContext, const FoliageType& type, DrawCallsList* drawCallsLists);
|
||||||
#else
|
#else
|
||||||
|
|||||||
Reference in New Issue
Block a user