Skip to content

Commit b90a562

Browse files
HnMaterial: reworked material buffer update
1 parent 1e536fe commit b90a562

File tree

3 files changed

+74
-84
lines changed

3 files changed

+74
-84
lines changed

Hydrogent/interface/HnMaterial.hpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ class HnMaterial final : public pxr::HdMaterial
7878
/// Creates an SRB cache that should be passed to UpdateSRB().
7979
static RefCntAutoPtr<IObject> CreateSRBCache();
8080

81-
bool UpdateSRB(HnRenderDelegate& RenderDelegate);
82-
void BindMaterialAttribsBuffer(HnRenderDelegate& RenderDelegate);
81+
bool UpdateSRB(HnRenderDelegate& RenderDelegate);
82+
static void CommitCacheResources(HnRenderDelegate& RenderDelegate);
8383

8484
IShaderResourceBinding* GetSRB() const { return m_SRB; }
8585
IShaderResourceBinding* GetSRB(Uint32 PrimitiveAttribsOffset) const
@@ -190,11 +190,6 @@ class HnMaterial final : public pxr::HdMaterial
190190
// The range that is used to bind the cbPrimitiveAttribs buffer.
191191
Uint32 m_PBRPrimitiveAttribsBufferRange = 0;
192192

193-
// The range that is used to bind the cbMaterialAttribs buffer.
194-
// This is the maximum of all material attribs buffer sizes for
195-
// all materials that use the same SRB.
196-
Uint32 m_PBRMaterialAttribsBufferRange = 0;
197-
198193
PBR_Renderer::PSO_FLAGS m_PSOFlags = PBR_Renderer::PSO_FLAG_NONE;
199194

200195
// Material attribs shader data size in bytes.

Hydrogent/src/HnMaterial.cpp

Lines changed: 71 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -693,45 +693,58 @@ class HnMaterialSRBCache : public ObjectBase<IObject>
693693
return it->second;
694694
}
695695

696-
void UpdateMaterialAttribsBufferRange(const IShaderResourceBinding* pSRB, Uint32 Range)
697-
{
698-
std::lock_guard<std::mutex> Lock{m_MaterialAttribsBufferRangeMtx};
699-
700-
auto& SRBRange = m_MaterialAttribsBufferRange[pSRB];
701-
SRBRange = std::max(SRBRange, Range);
702-
}
703-
704-
Uint32 GetMaterialAttribsBufferRange(const IShaderResourceBinding* pSRB) const
705-
{
706-
std::lock_guard<std::mutex> Lock{m_MaterialAttribsBufferRangeMtx};
707-
708-
auto it = m_MaterialAttribsBufferRange.find(pSRB);
709-
VERIFY(it != m_MaterialAttribsBufferRange.end(), "SRB is not found in the cache");
710-
return it != m_MaterialAttribsBufferRange.end() ? it->second : 0;
711-
}
712-
713696
Uint32 AllocateBufferOffset(Uint32 Size, Uint32 Alignment, Uint32 MaxAttribsDataSize)
714697
{
715698
std::lock_guard<std::mutex> Lock{m_CurrBufferOffsetMtx};
716699

717-
const Uint32 Offset = AlignUp(m_CurrBufferOffset, Alignment);
718-
m_CurrBufferOffset = Offset + Size;
700+
const Uint32 Offset = AlignUp(m_CurrBufferOffset, Alignment);
701+
m_CurrBufferOffset = Offset + Size;
702+
// Reserve enough space for the maximum possible attribs data size.
719703
m_RequiredBufferSize = AlignUp(Offset + MaxAttribsDataSize, Alignment);
720704
return Offset;
721705
}
722706

