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: