fixed race condition when writing prefabs during fbx import
This commit is contained in:
parent
c284ce9769
commit
24d1cb1887
|
@ -379,7 +379,7 @@ bool init(u8 workers_count, IAllocator& allocator)
|
|||
|
||||
int count = maximum(1, int(workers_count));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
WorkerTask* task = LUMIX_NEW(getAllocator(), WorkerTask)(*g_system, i < 64 ? u64(1) << i : 0);
|
||||
WorkerTask* task = LUMIX_NEW(getAllocator(), WorkerTask)(*g_system, i);
|
||||
if (task->create("Worker", false)) {
|
||||
task->m_is_enabled = true;
|
||||
g_system->m_workers.push(task);
|
||||
|
@ -499,4 +499,45 @@ void wait(Signal* handle) {
|
|||
waitEx(handle, false);
|
||||
}
|
||||
|
||||
u32 getWorkerIndex() {
|
||||
return getWorker()->m_worker_index;
|
||||
}
|
||||
|
||||
void moveJobToWorker(u8 worker_index) {
|
||||
g_system->m_sync.enter();
|
||||
FiberDecl* this_fiber = getWorker()->m_current_fiber;
|
||||
WorkerTask* worker = g_system->m_workers[worker_index % g_system->m_workers.size()];
|
||||
worker->m_work_queue.push(this_fiber, &g_system->m_job_queue_sync);
|
||||
wake();
|
||||
FiberDecl* new_fiber = g_system->m_free_fibers.back();
|
||||
g_system->m_free_fibers.pop();
|
||||
if (!Fiber::isValid(new_fiber->fiber)) {
|
||||
new_fiber->fiber = Fiber::create(64 * 1024, manage, new_fiber);
|
||||
}
|
||||
getWorker()->m_current_fiber = new_fiber;
|
||||
this_fiber->current_job.worker_index = worker_index;
|
||||
Fiber::switchTo(&this_fiber->fiber, new_fiber->fiber);
|
||||
getWorker()->m_current_fiber = this_fiber;
|
||||
ASSERT(getWorker()->m_worker_index == worker_index);
|
||||
g_system->m_sync.exit();
|
||||
}
|
||||
|
||||
void yield() {
|
||||
g_system->m_sync.enter();
|
||||
FiberDecl* this_fiber = getWorker()->m_current_fiber;
|
||||
g_system->m_work_queue.push(this_fiber, &g_system->m_job_queue_sync);
|
||||
|
||||
wake();
|
||||
FiberDecl* new_fiber = g_system->m_free_fibers.back();
|
||||
g_system->m_free_fibers.pop();
|
||||
if (!Fiber::isValid(new_fiber->fiber)) {
|
||||
new_fiber->fiber = Fiber::create(64 * 1024, manage, new_fiber);
|
||||
}
|
||||
this_fiber->current_job.worker_index = ANY_WORKER;
|
||||
getWorker()->m_current_fiber = new_fiber;
|
||||
Fiber::switchTo(&this_fiber->fiber, new_fiber->fiber);
|
||||
g_system->m_sync.exit();
|
||||
}
|
||||
|
||||
|
||||
} // namespace Lumix::jobs
|
||||
|
|
|
@ -19,6 +19,10 @@ LUMIX_ENGINE_API void shutdown();
|
|||
LUMIX_ENGINE_API u8 getWorkersCount();
|
||||
|
||||
LUMIX_ENGINE_API void enableBackupWorker(bool enable);
|
||||
// yield current job and push it to worker queue
|
||||
LUMIX_ENGINE_API void moveJobToWorker(u8 worker_index);
|
||||
// yield current job, push it to global queue
|
||||
LUMIX_ENGINE_API void yield();
|
||||
|
||||
LUMIX_ENGINE_API void enter(Mutex* mutex);
|
||||
LUMIX_ENGINE_API void exit(Mutex* mutex);
|
||||
|
|
|
@ -2586,7 +2586,6 @@ bool FBXImporter::writePhysicsPrefab(const Path& src, const ImportConfig& cfg) {
|
|||
|
||||
bool FBXImporter::writePrefab(const Path& src, const ImportConfig& cfg)
|
||||
{
|
||||
// TODO this is not threadsafe, since it can load/unload assets, access lua state, ...
|
||||
Engine& engine = m_app.getEngine();
|
||||
World& world = engine.createWorld(false);
|
||||
|
||||
|
@ -2625,7 +2624,6 @@ bool FBXImporter::writePrefab(const Path& src, const ImportConfig& cfg)
|
|||
|
||||
world.serialize(blob, WorldSerializeFlags::NONE);
|
||||
engine.destroyWorld(world);
|
||||
|
||||
if (!file.write(blob.data(), blob.size())) {
|
||||
logError("Could not write ", tmp);
|
||||
file.close();
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
|
||||
|
||||
using namespace Lumix;
|
||||
static AtomicI32 xx = 0;
|
||||
|
||||
static Animation::Flags operator | (Animation::Flags a, Animation::Flags b) {
|
||||
return Animation::Flags(u32(a) | u32(b));
|
||||
|
@ -2687,7 +2688,10 @@ struct ModelPlugin final : AssetBrowser::IPlugin, AssetCompiler::IPlugin {
|
|||
if (meta.split) {
|
||||
cfg.origin = FBXImporter::ImportConfig::Origin::CENTER_EACH_MESH;
|
||||
any_written = importer.writeSubmodels(filepath, cfg) || any_written;
|
||||
// writePrefab is not threadsafe, run on "main thread"
|
||||
jobs::moveJobToWorker(0);
|
||||
any_written = importer.writePrefab(filepath, cfg) || any_written;
|
||||
jobs::yield();
|
||||
}
|
||||
cfg.origin = meta.origin;
|
||||
any_written = importer.writeModel(src, cfg) || any_written;
|
||||
|
@ -2697,7 +2701,9 @@ struct ModelPlugin final : AssetBrowser::IPlugin, AssetCompiler::IPlugin {
|
|||
}
|
||||
any_written = importer.writePhysics(filepath, cfg) || any_written;
|
||||
if (meta.create_prefab_with_physics) {
|
||||
jobs::moveJobToWorker(0);
|
||||
importer.writePhysicsPrefab(filepath, cfg);
|
||||
jobs::yield();
|
||||
}
|
||||
return any_written;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue