From 5147ded0517d1e95b2bfadea15a5d37bc54387ed Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Fri, 3 Aug 2018 12:03:36 -0700 Subject: [PATCH] Fix skinning bugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - We were not setting the bones ubo staging buffer size correctly - The bones UBO was never bound to the shader - The default values for the bones ubo wasn’t identity --- filament/include/filament/RenderableManager.h | 5 +++-- filament/src/Material.cpp | 4 ++++ filament/src/RenderPass.cpp | 6 ++++++ filament/src/RenderPass.h | 3 ++- filament/src/Scene.cpp | 1 + filament/src/components/RenderableManager.cpp | 4 ++-- filament/src/components/RenderableManager.h | 6 ++++++ filament/src/details/Scene.h | 2 ++ 8 files changed, 26 insertions(+), 5 deletions(-) diff --git a/filament/include/filament/RenderableManager.h b/filament/include/filament/RenderableManager.h index 528c0f4bb8..3dfc6e27e1 100644 --- a/filament/include/filament/RenderableManager.h +++ b/filament/include/filament/RenderableManager.h @@ -54,8 +54,9 @@ public: Instance getInstance(utils::Entity e) const noexcept; struct Bone { - math::quatf unitQuaternion; - math::float3 translation = {}; + math::quatf unitQuaternion = { 1, 0, 0, 0 }; + math::float3 translation = { 0, 0, 0 }; + float reserved = 0; }; class Builder : public BuilderBase { diff --git a/filament/src/Material.cpp b/filament/src/Material.cpp index a489bc13ab..e4a32817eb 100644 --- a/filament/src/Material.cpp +++ b/filament/src/Material.cpp @@ -305,6 +305,10 @@ Handle FMaterial::getProgramSlow(uint8_t variantKey) const noexcept { .addSamplerBlock(BindingPoints::PER_VIEW, &SibGenerator::getPerViewSib()) .addSamplerBlock(BindingPoints::PER_MATERIAL_INSTANCE, &mSamplerInterfaceBlock); + if (Variant(variantKey).hasSkinning()) { + pb.addUniformBlock(BindingPoints::PER_RENDERABLE_BONES, &UibGenerator::getPerRenderableBonesUib()); + } + auto program = mEngine.getDriverApi().createProgram(std::move(pb)); assert(program); diff --git a/filament/src/RenderPass.cpp b/filament/src/RenderPass.cpp index b4c7814a64..6f4c1424da 100644 --- a/filament/src/RenderPass.cpp +++ b/filament/src/RenderPass.cpp @@ -132,6 +132,9 @@ void RenderPass::recordDriverCommands( // per-renderable uniform PrimitiveInfo const& UTILS_RESTRICT info = c->primitive; driver.bindUniforms(BindingPoints::PER_RENDERABLE, info.perRenderableUniforms); + if (info.perRenderableBones) { + driver.bindUniforms(BindingPoints::PER_RENDERABLE_BONES, info.perRenderableBones); + } FMaterialInstance const* const UTILS_RESTRICT mi = info.mi; if (UTILS_UNLIKELY(mi != previousMi)) { @@ -271,6 +274,7 @@ void RenderPass::generateCommandsImpl(uint32_t, auto const* const UTILS_RESTRICT soaVisibility = soa.data(); auto const* const UTILS_RESTRICT soaPrimitives = soa.data(); auto const* const UTILS_RESTRICT soaUbh = soa.data(); + auto const* const UTILS_RESTRICT soaBonesUbh = soa.data(); const bool hasShadowing = view->hasShadowing(); Variant materialVariant; @@ -321,6 +325,7 @@ void RenderPass::generateCommandsImpl(uint32_t, cmdColor.key = makeField(soaVisibility[i].priority, PRIORITY_MASK, PRIORITY_SHIFT); cmdColor.primitive.perRenderableUniforms = soaUbh[i]; + cmdColor.primitive.perRenderableBones = soaBonesUbh[i]; materialVariant.setShadowReceiver(soaVisibility[i].receiveShadows & hasShadowing); materialVariant.setSkinning(soaVisibility[i].skinning); @@ -330,6 +335,7 @@ void RenderPass::generateCommandsImpl(uint32_t, cmdDepth.key |= makeField(soaVisibility[i].priority, PRIORITY_MASK, PRIORITY_SHIFT); cmdDepth.key |= makeField(distanceBits, DISTANCE_BITS_MASK, DISTANCE_BITS_SHIFT); cmdDepth.primitive.perRenderableUniforms = soaUbh[i]; + cmdDepth.primitive.perRenderableBones = soaBonesUbh[i]; cmdDepth.primitive.materialVariant.setSkinning(soaVisibility[i].skinning); const bool shadowCaster = soaVisibility[i].castShadows & hasShadowing; diff --git a/filament/src/RenderPass.h b/filament/src/RenderPass.h index 1b52f3f94a..f395ae3253 100644 --- a/filament/src/RenderPass.h +++ b/filament/src/RenderPass.h @@ -171,10 +171,11 @@ public: return boolish ? -1llu : 0llu; } - struct PrimitiveInfo { // 24 bytes (20) + struct PrimitiveInfo { // 28 bytes FMaterialInstance const* mi = nullptr; // 8 bytes (4) Handle primitiveHandle; // 4 bytes Handle perRenderableUniforms; // 4 bytes + Handle perRenderableBones; // 4 bytes Driver::RasterState rasterState; // 4 bytes Variant materialVariant; // 1 byte uint8_t reserved[3] = { }; // 3 bytes (that helps the compiler) diff --git a/filament/src/Scene.cpp b/filament/src/Scene.cpp index 6e3d6d9a1b..4bd451836c 100644 --- a/filament/src/Scene.cpp +++ b/filament/src/Scene.cpp @@ -120,6 +120,7 @@ void FScene::prepare(FEngine& engine, mat4f const& worldOriginTansform) { worldTransform, rcm.getVisibility(ri), rcm.getUbh(ri), + rcm.getBonesUbh(ri), worldAABB.center, 0, rcm.getLayerMask(ri), diff --git a/filament/src/components/RenderableManager.cpp b/filament/src/components/RenderableManager.cpp index 7bb3587c12..9e0324c88c 100644 --- a/filament/src/components/RenderableManager.cpp +++ b/filament/src/components/RenderableManager.cpp @@ -288,8 +288,8 @@ void FRenderableManager::create(const RenderableManager::Builder& UTILS_RESTRICT std::unique_ptr& bones = manager[ci].bones; bones.reset(new Bones); // FIXME: maybe use a pool allocator - bones->bones = UniformBuffer(CONFIG_MAX_BONE_COUNT * 2); - bones->handle = driver.createUniformBuffer(CONFIG_MAX_BONE_COUNT * 2); + bones->bones = UniformBuffer(CONFIG_MAX_BONE_COUNT * sizeof(Bone)); + bones->handle = driver.createUniformBuffer(CONFIG_MAX_BONE_COUNT * sizeof(Bone)); } } if (builder->mSkinningBoneCount) { diff --git a/filament/src/components/RenderableManager.h b/filament/src/components/RenderableManager.h index a3714b565e..b0acb0decb 100644 --- a/filament/src/components/RenderableManager.h +++ b/filament/src/components/RenderableManager.h @@ -122,6 +122,7 @@ public: inline UniformBuffer& getUniformBuffer(Instance instance) noexcept; inline Handle getUbh(Instance instance) const noexcept; + inline Handle getBonesUbh(Instance instance) const noexcept; inline size_t getLevelCount(Instance instance) const noexcept { return 1; } @@ -310,6 +311,11 @@ Handle FRenderableManager::getUbh(Instance instance) const noex return mManager[instance].uniformsHandle; } +Handle FRenderableManager::getBonesUbh(Instance instance) const noexcept { + std::unique_ptr const& bones = mManager[instance].bones; + return bones ? bones->handle : Handle{}; +} + utils::Slice const& FRenderableManager::getRenderPrimitives( Instance instance, uint8_t level) const noexcept { return mManager[instance].primitives; diff --git a/filament/src/details/Scene.h b/filament/src/details/Scene.h index 1ea46b3b6f..1a43d545f9 100644 --- a/filament/src/details/Scene.h +++ b/filament/src/details/Scene.h @@ -92,6 +92,7 @@ public: WORLD_TRANSFORM, // 16 instance of the Transform component VISIBILITY_STATE, // 1 visibility data of the component UBH, // 4 uniform buffer handle + BONES_UBH, // 4 bones uniform buffer handle WORLD_AABB_CENTER, // 12 world-space bounding box center of the renderable VISIBLE_MASK, // 1 each bit represents a visibility in a pass @@ -109,6 +110,7 @@ public: math::mat4f, FRenderableManager::Visibility, Handle, + Handle, math::float3, Culler::result_type, uint8_t,