initial work to re-implement FFI with background thread render loop

This commit is contained in:
Nick Fisher
2023-09-29 13:54:04 +08:00
parent 1b49706eca
commit a6506e6346
39 changed files with 6819 additions and 53973 deletions

View File

@@ -1,5 +1,7 @@
#include "AssetManager.hpp"
#include <string>
#include <sstream>
#include <thread>
#include <filament/Engine.h>
#include <filament/TransformManager.h>
#include <filament/Texture.h>
@@ -17,8 +19,8 @@
#include "StreamBufferAdapter.hpp"
#include "SceneAsset.hpp"
#include "Log.hpp"
#include "AssetManager.hpp"
#include "material/StandardMaterialProvider.hpp"
#include "material/UnlitMaterialProvider.hpp"
#include "material/FileMaterialProvider.hpp"
#include "gltfio/materials/uberarchive.h"
@@ -52,16 +54,13 @@ _scene(scene) {
_gltfResourceLoader = new ResourceLoader({.engine = _engine,
.normalizeSkinningWeights = true });
// auto uberdata = resourceLoaderWrapper->load("packages/polyvox_filament/assets/materials.uberz");
// auto uberdata = resourceLoaderWrapper->load("packages/polyvox_filament/assets/materials_ios_arm64.uberz");
// _ubershaderProvider = gltfio::createUbershaderProvider(
// _engine, uberdata.data, uberdata.size);
// _engine, uberdata.data, uberdata.size);
_ubershaderProvider = gltfio::createUbershaderProvider(
_engine, UBERARCHIVE_DEFAULT_DATA, UBERARCHIVE_DEFAULT_SIZE);
// _ubershaderProvider = gltfio::createJitShaderProvider(_engine, true);
// _ubershaderProvider = new StandardMaterialProvider(_engine);
EntityManager &em = EntityManager::get();
//_unlitProvider = new UnlitMaterialProvider(_engine);
@@ -78,6 +77,7 @@ _scene(scene) {
AssetManager::~AssetManager() {
_gltfResourceLoader->asyncCancelLoad();
_ubershaderProvider->destroyMaterials();
//_unlitProvider->destroyMaterials();
destroyAll();
AssetLoader::destroy(&_assetLoader);
@@ -252,7 +252,8 @@ void AssetManager::updateAnimations() {
for (auto& asset : _assets) {
vector<AnimationStatus> completed;
vector<int> completed;
int index = 0;
for(auto& anim : asset.mAnimations) {
auto elapsed = float(std::chrono::duration_cast<std::chrono::milliseconds>(now - anim.mStart).count()) / 1000.0f;
@@ -316,10 +317,14 @@ void AssetManager::updateAnimations() {
}
// animation has completed
} else {
completed.push_back(anim);
completed.push_back(index);
asset.fadeGltfAnimationIndex = -1;
}
asset.mAnimator->updateBoneMatrices();
index++;
}
for(auto& it : completed) {
asset.mAnimations.erase(asset.mAnimations.begin() + it);
}
}
}
@@ -657,6 +662,8 @@ void AssetManager::playAnimation(EntityId e, int index, bool loop, bool reverse,
animation.mDuration = asset.mAnimator->getAnimationDuration(index);
asset.mAnimations.push_back(animation);
Log("Current animation count %d ", asset.mAnimations.size());
}
void AssetManager::stopAnimation(EntityId entityId, int index) {

View File

@@ -112,10 +112,8 @@ FilamentViewer::FilamentViewer(const void* context, const ResourceLoaderWrapper*
#if TARGET_OS_IPHONE
_engine = Engine::create(Engine::Backend::METAL);
#elif TARGET_OS_MAC
_engine = Engine::create(Engine::Backend::METAL);
#else
_engine = Engine::create(Engine::Backend::OPENGL, nullptr, (void*)context, nullptr);
_engine = Engine::create(Engine::Backend::OPENGL); //L, nullptr, (void*)context, nullptr);
#endif
_renderer = _engine->createRenderer();
@@ -153,7 +151,6 @@ FilamentViewer::FilamentViewer(const void* context, const ResourceLoaderWrapper*
const float aperture = _mainCamera->getAperture();
const float shutterSpeed = _mainCamera->getShutterSpeed();
const float sens = _mainCamera->getSensitivity();
// _mainCamera->setExposure(2.0f, 1.0f, 1.0f);
Log("Camera aperture %f shutter %f sensitivity %f", aperture, shutterSpeed, sens);
@@ -173,10 +170,6 @@ FilamentViewer::FilamentViewer(const void* context, const ResourceLoaderWrapper*
_view->setAntiAliasing(AntiAliasing::NONE);
// auto materialRb = _resourceLoader->load("file:///mnt/hdd_2tb/home/hydroxide/projects/filament/unlit.filamat");
// Log("Loaded resource of size %d", materialRb.size);
// _materialProvider = new FileMaterialProvider(_engine, (void*) materialRb.data, (size_t)materialRb.size);
EntityManager &em = EntityManager::get();
_ncm = new NameComponentManager(em);
@@ -377,7 +370,6 @@ void FilamentViewer::loadPngTexture(string path, ResourceBuffer rb) {
Texture::PixelBufferDescriptor::Callback freeCallback = [](void *buf, size_t,
void *data) {
Log("Deleting LinearImage");
delete reinterpret_cast<LinearImage*>(data);
};
@@ -423,14 +415,13 @@ void FilamentViewer::setBackgroundColor(const float r, const float g, const floa
void FilamentViewer::clearBackgroundImage() {
_imageMaterial->setDefaultParameter("showImage", 0);
if (_imageTexture) {
Log("Destroying existing texture");
_engine->destroy(_imageTexture);
Log("Destroyed.");
_imageTexture = nullptr;
Log("Destroyed background image texture");
}
}
void FilamentViewer::setBackgroundImage(const char *resourcePath) {
void FilamentViewer::setBackgroundImage(const char *resourcePath, bool fillHeight) {
string resourcePathString(resourcePath);
@@ -444,7 +435,18 @@ void FilamentViewer::setBackgroundImage(const char *resourcePath) {
// TODO - implement stretch/etc
const Viewport& vp = _view->getViewport();
Log("Image width %d height %d vp width %d height %d", _imageWidth, _imageHeight, vp.width, vp.height);
_imageScale = mat4f { float(vp.width) / float(_imageWidth) , 0.0f, 0.0f, 0.0f, 0.0f, float(vp.height) / float(_imageHeight), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f };
float xScale = float(vp.width) / float(_imageWidth);
float yScale;
if(fillHeight) {
yScale = 1.0f;
} else {
yScale = float(vp.height) / float(_imageHeight);
}
_imageScale = mat4f { xScale , 0.0f, 0.0f, 0.0f, 0.0f, yScale , 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f };
_imageMaterial->setDefaultParameter("transform", _imageScale);
_imageMaterial->setDefaultParameter("image", _imageTexture, _imageSampler);
@@ -550,14 +552,14 @@ FilamentViewer::~FilamentViewer() {
Renderer *FilamentViewer::getRenderer() { return _renderer; }
void FilamentViewer::createSwapChain(const void *surface, uint32_t width, uint32_t height) {
void FilamentViewer::createSwapChain(const void *window, uint32_t width, uint32_t height) {
#if TARGET_OS_IPHONE
_swapChain = _engine->createSwapChain((void*)surface, filament::backend::SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER);
_swapChain = _engine->createSwapChain((void*)window, filament::backend::SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER);
#else
if(surface) {
_swapChain = _engine->createSwapChain(width, height, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE);
if(window) {
_swapChain = _engine->createSwapChain((void*)window, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE);
} else {
_swapChain = _engine->createSwapChain((void*)surface, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE);
_swapChain = _engine->createSwapChain(width, height, filament::backend::SWAP_CHAIN_CONFIG_TRANSPARENT | filament::backend::SWAP_CHAIN_CONFIG_READABLE);
}
#endif
Log("Swapchain created.");
@@ -588,7 +590,7 @@ void FilamentViewer::createRenderTarget(intptr_t textureId, uint32_t width, uint
// Make a specific viewport just for our render target
_view->setRenderTarget(_rt);
Log("Set render target for textureId %u %u x %u", textureId, width, height);
Log("Set render target for glTextureId %u %u x %u", textureId, width, height);
}
@@ -861,8 +863,18 @@ void FilamentViewer::updateViewportAndCameraProjection(
contentScaleFactor);
}
void FilamentViewer::moveCameraToAsset(EntityId entityId) {
void FilamentViewer::setCameraPosition(float x, float y, float z) {
Camera& cam =_view->getCamera();
_cameraPosition = math::mat4f::translation(math::float3(x,y,z));
cam.setModelMatrix(_cameraPosition * _cameraRotation);
}
void FilamentViewer::setViewFrustumCulling(bool enabled) {
_view->setFrustumCullingEnabled(enabled);
}
void FilamentViewer::moveCameraToAsset(EntityId entityId) {
auto asset = _assetManager->getAssetByEntityId(entityId);
if(!asset) {
Log("Failed to find asset attached to specified entity id.");
@@ -878,20 +890,8 @@ void FilamentViewer::moveCameraToAsset(EntityId entityId) {
Log("Moved camera to %f %f %f, lookAt %f %f %f, near %f far %f", eye[0], eye[1], eye[2], lookAt[0], lookAt[1], lookAt[2], cam.getNear(), cam.getCullingFar());
}
void FilamentViewer::setViewFrustumCulling(bool enabled) {
_view->setFrustumCullingEnabled(enabled);
}
void FilamentViewer::setCameraPosition(float x, float y, float z) {
Camera& cam =_view->getCamera();
_cameraPosition = math::mat4f::translation(math::float3(x,y,z));
cam.setModelMatrix(_cameraPosition * _cameraRotation);
}
void FilamentViewer::setCameraRotation(float rads, float x, float y, float z) {
Camera& cam =_view->getCamera();
_cameraRotation = math::mat4f::rotation(rads, math::float3(x,y,z));
cam.setModelMatrix(_cameraPosition * _cameraRotation);
}
@@ -936,7 +936,7 @@ void FilamentViewer::grabUpdate(float x, float y) {
return;
}
Camera& cam =_view->getCamera();
auto eye = cam.getPosition();
auto eye = cam.getPosition();// math::float3 {0.0f, 0.5f, 50.0f } ;// ; //
auto target = eye + cam.getForwardVector();
auto upward = cam.getUpVector();
Viewport const& vp = _view->getViewport();
@@ -945,7 +945,9 @@ void FilamentViewer::grabUpdate(float x, float y) {
cam.setModelMatrix(trans);
} else {
auto trans = cam.getModelMatrix() * mat4::rotation(
0.02,
0.01,
// math::float3 { 0.0f, 1.0f, 0.0f });
math::float3 { (y - _startY) / vp.height, (x - _startX) / vp.width, 0.0f });
cam.setModelMatrix(trans);
}

View File

@@ -17,31 +17,31 @@ extern "C" {
#include "PolyvoxFilamentApi.h"
FLUTTER_PLUGIN_EXPORT const void* create_filament_viewer(const void* context, const ResourceLoaderWrapper* const loader) {
return (void*) new FilamentViewer(context, loader);
return (const void*) new FilamentViewer(context, loader);
}
FLUTTER_PLUGIN_EXPORT ResourceLoaderWrapper* make_resource_loader(LoadResourceFromOwner loadFn, FreeResourceFromOwner freeFn, void* const owner) {
FLUTTER_PLUGIN_EXPORT ResourceLoaderWrapper* make_resource_loader(LoadFilamentResourceFromOwner loadFn, FreeFilamentResourceFromOwner freeFn, void* const owner) {
return new ResourceLoaderWrapper(loadFn, freeFn, owner);
}
FLUTTER_PLUGIN_EXPORT void create_render_target(const void* const viewer, intptr_t textureId, uint32_t width, uint32_t height) {
FLUTTER_PLUGIN_EXPORT void create_render_target(const void* const viewer, uint32_t textureId, uint32_t width, uint32_t height) {
((FilamentViewer*)viewer)->createRenderTarget(textureId, width, height);
}
FLUTTER_PLUGIN_EXPORT void delete_filament_viewer(const void* const viewer) {
FLUTTER_PLUGIN_EXPORT void destroy_filament_viewer(const void* const viewer) {
delete((FilamentViewer*)viewer);
}
FLUTTER_PLUGIN_EXPORT void set_background_color(const void* const viewer, const float r, const float g, const float b, const float a) {
((FilamentViewer*)viewer)->setBackgroundColor(r, g, b, a);
((FilamentViewer*)viewer)->setBackgroundColor(r, g, b, a);
}
FLUTTER_PLUGIN_EXPORT void clear_background_image(const void* const viewer) {
((FilamentViewer*)viewer)->clearBackgroundImage();
}
FLUTTER_PLUGIN_EXPORT void set_background_image(const void* const viewer, const char* path) {
((FilamentViewer*)viewer)->setBackgroundImage(path);
FLUTTER_PLUGIN_EXPORT void set_background_image(const void* const viewer, const char* path, bool fillHeight) {
((FilamentViewer*)viewer)->setBackgroundImage(path, fillHeight);
}
FLUTTER_PLUGIN_EXPORT void set_background_image_position(const void* const viewer, float x, float y, bool clamp) {
@@ -97,14 +97,14 @@ extern "C" {
return ((FilamentViewer*)viewer)->setCamera(asset, nodeName);
}
FLUTTER_PLUGIN_EXPORT void move_camera_to_asset(const void* const viewer, EntityId asset) {
((FilamentViewer*)viewer)->moveCameraToAsset(asset);
}
FLUTTER_PLUGIN_EXPORT void set_view_frustum_culling(const void* const viewer, bool enabled) {
((FilamentViewer*)viewer)->setViewFrustumCulling(enabled);
}
FLUTTER_PLUGIN_EXPORT void move_camera_to_asset(const void* const viewer, EntityId asset) {
((FilamentViewer*)viewer)->moveCameraToAsset(asset);
}
FLUTTER_PLUGIN_EXPORT void set_camera_focus_distance(const void* const viewer, float distance) {
((FilamentViewer*)viewer)->setCameraFocusDistance(distance);
}
@@ -147,8 +147,8 @@ extern "C" {
((FilamentViewer*)viewer)->destroySwapChain();
}
FLUTTER_PLUGIN_EXPORT void create_swap_chain(const void* const viewer, const void* const surface=nullptr, uint32_t width=0, uint32_t height=0) {
((FilamentViewer*)viewer)->createSwapChain(surface, width, height);
FLUTTER_PLUGIN_EXPORT void create_swap_chain(const void* const viewer, const void* const window, uint32_t width, uint32_t height) {
((FilamentViewer*)viewer)->createSwapChain(window, width, height);
}
FLUTTER_PLUGIN_EXPORT void update_viewport_and_camera_projection(const void* const viewer, uint32_t width, uint32_t height, float scaleFactor) {
@@ -348,14 +348,6 @@ extern "C" {
((FilamentViewer*)viewer)->clearAssets();
}
FLUTTER_PLUGIN_EXPORT void load_texture(void* assetManager, EntityId asset, const char* assetPath, int renderableIndex) {
// ((AssetManager*)assetManager)->loadTexture(assetPath, renderableIndex);
}
FLUTTER_PLUGIN_EXPORT void set_texture(void* assetManager, EntityId asset) {
// ((AssetManager*)assetManager)->setTexture();
}
bool set_material_color(void* assetManager, EntityId asset, const char* meshName, int materialIndex, const float r, const float g, const float b, const float a) {
return ((AssetManager*)assetManager)->setMaterialColor(asset, meshName, materialIndex, r, g, b, a);
}
@@ -370,7 +362,7 @@ extern "C" {
FLUTTER_PLUGIN_EXPORT void set_rotation(void* assetManager, EntityId asset, float rads, float x, float y, float z) {
((AssetManager*)assetManager)->setRotation(asset, rads, x, y, z);
}
}
FLUTTER_PLUGIN_EXPORT void set_scale(void* assetManager, EntityId asset, float scale) {
((AssetManager*)assetManager)->setScale(asset, scale);

View File

@@ -0,0 +1,111 @@
#include "ResourceBuffer.hpp"
#include "FilamentViewer.hpp"
#include "filament/LightManager.h"
#include "Log.hpp"
#include "ThreadPool.hpp"
#include <thread>
#include <functional>
using namespace polyvox;
#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default")))
class RenderLoop {
public:
explicit RenderLoop() {
_t = new std::thread([this]() {
while(!_stop) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(_access);
if(_tasks.empty()) {
_cond.wait_for(lock, std::chrono::duration<int, std::milli>(5));
continue;
}
task = std::move(_tasks.front());
_tasks.pop_front();
std::this_thread::sleep_for(
std::chrono::milliseconds(_frameIntervalInMilliseconds));
}
task();
}
});
}
~RenderLoop() {
_stop = true;
_t->join();
}
void setRendering(bool rendering) {
_rendering = rendering;
}
template<class Rt>
auto add_task(std::packaged_task<Rt()>& pt) -> std::future<Rt> {
std::unique_lock<std::mutex> lock(_access);
auto ret = pt.get_future();
_tasks.push_back([pt=std::make_shared<std::packaged_task<Rt()>>(std::move(pt))]{ (*pt)();});
_cond.notify_one();
return ret;
}
private:
bool _stop = false;
bool _rendering = false;
int _frameIntervalInMilliseconds = 1000 / 60;
std::mutex _access;
FilamentViewer* _viewer = nullptr;
std::thread* _t = nullptr;
std::condition_variable _cond;
std::deque<std::function<void()>> _tasks;
};
extern "C" {
#include "PolyvoxFilamentApi.h"
static RenderLoop* _rl;
FLUTTER_PLUGIN_EXPORT const void* create_filament_viewer_ffi(const void* context, const ResourceLoaderWrapper* const loader) {
if(!_rl) {
_rl = new RenderLoop();
}
std::packaged_task<const void*()> lambda([&]() mutable {
return (const void*) new FilamentViewer(context, loader);
});
auto fut = _rl->add_task(lambda);
fut.wait();
return fut.get();
}
FLUTTER_PLUGIN_EXPORT bool set_rendering(bool rendering) {
if(!_rl) {
return false;
}
_rl->setRendering(rendering);
return true;
}
FLUTTER_PLUGIN_EXPORT void render_ffi(void* const viewer) {
std::packaged_task<void()> lambda([&]() mutable {
render(viewer, 0);
});
auto fut = _rl->add_task(lambda);
fut.wait();
}
FLUTTER_PLUGIN_EXPORT void set_background_color_ffi(const void* const viewer, const float r, const float g, const float b, const float a) {
std::packaged_task<void()> lambda([&]() mutable {
set_background_color(viewer, r, g,b, a);
});
auto fut = _rl->add_task(lambda);
fut.wait();
}
}