Add async scene drawing for Foliage and Terrain

This commit is contained in:
Wojtek Figat
2022-11-10 23:43:36 +01:00
parent ea5e38fdd1
commit 4ba1531cda
6 changed files with 62 additions and 48 deletions

View File

@@ -306,4 +306,21 @@ public:
Memory::ConstructItems(_allocation.Get() + index, &item, 1); Memory::ConstructItems(_allocation.Get() + index, &item, 1);
return index; return index;
} }
/// <summary>
/// Adds the specified item to the collection.
/// </summary>
/// <param name="item">The item to add.</param>
/// <returns>Index of the added element.</returns>
int32 Add(T&& item)
{
const int32 count = (int32)Platform::AtomicRead(&_count);
const int32 capacity = (int32)Platform::AtomicRead(&_capacity);
const int32 minCapacity = count + PLATFORM_THREADS_LIMIT; // Ensure there is a room for all threads (eg. all possible threads add item at once)
if (minCapacity >= capacity)
EnsureCapacity(minCapacity);
const int32 index = (int32)Platform::InterlockedIncrement(&_count) - 1;
Memory::MoveItems(_allocation.Get() + index, &item, 1);
return index;
}
}; };

View File

@@ -638,7 +638,7 @@ void Foliage::OnFoliageTypeModelLoaded(int32 index)
} }
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1) if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey); GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
} }
{ {
PROFILE_CPU_NAMED("Create Clusters"); PROFILE_CPU_NAMED("Create Clusters");
@@ -685,7 +685,7 @@ void Foliage::RebuildClusters()
_box = BoundingBox(_transform.Translation, _transform.Translation); _box = BoundingBox(_transform.Translation, _transform.Translation);
_sphere = BoundingSphere(_transform.Translation, 0.0f); _sphere = BoundingSphere(_transform.Translation, 0.0f);
if (_sceneRenderingKey != -1) if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey); GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
return; return;
} }
@@ -775,7 +775,7 @@ void Foliage::RebuildClusters()
_box = totalBounds; _box = totalBounds;
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1) if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey); GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
} }
// Insert all instances to the clusters // Insert all instances to the clusters
@@ -1129,8 +1129,29 @@ void Foliage::Draw(RenderContext& renderContext)
batch.DrawCall.Surface.Skinning = nullptr; batch.DrawCall.Surface.Skinning = nullptr;
batch.DrawCall.WorldDeterminantSign = 1; batch.DrawCall.WorldDeterminantSign = 1;
const int32 batchIndex = renderContext.List->BatchedDrawCalls.Count(); if (drawModes & DrawPass::Forward)
renderContext.List->BatchedDrawCalls.Add(MoveTemp(batch)); {
// Transparency requires sorting by depth so convert back the batched draw call into normal draw calls (RenderList impl will handle this)
DrawCall drawCall = batch.DrawCall;
for (int32 j = 0; j < batch.Instances.Count(); j++)
{
auto& instance = batch.Instances[j];
drawCall.ObjectPosition = instance.InstanceOrigin;
drawCall.PerInstanceRandom = instance.PerInstanceRandom;
lightmapArea = instance.InstanceLightmapArea.ToFloat4();
drawCall.Surface.LightmapUVsArea = *(Rectangle*)&lightmapArea;
drawCall.Surface.LODDitherFactor = instance.LODDitherFactor;
drawCall.World.SetRow1(Float4(instance.InstanceTransform1, 0.0f));
drawCall.World.SetRow2(Float4(instance.InstanceTransform2, 0.0f));
drawCall.World.SetRow3(Float4(instance.InstanceTransform3, 0.0f));
drawCall.World.SetRow4(Float4(instance.InstanceOrigin, 1.0f));
const int32 drawCallIndex = renderContext.List->DrawCalls.Add(drawCall);
renderContext.List->DrawCallsLists[(int32)DrawCallsListType::Forward].Indices.Add(drawCallIndex);
}
}
// Add draw call batch
const int32 batchIndex = renderContext.List->BatchedDrawCalls.Add(MoveTemp(batch));
// Add draw call to proper draw lists // Add draw call to proper draw lists
if (drawModes & DrawPass::Depth) if (drawModes & DrawPass::Depth)
@@ -1152,28 +1173,6 @@ void Foliage::Draw(RenderContext& renderContext)
{ {
renderContext.List->DrawCallsLists[(int32)DrawCallsListType::MotionVectors].PreBatchedDrawCalls.Add(batchIndex); renderContext.List->DrawCallsLists[(int32)DrawCallsListType::MotionVectors].PreBatchedDrawCalls.Add(batchIndex);
} }
if (drawModes & DrawPass::Forward)
{
// Transparency requires sorting by depth so convert back the batched draw call into normal draw calls (RenderList impl will handle this)
batch = renderContext.List->BatchedDrawCalls[batchIndex];
DrawCall drawCall = batch.DrawCall;
for (int32 j = 0; j < batch.Instances.Count(); j++)
{
auto& instance = batch.Instances[j];
drawCall.ObjectPosition = instance.InstanceOrigin;
drawCall.PerInstanceRandom = instance.PerInstanceRandom;
lightmapArea = instance.InstanceLightmapArea.ToFloat4();
drawCall.Surface.LightmapUVsArea = *(Rectangle*)&lightmapArea;
drawCall.Surface.LODDitherFactor = instance.LODDitherFactor;
drawCall.World.SetRow1(Float4(instance.InstanceTransform1, 0.0f));
drawCall.World.SetRow2(Float4(instance.InstanceTransform2, 0.0f));
drawCall.World.SetRow3(Float4(instance.InstanceTransform3, 0.0f));
drawCall.World.SetRow4(Float4(instance.InstanceOrigin, 1.0f));
const int32 drawCallIndex = renderContext.List->DrawCalls.Count();
renderContext.List->DrawCalls.Add(drawCall);
renderContext.List->DrawCallsLists[(int32)DrawCallsListType::Forward].Indices.Add(drawCallIndex);
}
}
} }
#else #else
DrawCluster(renderContext, type.Root, draw); DrawCluster(renderContext, type.Root, draw);
@@ -1399,12 +1398,12 @@ void Foliage::Deserialize(DeserializeStream& stream, ISerializeModifier* modifie
void Foliage::OnLayerChanged() void Foliage::OnLayerChanged()
{ {
if (_sceneRenderingKey != -1) if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey); GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
} }
void Foliage::OnEnable() void Foliage::OnEnable()
{ {
GetSceneRendering()->AddActor(this, _sceneRenderingKey); GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
// Base // Base
Actor::OnEnable(); Actor::OnEnable();
@@ -1412,7 +1411,7 @@ void Foliage::OnEnable()
void Foliage::OnDisable() void Foliage::OnDisable()
{ {
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey); GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
// Base // Base
Actor::OnDisable(); Actor::OnDisable();

View File

@@ -629,7 +629,7 @@ void RenderList::ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsL
} }
for (int32 i = 0; i < list.PreBatchedDrawCalls.Count(); i++) for (int32 i = 0; i < list.PreBatchedDrawCalls.Count(); i++)
{ {
auto& batch = BatchedDrawCalls[list.PreBatchedDrawCalls[i]]; auto& batch = BatchedDrawCalls.Get()[list.PreBatchedDrawCalls.Get()[i]];
if (batch.Instances.Count() > 1) if (batch.Instances.Count() > 1)
batchesCount += batch.Instances.Count(); batchesCount += batch.Instances.Count();
} }
@@ -661,7 +661,7 @@ void RenderList::ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsL
} }
for (int32 i = 0; i < list.PreBatchedDrawCalls.Count(); i++) for (int32 i = 0; i < list.PreBatchedDrawCalls.Count(); i++)
{ {
auto& batch = BatchedDrawCalls[list.PreBatchedDrawCalls[i]]; auto& batch = BatchedDrawCalls.Get()[list.PreBatchedDrawCalls.Get()[i]];
if (batch.Instances.Count() > 1) if (batch.Instances.Count() > 1)
{ {
Platform::MemoryCopy(instanceData, batch.Instances.Get(), batch.Instances.Count() * sizeof(InstanceData)); Platform::MemoryCopy(instanceData, batch.Instances.Get(), batch.Instances.Count() * sizeof(InstanceData));
@@ -736,7 +736,7 @@ DRAW:
} }
for (int32 i = 0; i < list.PreBatchedDrawCalls.Count(); i++) for (int32 i = 0; i < list.PreBatchedDrawCalls.Count(); i++)
{ {
auto& batch = BatchedDrawCalls[list.PreBatchedDrawCalls[i]]; auto& batch = BatchedDrawCalls.Get()[list.PreBatchedDrawCalls.Get()[i]];
auto& drawCall = batch.DrawCall; auto& drawCall = batch.DrawCall;
int32 vbCount = 0; int32 vbCount = 0;
@@ -812,7 +812,7 @@ DRAW:
} }
for (int32 i = 0; i < list.PreBatchedDrawCalls.Count(); i++) for (int32 i = 0; i < list.PreBatchedDrawCalls.Count(); i++)
{ {
auto& batch = BatchedDrawCalls[list.PreBatchedDrawCalls[i]]; auto& batch = BatchedDrawCalls.Get()[list.PreBatchedDrawCalls.Get()[i]];
auto drawCall = batch.DrawCall; auto drawCall = batch.DrawCall;
bindParams.FirstDrawCall = &drawCall; bindParams.FirstDrawCall = &drawCall;
const auto* instancesData = batch.Instances.Get(); const auto* instancesData = batch.Instances.Get();

View File

@@ -242,7 +242,7 @@ struct DrawCallsList
/// <summary> /// <summary>
/// The list of external draw calls indices to render. /// The list of external draw calls indices to render.
/// </summary> /// </summary>
Array<int32> PreBatchedDrawCalls; ConcurrentArray<int32> PreBatchedDrawCalls;
/// <summary> /// <summary>
/// The draw calls batches (for instancing). /// The draw calls batches (for instancing).
@@ -296,7 +296,7 @@ public:
/// <summary> /// <summary>
/// Draw calls list with pre-batched instances (for all draw passes). /// Draw calls list with pre-batched instances (for all draw passes).
/// </summary> /// </summary>
Array<BatchedDrawCall> BatchedDrawCalls; ConcurrentArray<BatchedDrawCall> BatchedDrawCalls;
/// <summary> /// <summary>
/// The draw calls lists. Each for the separate draw pass. /// The draw calls lists. Each for the separate draw pass.

View File

@@ -49,7 +49,7 @@ void Terrain::UpdateBounds()
} }
BoundingSphere::FromBox(_box, _sphere); BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1) if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey); GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
} }
void Terrain::CacheNeighbors() void Terrain::CacheNeighbors()
@@ -507,6 +507,7 @@ void Terrain::Draw(RenderContext& renderContext)
DrawPass drawModes = (DrawPass)(DrawModes & renderContext.View.Pass); DrawPass drawModes = (DrawPass)(DrawModes & renderContext.View.Pass);
if (drawModes == DrawPass::None) if (drawModes == DrawPass::None)
return; return;
PROFILE_CPU();
if (renderContext.View.Pass == DrawPass::GlobalSDF) if (renderContext.View.Pass == DrawPass::GlobalSDF)
{ {
if ((DrawModes & DrawPass::GlobalSDF) == 0) if ((DrawModes & DrawPass::GlobalSDF) == 0)
@@ -551,12 +552,8 @@ void Terrain::Draw(RenderContext& renderContext)
return; return;
} }
PROFILE_CPU();
// Collect chunks to render and calculate LOD/material for them (required to be done before to gather NeighborLOD) // Collect chunks to render and calculate LOD/material for them (required to be done before to gather NeighborLOD)
static Array<TerrainChunk*> chunks; _drawChunks.Clear();
chunks.Clear();
chunks.EnsureCapacity(_patches.Count() * TerrainPatch::CHUNKS_COUNT);
// Frustum vs Box culling for patches // Frustum vs Box culling for patches
const BoundingFrustum frustum = renderContext.View.CullingFrustum; const BoundingFrustum frustum = renderContext.View.CullingFrustum;
@@ -582,7 +579,7 @@ void Terrain::Draw(RenderContext& renderContext)
if (chunk->PrepareDraw(renderContext)) if (chunk->PrepareDraw(renderContext))
{ {
// Add chunk for drawing // Add chunk for drawing
chunks.Add(chunk); _drawChunks.Add(chunk);
} }
} }
} }
@@ -599,9 +596,9 @@ void Terrain::Draw(RenderContext& renderContext)
} }
// Draw all visible chunks // Draw all visible chunks
for (int32 i = 0; i < chunks.Count(); i++) for (int32 i = 0; i < _drawChunks.Count(); i++)
{ {
chunks[i]->Draw(renderContext); _drawChunks.Get()[i]->Draw(renderContext);
} }
} }
@@ -792,7 +789,7 @@ RigidBody* Terrain::GetAttachedRigidBody() const
void Terrain::OnEnable() void Terrain::OnEnable()
{ {
GetSceneRendering()->AddActor(this, _sceneRenderingKey); GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
#if TERRAIN_USE_PHYSICS_DEBUG #if TERRAIN_USE_PHYSICS_DEBUG
GetSceneRendering()->AddPhysicsDebug<Terrain, &Terrain::DrawPhysicsDebug>(this); GetSceneRendering()->AddPhysicsDebug<Terrain, &Terrain::DrawPhysicsDebug>(this);
#endif #endif
@@ -803,7 +800,7 @@ void Terrain::OnEnable()
void Terrain::OnDisable() void Terrain::OnDisable()
{ {
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey); GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
#if TERRAIN_USE_PHYSICS_DEBUG #if TERRAIN_USE_PHYSICS_DEBUG
GetSceneRendering()->RemovePhysicsDebug<Terrain, &Terrain::DrawPhysicsDebug>(this); GetSceneRendering()->RemovePhysicsDebug<Terrain, &Terrain::DrawPhysicsDebug>(this);
#endif #endif
@@ -844,7 +841,7 @@ void Terrain::OnLayerChanged()
UpdateLayerBits(); UpdateLayerBits();
if (_sceneRenderingKey != -1) if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey); GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
} }
void Terrain::OnActiveInTreeChanged() void Terrain::OnActiveInTreeChanged()

View File

@@ -59,6 +59,7 @@ private:
Vector3 _boundsExtent; Vector3 _boundsExtent;
Float3 _cachedScale; Float3 _cachedScale;
Array<TerrainPatch*, InlinedAllocation<64>> _patches; Array<TerrainPatch*, InlinedAllocation<64>> _patches;
Array<TerrainChunk*> _drawChunks;
public: public: