Optimize Animated Model bones matrices buffer update
This commit is contained in:
@@ -7,7 +7,6 @@
|
|||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
|
|
||||||
Array<AnimatedModel*> UpdateList;
|
Array<AnimatedModel*> UpdateList;
|
||||||
Array<Matrix> UpdateBones;
|
|
||||||
|
|
||||||
class AnimationsService : public EngineService
|
class AnimationsService : public EngineService
|
||||||
{
|
{
|
||||||
@@ -81,7 +80,6 @@ void AnimationsService::Update()
|
|||||||
void AnimationsService::Dispose()
|
void AnimationsService::Dispose()
|
||||||
{
|
{
|
||||||
UpdateList.Resize(0);
|
UpdateList.Resize(0);
|
||||||
UpdateBones.Resize(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animations::AddToUpdate(AnimatedModel* obj)
|
void Animations::AddToUpdate(AnimatedModel* obj)
|
||||||
|
|||||||
@@ -41,10 +41,27 @@ void SkinnedMeshDrawData::SetData(const Matrix* bones, bool dropHistory)
|
|||||||
{
|
{
|
||||||
if (!bones)
|
if (!bones)
|
||||||
return;
|
return;
|
||||||
ASSERT(BonesCount > 0);
|
|
||||||
|
|
||||||
ANIM_GRAPH_PROFILE_EVENT("SetSkinnedMeshData");
|
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
|
// Setup previous frame bone matrices if needed
|
||||||
if (_hasValidData && !dropHistory)
|
if (_hasValidData && !dropHistory)
|
||||||
{
|
{
|
||||||
@@ -64,20 +81,6 @@ void SkinnedMeshDrawData::SetData(const Matrix* bones, bool dropHistory)
|
|||||||
SAFE_DELETE_GPU_RESOURCE(PrevBoneMatrices);
|
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;
|
_isDirty = true;
|
||||||
_hasValidData = true;
|
_hasValidData = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether this instance is ready for rendering.
|
/// Determines whether this instance is ready for rendering.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>True if has valid data and can be rendered, otherwise false.</returns>
|
|
||||||
FORCE_INLINE bool IsReady() const
|
FORCE_INLINE bool IsReady() const
|
||||||
{
|
{
|
||||||
return BoneMatrices != nullptr && BoneMatrices->IsAllocated();
|
return BoneMatrices != nullptr && BoneMatrices->IsAllocated();
|
||||||
@@ -73,6 +72,12 @@ public:
|
|||||||
/// <param name="dropHistory">True if drop previous update bones used for motion blur, otherwise will keep them and do the update.</param>
|
/// <param name="dropHistory">True if drop previous update bones used for motion blur, otherwise will keep them and do the update.</param>
|
||||||
void SetData(const Matrix* bones, bool dropHistory);
|
void SetData(const Matrix* bones, bool dropHistory);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// After bones Data has been modified externally. Updates the bone matrices data for the GPU buffer. Ensure to call Flush before rendering.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dropHistory">True if drop previous update bones used for motion blur, otherwise will keep them and do the update.</param>
|
||||||
|
void OnDataChanged(bool dropHistory);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flushes the bones data buffer with the GPU by sending the data fro the CPU.
|
/// Flushes the bones data buffer with the GPU by sending the data fro the CPU.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "AnimatedModel.h"
|
#include "AnimatedModel.h"
|
||||||
#include "BoneSocket.h"
|
#include "BoneSocket.h"
|
||||||
|
#include "Engine/Core/Math/Matrix3x4.h"
|
||||||
#include "Engine/Animations/Animations.h"
|
#include "Engine/Animations/Animations.h"
|
||||||
#include "Engine/Engine/Engine.h"
|
#include "Engine/Engine/Engine.h"
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
@@ -13,8 +14,6 @@
|
|||||||
#include "Engine/Level/SceneObjectsFactory.h"
|
#include "Engine/Level/SceneObjectsFactory.h"
|
||||||
#include "Engine/Serialization/Serialization.h"
|
#include "Engine/Serialization/Serialization.h"
|
||||||
|
|
||||||
extern Array<Matrix> UpdateBones;
|
|
||||||
|
|
||||||
AnimatedModel::AnimatedModel(const SpawnParams& params)
|
AnimatedModel::AnimatedModel(const SpawnParams& params)
|
||||||
: ModelInstanceActor(params)
|
: ModelInstanceActor(params)
|
||||||
, _actualMode(AnimationUpdateMode::Never)
|
, _actualMode(AnimationUpdateMode::Never)
|
||||||
@@ -470,14 +469,17 @@ void AnimatedModel::OnAnimationUpdated()
|
|||||||
// Calculate the final bones transformations and update skinning
|
// Calculate the final bones transformations and update skinning
|
||||||
{
|
{
|
||||||
ANIM_GRAPH_PROFILE_EVENT("Final Pose");
|
ANIM_GRAPH_PROFILE_EVENT("Final Pose");
|
||||||
UpdateBones.Resize(skeleton.Bones.Count(), false);
|
const int32 bonesCount = skeleton.Bones.Count();
|
||||||
for (int32 boneIndex = 0; boneIndex < skeleton.Bones.Count(); boneIndex++)
|
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];
|
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();
|
UpdateBounds();
|
||||||
UpdateSockets();
|
UpdateSockets();
|
||||||
|
|||||||
Reference in New Issue
Block a user