Optimize updating actor rendering entry with better thread locking that support async writes on actor update
This commit is contained in:
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user