BGE: Fix issues with async libload.
This patch fixes: - the call of LibFree on a unfinished loaded library; - memory leak created on end of game : the async libraries are loaded but not converted, so not freed with the master scene. Reviewers: campbellbarton, sybren, youle, hg1, moguri, lordloki Reviewed By: moguri, lordloki Differential Revision: https://developer.blender.org/D1571
This commit is contained in:
parent
0d59acccd3
commit
06d2ad0185
|
@ -25,6 +25,12 @@ base class --- :class:`PyObjectPlus`
|
|||
|
||||
:type: callable
|
||||
|
||||
.. attribute:: finished
|
||||
|
||||
The current status of the lib load.
|
||||
|
||||
:type: boolean
|
||||
|
||||
.. attribute:: progress
|
||||
|
||||
The current progress of the lib load as a normalized value from 0.0 to 1.0.
|
||||
|
|
|
@ -138,14 +138,6 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
|
|||
// clears meshes, and hashmaps from blender to gameengine data
|
||||
// delete sumoshapes
|
||||
|
||||
if (m_threadinfo) {
|
||||
BLI_task_pool_work_and_wait(m_threadinfo->m_pool);
|
||||
BLI_task_pool_free(m_threadinfo->m_pool);
|
||||
|
||||
BLI_mutex_end(&m_threadinfo->m_mutex);
|
||||
delete m_threadinfo;
|
||||
}
|
||||
|
||||
int numAdtLists = m_map_blender_to_gameAdtList.size();
|
||||
for (int i = 0; i < numAdtLists; i++) {
|
||||
BL_InterpolatorList *adtList = *m_map_blender_to_gameAdtList.at(i);
|
||||
|
@ -188,6 +180,15 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
|
|||
}
|
||||
|
||||
m_DynamicMaggie.clear();
|
||||
|
||||
if (m_threadinfo) {
|
||||
/* Thread infos like mutex must be freed after FreeBlendFile function.
|
||||
Because it needs to lock the mutex, even if there's no active task when it's
|
||||
in the scene converter destructor. */
|
||||
BLI_task_pool_free(m_threadinfo->m_pool);
|
||||
BLI_mutex_end(&m_threadinfo->m_mutex);
|
||||
delete m_threadinfo;
|
||||
}
|
||||
}
|
||||
|
||||
void KX_BlenderSceneConverter::SetNewFileName(const STR_String &filename)
|
||||
|
@ -806,6 +807,16 @@ void KX_BlenderSceneConverter::MergeAsyncLoads()
|
|||
BLI_mutex_unlock(&m_threadinfo->m_mutex);
|
||||
}
|
||||
|
||||
void KX_BlenderSceneConverter::FinalizeAsyncLoads()
|
||||
{
|
||||
// Finish all loading libraries.
|
||||
if (m_threadinfo) {
|
||||
BLI_task_pool_work_and_wait(m_threadinfo->m_pool);
|
||||
}
|
||||
// Merge all libraries data in the current scene, to avoid memory leak of unmerged scenes.
|
||||
MergeAsyncLoads();
|
||||
}
|
||||
|
||||
void KX_BlenderSceneConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status)
|
||||
{
|
||||
BLI_mutex_lock(&m_threadinfo->m_mutex);
|
||||
|
@ -1017,7 +1028,19 @@ bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie)
|
|||
|
||||
if (maggie == NULL)
|
||||
return false;
|
||||
|
||||
|
||||
// If the given library is currently in loading, we do nothing.
|
||||
if (m_status_map.count(maggie->name)) {
|
||||
BLI_mutex_lock(&m_threadinfo->m_mutex);
|
||||
const bool finished = m_status_map[maggie->name]->IsFinished();
|
||||
BLI_mutex_unlock(&m_threadinfo->m_mutex);
|
||||
|
||||
if (!finished) {
|
||||
printf("Library (%s) is currently being loaded asynchronously, and cannot be freed until this process is done\n", maggie->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* tag all false except the one we remove */
|
||||
for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) {
|
||||
Main *main = *it;
|
||||
|
|
|
@ -184,6 +184,7 @@ public:
|
|||
bool FreeBlendFile(const char *path);
|
||||
|
||||
virtual void MergeAsyncLoads();
|
||||
virtual void FinalizeAsyncLoads();
|
||||
void AddScenesToMergeQueue(class KX_LibLoadStatus *status);
|
||||
|
||||
void PrintStats() {
|
||||
|
|
|
@ -36,7 +36,8 @@ KX_LibLoadStatus::KX_LibLoadStatus(class KX_BlenderSceneConverter* kx_converter,
|
|||
m_mergescene(merge_scene),
|
||||
m_data(NULL),
|
||||
m_libname(path),
|
||||
m_progress(0.f)
|
||||
m_progress(0.0f),
|
||||
m_finished(false)
|
||||
#ifdef WITH_PYTHON
|
||||
,
|
||||
m_finish_cb(NULL),
|
||||
|
@ -48,6 +49,7 @@ KX_LibLoadStatus::KX_LibLoadStatus(class KX_BlenderSceneConverter* kx_converter,
|
|||
|
||||
void KX_LibLoadStatus::Finish()
|
||||
{
|
||||
m_finished = true;
|
||||
m_progress = 1.f;
|
||||
m_endtime = PIL_check_seconds_timer();
|
||||
|
||||
|
@ -157,6 +159,7 @@ PyAttributeDef KX_LibLoadStatus::Attributes[] = {
|
|||
KX_PYATTRIBUTE_FLOAT_RO("progress", KX_LibLoadStatus, m_progress),
|
||||
KX_PYATTRIBUTE_STRING_RO("libraryName", KX_LibLoadStatus, m_libname),
|
||||
KX_PYATTRIBUTE_RO_FUNCTION("timeTaken", KX_LibLoadStatus, pyattr_get_timetaken),
|
||||
KX_PYATTRIBUTE_BOOL_RO("finished", KX_LibLoadStatus, m_finished),
|
||||
{ NULL } //Sentinel
|
||||
};
|
||||
|
||||
|
|
|
@ -43,6 +43,9 @@ private:
|
|||
double m_starttime;
|
||||
double m_endtime;
|
||||
|
||||
// The current status of this libload, used by the scene converter.
|
||||
bool m_finished;
|
||||
|
||||
#ifdef WITH_PYTHON
|
||||
PyObject* m_finish_cb;
|
||||
PyObject* m_progress_cb;
|
||||
|
@ -68,6 +71,11 @@ public:
|
|||
void SetData(void *data);
|
||||
void *GetData();
|
||||
|
||||
inline bool IsFinished() const
|
||||
{
|
||||
return m_finished;
|
||||
}
|
||||
|
||||
void SetProgress(float progress);
|
||||
float GetProgress();
|
||||
void AddProgress(float progress);
|
||||
|
|
|
@ -64,6 +64,7 @@ public:
|
|||
|
||||
// handle any pending merges from asynchronous loads
|
||||
virtual void MergeAsyncLoads()=0;
|
||||
virtual void FinalizeAsyncLoads() = 0;
|
||||
|
||||
virtual void SetAlwaysUseExpandFraming(bool to_what) = 0;
|
||||
|
||||
|
|
|
@ -1273,6 +1273,7 @@ void KX_KetsjiEngine::StopEngine()
|
|||
{
|
||||
if (m_bInitialized)
|
||||
{
|
||||
m_sceneconverter->FinalizeAsyncLoads();
|
||||
|
||||
if (m_animation_record)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue