Add optional async scene drawing and improve stability
This commit is contained in:
@@ -299,7 +299,7 @@ public:
|
||||
{
|
||||
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)
|
||||
const int32 minCapacity = GetMinCapacity(count);
|
||||
if (minCapacity > capacity)
|
||||
EnsureCapacity(minCapacity);
|
||||
auto ptr = _allocation.Get();
|
||||
@@ -318,7 +318,7 @@ public:
|
||||
{
|
||||
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)
|
||||
const int32 minCapacity = GetMinCapacity(count);
|
||||
if (minCapacity > capacity)
|
||||
EnsureCapacity(minCapacity);
|
||||
auto ptr = _allocation.Get();
|
||||
@@ -327,4 +327,14 @@ public:
|
||||
ASSERT(ptr == _allocation.Get());
|
||||
return index;
|
||||
}
|
||||
|
||||
private:
|
||||
FORCE_INLINE static int32 GetMinCapacity(const int32 count)
|
||||
{
|
||||
// Ensure there is a room for all threads (for example if all possible threads add multiple items at once)
|
||||
// It's kind of UB if ConstructItems or MoveItems is short enough for other threads to append multiple items causing resize
|
||||
// Thus increase the minimum slack space for smaller items (eg. int32 indices which are fast to copy)
|
||||
constexpr int32 slack = PLATFORM_THREADS_LIMIT * (sizeof(T) <= 64 ? 16 : (sizeof(T) <= 512 ? 4 : 2));
|
||||
return count + slack;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1216,7 +1216,7 @@ void Foliage::Draw(RenderContextBatch& renderContextBatch)
|
||||
#if !FOLIAGE_USE_SINGLE_QUAD_TREE
|
||||
// Run async job for each foliage type
|
||||
const RenderView& view = renderContextBatch.GetMainContext().View;
|
||||
if ((view.Pass & DrawPass::GBuffer) && !(view.Pass & (DrawPass::GlobalSDF | DrawPass::GlobalSurfaceAtlas)))
|
||||
if ((view.Pass & DrawPass::GBuffer) && !(view.Pass & (DrawPass::GlobalSDF | DrawPass::GlobalSurfaceAtlas)) && renderContextBatch.EnableAsync)
|
||||
{
|
||||
// Cache data per foliage instance type
|
||||
for (FoliageType& type : FoliageTypes)
|
||||
|
||||
@@ -472,6 +472,11 @@ API_STRUCT(NoDefault) struct RenderContextBatch
|
||||
/// </summary>
|
||||
API_FIELD() Array<uint64, InlinedAllocation<8>> WaitLabels;
|
||||
|
||||
/// <summary>
|
||||
/// Enables using async tasks via Job System when performing drawing.
|
||||
/// </summary>
|
||||
API_FIELD() bool EnableAsync = true;
|
||||
|
||||
RenderContextBatch() = default;
|
||||
RenderContextBatch(SceneRenderTask* task);
|
||||
RenderContextBatch(const RenderContext& context);
|
||||
|
||||
@@ -62,7 +62,7 @@ void SceneRendering::Draw(RenderContextBatch& renderContextBatch, DrawCategory c
|
||||
|
||||
// Draw all visual components
|
||||
_drawListIndex = -1;
|
||||
if (_drawListSize >= 64 && category == SceneDrawAsync)
|
||||
if (_drawListSize >= 64 && category == SceneDrawAsync && renderContextBatch.EnableAsync)
|
||||
{
|
||||
// Run in async via Job System
|
||||
Function<void(int32)> func;
|
||||
|
||||
@@ -353,7 +353,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont
|
||||
|
||||
// Wait for async jobs to finish
|
||||
JobSystem::SetJobStartingOnDispatch(true);
|
||||
for (const int64 label : renderContextBatch.WaitLabels)
|
||||
for (const uint64 label : renderContextBatch.WaitLabels)
|
||||
JobSystem::Wait(label);
|
||||
renderContextBatch.WaitLabels.Clear();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user