Optimize updating actor rendering entry with better thread locking that support async writes on actor update

This commit is contained in:
Wojtek Figat
2025-06-19 14:04:06 +02:00
parent 4ac870f701
commit 2e10d776e9
3 changed files with 10 additions and 10 deletions

View File

@@ -43,7 +43,7 @@ FORCE_INLINE bool FrustumsListCull(const BoundingSphere& bounds, const Array<Bou
void SceneRendering::Draw(RenderContextBatch& renderContextBatch, DrawCategory category) void SceneRendering::Draw(RenderContextBatch& renderContextBatch, DrawCategory category)
{ {
PROFILE_MEM(Graphics); PROFILE_MEM(Graphics);
ScopeLock lock(Locker); ConcurrentSystemLocker::ReadScope lock(Locker);
if (category == PreRender) if (category == PreRender)
{ {
// Register scene // Register scene
@@ -51,12 +51,12 @@ void SceneRendering::Draw(RenderContextBatch& renderContextBatch, DrawCategory c
renderContext.List->Scenes.Add(this); renderContext.List->Scenes.Add(this);
// Add additional lock during scene rendering (prevents any Actors cache modifications on content streaming threads - eg. when model residency changes) // Add additional lock during scene rendering (prevents any Actors cache modifications on content streaming threads - eg. when model residency changes)
Locker.Lock(); Locker.Begin(false);
} }
else if (category == PostRender) else if (category == PostRender)
{ {
// Release additional lock // Release additional lock
Locker.Unlock(); Locker.End(false);
} }
auto& view = renderContextBatch.GetMainContext().View; auto& view = renderContextBatch.GetMainContext().View;
auto& list = Actors[(int32)category]; auto& list = Actors[(int32)category];
@@ -127,7 +127,7 @@ void SceneRendering::CollectPostFxVolumes(RenderContext& renderContext)
void SceneRendering::Clear() void SceneRendering::Clear()
{ {
ScopeLock lock(Locker); ConcurrentSystemLocker::WriteScope lock(Locker);
for (auto* listener : _listeners) for (auto* listener : _listeners)
{ {
listener->OnSceneRenderingClear(this); listener->OnSceneRenderingClear(this);
@@ -149,7 +149,7 @@ void SceneRendering::AddActor(Actor* a, int32& key)
return; return;
PROFILE_MEM(Graphics); PROFILE_MEM(Graphics);
const int32 category = a->_drawCategory; const int32 category = a->_drawCategory;
ScopeLock lock(Locker); ConcurrentSystemLocker::WriteScope lock(Locker);
auto& list = Actors[category]; auto& list = Actors[category];
if (FreeActors[category].HasItems()) if (FreeActors[category].HasItems())
{ {
@@ -174,7 +174,7 @@ void SceneRendering::AddActor(Actor* a, int32& key)
void SceneRendering::UpdateActor(Actor* a, int32& key, ISceneRenderingListener::UpdateFlags flags) void SceneRendering::UpdateActor(Actor* a, int32& key, ISceneRenderingListener::UpdateFlags flags)
{ {
const int32 category = a->_drawCategory; const int32 category = a->_drawCategory;
ScopeLock lock(Locker); ConcurrentSystemLocker::ReadScope lock(Locker); // Read-access only as list doesn't get resized (like Add/Remove do) so allow updating actors from different threads at once
auto& list = Actors[category]; auto& list = Actors[category];
if (list.Count() <= key) // Ignore invalid key softly if (list.Count() <= key) // Ignore invalid key softly
return; return;
@@ -193,7 +193,7 @@ void SceneRendering::UpdateActor(Actor* a, int32& key, ISceneRenderingListener::
void SceneRendering::RemoveActor(Actor* a, int32& key) void SceneRendering::RemoveActor(Actor* a, int32& key)
{ {
const int32 category = a->_drawCategory; const int32 category = a->_drawCategory;
ScopeLock lock(Locker); ConcurrentSystemLocker::WriteScope lock(Locker);
auto& list = Actors[category]; auto& list = Actors[category];
if (list.Count() > key) // Ignore invalid key softly (eg. list after batch clear during scene unload) if (list.Count() > key) // Ignore invalid key softly (eg. list after batch clear during scene unload)
{ {

View File

@@ -7,7 +7,7 @@
#include "Engine/Core/Math/BoundingSphere.h" #include "Engine/Core/Math/BoundingSphere.h"
#include "Engine/Core/Math/BoundingFrustum.h" #include "Engine/Core/Math/BoundingFrustum.h"
#include "Engine/Level/Actor.h" #include "Engine/Level/Actor.h"
#include "Engine/Platform/CriticalSection.h" #include "Engine/Threading/ConcurrentSystemLocker.h"
class SceneRenderTask; class SceneRenderTask;
class SceneRendering; class SceneRendering;
@@ -102,7 +102,7 @@ public:
Array<DrawActor> Actors[MAX]; Array<DrawActor> Actors[MAX];
Array<int32> FreeActors[MAX]; Array<int32> FreeActors[MAX];
Array<IPostFxSettingsProvider*> PostFxProviders; Array<IPostFxSettingsProvider*> PostFxProviders;
CriticalSection Locker; ConcurrentSystemLocker Locker;
private: private:
#if USE_EDITOR #if USE_EDITOR

View File

@@ -18,7 +18,7 @@ RETRY:
{ {
// Someone else is doing opposite operation so wait for it's end // Someone else is doing opposite operation so wait for it's end
// TODO: use ConditionVariable+CriticalSection to prevent active-waiting // TODO: use ConditionVariable+CriticalSection to prevent active-waiting
Platform::Sleep(1); Platform::Sleep(0);
goto RETRY; goto RETRY;
} }