723-
IBuffer* UpdateMaterialAttribsBuffer(IRenderDevice* pDevice, IDeviceContext* pContext)
707+
IBuffer* PrepareMaterialAttribsBuffer(IRenderDevice* pDevice, IDeviceContext* pContext)
724708
{
725709
if (m_RequiredBufferSize > m_MaterialAttribsBuffer.GetDesc().Size)
726710
{
727-
m_MaterialAttribsBuffer.Resize(pDevice, pContext, m_RequiredBufferSize);
711+
m_MaterialAttribsData.resize(m_RequiredBufferSize);
712+
return m_MaterialAttribsBuffer.Resize(pDevice, pContext, m_RequiredBufferSize);
713+
}
714+
else
715+
{
716+
return m_MaterialAttribsBuffer.GetBuffer();
717+
}
718+
}
719+
720+
void UpdateMaterialAttribsData(Uint32 Offset, Uint32 Size, const GLTF_PBR_Renderer::PBRMaterialShaderAttribsData AttribsData)
721+
{
722+
if (Offset + Size > m_MaterialAttribsData.size())
723+
{
724+
UNEXPECTED("Offset + Size (", Offset + Size, ") exceeds the size of the material attribs data buffer (", m_MaterialAttribsData.size(), ")");
725+
return;
728726
}
729-
return m_MaterialAttribsBuffer.GetBuffer();
727+
void* pEnd = GLTF_PBR_Renderer::WritePBRMaterialShaderAttribs(&m_MaterialAttribsData[Offset], AttribsData);
728+
VERIFY_EXPR(static_cast<Uint32>(reinterpret_cast<const Uint8*>(pEnd) - &m_MaterialAttribsData[Offset]) == Size);
729+
(void)pEnd;
730+
m_DirtyRangeStart = std::min(m_DirtyRangeStart, Offset);
731+
m_DirtyRangeEnd = std::max(m_DirtyRangeEnd, Offset + Size);
730732
}
731733

732-
IBuffer* GetMaterialAttribsBuffer() const
734+
IBuffer* CommitUpdates(IRenderDevice* pDevice, IDeviceContext* pContext)
733735
{
734-
return m_MaterialAttribsBuffer.GetBuffer();
736+
IBuffer* pBuffer = m_MaterialAttribsBuffer.GetBuffer();
737+
if (m_DirtyRangeStart < m_DirtyRangeEnd)
738+
{
739+
if (pDevice->GetDeviceInfo().Type == RENDER_DEVICE_TYPE_D3D11)
740+
{
741+
// Direct3D11 for unknown reason does not support partial constant buffer updates
742+
m_DirtyRangeStart = 0;
743+
m_DirtyRangeEnd = m_MaterialAttribsData.size();
744+
}
745+
pContext->UpdateBuffer(pBuffer, m_DirtyRangeStart, m_DirtyRangeEnd - m_DirtyRangeStart, &m_MaterialAttribsData[m_DirtyRangeStart], RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
746+
}
747+
return pBuffer;
735748
}
736749

737750
Uint32 GetMaterialAttribsBufferVersion() const
@@ -758,15 +771,14 @@ class HnMaterialSRBCache : public ObjectBase<IObject>
758771

759772
std::unordered_map<ShaderTextureIndexingIdType, const StaticShaderTextureIdsArrayType&> m_IdToIndexing;
760773

761-
// A mapping from the SRB to the maximum buffer range required by a material that uses the SRB.
762-
mutable std::mutex m_MaterialAttribsBufferRangeMtx;
763-
std::unordered_map<const IShaderResourceBinding*, Uint32> m_MaterialAttribsBufferRange;
764-
765774
std::mutex m_CurrBufferOffsetMtx;
766775
Uint32 m_CurrBufferOffset = 0;
767776
Uint32 m_RequiredBufferSize = 0;
768777

769-
DynamicBuffer m_MaterialAttribsBuffer;
778+
DynamicBuffer m_MaterialAttribsBuffer;
779+
std::vector<Uint8> m_MaterialAttribsData;
780+
Uint32 m_DirtyRangeStart = 0;
781+
Uint32 m_DirtyRangeEnd = 0;
770782
};
771783

772784
void HnMaterial::AllocateBufferSpace(HnRenderDelegate& RenderDelegate)
@@ -907,24 +919,17 @@ bool HnMaterial::UpdateSRB(HnRenderDelegate& RenderDelegate)
907919

908920
RefCntAutoPtr<HnMaterialSRBCache> SRBCache{RenderDelegate.GetMaterialSRBCache(), IID_HnMaterialSRBCache};
909921
VERIFY_EXPR(SRBCache);
922+
IBuffer* pMaterialAttribsBuffer = SRBCache->PrepareMaterialAttribsBuffer(RenderDelegate.GetDevice(), RenderDelegate.GetDeviceContext());
910923

