improve skinning memory usage and udpates
- use the exact required size for bone data instead of always the max of 256 bones. This also reduces the amount of data to update and copy into the command stream. - also get rid of the "reuse component" optimization, which is less needed now that renderables don't have their own transform UBO.
This commit is contained in:
committed by
Mathias Agopian
parent
5bbdc673f2
commit
4d9788ffb9
@@ -72,6 +72,10 @@ public:
|
||||
return static_cast<char*>(mBuffer) + offset;
|
||||
}
|
||||
|
||||
void* invalidate() noexcept {
|
||||
return invalidateUniforms(0, mSize);
|
||||
}
|
||||
|
||||
// pointer to the uniform buffer
|
||||
void const* getBuffer() const noexcept { return mBuffer; }
|
||||
|
||||
|
||||
@@ -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<Bones> 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<Visibility&>(manager[ci].visibility).skinning = builder->mSkinningBoneCount > 0;
|
||||
setSkinning(ci, false);
|
||||
|
||||
if (!canReuse) {
|
||||
if (builder->mSkinningBoneCount) {
|
||||
std::unique_ptr<Bones>& 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<Bones> const& bones = manager[ci].bones;
|
||||
const size_t count = builder->mSkinningBoneCount;
|
||||
if (UTILS_UNLIKELY(count)) {
|
||||
std::unique_ptr<Bones>& bones = manager[ci].bones;
|
||||
bones = std::unique_ptr<Bones>(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{});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<FRenderPrimitive> 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> aabb;
|
||||
Field<LAYERS> layers;
|
||||
Field<VISIBILITY> visibility;
|
||||
Field<PRIMITIVES> primitives;
|
||||
Field<BONES> bones;
|
||||
Field<AABB> aabb;
|
||||
Field<LAYERS> layers;
|
||||
Field<VISIBILITY> visibility;
|
||||
Field<PRIMITIVES> primitives;
|
||||
Field<BONES> 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<FRenderPrimitive> const& primitives) noexcept {
|
||||
if (instance) {
|
||||
|
||||
Reference in New Issue
Block a user