diff --git a/filament/src/UniformBuffer.h b/filament/src/UniformBuffer.h index cac637301a..7b5e4c783e 100644 --- a/filament/src/UniformBuffer.h +++ b/filament/src/UniformBuffer.h @@ -72,6 +72,10 @@ public: return static_cast(mBuffer) + offset; } + void* invalidate() noexcept { + return invalidateUniforms(0, mSize); + } + // pointer to the uniform buffer void const* getBuffer() const noexcept { return mBuffer; } diff --git a/filament/src/components/RenderableManager.cpp b/filament/src/components/RenderableManager.cpp index a5028fe10c..28261beba5 100644 --- a/filament/src/components/RenderableManager.cpp +++ b/filament/src/components/RenderableManager.cpp @@ -255,21 +255,10 @@ void FRenderableManager::create( auto& manager = mManager; FEngine::DriverApi& driver = engine.getDriverApi(); - // If we already have an instance we can reuse parts of it without completely - // destroying it. In particular we can reuse the UBO since it's the same for - // all renderables - bool canReuse = false; - Instance ci = getInstance(entity); - if (UTILS_UNLIKELY(ci)) { - canReuse = true; - destroyComponentPrimitives(engine, manager[ci].primitives); - std::unique_ptr const& bones = manager[ci].bones; - if (bones && !builder->mSkinningBoneCount) { - driver.destroyUniformBuffer(bones->handle); - } + if (UTILS_UNLIKELY(manager.hasComponent(entity))) { + destroy(entity); } - - ci = manager.addComponent(entity); + Instance ci = manager.addComponent(entity); assert(ci); if (ci) { @@ -288,31 +277,29 @@ void FRenderableManager::create( setCastShadows(ci, builder->mCastShadows); setReceiveShadows(ci, builder->mReceiveShadows); setCulling(ci, builder->mCulling); - static_cast(manager[ci].visibility).skinning = builder->mSkinningBoneCount > 0; + setSkinning(ci, false); - if (!canReuse) { - if (builder->mSkinningBoneCount) { - std::unique_ptr& bones = manager[ci].bones; - - bones.reset(new Bones); // FIXME: maybe use a pool allocator - bones->bones = UniformBuffer(CONFIG_MAX_BONE_COUNT * sizeof(PerRenderableUibBone)); - bones->handle = driver.createUniformBuffer(CONFIG_MAX_BONE_COUNT * sizeof(PerRenderableUibBone), - driver::BufferUsage::DYNAMIC); - } - } - if (builder->mSkinningBoneCount) { - std::unique_ptr const& bones = manager[ci].bones; + const size_t count = builder->mSkinningBoneCount; + if (UTILS_UNLIKELY(count)) { + std::unique_ptr& bones = manager[ci].bones; + bones = std::unique_ptr(new Bones{ + driver.createUniformBuffer(count * sizeof(PerRenderableUibBone), + driver::BufferUsage::DYNAMIC), + UniformBuffer{ count * sizeof(PerRenderableUibBone) }, + (uint8_t)count + }); assert(bones); - bones->count = (uint8_t)builder->mSkinningBoneCount; - if (builder->mUserBones) { - setBones(ci, builder->mUserBones, bones->count); - } else if (builder->mUserBoneMatrices) { - setBones(ci, builder->mUserBoneMatrices, bones->count); - } else { - // initialize the bones to identity - PerRenderableUibBone* UTILS_RESTRICT out = - (PerRenderableUibBone*)bones->bones.invalidateUniforms(0, bones->count * sizeof(PerRenderableUibBone)); - std::uninitialized_fill_n(out, bones->count, PerRenderableUibBone{}); + if (bones) { + setSkinning(ci, true); + if (builder->mUserBones) { + setBones(ci, builder->mUserBones, count); + } else if (builder->mUserBoneMatrices) { + setBones(ci, builder->mUserBoneMatrices, count); + } else { + // initialize the bones to identity + PerRenderableUibBone* out = (PerRenderableUibBone*)bones->bones.invalidate(); + std::uninitialized_fill_n(out, count, PerRenderableUibBone{}); + } } } } diff --git a/filament/src/components/RenderableManager.h b/filament/src/components/RenderableManager.h index 5c60070f42..e3e572f6d0 100644 --- a/filament/src/components/RenderableManager.h +++ b/filament/src/components/RenderableManager.h @@ -99,6 +99,7 @@ public: inline void setLayerMask(Instance instance, uint8_t layerMask) noexcept; inline void setReceiveShadows(Instance instance, bool enable) noexcept; inline void setCulling(Instance instance, bool enable) noexcept; + inline void setSkinning(Instance instance, bool enable) noexcept; inline void setPrimitives(Instance instance, utils::Slice const& primitives) noexcept; inline void setBones(Instance instance, Bone const* transforms, size_t boneCount, size_t offset = 0) noexcept; inline void setBones(Instance instance, math::mat4f const* transforms, size_t boneCount, size_t offset = 0) noexcept; @@ -175,11 +176,11 @@ private: union { // this specific usage of union is permitted. All fields are identical - Field aabb; - Field layers; - Field visibility; - Field primitives; - Field bones; + Field aabb; + Field layers; + Field visibility; + Field primitives; + Field bones; }; }; @@ -245,6 +246,13 @@ void FRenderableManager::setCulling(Instance instance, bool enable) noexcept { } } +void FRenderableManager::setSkinning(Instance instance, bool enable) noexcept { + if (instance) { + Visibility& visibility = mManager[instance].visibility; + visibility.skinning = enable; + } +} + void FRenderableManager::setPrimitives(Instance instance, utils::Slice const& primitives) noexcept { if (instance) {