Fix crash when loading CollisionData before physics init

#3971
This commit is contained in:
Wojtek Figat
2026-03-26 12:28:31 +01:00
parent 0f09cad1cf
commit a48ce78733
4 changed files with 42 additions and 11 deletions

View File

@@ -8,6 +8,8 @@
#include "Loading/Tasks/LoadAssetTask.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/LogContext.h"
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Physics/Physics.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Profiler/ProfilerMemory.h"
#include "Engine/Scripting/ManagedCLR/MCore.h"
@@ -703,6 +705,38 @@ void Asset::onUnload_MainThread()
OnUnloaded(this);
}
bool Asset::WaitForInitGraphics()
{
#define IS_GPU_NOT_READY() (GPUDevice::Instance == nullptr || GPUDevice::Instance->GetState() != GPUDevice::DeviceState::Ready)
if (!IsInMainThread() && IS_GPU_NOT_READY())
{
PROFILE_CPU();
ZoneColor(TracyWaitZoneColor);
int32 timeout = 1000;
while (IS_GPU_NOT_READY() && timeout-- > 0)
Platform::Sleep(1);
if (IS_GPU_NOT_READY())
return true;
}
#undef IS_GPU_NOT_READY
return false;
}
bool Asset::WaitForInitPhysics()
{
if (!IsInMainThread() && !Physics::DefaultScene)
{
PROFILE_CPU();
ZoneColor(TracyWaitZoneColor);
int32 timeout = 1000;
while (!Physics::DefaultScene && timeout-- > 0)
Platform::Sleep(1);
if (!Physics::DefaultScene)
return true;
}
return false;
}
#if USE_EDITOR
bool Asset::OnCheckSave(const StringView& path) const

View File

@@ -285,6 +285,10 @@ protected:
virtual void onRename(const StringView& newPath) = 0;
#endif
// Utilities to ensure specific engine systems are initialized before loading asset (eg. assets can be loaded during engine startup).
static bool WaitForInitGraphics();
static bool WaitForInitPhysics();
public:
// [ManagedScriptingObject]
String ToString() const override;

View File

@@ -5,7 +5,6 @@
#include "Engine/Core/Types/DataContainer.h"
#include "Engine/Content/Upgraders/ShaderAssetUpgrader.h"
#include "Engine/Content/Factories/BinaryAssetFactory.h"
#include "Engine/Graphics/GPUDevice.h"
#include "Engine/Graphics/RenderTools.h"
#include "Engine/Graphics/Materials/MaterialShader.h"
#include "Engine/Graphics/Shaders/Cache/ShaderCacheManager.h"
@@ -156,16 +155,8 @@ Asset::LoadResult Material::load()
FlaxChunk* materialParamsChunk;
// Wait for the GPU Device to be ready (eg. case when loading material before GPU init)
#define IS_GPU_NOT_READY() (GPUDevice::Instance == nullptr || GPUDevice::Instance->GetState() != GPUDevice::DeviceState::Ready)
if (!IsInMainThread() && IS_GPU_NOT_READY())
{
int32 timeout = 1000;
while (IS_GPU_NOT_READY() && timeout-- > 0)
Platform::Sleep(1);
if (IS_GPU_NOT_READY())
return LoadResult::InvalidData;
}
#undef IS_GPU_NOT_READY
if (WaitForInitGraphics())
return LoadResult::CannotLoadData;
// If engine was compiled with shaders compiling service:
// - Material should be changed in need to convert it to the newer version (via Visject Surface)

View File

@@ -257,6 +257,8 @@ Asset::LoadResult CollisionData::load()
CollisionData::LoadResult CollisionData::load(const SerializedOptions* options, byte* dataPtr, int32 dataSize)
{
if (WaitForInitPhysics())
return LoadResult::CannotLoadData;
PROFILE_MEM(Physics);
// Load options