Skip to content

Commit

Permalink
HnRenderPass: batch joint data uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMostDiligent committed Nov 28, 2024
1 parent 4f4b83d commit 67c2de7
Show file tree
Hide file tree
Showing 6 changed files with 350 additions and 190 deletions.
4 changes: 3 additions & 1 deletion Hydrogent/include/Computations/HnSkinningComputation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class HnSkinningComputation final : public HnExtComputationImpl
static bool IsCompatible(const HnExtComputation& Owner);

const pxr::VtMatrix4fArray& GetXforms() const { return m_Xforms[m_CurrXformsIdx]; }
const pxr::VtMatrix4fArray& GetLastFrameXforms() const { return m_Xforms[1 - m_CurrXformsIdx]; }
const pxr::VtMatrix4fArray& GetPrevFrameXforms(Uint32 FrameNumber) const;
size_t GetXformsHash() const { return m_XformsHash; }

const float4x4& GetPrimWorldToLocal() const { return m_PrimWorldToLocal; }
Expand All @@ -75,6 +75,8 @@ class HnSkinningComputation final : public HnExtComputationImpl
float4x4 m_PrimWorldToLocal = float4x4::Identity();
float4x4 m_SkelLocalToWorld = float4x4::Identity();
float4x4 m_SkelLocalToPrimLocal = float4x4::Identity();

Uint32 m_LastXformSyncFrameNumber = 0;
};

} // namespace USD
Expand Down
11 changes: 5 additions & 6 deletions Hydrogent/interface/HnMesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ namespace USD
{

class HnRenderDelegate;
class HnExtComputation;
class HnSkinningComputation;

/// Hydra mesh implementation in Hydrogent.
class HnMesh final : public pxr::HdMesh
Expand Down Expand Up @@ -112,12 +112,11 @@ class HnMesh final : public pxr::HdMesh

struct Skinning
{
const pxr::VtMatrix4fArray* Xforms = nullptr;
const pxr::VtMatrix4fArray* LastFrameXforms = nullptr;
size_t XformsHash = 0;
float4x4 GeomBindXform = float4x4::Identity();
const HnSkinningComputation* Computation = nullptr;

explicit operator bool() const { return Xforms != nullptr; }
float4x4 GeomBindXform = float4x4::Identity();

explicit operator bool() const { return Computation != nullptr; }
};
};

Expand Down
39 changes: 35 additions & 4 deletions Hydrogent/interface/HnRenderPass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace USD
class HnDrawItem;
class HnRenderPassState;
class HnMaterial;
class HnSkinningComputation;

struct HnRenderPassParams
{
Expand Down Expand Up @@ -165,17 +166,27 @@ class HnRenderPass final : public pxr::HdRenderPass

PBR_Renderer::PSO_FLAGS PSOFlags = PBR_Renderer::PSO_FLAG_NONE;

const pxr::VtMatrix4fArray* PrevXforms = nullptr;
float4x4 PrevTransform = float4x4::Identity();
float4x4 PrevTransform = float4x4::Identity();

// Primitive attributes shader data size computed from the value of PSOFlags.
// Note: unshaded (aka wireframe/point) rendering modes don't use any textures, so the shader data
// is smaller than that for the shaded mode.
Uint32 ShaderAttribsDataSize = 0;
Uint16 ShaderAttribsDataSize = 0;

// Primitive attributes buffer range used to set the cbPrimitiveAttribs buffer
// in the material's SRB.
Uint32 PrimitiveAttribsBufferRange = 0;
Uint16 PrimitiveAttribsBufferRange = 0;

// Joints data index in m_DrawItemJoints.
// Mutiple draw items can share the same joints data.
//
// Draw Items [ 0 ][ 0 ][ -1 ][ 1 ][ 1 ]
// | | | |
// |.----' .-----------'------'
// V V
// Joints Data [ ][ ]
//
Uint32 JointsIdx = ~0u;

IBuffer* IndexBuffer = nullptr;

Expand All @@ -190,9 +201,11 @@ class HnRenderPass final : public pxr::HdRenderPass
};

void UpdateDrawList(const pxr::TfTokenVector& RenderTags);
void UpdateDrawListJoints(HnRenderDelegate& RenderDelegate);
void UpdateDrawListGPUResources(RenderState& State);
void UpdateDrawListItemGPUResources(DrawListItem& ListItem, RenderState& State, DRAW_LIST_ITEM_DIRTY_FLAGS DirtyFlags);

void WriteJointsDataBatch(RenderState& State, Uint32 BatchIdx, PBR_Renderer::PSO_FLAGS PSOFlags);
void RenderPendingDrawItems(RenderState& State);

GraphicsPipelineDesc GetGraphicsDesc(const HnRenderPassState& RPState, bool UseStripTopology) const;
Expand Down Expand Up @@ -226,6 +239,24 @@ class HnRenderPass final : public pxr::HdRenderPass
// Rendering order of the draw list items sorted by the PSO.
std::vector<Uint32> m_RenderOrder;

struct DrawItemJointsData
{
Uint32 BatchIdx = ~0u;
Uint32 BufferOffset = ~0u;
Uint32 JointCount = 0;
Uint32 FirstJoint = 0;
Uint32 DataSize = 0;

const HnSkinningComputation* SkinComp = nullptr;

constexpr operator bool() const noexcept
{
return BatchIdx != ~0u;
}
};
std::vector<DrawItemJointsData> m_DrawItemJoints;
size_t m_CurrDrawItemJointIdx = 0;

// Scratch space to prepare data for the primitive attributes buffer.
std::vector<Uint8> m_PrimitiveAttribsData;

Expand Down
25 changes: 20 additions & 5 deletions Hydrogent/src/Computations/HnSkinningComputation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "Computations/HnSkinningComputation.hpp"
#include "HnExtComputation.hpp"
#include "HnTokens.hpp"
#include "HnRenderParam.hpp"
#include "DebugUtilities.hpp"
#include "GfTypeConversions.hpp"
#include "HnRenderDelegate.hpp"
Expand Down Expand Up @@ -74,17 +75,15 @@ void HnSkinningComputation::Sync(pxr::HdSceneDelegate* SceneDelegate,
pxr::VtValue SkinningXformsVal = SceneDelegate->GetExtComputationInput(Id, HnSkinningComputationPrivateTokens->skinningXforms);
if (SkinningXformsVal.IsHolding<pxr::VtMatrix4fArray>())
{
pxr::VtMatrix4fArray& LastXforms = m_Xforms[m_CurrXformsIdx];
VERIFY_EXPR(m_Xforms.size() == 2);
m_CurrXformsIdx = 1 - m_CurrXformsIdx;
pxr::VtMatrix4fArray& Xforms = m_Xforms[m_CurrXformsIdx];

Xforms = SkinningXformsVal.UncheckedGet<pxr::VtMatrix4fArray>();
if (LastXforms.empty())
LastXforms = Xforms;

Xforms = SkinningXformsVal.UncheckedGet<pxr::VtMatrix4fArray>();
m_XformsHash = pxr::TfHash{}(Xforms);

m_LastXformSyncFrameNumber = static_cast<const HnRenderParam*>(RenderParam)->GetFrameNumber();

const HnRenderDelegate* RenderDelegate = static_cast<const HnRenderDelegate*>(SceneDelegate->GetRenderIndex().GetRenderDelegate());
const USD_Renderer& USDRenderer = *RenderDelegate->GetUSDRenderer();
const Uint32 MaxJointCount = USDRenderer.GetSettings().MaxJointCount;
Expand Down Expand Up @@ -151,6 +150,22 @@ bool HnSkinningComputation::IsCompatible(const HnExtComputation& Owner)
return Outputs.size() == 1 && Outputs[0].name == HnSkinningComputationPrivateTokens->skinnedPoints;
}

const pxr::VtMatrix4fArray& HnSkinningComputation::GetPrevFrameXforms(Uint32 FrameNumber) const
{
// Frame number is incremented by HnBeginFrameTask after all computations have been synced.
if (FrameNumber == m_LastXformSyncFrameNumber + 1)
{
const pxr::VtMatrix4fArray& PrevXforms = m_Xforms[1 - m_CurrXformsIdx];
return !PrevXforms.empty() ? PrevXforms : m_Xforms[m_CurrXformsIdx];
}
else
{
// Skinning xforms have not been updated for the current frame, so
// they are the same as the previous frame.
return m_Xforms[m_CurrXformsIdx];
}
}

} // namespace USD

} // namespace Diligent
4 changes: 1 addition & 3 deletions Hydrogent/src/HnMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -915,9 +915,7 @@ void HnMesh::UpdateSkinningPrimvars(pxr::HdSceneDelegate&

if (const HnSkinningComputation* SkinningCompImpl = SkinningComp->GetImpl<HnSkinningComputation>())
{
SkinningData.Xforms = &SkinningCompImpl->GetXforms();
SkinningData.LastFrameXforms = &SkinningCompImpl->GetLastFrameXforms();
SkinningData.XformsHash = SkinningCompImpl->GetXformsHash();
SkinningData.Computation = SkinningCompImpl;

const float4x4& SkelLocalToPrimLocal = SkinningCompImpl->GetSkelLocalToPrimLocal();
if (SkelLocalToPrimLocal != m_SkelLocalToPrimLocal)
Expand Down
Loading

0 comments on commit 67c2de7

Please sign in to comment.