diff --git a/Source/Engine/Core/Collections/ConcurrentArray.h b/Source/Engine/Core/Collections/ConcurrentArray.h
index 441abeae6..67d933bf9 100644
--- a/Source/Engine/Core/Collections/ConcurrentArray.h
+++ b/Source/Engine/Core/Collections/ConcurrentArray.h
@@ -306,4 +306,21 @@ public:
Memory::ConstructItems(_allocation.Get() + index, &item, 1);
return index;
}
+
+ ///
+ /// Adds the specified item to the collection.
+ ///
+ /// The item to add.
+ /// Index of the added element.
+ 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;
+ }
};
diff --git a/Source/Engine/Foliage/Foliage.cpp b/Source/Engine/Foliage/Foliage.cpp
index d6a8fba44..819293943 100644
--- a/Source/Engine/Foliage/Foliage.cpp
+++ b/Source/Engine/Foliage/Foliage.cpp
@@ -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();
diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp
index 49bfc8f22..7021570aa 100644
--- a/Source/Engine/Renderer/RenderList.cpp
+++ b/Source/Engine/Renderer/RenderList.cpp
@@ -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();
diff --git a/Source/Engine/Renderer/RenderList.h b/Source/Engine/Renderer/RenderList.h
index a0f23f2e7..a95c9ddd6 100644
--- a/Source/Engine/Renderer/RenderList.h
+++ b/Source/Engine/Renderer/RenderList.h
@@ -242,7 +242,7 @@ struct DrawCallsList
///
/// The list of external draw calls indices to render.
///
- Array PreBatchedDrawCalls;
+ ConcurrentArray PreBatchedDrawCalls;
///
/// The draw calls batches (for instancing).
@@ -296,7 +296,7 @@ public:
///
/// Draw calls list with pre-batched instances (for all draw passes).
///
- Array BatchedDrawCalls;
+ ConcurrentArray BatchedDrawCalls;
///
/// The draw calls lists. Each for the separate draw pass.
diff --git a/Source/Engine/Terrain/Terrain.cpp b/Source/Engine/Terrain/Terrain.cpp
index 5d98bdbc0..ec3457f03 100644
--- a/Source/Engine/Terrain/Terrain.cpp
+++ b/Source/Engine/Terrain/Terrain.cpp
@@ -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 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(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(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()
diff --git a/Source/Engine/Terrain/Terrain.h b/Source/Engine/Terrain/Terrain.h
index 7d2ec7714..908bdec11 100644
--- a/Source/Engine/Terrain/Terrain.h
+++ b/Source/Engine/Terrain/Terrain.h
@@ -59,6 +59,7 @@ private:
Vector3 _boundsExtent;
Float3 _cachedScale;
Array> _patches;
+ Array _drawChunks;
public: