Add error log when adding/removign actors during rendering or when ConcurrentSystemLocker deadlocks
This commit is contained in:
@@ -7,9 +7,23 @@
|
|||||||
#include "Engine/Graphics/RenderView.h"
|
#include "Engine/Graphics/RenderView.h"
|
||||||
#include "Engine/Renderer/RenderList.h"
|
#include "Engine/Renderer/RenderList.h"
|
||||||
#include "Engine/Threading/JobSystem.h"
|
#include "Engine/Threading/JobSystem.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
|
||||||
#include "Engine/Profiler/ProfilerCPU.h"
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
#include "Engine/Profiler/ProfilerMemory.h"
|
#include "Engine/Profiler/ProfilerMemory.h"
|
||||||
|
#if !BUILD_RELEASE
|
||||||
|
#include "Engine/Graphics/GPUDevice.h"
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BUILD_RELEASE
|
||||||
|
#define CHECK_SCENE_EDIT_ACCESS()
|
||||||
|
#else
|
||||||
|
#define CHECK_SCENE_EDIT_ACCESS() \
|
||||||
|
if (Locker.HasLock(false) && IsInMainThread() && GPUDevice::Instance && GPUDevice::Instance->IsRendering()) \
|
||||||
|
{ \
|
||||||
|
LOG(Error, "Adding/removing actors during rendering is not supported ({}, '{}').", a->ToString(), a->GetNamePath()); \
|
||||||
|
return; \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ISceneRenderingListener::~ISceneRenderingListener()
|
ISceneRenderingListener::~ISceneRenderingListener()
|
||||||
{
|
{
|
||||||
@@ -148,6 +162,7 @@ void SceneRendering::AddActor(Actor* a, int32& key)
|
|||||||
if (key != -1)
|
if (key != -1)
|
||||||
return;
|
return;
|
||||||
PROFILE_MEM(Graphics);
|
PROFILE_MEM(Graphics);
|
||||||
|
CHECK_SCENE_EDIT_ACCESS();
|
||||||
const int32 category = a->_drawCategory;
|
const int32 category = a->_drawCategory;
|
||||||
ConcurrentSystemLocker::WriteScope lock(Locker, true);
|
ConcurrentSystemLocker::WriteScope lock(Locker, true);
|
||||||
auto& list = Actors[category];
|
auto& list = Actors[category];
|
||||||
@@ -192,6 +207,7 @@ void SceneRendering::UpdateActor(Actor* a, int32& key, ISceneRenderingListener::
|
|||||||
|
|
||||||
void SceneRendering::RemoveActor(Actor* a, int32& key)
|
void SceneRendering::RemoveActor(Actor* a, int32& key)
|
||||||
{
|
{
|
||||||
|
CHECK_SCENE_EDIT_ACCESS();
|
||||||
const int32 category = a->_drawCategory;
|
const int32 category = a->_drawCategory;
|
||||||
ConcurrentSystemLocker::WriteScope lock(Locker, true);
|
ConcurrentSystemLocker::WriteScope lock(Locker, true);
|
||||||
auto& list = Actors[category];
|
auto& list = Actors[category];
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
#include "ConcurrentSystemLocker.h"
|
#include "ConcurrentSystemLocker.h"
|
||||||
#include "Engine/Platform/Platform.h"
|
#include "Engine/Platform/Platform.h"
|
||||||
|
#if !BUILD_RELEASE
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
ConcurrentSystemLocker::ConcurrentSystemLocker()
|
ConcurrentSystemLocker::ConcurrentSystemLocker()
|
||||||
{
|
{
|
||||||
@@ -12,7 +15,25 @@ void ConcurrentSystemLocker::Begin(bool write, bool exclusively)
|
|||||||
{
|
{
|
||||||
volatile int64* thisCounter = &_counters[write];
|
volatile int64* thisCounter = &_counters[write];
|
||||||
volatile int64* otherCounter = &_counters[!write];
|
volatile int64* otherCounter = &_counters[!write];
|
||||||
|
|
||||||
|
#if !BUILD_RELEASE
|
||||||
|
int32 retries = 0;
|
||||||
|
double startTime = Platform::GetTimeSeconds();
|
||||||
|
#endif
|
||||||
RETRY:
|
RETRY:
|
||||||
|
#if !BUILD_RELEASE
|
||||||
|
retries++;
|
||||||
|
if (retries > 1000)
|
||||||
|
{
|
||||||
|
double endTime = Platform::GetTimeSeconds();
|
||||||
|
if (endTime - startTime > 0.5f)
|
||||||
|
{
|
||||||
|
LOG(Error, "Deadlock detected in ConcurrentSystemLocker! Thread 0x{0:x} waits for {1} ms...", Platform::GetCurrentThreadID(), (int32)((endTime - startTime) * 1000.0));
|
||||||
|
retries = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Check if we can enter (cannot read while someone else is writing and vice versa)
|
// Check if we can enter (cannot read while someone else is writing and vice versa)
|
||||||
if (Platform::AtomicRead(otherCounter) != 0)
|
if (Platform::AtomicRead(otherCounter) != 0)
|
||||||
{
|
{
|
||||||
@@ -47,3 +68,8 @@ void ConcurrentSystemLocker::End(bool write)
|
|||||||
// Mark that we left this section
|
// Mark that we left this section
|
||||||
Platform::InterlockedDecrement(&_counters[write]);
|
Platform::InterlockedDecrement(&_counters[write]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ConcurrentSystemLocker::HasLock(bool write) const
|
||||||
|
{
|
||||||
|
return Platform::AtomicRead(&_counters[write]) != 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public:
|
|||||||
|
|
||||||
void Begin(bool write, bool exclusively = false);
|
void Begin(bool write, bool exclusively = false);
|
||||||
void End(bool write);
|
void End(bool write);
|
||||||
|
bool HasLock(bool write) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<bool Write>
|
template<bool Write>
|
||||||
|
|||||||
Reference in New Issue
Block a user