Skip to content

Commit

Permalink
UPBGE: Handle non-threadable libloading data.
Browse files Browse the repository at this point in the history
As python is badly managing threading, it is better to delay any python call
to the main thread. This situation happen in case of libload is python
components are registered.

The component conversion is moved into the function BL_PostConvertBlenderObjects
which can later manage more than just the components. This function is
called by BL_Converter::PostConvertScene based on a scene converter.
Because the post conversion needs to iterate over all the objects, the scene
converter expose a list of all the objects registered (active and inactive).

The introduction of this new function helped to clarify the process of scene
or data conversion.
For a simple scene conversion without merge:
- scene creation
- conversion (BL_Converter::ConvertScene)
- post conversion (BL_Converter::PostConvertScene)
- finalizing data (BL_Converter::FinalizeSceneData)

This procedure can be find in KX_KetsjiEngine::ConvertScene, FinalizeSceneData
does less work than before as it is calling KX_BlenderMaterial::InitShader
to create the shaders and so assume that all the data are using the correct
scene. In consideration during a merge of scene an extra step is required
to set the destination scene in the mesh and material. This is an effect of
the BL_Converter::MergeSceneData which also merge to the destination SceneSlot
the scene converter of the scene to merge.

To summarize, in case of libload, the procedure is:
- scene creation (optional)
- conversion
- post conversion (optional)
- merging data (BL_Converter::MergeSceneData)
- merging scene (KX_Scene::MergeScene) (optional)
- finalizing data

FinalizeSceneData is still called after the merging of the scene because the
material shaders are depending of the scene state and especially the lamps
contained by the scene used to generate the shader.
  • Loading branch information
panzergame committed Aug 19, 2018
1 parent a7c5a5f commit 8765a15
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 101 deletions.
71 changes: 38 additions & 33 deletions source/gameengine/Converter/BL_BlenderDataConversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ static RAS_MaterialBucket *BL_ConvertMaterial(Material *ma, KX_Scene *scene, BL_
name = "MA";
}

mat = new KX_BlenderMaterial(ma, name);
mat = new KX_BlenderMaterial(ma, name, scene);

