Skip to content

Commit b249bae

Browse files
HnMaterial: improved material attribs buffer region allocation strategy
1 parent 957b53a commit b249bae

File tree

2 files changed

+71
-27
lines changed

2 files changed

+71
-27
lines changed

Hydrogent/interface/HnMaterial.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ namespace USD
5656

5757
class HnRenderDelegate;
5858
class HnMaterialNetwork;
59+
class HnMaterialSRBCache;
5960

6061
/// Hydra material implementation in Hydrogent.
6162
class HnMaterial final : public pxr::HdMaterial
@@ -210,6 +211,8 @@ class HnMaterial final : public pxr::HdMaterial
210211
Uint32 m_ResourceCacheVersion = ~0u;
211212

212213
ShaderTextureIndexingIdType m_ShaderTextureIndexingId = 0;
214+
215+
RefCntAutoPtr<HnMaterialSRBCache> m_SRBCache;
213216
};
214217

215218
} // namespace USD

Hydrogent/src/HnMaterial.cpp

Lines changed: 68 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
#include "GLTFBuilder.hpp"
4646
#include "GLTF_PBR_Renderer.hpp"
4747
#include "DataBlobImpl.hpp"
48+
#include "VariableSizeAllocationsManager.hpp"
49+
#include "DefaultRawMemoryAllocator.hpp"
4850

4951
#include "pxr/imaging/hd/sceneDelegate.h"
5052

@@ -101,10 +103,6 @@ HnMaterial::HnMaterial(HnRenderDelegate& RenderDelegate) :
101103
AllocateTextures({}, RenderDelegate);
102104
}
103105