911924
if (m_GPUDataDirty.load())
912925
{
913-
IDeviceContext* pContext = RenderDelegate.GetDeviceContext();
914-
IBuffer* pMaterialAttribsBuffer = SRBCache->UpdateMaterialAttribsBuffer(RenderDelegate.GetDevice(), pContext);
915926
VERIFY_EXPR(m_PSOFlags == HnRenderPass::GetMaterialPSOFlags(*this));
916-
917-
GLTF_PBR_Renderer::PBRMaterialShaderAttribsData AttribsData{
918-
m_PSOFlags,
919-
UsdRenderer.GetSettings().TextureAttribIndices,
920-
m_MaterialData,
921-
};
922-
std::vector<Uint8> MaterialAttribsData(m_PBRMaterialAttribsSize);
923-
void* pEnd = GLTF_PBR_Renderer::WritePBRMaterialShaderAttribs(MaterialAttribsData.data(), AttribsData);
924-
VERIFY_EXPR(static_cast<size_t>(reinterpret_cast<const Uint8*>(pEnd) - MaterialAttribsData.data()) == m_PBRMaterialAttribsSize);
925-
926-
pContext->UpdateBuffer(pMaterialAttribsBuffer, m_PBRMaterialAttribsBufferOffset, m_PBRMaterialAttribsSize, MaterialAttribsData.data(), RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
927-
927+
SRBCache->UpdateMaterialAttribsData(m_PBRMaterialAttribsBufferOffset, m_PBRMaterialAttribsSize,
928+
{
929+
m_PSOFlags,
930+
UsdRenderer.GetSettings().TextureAttribIndices,
931+
m_MaterialData,
932+
});
928933
m_GPUDataDirty.store(false);
929934
}
930935

@@ -936,12 +941,11 @@ bool HnMaterial::UpdateSRB(HnRenderDelegate& RenderDelegate)
936941
m_MaterialAttribsBufferVersion != MaterialAttribsBufferVersion)
937942
{
938943
m_SRB.Release();
939-
m_PrimitiveAttribsVar = nullptr;
940-
m_MaterialAttribsVar = nullptr;
941-
m_JointTransformsVar = nullptr;
942-
m_PBRMaterialAttribsBufferRange = 0;
943-
m_TexRegistryStorageVersion = TexStorageVersion;
944-
m_MaterialAttribsBufferVersion = MaterialAttribsBufferVersion;
944+
m_PrimitiveAttribsVar = nullptr;
945+
m_MaterialAttribsVar = nullptr;
946+
m_JointTransformsVar = nullptr;
947+
m_TexRegistryStorageVersion = TexStorageVersion;
948+
m_MaterialAttribsBufferVersion = MaterialAttribsBufferVersion;
945949
}
946950

947951
if (m_SRB)
@@ -1232,9 +1236,15 @@ bool HnMaterial::UpdateSRB(HnRenderDelegate& RenderDelegate)
12321236