// this is needed to free up memory afterwards.
converter.RegisterMaterial(mat, ma);
Expand Down Expand Up @@ -1195,7 +1195,6 @@ static void bl_ConvertBlenderObject_Single(BL_SceneConverter& converter,
std::vector<BL_ParentChildLink> &vec_parent_child,
EXP_ListValue<KX_GameObject> *logicbrick_conversionlist,
EXP_ListValue<KX_GameObject> *objectlist, EXP_ListValue<KX_GameObject> *inactivelist,
EXP_ListValue<KX_GameObject> *sumolist,
KX_Scene *kxscene, KX_GameObject *gameobj,
SCA_LogicManager *logicmgr, SCA_TimeEventManager *timemgr,
bool isInActiveLayer)
Expand All @@ -1219,8 +1218,6 @@ static void bl_ConvertBlenderObject_Single(BL_SceneConverter& converter,
gameobj->NodeSetLocalScale(scale);
gameobj->NodeUpdate();

sumolist->Add(CM_AddRef(gameobj));

BL_ConvertProperties(blenderobject, gameobj, timemgr, kxscene, isInActiveLayer);

gameobj->SetName(blenderobject->id.name + 2);
Expand Down Expand Up @@ -1293,7 +1290,7 @@ void BL_ConvertBlenderObjects(struct Main *maggie,
blenderobject, \
vec_parent_child, \
logicbrick_conversionlist, \
objectlist, inactivelist, sumolist, \
objectlist, inactivelist, \
kxscene, gameobj, \
logicmgr, timemgr, \
isInActiveLayer \
Expand Down Expand Up @@ -1417,9 +1414,6 @@ void BL_ConvertBlenderObjects(struct Main *maggie,

int activeLayerBitInfo = blenderscene->lay;

// List of all object converted, active and inactive.
EXP_ListValue<KX_GameObject> *sumolist = new EXP_ListValue<KX_GameObject>();

std::vector<BL_ParentChildLink> vec_parent_child;

EXP_ListValue<KX_GameObject> *objectlist = kxscene->GetObjectList();
Expand Down Expand Up @@ -1547,9 +1541,6 @@ void BL_ConvertBlenderObjects(struct Main *maggie,
// The returned list by GetChildrenRecursive is not owned by anyone and must not own items, so no AddRef().
childrenlist.push_back(childobj);
for (KX_GameObject *obj : childrenlist) {
if (sumolist->RemoveValue(obj)) {
obj->Release();
}
if (logicbrick_conversionlist->RemoveValue(obj)) {
obj->Release();
}
Expand Down Expand Up @@ -1603,6 +1594,8 @@ void BL_ConvertBlenderObjects(struct Main *maggie,
}
vec_parent_child.clear();

const std::vector<KX_GameObject *>& sumolist = converter.GetObjects();

// Find 'root' parents (object that has not parents in SceneGraph).
for (KX_GameObject *gameobj : sumolist) {
if (!gameobj->GetNode()->GetParent()) {
Expand Down Expand Up @@ -1788,11 +1781,14 @@ void BL_ConvertBlenderObjects(struct Main *maggie,
continue;
}

KX_GameObject *gotar = sumolist->FindValue(dat->tar->id.name + 2);

if (gotar && (gotar->GetLayer() & activeLayerBitInfo) && gotar->GetPhysicsController() &&
(gameobj->GetLayer() & activeLayerBitInfo) && gameobj->GetPhysicsController()) {
physEnv->SetupObjectConstraints(gameobj, gotar, dat);
for (KX_GameObject *gotar : sumolist) {
if (gotar->GetName() == (dat->tar->id.name + 2) &&
(gotar->GetLayer() & activeLayerBitInfo) && gotar->GetPhysicsController() &&
(gameobj->GetLayer() & activeLayerBitInfo) && gameobj->GetPhysicsController())
{
physEnv->SetupObjectConstraints(gameobj, gotar, dat);
break;
}
}
}
}
Expand Down Expand Up @@ -1857,6 +1853,31 @@ void BL_ConvertBlenderObjects(struct Main *maggie,
gameobj->ResetState();
}

// Cleanup converted set of group objects.
convertedlist->Release();
logicbrick_conversionlist->Release();

/* Instantiate dupli group, we will loop trough the object
* that are in active layers. Note that duplicating group
* has the effect of adding objects at the end of objectlist.
* Only loop through the first part of the list.
*/
int objcount = objectlist->GetCount();
for (unsigned int i = 0; i < objcount; ++i) {
KX_GameObject *gameobj = objectlist->GetValue(i);
if (gameobj->IsDupliGroup()) {
kxscene->DupliGroupRecurse(gameobj, 0);
}
}
}

void BL_PostConvertBlenderObjects(KX_Scene *kxscene, const BL_SceneConverter& sceneconverter)
{
const std::vector<KX_GameObject *>& sumolist = sceneconverter.GetObjects();
EXP_ListValue<KX_GameObject> *objectlist = kxscene->GetObjectList();

#ifdef WITH_PYTHON

// Convert the python components of each object if the component execution is available.
if (G.f & G_SCRIPT_AUTOEXEC) {
for (KX_GameObject *gameobj : sumolist) {
Expand All @@ -1875,22 +1896,6 @@ void BL_ConvertBlenderObjects(struct Main *maggie,
CM_Warning("Python components auto-execution disabled");
}

// Cleanup converted set of group objects.
convertedlist->Release();
sumolist->Release();
logicbrick_conversionlist->Release();

/* Instantiate dupli group, we will loop trough the object
* that are in active layers. Note that duplicating group
* has the effect of adding objects at the end of objectlist.
* Only loop through the first part of the list.
*/
int objcount = objectlist->GetCount();
for (unsigned int i = 0; i < objcount; ++i) {
KX_GameObject *gameobj = objectlist->GetValue(i);
if (gameobj->IsDupliGroup()) {
kxscene->DupliGroupRecurse(gameobj, 0);
}
}
#endif // WITH_PYTHON
}

2 changes: 2 additions & 0 deletions source/gameengine/Converter/BL_BlenderDataConversion.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ RAS_Deformer *BL_ConvertDeformer(KX_GameObject *object, KX_Mesh *meshobj);
void BL_ConvertBlenderObjects(Main *maggie, KX_Scene *kxscene, KX_KetsjiEngine *ketsjiEngine,
RAS_Rasterizer *rendertools, RAS_ICanvas *canvas, BL_SceneConverter& sceneconverter,
bool alwaysUseExpandFraming, float camZoom, bool libloading);
// Non-multithreadable conversion.
void BL_PostConvertBlenderObjects(KX_Scene *kxscene, const BL_SceneConverter& sceneconverter);


SCA_IInputDevice::SCA_EnumInputs BL_ConvertKeyCode(int key_code);
Expand Down
79 changes: 37 additions & 42 deletions source/gameengine/Converter/BL_Converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@

#include "KX_Scene.h"
#include "KX_GameObject.h"
#include "KX_WorldInfo.h"
#include "KX_Mesh.h"
#include "RAS_BucketManager.h"
#include "KX_PhysicsEngineEnums.h"
Expand Down Expand Up @@ -191,29 +190,15 @@ void BL_Converter::ConvertScene(BL_SceneConverter& converter, bool libloading)
m_alwaysUseExpandFraming,
m_camZoom,
libloading);

m_sceneSlots.emplace(scene, converter);
}

void BL_Converter::FinalizeSceneData(const BL_SceneConverter& converter, KX_Scene *mergeScene)
void BL_Converter::PostConvertScene(const BL_SceneConverter& converter)
{
for (KX_Mesh *mesh : converter.m_meshobjects) {
mesh->ReplaceScene(mergeScene);
}

for (KX_BlenderMaterial *mat : converter.m_materials) {
// Do this after lights are available so materials can use the lights in shaders.
mat->InitScene(mergeScene);
}
BL_PostConvertBlenderObjects(converter.GetScene(), converter);
}

void BL_Converter::RemoveScene(KX_Scene *scene)
{
KX_WorldInfo *world = scene->GetWorldInfo();
if (world) {
delete world;
}

#ifdef WITH_PYTHON
Texture::FreeAllTextures(scene);
#endif // WITH_PYTHON
Expand Down Expand Up @@ -280,11 +265,7 @@ void BL_Converter::MergeAsyncLoads()
for (KX_LibLoadStatus *libload : m_mergequeue) {
KX_Scene *mergeScene = libload->GetMergeScene();
for (const BL_SceneConverter& converter : libload->GetSceneConverters()) {
KX_Scene *scene = converter.GetScene();
MergeScene(mergeScene, scene);
// Finalize material and mesh conversion.
FinalizeSceneData(converter, mergeScene);
delete scene;
MergeScene(mergeScene, converter);
}

libload->Finish();
Expand Down Expand Up @@ -313,7 +294,6 @@ void BL_Converter::AddScenesToMergeQueue(KX_LibLoadStatus *status)
static void async_convert(TaskPool *pool, void *ptr, int UNUSED(threadid))
{
KX_LibLoadStatus *status = static_cast<KX_LibLoadStatus *>(ptr);
KX_KetsjiEngine *engine = status->GetEngine();
BL_Converter *converter = status->GetConverter();

const std::vector<KX_Scene *>& scenes = status->GetScenes();
Expand Down Expand Up @@ -438,9 +418,8 @@ KX_LibLoadStatus *BL_Converter::LinkBlendFile(BlendHandle *blendlib, const char
scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj);
}

// Finalize material and mesh conversion.
FinalizeSceneData(sceneConverter, scene_merge);
m_sceneSlots[scene_merge].Merge(sceneConverter);
MergeSceneData(scene_merge, sceneConverter);
FinalizeSceneData(sceneConverter);
}
else if (idcode == ID_AC) {
// Convert all actions
Expand Down Expand Up @@ -483,13 +462,7 @@ KX_LibLoadStatus *BL_Converter::LinkBlendFile(BlendHandle *blendlib, const char

BL_SceneConverter sceneConverter(other);
ConvertScene(sceneConverter, true);

MergeScene(scene_merge, other);

// Finalize material and mesh conversion.
FinalizeSceneData(sceneConverter, scene_merge);

delete other;
MergeScene(scene_merge, sceneConverter);
}
}

Expand Down Expand Up @@ -706,16 +679,39 @@ bool BL_Converter::FreeBlendFile(const std::string& path)
return FreeBlendFile(GetMainDynamicPath(path));
}

void BL_Converter::MergeScene(KX_Scene *to, KX_Scene *from)
void BL_Converter::MergeSceneData(KX_Scene *to, const BL_SceneConverter& converter)
{
for (KX_Mesh *mesh : converter.m_meshobjects) {
mesh->ReplaceScene(to);
}

// Do this after lights are available (scene merged) so materials can use the lights in shaders.
for (KX_BlenderMaterial *mat : converter.m_materials) {
mat->ReplaceScene(to);
}

m_sceneSlots[to].Merge(converter);
}

void BL_Converter::MergeScene(KX_Scene *to, const BL_SceneConverter& converter)
{
PostConvertScene(converter);

MergeSceneData(to, converter);

KX_Scene *from = converter.GetScene();
to->MergeScene(from);

m_sceneSlots[to].Merge(m_sceneSlots[from]);
m_sceneSlots.erase(from);
FinalizeSceneData(converter);

delete from;
}

// Delete from scene's world info.
delete from->GetWorldInfo();
from->SetWorldInfo(nullptr);
void BL_Converter::FinalizeSceneData(const BL_SceneConverter& converter)
{
for (KX_BlenderMaterial *mat : converter.m_materials) {
mat->InitShader();
}
}

/** This function merges a mesh from the current scene into another main
Expand Down Expand Up @@ -797,9 +793,8 @@ KX_Mesh *BL_Converter::ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, cons
KX_Mesh *meshobj = BL_ConvertMesh((Mesh *)me, nullptr, kx_scene, sceneConverter);
kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj);

// Finalize material and mesh conversion.
FinalizeSceneData(sceneConverter, kx_scene);
m_sceneSlots[kx_scene].Merge(sceneConverter);
MergeSceneData(kx_scene, sceneConverter);
FinalizeSceneData(sceneConverter);

return meshobj;
}
Expand Down
30 changes: 22 additions & 8 deletions source/gameengine/Converter/BL_Converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,20 +106,36 @@ class BL_Converter
bool m_alwaysUseExpandFraming;
float m_camZoom;

/** Merge all data contained in the scene converter to the scene slot of
* the destination scene and update the data to use the destination scene.
* \param to The destination scene.
* \param converter The scene converted of the data to merge.
*/
void MergeSceneData(KX_Scene *to, const BL_SceneConverter& converter);

/** Complete process of scene merging:
* - post convert
* - merge data
* - merge scene (KX_Scene::MergeScene)
* - finalize data
*/
void MergeScene(KX_Scene *to, const BL_SceneConverter& converter);

public:
BL_Converter(Main *maggie, KX_KetsjiEngine *engine, bool alwaysUseExpandFraming, float camZoom);
virtual ~BL_Converter();

void ConvertScene(BL_SceneConverter& converter, bool libloading);

/** Generate shaders and mesh attributes depending on.
* This function is separated from ConvertScene to be synchronized when compiling shaders
* and select a scene to generate shaders with. This last point is used for scene libload
* merging.
/** Convert all scene data that can't in a separate thread such as python components.
* \param converter The scene convert to finalize.
* \param mergeScene The scene used to generate shaders.
*/
void FinalizeSceneData(const BL_SceneConverter& converter, KX_Scene *mergeScene);
void PostConvertScene(const BL_SceneConverter& converter);

/** Finalize all data depending on scene context after a potential scene merging,
* such as shader creation depending on lights into scene.
*/
void FinalizeSceneData(const BL_SceneConverter& converter);

/** This function removes all entities stored in the converter for that scene
* It should be used instead of direct delete scene
Expand Down Expand Up @@ -151,8 +167,6 @@ class BL_Converter

KX_Mesh *ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, const std::string& name);

void MergeScene(KX_Scene *to, KX_Scene *from);

void MergeAsyncLoads();
void FinalizeAsyncLoads();
void AddScenesToMergeQueue(KX_LibLoadStatus *status);
Expand Down
11 changes: 11 additions & 0 deletions source/gameengine/Converter/BL_SceneConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include "BL_ConvertObjectInfo.h"
#include "KX_GameObject.h"

#include "CM_List.h"

BL_SceneConverter::BL_SceneConverter(KX_Scene *scene)
:m_scene(scene)
{
Expand All @@ -43,6 +45,7 @@ BL_SceneConverter::BL_SceneConverter(BL_SceneConverter&& other)
m_materials(std::move(other.m_materials)),
m_meshobjects(std::move(other.m_meshobjects)),
m_objectInfos(std::move(other.m_objectInfos)),
m_objects(std::move(other.m_objects)),
m_blenderToObjectInfos(std::move(other.m_blenderToObjectInfos)),
m_map_blender_to_gameobject(std::move(other.m_map_blender_to_gameobject)),
m_map_mesh_to_gamemesh(std::move(other.m_map_mesh_to_gamemesh)),
Expand All @@ -61,6 +64,7 @@ void BL_SceneConverter::RegisterGameObject(KX_GameObject *gameobject, Object *fo
{
// only maintained while converting, freed during game runtime
m_map_blender_to_gameobject[for_blenderobject] = gameobject;
m_objects.push_back(gameobject);
}

/** only need to run this during conversion since
Expand All @@ -76,6 +80,8 @@ void BL_SceneConverter::UnregisterGameObject(KX_GameObject *gameobject)
m_map_blender_to_gameobject.erase(it);
}
}

CM_ListRemoveIfFound(m_objects, gameobject);
}

KX_GameObject *BL_SceneConverter::FindGameObject(Object *for_blenderobject)
Expand Down Expand Up @@ -140,3 +146,8 @@ BL_ConvertObjectInfo *BL_SceneConverter::GetObjectInfo(Object *blenderobj)

return it->second;
}

const std::vector<KX_GameObject *> &BL_SceneConverter::GetObjects() const
{
return m_objects;
}
Loading

0 comments on commit 8765a15

Please sign in to comment.