From 852cb58ba9c5e8ab9ede643dcbbdc5b4d3e7857e Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Mon, 16 Dec 2024 15:25:19 +0800 Subject: [PATCH] fix: move material/instance creation to render thread --- .../src/ffi/src/ffi_material_instance.dart | 124 ------------------ .../viewer/src/ffi/src/thermion_dart.g.dart | 106 ++++++++++++--- .../src/ffi/src/thermion_viewer_ffi.dart | 47 ++++--- .../src/viewer/src/shared_types/material.dart | 7 + .../c_api/ThermionDartRenderThreadApi.h | 5 + .../src/c_api/ThermionDartRenderThreadApi.cpp | 31 +++++ 6 files changed, 158 insertions(+), 162 deletions(-) delete mode 100644 thermion_dart/lib/src/viewer/src/ffi/src/ffi_material_instance.dart diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_material_instance.dart b/thermion_dart/lib/src/viewer/src/ffi/src/ffi_material_instance.dart deleted file mode 100644 index 81266a4c..00000000 --- a/thermion_dart/lib/src/viewer/src/ffi/src/ffi_material_instance.dart +++ /dev/null @@ -1,124 +0,0 @@ -import 'dart:ffi'; - -import 'package:ffi/ffi.dart'; -import 'package:thermion_dart/src/viewer/src/ffi/src/thermion_dart.g.dart'; -import 'package:thermion_dart/thermion_dart.dart'; - -class ThermionFFIMaterialInstance extends MaterialInstance { - final Pointer pointer; - final Pointer sceneManager; - - ThermionFFIMaterialInstance(this.pointer, this.sceneManager) { - if (pointer == nullptr) { - throw Exception("MaterialInstance not found"); - } - } - - @override - Future setDepthCullingEnabled(bool enabled) async { - MaterialInstance_setDepthCulling(this.pointer, enabled); - } - - @override - Future setDepthWriteEnabled(bool enabled) async { - MaterialInstance_setDepthWrite(this.pointer, enabled); - } - - @override - Future setParameterFloat4( - String name, double x, double y, double z, double w) async { - MaterialInstance_setParameterFloat4( - pointer, name.toNativeUtf8().cast(), x, y, z, w); - } - - @override - Future setParameterFloat2(String name, double x, double y) async { - MaterialInstance_setParameterFloat2( - pointer, name.toNativeUtf8().cast(), x, y); - } - - @override - Future setParameterFloat(String name, double value) async { - MaterialInstance_setParameterFloat( - pointer, name.toNativeUtf8().cast(), value); - } - - @override - Future setParameterInt(String name, int value) async { - MaterialInstance_setParameterInt( - pointer, name.toNativeUtf8().cast(), value); - } - - @override - Future setDepthFunc(SamplerCompareFunction depthFunc) async { - MaterialInstance_setDepthFunc( - pointer, TSamplerCompareFunc.values[depthFunc.index]); - } - - @override - Future setStencilCompareFunction(SamplerCompareFunction func, - [StencilFace face = StencilFace.FRONT_AND_BACK]) async { - MaterialInstance_setStencilCompareFunction( - pointer, - TSamplerCompareFunc.values[func.index], - TStencilFace.values[face.index]); - } - - @override - Future setStencilOpDepthFail(StencilOperation op, - [StencilFace face = StencilFace.FRONT_AND_BACK]) async { - MaterialInstance_setStencilOpDepthFail(pointer, - TStencilOperation.values[op.index], TStencilFace.values[face.index]); - } - - @override - Future setStencilOpDepthStencilPass(StencilOperation op, - [StencilFace face = StencilFace.FRONT_AND_BACK]) async { - MaterialInstance_setStencilOpDepthStencilPass(pointer, - TStencilOperation.values[op.index], TStencilFace.values[face.index]); - } - - @override - Future setStencilOpStencilFail(StencilOperation op, - [StencilFace face = StencilFace.FRONT_AND_BACK]) async { - MaterialInstance_setStencilOpStencilFail(pointer, - TStencilOperation.values[op.index], TStencilFace.values[face.index]); - } - - @override - Future setStencilReferenceValue(int value, - [StencilFace face = StencilFace.FRONT_AND_BACK]) async { - MaterialInstance_setStencilReferenceValue( - pointer, value, TStencilFace.values[face.index]); - } - - @override - Future setStencilWriteEnabled(bool enabled) async { - MaterialInstance_setStencilWrite(pointer, enabled); - } - - @override - Future setCullingMode(CullingMode cullingMode) async { - MaterialInstance_setCullingMode( - pointer, TCullingMode.values[cullingMode.index]); - } - - @override - Future isStencilWriteEnabled() async { - return MaterialInstance_isStencilWriteEnabled(pointer); - } - - @override - Future setStencilReadMask(int mask) async { - MaterialInstance_setStencilReadMask(pointer, mask); - } - - @override - Future setStencilWriteMask(int mask) async { - MaterialInstance_setStencilWriteMask(pointer, mask); - } - - Future dispose() async { - SceneManager_destroyMaterialInstance(sceneManager, pointer); - } -} diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart index 306cd0dd..a5a5f4c3 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_dart.g.dart @@ -7,6 +7,12 @@ library; import 'dart:ffi' as ffi; +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer Material_createInstance( + ffi.Pointer tMaterial, +); + @ffi.Native)>(isLeaf: true) external bool MaterialInstance_isStencilWriteEnabled( ffi.Pointer materialInstance, @@ -372,6 +378,40 @@ external ffi.Pointer Engine_getCameraComponent( int entityId, ); +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer Engine_getTransformManager( + ffi.Pointer engine, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer Engine_getRenderableManager( + ffi.Pointer engine, +); + +@ffi.Native Function(ffi.Pointer)>( + isLeaf: true) +external ffi.Pointer Engine_getEntityManager( + ffi.Pointer engine, +); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer, ffi.Size)>(isLeaf: true) +external ffi.Pointer Engine_buildMaterial( + ffi.Pointer tEngine, + ffi.Pointer materialData, + int length, +); + +@ffi.Native, ffi.Pointer)>( + isLeaf: true) +external void Engine_destroyMaterial( + ffi.Pointer tEngine, + ffi.Pointer tMaterial, +); + @ffi.Native)>(isLeaf: true) external void clear_background_image( ffi.Pointer viewer, @@ -558,24 +598,6 @@ external void queue_position_update_from_viewport_coords( double viewportY, ); -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer Engine_getTransformManager( - ffi.Pointer engine, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer Engine_getRenderableManager( - ffi.Pointer engine, -); - -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) -external ffi.Pointer Engine_getEntityManager( - ffi.Pointer engine, -); - @ffi.Native(isLeaf: true) external void ios_dummy(); @@ -1288,6 +1310,46 @@ external void Viewer_createRenderTargetRenderThread( onComplete, ); +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Pointer< + ffi + .NativeFunction)>>)>( + isLeaf: true) +external void Engine_buildMaterialRenderThread( + ffi.Pointer tEngine, + ffi.Pointer materialData, + int length, + ffi.Pointer)>> + onComplete, +); + +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer>)>(isLeaf: true) +external void Engine_destroyMaterialRenderThread( + ffi.Pointer tEngine, + ffi.Pointer tMaterial, + ffi.Pointer> onComplete, +); + +@ffi.Native< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer)>>)>(isLeaf: true) +external void Material_createInstanceRenderThread( + ffi.Pointer tMaterial, + ffi.Pointer< + ffi.NativeFunction)>> + onComplete, +); + @ffi.Native< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Int)>(isLeaf: true) @@ -1956,10 +2018,12 @@ external ffi.Pointer ffi.Pointer tSceneManager, ); -@ffi.Native Function(ffi.Pointer)>( - isLeaf: true) +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>(isLeaf: true) external ffi.Pointer SceneManager_createGrid( ffi.Pointer tSceneManager, + ffi.Pointer tMaterial, ); @ffi.Native, EntityId)>( @@ -2324,6 +2388,8 @@ final class TSceneAsset extends ffi.Opaque {} final class TNameComponentManager extends ffi.Opaque {} +final class TMaterial extends ffi.Opaque {} + final class TMaterialInstance extends ffi.Opaque {} final class TMaterialProvider extends ffi.Opaque {} diff --git a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart index 35903c72..4ac1bbc6 100644 --- a/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart +++ b/thermion_dart/lib/src/viewer/src/ffi/src/thermion_viewer_ffi.dart @@ -5,16 +5,15 @@ import 'dart:typed_data'; import 'package:animation_tools_dart/animation_tools_dart.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_asset.dart'; import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_gizmo.dart'; +import 'package:thermion_dart/src/viewer/src/ffi/src/ffi_material.dart'; import 'package:vector_math/vector_math_64.dart'; import 'package:vector_math/vector_math_64.dart' as v64; -import '../../../../utils/src/gizmo.dart'; import '../../../../utils/src/matrix.dart'; import '../../thermion_viewer_base.dart'; import 'package:logging/logging.dart'; import 'callbacks.dart'; import 'ffi_camera.dart'; -import 'ffi_material_instance.dart'; import 'ffi_view.dart'; // ignore: constant_identifier_names @@ -282,7 +281,7 @@ class ThermionViewerFFI extends ThermionViewer { final _onDispose = []; bool _disposing = false; - final _materialInstances = []; + final _materialInstances = []; /// /// @@ -1626,7 +1625,7 @@ class ThermionViewerFFI extends ThermionViewer { 0, materialInstances.length, materialInstances - .cast() + .cast() .map((mi) => mi.pointer.address) .toList()); } @@ -1760,8 +1759,13 @@ class ThermionViewerFFI extends ThermionViewer { /// /// /// - Future showGridOverlay() async { - final ptr = SceneManager_createGrid(_sceneManager!); + Future showGridOverlay({FFIMaterial? material}) async { + late Pointer ptr; + if (material == null) { + ptr = SceneManager_createGrid(_sceneManager!, nullptr); + } else { + ptr = SceneManager_createGrid(_sceneManager!, material.pointer); + } _grid ??= FFIAsset(ptr, _sceneManager!, _engine!, _unlitMaterialProvider!); await _grid!.addToScene(); } @@ -1819,6 +1823,16 @@ class ThermionViewerFFI extends ThermionViewer { destroy_texture(_sceneManager!, texture.pointer); } + /// + /// + /// + Future createMaterial(Uint8List data) async { + var ptr = await withPointerCallback((cb) { + Engine_buildMaterialRenderThread(_engine!, data.address, data.length, cb); + }); + return FFIMaterial(ptr, _engine!, _sceneManager!); + } + /// /// /// @@ -1905,8 +1919,7 @@ class ThermionViewerFFI extends ThermionViewer { throw Exception("Failed to create material instance"); } - var instance = - ThermionFFIMaterialInstance(materialInstance, _sceneManager!); + var instance = FFIMaterialInstance(materialInstance, _sceneManager!); _materialInstances.add(instance); return instance; } @@ -1914,8 +1927,7 @@ class ThermionViewerFFI extends ThermionViewer { /// /// /// - Future destroyMaterialInstance( - ThermionFFIMaterialInstance materialInstance) async { + Future destroyMaterialInstance(FFIMaterialInstance materialInstance) async { await materialInstance.dispose(); _materialInstances.remove(materialInstance); } @@ -1923,11 +1935,11 @@ class ThermionViewerFFI extends ThermionViewer { /// /// /// - Future createUnlitMaterialInstance() async { + Future createUnlitMaterialInstance() async { var instancePtr = await withPointerCallback((cb) { SceneManager_createUnlitMaterialInstanceRenderThread(_sceneManager!, cb); }); - final instance = ThermionFFIMaterialInstance(instancePtr, _sceneManager!); + final instance = FFIMaterialInstance(instancePtr, _sceneManager!); _materialInstances.add(instance); return instance; } @@ -1935,13 +1947,12 @@ class ThermionViewerFFI extends ThermionViewer { /// /// /// - Future - createUnlitFixedSizeMaterialInstance() async { + Future createUnlitFixedSizeMaterialInstance() async { var instancePtr = await withPointerCallback((cb) { SceneManager_createUnlitFixedSizeMaterialInstanceRenderThread( _sceneManager!, cb); }); - final instance = ThermionFFIMaterialInstance(instancePtr, _sceneManager!); + final instance = FFIMaterialInstance(instancePtr, _sceneManager!); _materialInstances.add(instance); return instance; } @@ -1954,7 +1965,7 @@ class ThermionViewerFFI extends ThermionViewer { final instancePtr = RenderableManager_getMaterialInstanceAt( _renderableManager!, entity, index); - final instance = ThermionFFIMaterialInstance(instancePtr, _sceneManager!); + final instance = FFIMaterialInstance(instancePtr, _sceneManager!); return instance; } @@ -2065,8 +2076,8 @@ class ThermionViewerFFI extends ThermionViewer { Future createGizmo(FFIView view, GizmoType gizmoType) async { var scene = View_getScene(view.view); final gizmo = await withPointerCallback((cb) { - SceneManager_createGizmoRenderThread( - _sceneManager!, view.view, scene, TGizmoType.values[gizmoType.index], cb); + SceneManager_createGizmoRenderThread(_sceneManager!, view.view, scene, + TGizmoType.values[gizmoType.index], cb); }); if (gizmo == nullptr) { throw Exception("Failed to create gizmo"); diff --git a/thermion_dart/lib/src/viewer/src/shared_types/material.dart b/thermion_dart/lib/src/viewer/src/shared_types/material.dart index 38cd5abc..4aa4eda1 100644 --- a/thermion_dart/lib/src/viewer/src/shared_types/material.dart +++ b/thermion_dart/lib/src/viewer/src/shared_types/material.dart @@ -72,6 +72,11 @@ enum StencilFace { enum AlphaMode { OPAQUE, MASK, BLEND } +abstract class Material { + Future createInstance(); + Future dispose(); +} + abstract class MaterialInstance { Future isStencilWriteEnabled(); Future setDepthWriteEnabled(bool enabled); @@ -110,4 +115,6 @@ abstract class MaterialInstance { Future setStencilReadMask(int mask); Future setStencilWriteMask(int mask); + Future dispose(); + } diff --git a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h index 6d8b4ebe..9d39070c 100644 --- a/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h +++ b/thermion_dart/native/include/c_api/ThermionDartRenderThreadApi.h @@ -40,6 +40,11 @@ namespace thermion EMSCRIPTEN_KEEPALIVE void Viewer_loadIblRenderThread(TViewer *viewer, const char *iblPath, float intensity, void (*onComplete)()); EMSCRIPTEN_KEEPALIVE void Viewer_createRenderTargetRenderThread(TViewer *viewer, intptr_t texture, uint32_t width, uint32_t height, void (*onComplete)(TRenderTarget *)); + EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t* materialData, size_t length, void (*onComplete)(TMaterial *)); + EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, void (*onComplete)()); + + EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance*)); + EMSCRIPTEN_KEEPALIVE void View_setToneMappingRenderThread(TView *tView, TEngine *tEngine, thermion::ToneMapping toneMapping); EMSCRIPTEN_KEEPALIVE void View_setBloomRenderThread(TView *tView, double bloom); EMSCRIPTEN_KEEPALIVE void View_setCameraRenderThread(TView *tView, TCamera *tCamera, void (*callback)()); diff --git a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp index 5341311c..734fec13 100644 --- a/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp +++ b/thermion_dart/native/src/c_api/ThermionDartRenderThreadApi.cpp @@ -280,6 +280,37 @@ extern "C" auto fut = _rl->add_task(lambda); } + EMSCRIPTEN_KEEPALIVE void Engine_buildMaterialRenderThread(TEngine *tEngine, const uint8_t* materialData, size_t length, void (*onComplete)(TMaterial *)) { + std::packaged_task lambda( + [=]() mutable + { + auto material = Engine_buildMaterial(tEngine, materialData, length); + onComplete(material); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Engine_destroyMaterialRenderThread(TEngine *tEngine, TMaterial *tMaterial, void (*onComplete)()) { + std::packaged_task lambda( + [=]() mutable + { + Engine_destroyMaterial(tEngine, tMaterial); + onComplete(); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void Material_createInstanceRenderThread(TMaterial *tMaterial, void (*onComplete)(TMaterialInstance*)) { + std::packaged_task lambda( + [=]() mutable + { + auto *instance = Material_createInstance(tMaterial); + onComplete(instance); + }); + auto fut = _rl->add_task(lambda); + } + + EMSCRIPTEN_KEEPALIVE void set_frame_interval_render_thread(TViewer *viewer, float frameIntervalInMilliseconds) {