12331237
if (m_SRB)
12341238
{
1235-
const PBR_Renderer::PSO_FLAGS PSOFlags = HnRenderPass::GetMaterialPSOFlags(*this);
1236-
const Uint32 PBRMaterialAttribsSize = UsdRenderer.GetPBRMaterialAttribsSize(PSOFlags);
1237-
SRBCache->UpdateMaterialAttribsBufferRange(m_SRB, PBRMaterialAttribsSize);
1239+
m_MaterialAttribsVar = m_SRB->GetVariableByName(SHADER_TYPE_PIXEL, "cbMaterialAttribs");
1240+
VERIFY_EXPR(m_MaterialAttribsVar != nullptr);
1241+
if (m_MaterialAttribsVar->Get() == nullptr)
1242+
{
1243+
// Bind maximum possible buffer range
1244+
const Uint32 PBRMaterialAttribsMaxSize = UsdRenderer.GetPBRMaterialAttribsSize(PBR_Renderer::PSO_FLAG_ALL);
1245+
m_MaterialAttribsVar->SetBufferRange(pMaterialAttribsBuffer, 0, PBRMaterialAttribsMaxSize);
1246+
}
1247+
12381248
m_JointTransformsVar = m_SRB->GetVariableByName(SHADER_TYPE_VERTEX, UsdRenderer.GetJointTransformsVarName());
12391249
VERIFY_EXPR(m_JointTransformsVar != nullptr || RendererSettings.MaxJointCount == 0);
12401250

@@ -1244,7 +1254,10 @@ bool HnMaterial::UpdateSRB(HnRenderDelegate& RenderDelegate)
12441254

12451255
m_PrimitiveAttribsVar = m_SRB->GetVariableByName(SHADER_TYPE_PIXEL, "cbPrimitiveAttribs");
12461256
VERIFY_EXPR(m_PrimitiveAttribsVar != nullptr);
1247-
m_PrimitiveAttribsVar->SetBufferRange(UsdRenderer.GetPBRPrimitiveAttribsCB(), 0, m_PBRPrimitiveAttribsBufferRange);
1257+
if (m_PrimitiveAttribsVar->Get() == nullptr)
1258+
{
1259+
m_PrimitiveAttribsVar->SetBufferRange(UsdRenderer.GetPBRPrimitiveAttribsCB(), 0, m_PBRPrimitiveAttribsBufferRange);
1260+
}
12481261
}
12491262
else
12501263
{
@@ -1254,30 +1267,15 @@ bool HnMaterial::UpdateSRB(HnRenderDelegate& RenderDelegate)
12541267
return true;
12551268
}
12561269

1257-
void HnMaterial::BindMaterialAttribsBuffer(HnRenderDelegate& RenderDelegate)
1270+
void HnMaterial::CommitCacheResources(HnRenderDelegate& RenderDelegate)
12581271
{
1259-
if (!m_SRB || m_MaterialAttribsVar != nullptr)
1260-
return;
1261-
1262-
m_MaterialAttribsVar = m_SRB->GetVariableByName(SHADER_TYPE_PIXEL, "cbMaterialAttribs");
1263-
if (m_MaterialAttribsVar == nullptr)
1264-
{
1265-
UNEXPECTED("Failed to find 'cbMaterialAttribs' variable in the shader resource binding.");
1266-
return;
1267-
}
1268-
12691272
RefCntAutoPtr<HnMaterialSRBCache> SRBCache{RenderDelegate.GetMaterialSRBCache(), IID_HnMaterialSRBCache};
12701273
VERIFY_EXPR(SRBCache);
12711274

1272-
m_PBRMaterialAttribsBufferRange = SRBCache->GetMaterialAttribsBufferRange(m_SRB);
1273-
VERIFY(m_PBRMaterialAttribsBufferRange != 0,
1274-
"PBRMaterialAttribsBufferRange is zero, which indicates the SRB was not found in the cache. This appears to be a bug.");
1275-
1276-
// Check if the buffer has already been set by another material that uses the same SRB
1277-
if (m_MaterialAttribsVar->Get() == nullptr)
1278-
{
1279-
m_MaterialAttribsVar->SetBufferRange(SRBCache->GetMaterialAttribsBuffer(), 0, m_PBRMaterialAttribsBufferRange);
1280-
}
1275+
IDeviceContext* pContext = RenderDelegate.GetDeviceContext();
1276+
IBuffer* pBuffer = SRBCache->CommitUpdates(RenderDelegate.GetDevice(), pContext);
1277+
StateTransitionDesc Barrier{pBuffer, RESOURCE_STATE_UNKNOWN, RESOURCE_STATE_CONSTANT_BUFFER, STATE_TRANSITION_FLAG_UPDATE_STATE};
1278+
pContext->TransitionResourceStates(1, &Barrier);
12811279
}
12821280

12831281
} // namespace USD

Hydrogent/src/HnRenderDelegate.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -747,10 +747,7 @@ void HnRenderDelegate::CommitResources(pxr::HdChangeTracker* tracker)
747747
if (!pMat->UpdateSRB(*this))
748748
AllMaterialsUpdated = false;
749749
}
750-
for (auto* pMat : m_Materials)
751-
{
752-
pMat->BindMaterialAttribsBuffer(*this);
753-
}
750+
HnMaterial::CommitCacheResources(*this);
754751

755752
if (AllMaterialsUpdated)
756753
{

0 commit comments

Comments
 (0)