Add async scene drawing for Foliage and Terrain
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user