separate out RenderLoop/FilamentViewer construction/destruction

This commit is contained in:
Nick Fisher
2025-03-07 18:53:36 +08:00
parent be61d5e5ca
commit aa26f4d0df
7 changed files with 125 additions and 68 deletions

View File

@@ -1396,6 +1396,12 @@ external int TransformManager_getAncestor(
int childEntityId,
);
@ffi.Native<ffi.Void Function()>(isLeaf: true)
external void RenderLoop_create();
@ffi.Native<ffi.Void Function()>(isLeaf: true)
external void RenderLoop_destroy();
@ffi.Native<
ffi.Void Function(
ffi.Pointer<ffi.Void>,

View File

@@ -179,6 +179,11 @@ class ThermionViewerFFI extends ThermionViewer {
}
Future _initialize() async {
_logger.info("Initializing ThermionViewerFFI");
RenderLoop_destroy();
RenderLoop_create();
final uberarchivePtr =
uberArchivePath?.toNativeUtf8(allocator: allocator).cast<Char>() ??
nullptr;
@@ -205,6 +210,7 @@ class ThermionViewerFFI extends ThermionViewer {
_nameComponentManager =
SceneManager_getNameComponentManager(_sceneManager!);
_renderableManager = Engine_getRenderableManager(_engine!);
this._initialized.complete(true);
}
@@ -302,14 +308,17 @@ class ThermionViewerFFI extends ThermionViewer {
await mInstance.dispose();
}
await destroyLights();
Viewer_destroyOnRenderThread(_viewer!);
RenderLoop_destroy();
_sceneManager = null;
_viewer = null;
for (final callback in _onDispose) {
await callback.call();
}
_onDispose.clear();
_disposing = false;
}
@@ -2194,7 +2203,8 @@ class ThermionViewerFFI extends ThermionViewer {
///
///
Future setReceiveShadows(ThermionEntity entity, bool receiveShadows) async {
RenderableManager_setReceiveShadows(_renderableManager!, entity, receiveShadows);
RenderableManager_setReceiveShadows(
_renderableManager!, entity, receiveShadows);
}
///

View File

@@ -22,6 +22,9 @@ namespace thermion
typedef int32_t EntityId;
typedef void (*FilamentRenderCallback)(void *const owner);
EMSCRIPTEN_KEEPALIVE void RenderLoop_create();
EMSCRIPTEN_KEEPALIVE void RenderLoop_destroy();
EMSCRIPTEN_KEEPALIVE void Viewer_createOnRenderThread(
void *const context,
void *const platform,

View File

@@ -516,9 +516,8 @@ namespace thermion
FilamentViewer::~FilamentViewer()
{
TRACE("Destroying FilamentViewer");
_sceneManager->destroyAll();
for (auto view : _views)
{
view->setRenderTarget(nullptr);
@@ -526,20 +525,20 @@ namespace thermion
}
_views.clear();
TRACE("Destroying render targets");
for(auto rt : _renderTargets) {
destroyRenderTarget(rt);
}
_renderTargets.clear();
TRACE("Destroying swapchains");
for (auto swapChain : _swapChains)
{
_engine->destroy(swapChain);
}
_swapChains.clear();
TRACE("Destroying background image");
if (!_imageEntity.isNull())
{
_engine->destroy(_imageEntity);
@@ -548,13 +547,18 @@ namespace thermion
_engine->destroy(_imageIb);
_engine->destroy(_imageMaterial);
}
TRACE("Destroying SceneManager");
delete _sceneManager;
TRACE("SceneManager destroyed");
_engine->destroyCameraComponent(_mainCamera->getEntity());
_mainCamera = nullptr;
_engine->destroy(_scene);
_engine->destroy(_renderer);
TRACE("Destroying engine");
Engine::destroy(&_engine);
TRACE("Engine destroyed");
delete _resourceLoaderWrapper;
TRACE("Destruction complete.");
}
Renderer *FilamentViewer::getRenderer() { return _renderer; }

View File

@@ -49,9 +49,10 @@ extern "C"
viewer->destroyRenderTarget(renderTarget);
}
EMSCRIPTEN_KEEPALIVE void Viewer_destroy(TViewer *viewer)
EMSCRIPTEN_KEEPALIVE void Viewer_destroy(TViewer *tViewer)
{
delete ((FilamentViewer *)viewer);
auto *viewer = reinterpret_cast<FilamentViewer*>(tViewer);
delete viewer;
}
EMSCRIPTEN_KEEPALIVE void set_background_color(TViewer *viewer, const float r, const float g, const float b, const float a)

View File

@@ -35,20 +35,12 @@ public:
~RenderLoop()
{
TRACE("Destroying RenderLoop");
_stop = true;
_cv.notify_one();
TRACE("Joining RenderLoop thread..");
t->join();
}
static void mainLoop(void *arg)
{
((RenderLoop *)arg)->iter();
}
static void *startHelper(void *parm)
{
((RenderLoop *)parm)->start();
return nullptr;
TRACE("RenderLoop destructor complete");
}
void start()
@@ -59,6 +51,42 @@ public:
}
}
void destroyViewer() {
std::packaged_task<void()> lambda([=]() mutable
{
if(viewer) {
Viewer_destroy(viewer);
}
viewer = nullptr;
_renderCallback = nullptr;
_renderCallbackOwner = nullptr;
});
auto fut = add_task(lambda);
fut.wait();
}
void createViewer(
void *const context,
void *const platform,
const char *uberArchivePath,
const void *const loader,
void (*renderCallback)(void *),
void *const owner,
void (*callback)(TViewer *))
{
_renderCallback = renderCallback;
_renderCallbackOwner = owner;
std::packaged_task<void()> lambda([=]() mutable
{
if(viewer) {
Viewer_destroy(viewer);
}
viewer = Viewer_create(context, loader, platform, uberArchivePath);
callback(viewer); });
add_task(lambda);
}
void requestFrame(void (*callback)())
{
std::unique_lock<std::mutex> lock(_mutex);
@@ -109,37 +137,9 @@ public:
{ return !_tasks.empty() || _stop; });
}
void createViewer(void *const context,
void *const platform,
const char *uberArchivePath,
const ResourceLoaderWrapper *const loader,
void (*renderCallback)(void *),
void *const owner,
void (*callback)(TViewer *))
{
_renderCallback = renderCallback;
_renderCallbackOwner = owner;
std::packaged_task<void()> lambda([=]() mutable
{
auto viewer = (FilamentViewer *)Viewer_create(context, loader, platform, uberArchivePath);
_viewer = reinterpret_cast<TViewer*>(viewer);
callback(_viewer); });
auto fut = add_task(lambda);
}
void destroyViewer(FilamentViewer *viewer)
{
std::packaged_task<void()> lambda([=]() mutable
{
_viewer = nullptr;
Viewer_destroy(reinterpret_cast<TViewer*>(viewer)); });
auto fut = add_task(lambda);
fut.wait();
}
void doRender()
{
Viewer_render(_viewer);
Viewer_render(viewer);
if (_renderCallback)
{
_renderCallback(_renderCallbackOwner);
@@ -163,6 +163,8 @@ public:
return ret;
}
TViewer *viewer = std::nullptr_t();
private:
void (*_requestFrameRenderCallback)() = nullptr;
bool _stop = false;
@@ -173,7 +175,6 @@ private:
void (*_renderCallback)(void *const) = nullptr;
void *_renderCallbackOwner = nullptr;
std::deque<std::function<void()>> _tasks;
TViewer *_viewer = nullptr;
std::chrono::high_resolution_clock::time_point _lastFrameTime;
int _frameCount = 0;
float _accumulatedTime = 0.0f;
@@ -184,7 +185,25 @@ private:
extern "C"
{
static RenderLoop *_rl;
static std::unique_ptr<RenderLoop> _rl;
EMSCRIPTEN_KEEPALIVE void RenderLoop_create() {
TRACE("RenderLoop_create");
if (_rl)
{
Log("WARNING - you are attempting to create a RenderLoop when the previous one has not been disposed.");
}
_rl = std::make_unique<RenderLoop>();
}
EMSCRIPTEN_KEEPALIVE void RenderLoop_destroy() {
TRACE("RenderLoop_destroy");
if (_rl)
{
_rl->destroyViewer();
_rl = nullptr;
}
}
EMSCRIPTEN_KEEPALIVE void Viewer_createOnRenderThread(
void *const context, void *const platform, const char *uberArchivePath,
@@ -193,20 +212,27 @@ extern "C"
void *const renderCallbackOwner,
void (*callback)(TViewer *))
{
if (!_rl)
{
_rl = new RenderLoop();
}
_rl->createViewer(context, platform, uberArchivePath, (const ResourceLoaderWrapper *const)loader,
renderCallback, renderCallbackOwner, callback);
TRACE("Viewer_createOnRenderThread");
_rl->createViewer(
context,
platform,
uberArchivePath,
loader,
renderCallback,
renderCallbackOwner,
callback
);
}
EMSCRIPTEN_KEEPALIVE void Viewer_destroyOnRenderThread(TViewer *viewer)
{
_rl->destroyViewer((FilamentViewer *)viewer);
delete _rl;
_rl = nullptr;
TRACE("Viewer_destroyOnRenderThread");
if (!_rl)
{
Log("Warning - cannot destroy viewer, no RenderLoop has been created");
} else {
_rl->destroyViewer();
}
}
EMSCRIPTEN_KEEPALIVE void Viewer_createHeadlessSwapChainRenderThread(TViewer *viewer,
@@ -320,14 +346,15 @@ extern "C"
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void Engine_destroyTextureRenderThread(TEngine *engine, TTexture* tTexture, void (*onComplete)()) {
EMSCRIPTEN_KEEPALIVE void Engine_destroyTextureRenderThread(TEngine *engine, TTexture *tTexture, void (*onComplete)())
{
std::packaged_task<void()> lambda(
[=]() mutable
{
Engine_destroyTexture(engine, tTexture);
onComplete();
});
auto fut = _rl->add_task(lambda);
[=]() mutable
{
Engine_destroyTexture(engine, tTexture);
onComplete();
});
auto fut = _rl->add_task(lambda);
}
EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t *materialData, size_t length, void (*onComplete)(TMaterial *))

View File

@@ -124,17 +124,21 @@ namespace thermion
SceneManager::~SceneManager()
{
TRACE("Destroying cameras");
for (auto camera : _cameras)
{
auto entity = camera->getEntity();
_engine->destroyCameraComponent(entity);
_engine->getEntityManager().destroy(entity);
}
TRACE("Cameras destroyed");
destroyAll();
TRACE("Destroyed all assets");
_engine->destroy(_unlitFixedSizeMaterial);
_engine->destroy(_gizmoMaterial);
TRACE("Destroyed materials");
_cameras.clear();
_grid = nullptr;
@@ -150,7 +154,9 @@ namespace thermion
delete _stbDecoder;
delete _ktxDecoder;
delete _ubershaderProvider;
TRACE("Destroying asset loader");
AssetLoader::destroy(&_assetLoader);
TRACE("Destroyed asset loader");
}
SceneAsset *SceneManager::createGrid(Material *material)