Skip to content

Commit 3d505cd

Browse files
committed
UPBGE: Refactoring scene shader generation.
Previously the shader in a converted scene were loaded in two ways depending if the scene was libloaded or not. When the scene wasn't libloaded BL_ConvertMesh managed the shader generation but in case of libloading this was proceeded in BL_BlenderConverter::MergeScene. To use a common bahaviour the function BL_BlenderConverter::InitSceneShader is introduced, this function iterate over all materials and meshes of a given scene converter and generate both shader and attributes, the function is called from KX_KetsjiEngine::ConvertScene (new function to convert scene), ConvertMeshSpecial, LinkBlendFile and MergeAsyncLoads. In the same time KX_LibLoadStatus is modified to use a list of blender scenes instead of a pointer to opaque data.
1 parent 89a4899 commit 3d505cd

19 files changed

+213
-228
lines changed

source/gameengine/Converter/BL_BlenderConverter.cpp

Lines changed: 75 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ CListValue<CStringValue> *BL_BlenderConverter::GetInactiveSceneNames()
177177
return list;
178178
}
179179

180-
void BL_BlenderConverter::ConvertScene(KX_Scene *destinationscene, RAS_Rasterizer *rasty, RAS_ICanvas *canvas, bool libloading)
180+
void BL_BlenderConverter::ConvertScene(BL_BlenderSceneConverter& converter, bool libloading)
181181
{
182-
182+
KX_Scene *scene = converter.GetScene();
183183
// Find out which physics engine
184-
Scene *blenderscene = destinationscene->GetBlenderScene();
184+
Scene *blenderscene = scene->GetBlenderScene();
185185

186186
PHY_IPhysicsEnvironment *phy_env = nullptr;
187187

@@ -214,31 +214,34 @@ void BL_BlenderConverter::ConvertScene(KX_Scene *destinationscene, RAS_Rasterize
214214
}
215215
}
216216

217-
destinationscene->SetPhysicsEnvironment(phy_env);
218-
219-
BL_BlenderSceneConverter sceneConverter;
217+
scene->SetPhysicsEnvironment(phy_env);
220218

221219
BL_ConvertBlenderObjects(
222220
m_maggie,
223-
destinationscene,
221+
scene,
224222
m_ketsjiEngine,
225223
physics_engine,
226-
rasty,
227-
canvas,
228-
sceneConverter,
224+
m_ketsjiEngine->GetRasterizer(),
225+
m_ketsjiEngine->GetCanvas(),
226+
converter,
229227
m_alwaysUseExpandFraming,
230228
libloading);
231229

232-
m_sceneSlots.emplace(destinationscene, sceneConverter);
230+
m_sceneSlots.emplace(scene, converter);
231+
}
232+
233+
void BL_BlenderConverter::InitSceneShaders(const BL_BlenderSceneConverter& converter, KX_Scene *mergeScene)
234+
{
235+
for (KX_BlenderMaterial *mat : converter.m_materials) {
236+
// Do this after lights are available so materials can use the lights in shaders.
237+
mat->InitScene(mergeScene);
238+
}
239+
for (RAS_MeshObject *meshobj : converter.m_meshobjects) {
240+
// Generate mesh to material attribute's layers since the materials are constructed now.
241+
meshobj->GenerateAttribLayers();
242+
}
233243
}
234244

235-
/** This function removes all entities stored in the converter for that scene
236-
* It should be used instead of direct delete scene
237-
* Note that there was some provision for sharing entities (meshes...) between
238-
* scenes but that is now disabled so all scene will have their own copy
239-
* and we can delete them here. If the sharing is reactivated, change this code too..
240-
* (see BL_BlenderConverter::ConvertScene)
241-
*/
242245
void BL_BlenderConverter::RemoveScene(KX_Scene *scene)
243246
{
244247
KX_WorldInfo *world = scene->GetWorldInfo();
@@ -310,16 +313,15 @@ void BL_BlenderConverter::MergeAsyncLoads()
310313
m_threadinfo.m_mutex.Lock();
311314

312315
for (KX_LibLoadStatus *libload : m_mergequeue) {
313-
std::vector<KX_Scene *> *mergeScenes = (std::vector<KX_Scene *> *)libload->GetData();
314-
315-
for (KX_Scene *scene : *mergeScenes) {
316-
MergeScene(libload->GetMergeScene(), scene);
316+
KX_Scene *mergeScene = libload->GetMergeScene();
317+
for (const BL_BlenderSceneConverter& converter : libload->GetSceneConverters()) {
318+
KX_Scene *scene = converter.GetScene();
319+
MergeScene(mergeScene, scene);
320+
// Finalize material and mesh conversion.
321+
InitSceneShaders(converter, mergeScene);
317322
delete scene;
318323
}
319324

320-
delete mergeScenes;
321-
libload->SetData(nullptr);
322-
323325
libload->Finish();
324326
}
325327

@@ -345,23 +347,22 @@ void BL_BlenderConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status)
345347

346348
static void async_convert(TaskPool *pool, void *ptr, int UNUSED(threadid))
347349
{
348-
KX_Scene *new_scene = nullptr;
349-
KX_LibLoadStatus *status = (KX_LibLoadStatus *)ptr;
350-
std::vector<Scene *> *scenes = (std::vector<Scene *> *)status->GetData();
351-
std::vector<KX_Scene *> *merge_scenes = new std::vector<KX_Scene *>(); // Deleted in MergeAsyncLoads
350+
KX_LibLoadStatus *status = static_cast<KX_LibLoadStatus *>(ptr);
351+
KX_KetsjiEngine *engine = status->GetEngine();
352+
BL_BlenderConverter *converter = status->GetConverter();
352353

353-
for (unsigned int i = 0; i < scenes->size(); ++i) {
354-
new_scene = status->GetEngine()->CreateScene((*scenes)[i], true);
354+
const std::vector<Scene *>& blenderScenes = status->GetBlenderScenes();
355355

356-
if (new_scene) {
357-
merge_scenes->push_back(new_scene);
358-
}
356+
for (Scene *blenderScene : blenderScenes) {
357+
KX_Scene *scene = engine->CreateScene(blenderScene);
359358

360-
status->AddProgress((1.0f / scenes->size()) * 0.9f); // We'll call conversion 90% and merging 10% for now
361-
}
359+
BL_BlenderSceneConverter sceneConverter(scene);
360+
converter->ConvertScene(sceneConverter, true);
361+
362+
status->AddSceneConverter(std::move(sceneConverter));
362363

363-
delete scenes;
364-
status->SetData(merge_scenes);
364+
status->AddProgress((1.0f / blenderScenes.size()) * 0.9f); // We'll call conversion 90% and merging 10% for now
365+
}
365366

366367
status->GetConverter()->AddScenesToMergeQueue(status);
367368
}
@@ -465,14 +466,17 @@ KX_LibLoadStatus *BL_BlenderConverter::LinkBlendFile(BlendHandle *bpy_openlib, c
465466
// Convert all new meshes into BGE meshes
466467
ID *mesh;
467468

468-
BL_BlenderSceneConverter sceneConverter;
469+
BL_BlenderSceneConverter sceneConverter(scene_merge);
469470
for (mesh = (ID *)main_newlib->mesh.first; mesh; mesh = (ID *)mesh->next) {
470471
if (options & LIB_LOAD_VERBOSE) {
471472
CM_Debug("mesh name: " << mesh->name + 2);
472473
}
473-
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, nullptr, scene_merge, sceneConverter, false); // For now only use the libloading option for scenes, which need to handle materials/shaders
474+
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, nullptr, scene_merge, sceneConverter);
474475
scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj);
475476
}
477+
478+
// Finalize material and mesh conversion.
479+
InitSceneShaders(sceneConverter, scene_merge);
476480
m_sceneSlots[scene_merge].Merge(sceneConverter);
477481
}
478482
else if (idcode == ID_AC) {
@@ -488,32 +492,42 @@ KX_LibLoadStatus *BL_BlenderConverter::LinkBlendFile(BlendHandle *bpy_openlib, c
488492
}
489493
else if (idcode == ID_SCE) {
490494
// Merge all new linked in scene into the existing one
491-
ID *scene;
492-
// scenes gets deleted by the thread when it's done using it (look in async_convert())
493-
std::vector<Scene *> *scenes = (options & LIB_LOAD_ASYNC) ? new std::vector<Scene *>() : nullptr;
494495

495-
for (scene = (ID *)main_newlib->scene.first; scene; scene = (ID *)scene->next) {
496-
if (options & LIB_LOAD_VERBOSE) {
497-
CM_Debug("scene name: " << scene->name + 2);
498-
}
496+
if (options & LIB_LOAD_ASYNC) {
497+
std::vector<Scene *> blenderScenes;
498+
for (Scene *scene = (Scene *)main_newlib->scene.first; scene; scene = (Scene *)scene->id.next) {
499+
if (options & LIB_LOAD_VERBOSE) {
500+
CM_Debug("scene name: " << scene->id.name + 2);
501+
}
499502

500-
if (options & LIB_LOAD_ASYNC) {
501-
scenes->push_back((Scene *)scene);
503+
// Build list of scene to convert.
504+
blenderScenes.push_back(scene);
502505
}
503-
else {
506+
507+
status->SetBlenderScenes(blenderScenes);
508+
BLI_task_pool_push(m_threadinfo.m_pool, async_convert, (void *)status, false, TASK_PRIORITY_LOW);
509+
}
510+
else {
511+
for (Scene *scene = (Scene *)main_newlib->scene.first; scene; scene = (Scene *)scene->id.next) {
512+
if (options & LIB_LOAD_VERBOSE) {
513+
CM_Debug("scene name: " << scene->id.name + 2);
514+
}
515+
504516
// merge into the base scene
505-
KX_Scene *other = m_ketsjiEngine->CreateScene((Scene *)scene, true);
517+
KX_Scene *other = m_ketsjiEngine->CreateScene(scene);
518+
519+
BL_BlenderSceneConverter sceneConverter(other);
520+
ConvertScene(sceneConverter, true);
521+
506522
MergeScene(scene_merge, other);
507523

524+
// Finalize material and mesh conversion.
525+
InitSceneShaders(sceneConverter, scene_merge);
526+
508527
delete other;
509528
}
510529
}
511530

512-
if (options & LIB_LOAD_ASYNC) {
513-
status->SetData(scenes);
514-
BLI_task_pool_push(m_threadinfo.m_pool, async_convert, (void *)status, false, TASK_PRIORITY_LOW);
515-
}
516-
517531
#ifdef WITH_PYTHON
518532
// Handle any text datablocks
519533
if (options & LIB_LOAD_LOAD_SCRIPTS) {
@@ -733,18 +747,7 @@ void BL_BlenderConverter::MergeScene(KX_Scene *to, KX_Scene *from)
733747
{
734748
to->MergeScene(from);
735749

736-
SceneSlot& sceneSlotFrom = m_sceneSlots[from];
737-
738-
for (std::unique_ptr<KX_BlenderMaterial>& mat : sceneSlotFrom.m_materials) {
739-
// Do this after lights are merged so materials can use the lights in shaders.
740-
mat->ReplaceScene(to);
741-
}
742-
for (std::unique_ptr<RAS_MeshObject>& meshobj : sceneSlotFrom.m_meshobjects) {
743-
// Generate mesh to material attribute's layers since the materials are constructed now.
744-
meshobj->GenerateAttribLayers();
745-
}
746-
747-
m_sceneSlots[to].Merge(sceneSlotFrom);
750+
m_sceneSlots[to].Merge(m_sceneSlots[from]);
748751
m_sceneSlots.erase(from);
749752

750753
// Delete from scene's world info.
@@ -827,11 +830,13 @@ RAS_MeshObject *BL_BlenderConverter::ConvertMeshSpecial(KX_Scene *kx_scene, Main
827830
}
828831
}
829832

830-
BL_BlenderSceneConverter sceneConverter;
833+
BL_BlenderSceneConverter sceneConverter(kx_scene);
831834

832-
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, nullptr, kx_scene, sceneConverter, false);
835+
RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, nullptr, kx_scene, sceneConverter);
833836
kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj);
834837

838+
// Finalize material and mesh conversion.
839+
InitSceneShaders(sceneConverter, kx_scene);
835840
m_sceneSlots[kx_scene].Merge(sceneConverter);
836841

837842
return meshobj;

source/gameengine/Converter/BL_BlenderConverter.h

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ class BL_InterpolatorList;
5353
class SCA_IActuator;
5454
class SCA_IController;
5555
class RAS_MeshObject;
56-
class RAS_Rasterizer;
5756
struct Main;
5857
struct BlendHandle;
5958
struct Mesh;
@@ -108,11 +107,24 @@ class BL_BlenderConverter
108107
BL_BlenderConverter(Main *maggie, KX_KetsjiEngine *engine);
109108
virtual ~BL_BlenderConverter();
110109

111-
/** \param Scenename name of the scene to be converted.
112-
* \param destinationscene pass an empty scene, everything goes into this
113-
* \param dictobj python dictionary (for pythoncontrollers)
110+
void ConvertScene(BL_BlenderSceneConverter& converter, bool libloading);
111+
112+
/** Generate shaders and mesh attributes depending on.
113+
* This function is separated from ConvertScene to be synchronized when compiling shaders
114+
* and select a scene to generate shaders with. This last point is used for scene libload
115+
* merging.
116+
* \param converter The scene convert to finalize.
117+
* \param mergeScene The scene used to generate shaders.
118+
*/
119+
void InitSceneShaders(const BL_BlenderSceneConverter& converter, KX_Scene *mergeScene);
120+
121+
/** This function removes all entities stored in the converter for that scene
122+
* It should be used instead of direct delete scene
123+
* Note that there was some provision for sharing entities (meshes...) between
124+
* scenes but that is now disabled so all scene will have their own copy
125+
* and we can delete them here.
126+
* \param scene The scene to clean.
114127
*/
115-
void ConvertScene(KX_Scene *destinationscene, RAS_Rasterizer *rasty, RAS_ICanvas *canvas, bool libloading);
116128
void RemoveScene(KX_Scene *scene);
117129

118130
void SetAlwaysUseExpandFraming(bool to_what);

0 commit comments

Comments
 (0)