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);
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);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
}
{
PROFILE_CPU_NAMED("Create Clusters");
@@ -685,7 +685,7 @@ void Foliage::RebuildClusters()
_box = BoundingBox(_transform.Translation, _transform.Translation);
_sphere = BoundingSphere(_transform.Translation, 0.0f);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
return;
}
@@ -775,7 +775,7 @@ void Foliage::RebuildClusters()
_box = totalBounds;
BoundingSphere::FromBox(_box, _sphere);
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
}
// Insert all instances to the clusters
@@ -1129,8 +1129,29 @@ void Foliage::Draw(RenderContext& renderContext)
batch.DrawCall.Surface.Skinning = nullptr;
batch.DrawCall.WorldDeterminantSign = 1;
const int32 batchIndex = renderContext.List->BatchedDrawCalls.Count();
renderContext.List->BatchedDrawCalls.Add(MoveTemp(batch));
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)
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
if (drawModes & DrawPass::Depth)
@@ -1152,28 +1173,6 @@ void Foliage::Draw(RenderContext& renderContext)
{
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
DrawCluster(renderContext, type.Root, draw);
@@ -1399,12 +1398,12 @@ void Foliage::Deserialize(DeserializeStream& stream, ISerializeModifier* modifie
void Foliage::OnLayerChanged()
{
if (_sceneRenderingKey != -1)
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey);
GetSceneRendering()->UpdateActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
}
void Foliage::OnEnable()
{
GetSceneRendering()->AddActor(this, _sceneRenderingKey);
GetSceneRendering()->AddActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
// Base
Actor::OnEnable();
@@ -1412,7 +1411,7 @@ void Foliage::OnEnable()
void Foliage::OnDisable()
{
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey);
GetSceneRendering()->RemoveActor(this, _sceneRenderingKey, SceneRendering::SceneDrawAsync);
// Base
Actor::OnDisable();

View File

@@ -629,7 +629,7 @@ void RenderList::ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsL
}
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)
batchesCount += batch.Instances.Count();
}
@@ -661,7 +661,7 @@ void RenderList::ExecuteDrawCalls(const RenderContext& renderContext, DrawCallsL
}
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)
{
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++)
{
auto& batch = BatchedDrawCalls[list.PreBatchedDrawCalls[i]];
auto& batch = BatchedDrawCalls.Get()[list.PreBatchedDrawCalls.Get()[i]];
auto& drawCall = batch.DrawCall;
int32 vbCount = 0;
@@ -812,7 +812,7 @@ DRAW:
}
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;
bindParams.FirstDrawCall = &drawCall;
const auto* instancesData = batch.Instances.Get();

View File

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

View File

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

View File

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