From 07ad94de13612d27255dacdd6299797b7a6292c1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 6 Jun 2021 23:15:41 +0200 Subject: [PATCH] Optimize Animated Model bones matrices buffer update --- Source/Engine/Animations/Animations.cpp | 2 -- .../Graphics/Models/SkinnedMeshDrawData.cpp | 35 ++++++++++--------- .../Graphics/Models/SkinnedMeshDrawData.h | 7 +++- Source/Engine/Level/Actors/AnimatedModel.cpp | 14 ++++---- 4 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Source/Engine/Animations/Animations.cpp b/Source/Engine/Animations/Animations.cpp index 9ef229d23..d2e095fa6 100644 --- a/Source/Engine/Animations/Animations.cpp +++ b/Source/Engine/Animations/Animations.cpp @@ -7,7 +7,6 @@ #include "Engine/Engine/EngineService.h" Array UpdateList; -Array UpdateBones; class AnimationsService : public EngineService { @@ -81,7 +80,6 @@ void AnimationsService::Update() void AnimationsService::Dispose() { UpdateList.Resize(0); - UpdateBones.Resize(0); } void Animations::AddToUpdate(AnimatedModel* obj) diff --git a/Source/Engine/Graphics/Models/SkinnedMeshDrawData.cpp b/Source/Engine/Graphics/Models/SkinnedMeshDrawData.cpp index a99984a0c..a8fc48889 100644 --- a/Source/Engine/Graphics/Models/SkinnedMeshDrawData.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMeshDrawData.cpp @@ -41,10 +41,27 @@ void SkinnedMeshDrawData::SetData(const Matrix* bones, bool dropHistory) { if (!bones) return; - ASSERT(BonesCount > 0); - ANIM_GRAPH_PROFILE_EVENT("SetSkinnedMeshData"); + // Copy bones to the buffer + const int32 count = BonesCount; + const int32 preFetchStride = 2; + const Matrix* input = bones; + const auto output = (Matrix3x4*)Data.Get(); + ASSERT(Data.Count() == count * sizeof(Matrix3x4)); + for (int32 i = 0; i < count; i++) + { + Matrix3x4* bone = output + i; + Platform::Prefetch(bone + preFetchStride); + Platform::Prefetch((byte*)(bone + preFetchStride) + PLATFORM_CACHE_LINE_SIZE); + bone->SetMatrixTranspose(input[i]); + } + + OnDataChanged(dropHistory); +} + +void SkinnedMeshDrawData::OnDataChanged(bool dropHistory) +{ // Setup previous frame bone matrices if needed if (_hasValidData && !dropHistory) { @@ -64,20 +81,6 @@ void SkinnedMeshDrawData::SetData(const Matrix* bones, bool dropHistory) SAFE_DELETE_GPU_RESOURCE(PrevBoneMatrices); } - // Copy bones to the buffer - const int32 count = BonesCount; - const int32 preFetchStride = 2; - const Matrix* input = bones; - const auto output = (Matrix3x4*)Data.Get(); - ASSERT(Data.Count() == count * sizeof(Matrix3x4)); - for (int32 i = 0; i < count; i++) - { - Matrix3x4* bone = output + i; - Platform::Prefetch(bone + preFetchStride); - Platform::Prefetch((byte*)(bone + preFetchStride) + PLATFORM_CACHE_LINE_SIZE); - bone->SetMatrixTranspose(input[i]); - } - _isDirty = true; _hasValidData = true; } diff --git a/Source/Engine/Graphics/Models/SkinnedMeshDrawData.h b/Source/Engine/Graphics/Models/SkinnedMeshDrawData.h index f9d434fee..a9a882684 100644 --- a/Source/Engine/Graphics/Models/SkinnedMeshDrawData.h +++ b/Source/Engine/Graphics/Models/SkinnedMeshDrawData.h @@ -54,7 +54,6 @@ public: /// /// Determines whether this instance is ready for rendering. /// - /// True if has valid data and can be rendered, otherwise false. FORCE_INLINE bool IsReady() const { return BoneMatrices != nullptr && BoneMatrices->IsAllocated(); @@ -73,6 +72,12 @@ public: /// True if drop previous update bones used for motion blur, otherwise will keep them and do the update. void SetData(const Matrix* bones, bool dropHistory); + /// + /// After bones Data has been modified externally. Updates the bone matrices data for the GPU buffer. Ensure to call Flush before rendering. + /// + /// True if drop previous update bones used for motion blur, otherwise will keep them and do the update. + void OnDataChanged(bool dropHistory); + /// /// Flushes the bones data buffer with the GPU by sending the data fro the CPU. /// diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp index ece54b78b..701df3d6e 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.cpp +++ b/Source/Engine/Level/Actors/AnimatedModel.cpp @@ -2,6 +2,7 @@ #include "AnimatedModel.h" #include "BoneSocket.h" +#include "Engine/Core/Math/Matrix3x4.h" #include "Engine/Animations/Animations.h" #include "Engine/Engine/Engine.h" #if USE_EDITOR @@ -13,8 +14,6 @@ #include "Engine/Level/SceneObjectsFactory.h" #include "Engine/Serialization/Serialization.h" -extern Array UpdateBones; - AnimatedModel::AnimatedModel(const SpawnParams& params) : ModelInstanceActor(params) , _actualMode(AnimationUpdateMode::Never) @@ -470,14 +469,17 @@ void AnimatedModel::OnAnimationUpdated() // Calculate the final bones transformations and update skinning { ANIM_GRAPH_PROFILE_EVENT("Final Pose"); - UpdateBones.Resize(skeleton.Bones.Count(), false); - for (int32 boneIndex = 0; boneIndex < skeleton.Bones.Count(); boneIndex++) + const int32 bonesCount = skeleton.Bones.Count(); + Matrix3x4* output = (Matrix3x4*)_skinningData.Data.Get(); + ASSERT(_skinningData.Data.Count() == bonesCount * sizeof(Matrix3x4)); + for (int32 boneIndex = 0; boneIndex < bonesCount; boneIndex++) { auto& bone = skeleton.Bones[boneIndex]; - UpdateBones[boneIndex] = bone.OffsetMatrix * GraphInstance.NodesPose[bone.NodeIndex]; + Matrix matrix = bone.OffsetMatrix * GraphInstance.NodesPose[bone.NodeIndex]; + output[boneIndex].SetMatrixTranspose(matrix); } + _skinningData.OnDataChanged(!PerBoneMotionBlur); } - _skinningData.SetData(UpdateBones.Get(), !PerBoneMotionBlur); UpdateBounds(); UpdateSockets();