104-
HnMaterial::~HnMaterial()
105-
{
106-
}
107-
108106
void HnMaterial::Sync(pxr::HdSceneDelegate* SceneDelegate,
109107
pxr::HdRenderParam* RenderParam,
110108
pxr::HdDirtyBits* DirtyBits)
@@ -617,6 +615,13 @@ class HnMaterialSRBCache : public ObjectBase<IObject>
617615
HnMaterialSRBCache(IReferenceCounters* pRefCounters) :
618616
ObjectBase<IObject>{pRefCounters},
619617
m_Cache{/*NumRequestsToPurge = */ 128},
618+
m_BufferRegionMgr{
619+
VariableSizeAllocationsManager::CreateInfo{
620+
DefaultRawMemoryAllocator::GetAllocator(),
621+
2048,
622+
true, // DisableDebugValidation,
623+
},
624+
},
620625
m_MaterialAttribsBuffer{
621626
nullptr,
622627
DynamicBufferCreateInfo{
@@ -630,6 +635,11 @@ class HnMaterialSRBCache : public ObjectBase<IObject>
630635
}
631636
{}
632637

638+
~HnMaterialSRBCache()
639+
{
640+
VERIFY(m_BufferRegionMgr.GetUsedSize() == 0, "Not all buffer regions have been released");
641+
}
642+
633643
static RefCntAutoPtr<IObject> Create()
634644
{
635645
return RefCntAutoPtr<IObject>{MakeNewRCObj<HnMaterialSRBCache>()()};
@@ -703,17 +713,41 @@ class HnMaterialSRBCache : public ObjectBase<IObject>
703713
return it->second;
704714
}
705715

706-
Uint32 AllocateBufferOffset(Uint32 Size)
716+
void AllocateBufferOffset(Uint32& Offset, Uint32& Size, Uint32 RequiredSize)
707717
{
708-
std::lock_guard<std::mutex> Lock{m_CurrBufferOffsetMtx};
718+
std::lock_guard<std::mutex> Lock{m_BufferRegionMgrMtx};
709719

710720
VERIFY(m_ConstantBufferOffsetAlignment != 0 && m_MaxAttribsDataSize != 0, "The cache is not initialized");
721+
// Release the previously allocated region
722+
if (Offset != ~0u)
723+
{
724+
VERIFY_EXPR(Size != 0);
725+
VERIFY_EXPR(AlignUp(Offset, m_ConstantBufferOffsetAlignment) == Offset);
726+
m_BufferRegionMgr.Free(Offset, AlignUp(Size, m_ConstantBufferOffsetAlignment));
727+
}
728+
729+
Size = RequiredSize;
730+
if (RequiredSize != 0)
731+
{
732+
RequiredSize = AlignUp(RequiredSize, m_ConstantBufferOffsetAlignment);
733+
734+
VariableSizeAllocationsManager::Allocation Allocation = m_BufferRegionMgr.Allocate(RequiredSize, 1);
735+
if (!Allocation.IsValid())
736+
{
737+
VERIFY_EXPR(RequiredSize <= m_BufferRegionMgr.GetMaxSize());
738+
m_BufferRegionMgr.Extend(m_BufferRegionMgr.GetMaxSize());
739+
Allocation = m_BufferRegionMgr.Allocate(RequiredSize, 1);
740+
VERIFY_EXPR(Allocation.IsValid());
741+
}
711742

712-
const Uint32 Offset = AlignUp(m_CurrBufferOffset, m_ConstantBufferOffsetAlignment);
713-
m_CurrBufferOffset = Offset + Size;
714-
// Reserve enough space for the maximum possible attribs data size.
715-
m_RequiredBufferSize = AlignUp(Offset + m_MaxAttribsDataSize, m_ConstantBufferOffsetAlignment);
716-
return Offset;
743+
Offset = Allocation.UnalignedOffset;
744+
// Reserve enough space for the maximum possible attribs data size.
745+
m_RequiredBufferSize = std::max(m_RequiredBufferSize, AlignUp(Offset + m_MaxAttribsDataSize, m_ConstantBufferOffsetAlignment));
746+
}
747+
else
748+
{
749+
Offset = ~0u;
750+
}
717751
}
718752

719753
IBuffer* PrepareMaterialAttribsBuffer(IRenderDevice* pDevice, IDeviceContext* pContext)
@@ -731,7 +765,7 @@ class HnMaterialSRBCache : public ObjectBase<IObject>
731765

732766
IBuffer* GetMaterialAttribsBuffer() const
733767
{
734-
VERIFY_EXPR(m_RequiredBufferSize == m_MaterialAttribsBuffer.GetDesc().Size, "The buffer needs to be resized.");
768+
VERIFY(m_RequiredBufferSize == m_MaterialAttribsBuffer.GetDesc().Size, "The buffer needs to be resized.");
735769
return m_MaterialAttribsBuffer.GetBuffer();
736770
}
737771

@@ -751,7 +785,7 @@ class HnMaterialSRBCache : public ObjectBase<IObject>
751785

752786
IBuffer* CommitUpdates(IRenderDevice* pDevice, IDeviceContext* pContext)
753787
{
754-
VERIFY_EXPR(m_RequiredBufferSize == m_MaterialAttribsBuffer.GetDesc().Size, "The buffer needs to be resized.");
788+
VERIFY(m_RequiredBufferSize == m_MaterialAttribsBuffer.GetDesc().Size, "The buffer needs to be resized.");
755789
IBuffer* pBuffer = m_MaterialAttribsBuffer.GetBuffer();
756790
if (m_DirtyRangeStart < m_DirtyRangeEnd)
757791
{
@@ -800,9 +834,9 @@ class HnMaterialSRBCache : public ObjectBase<IObject>
800834
Uint32 m_ConstantBufferOffsetAlignment = 0;
801835
Uint32 m_MaxAttribsDataSize = 0;
802836

803-
std::mutex m_CurrBufferOffsetMtx;
804-
Uint32 m_CurrBufferOffset = 0;
805-
Uint32 m_RequiredBufferSize = 0;
837+
std::mutex m_BufferRegionMgrMtx;
838+
VariableSizeAllocationsManager m_BufferRegionMgr;
839+
Uint32 m_RequiredBufferSize = 0;
806840

807841
// Material attribs data resides in a single buffer shared by all SRBs.
808842
DynamicBuffer m_MaterialAttribsBuffer;
@@ -815,18 +849,20 @@ void HnMaterial::AllocateBufferSpace(HnRenderDelegate& RenderDelegate)
815849
{
816850
const USD_Renderer& UsdRenderer = *RenderDelegate.GetUSDRenderer();
817851

818-
m_PSOFlags = HnRenderPass::GetMaterialPSOFlags(*this);
819-
Uint32 LastPBRMaterialAttribsSize = m_PBRMaterialAttribsSize;
820-
m_PBRMaterialAttribsSize = UsdRenderer.GetPBRMaterialAttribsSize(m_PSOFlags);
821-
822-
// Note that in case material attribs size increases, previously allocated space will not be reused.
823-
// This, however, is unlikely to happen in practice.
824-
if (m_PBRMaterialAttribsBufferOffset == ~0u || m_PBRMaterialAttribsSize > LastPBRMaterialAttribsSize)
852+
m_PSOFlags = HnRenderPass::GetMaterialPSOFlags(*this);
853+
Uint32 AttribsSize = UsdRenderer.GetPBRMaterialAttribsSize(m_PSOFlags);
854+
if (m_PBRMaterialAttribsBufferOffset == ~0u || AttribsSize > m_PBRMaterialAttribsSize)
825855
{
826-
RefCntAutoPtr<HnMaterialSRBCache> SRBCache{RenderDelegate.GetMaterialSRBCache(), IID_HnMaterialSRBCache};
827-
VERIFY_EXPR(SRBCache);
828-
829-
m_PBRMaterialAttribsBufferOffset = SRBCache->AllocateBufferOffset(m_PBRMaterialAttribsSize);
856+
if (!m_SRBCache)
857+
{
858+
m_SRBCache = RefCntAutoPtr<HnMaterialSRBCache>{RenderDelegate.GetMaterialSRBCache(), IID_HnMaterialSRBCache};
859+
VERIFY_EXPR(m_SRBCache);
860+
}
861+
else
862+
{
863+
VERIFY_EXPR(m_SRBCache == RenderDelegate.GetMaterialSRBCache());
864+
}
865+
m_SRBCache->AllocateBufferOffset(m_PBRMaterialAttribsBufferOffset, m_PBRMaterialAttribsSize, AttribsSize);
830866
}
831867
}
832868

@@ -1325,6 +1361,11 @@ void HnMaterial::EndResourceUpdate(HnRenderDelegate& RenderDelegate)
13251361
}
13261362
}
13271363

1364+
HnMaterial::~HnMaterial()
1365+
{
1366+
m_SRBCache->AllocateBufferOffset(m_PBRMaterialAttribsBufferOffset, m_PBRMaterialAttribsSize, 0);
1367+
}
1368+
13281369
} // namespace USD
13291370

13301371
} // namespace Diligent

0 commit comments

Comments
 (0)