From 30742ed471cb10534e6aa9b4211b4f80617fc7a0 Mon Sep 17 00:00:00 2001 From: Norbert Prokopiuk Date: Wed, 6 May 2026 07:45:04 +0200 Subject: [PATCH 1/2] Minimal working subset of c3f54576441eafc60253ed4ad3d7951ca28bbb17 Signed-off-by: Norbert Prokopiuk --- .../Feature/Mesh/MeshFeatureProcessorInterface.h | 3 +++ .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 15 ++++++++++++++- .../Code/Source/Mesh/MeshFeatureProcessor.h | 1 + .../RPI/ShaderResourceGroups/DefaultDrawSrg.azsli | 1 + .../Code/Include/Atom/RPI.Public/MeshDrawPacket.h | 4 ++++ .../RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp | 12 ++++++++++++ 6 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h index ae61d25f948d..3c243eed590b 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Mesh/MeshFeatureProcessorInterface.h @@ -132,6 +132,9 @@ namespace AZ virtual void ConnectMeshDrawPacketUpdatedHandler(MeshDrawPacketUpdatedEvent::Handler& handler) = 0; virtual CustomMaterialInfo GetCustomMaterialWithFallback(const CustomMaterialId& id) const = 0; + + //! Returns lodIndex * 32 + meshIndex, the value placed in DrawSrg::m_meshInfoIndex per draw call. + virtual int32_t GetMeshInfoIndex(size_t modelLodIndex, size_t meshIndex) const = 0; }; using CustomMaterialMap = AZStd::unordered_map; diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 7adcda43513c..5279a732cbd4 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -2197,7 +2197,13 @@ namespace AZ if (!r_meshInstancingEnabled || instanceGroupInsertResult.m_instanceCount == 1) { // setup the mesh draw packet - RPI::MeshDrawPacket drawPacket(modelLod, meshIndex, material, meshObjectSrg, customMaterialInfo.m_uvMapping); + RPI::MeshDrawPacket drawPacket( + modelLod, + meshIndex, + GetMeshInfoIndex(modelLodIndex, meshIndex), + material, + meshObjectSrg, + customMaterialInfo.m_uvMapping); // set the shader option to select forward pass IBL specular if necessary if (!drawPacket.SetShaderOption(s_o_meshUseForwardPassIBLSpecular_Name, AZ::RPI::ShaderOptionValue{ m_descriptor.m_useForwardPassIblSpecular })) @@ -3146,5 +3152,12 @@ namespace AZ handler.Connect(m_meshDrawPacketUpdatedEvent); } + int32_t ModelDataInstance::GetMeshInfoIndex(size_t modelLodIndex, size_t meshIndex) const + { + // Stride must be >= max meshes per LOD; matches MaxSubmeshPerEntity in SegmentationFeatureProcessorInterface.h. + static constexpr int32_t MeshInfoIndexMeshesPerLod = 32; + return static_cast(modelLodIndex * MeshInfoIndexMeshesPerLod + meshIndex); + } + } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.h index 46f7a9d735ca..8dde762754ea 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.h @@ -115,6 +115,7 @@ namespace AZ void BuildDrawPacketList(MeshFeatureProcessor* meshFeatureProcessor, size_t modelLodIndex); void SetRayTracingData(MeshFeatureProcessor* meshFeatureProcessor); void RemoveRayTracingData(RayTracingFeatureProcessor* rayTracingFeatureProcessor); + int32_t GetMeshInfoIndex(size_t modelLodIndex, size_t meshIndex) const override; void SetIrradianceData( RayTracingFeatureProcessor::SubMesh& subMesh, const Data::Instance material, diff --git a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli index fe862dfd10a5..0b7ebc0198f9 100644 --- a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli +++ b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli @@ -28,6 +28,7 @@ ShaderResourceGroup DrawSrg : SRG_PerDraw { // This SRG is unique per draw packet uint m_uvStreamTangentBitmask; + uint m_meshInfoIndex; #if USE_DRAWSRG_MESHLOD_MESHINDEX // See MeshDrawPacket.h diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/MeshDrawPacket.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/MeshDrawPacket.h index 7d086fb7a32d..9f3390d44d15 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/MeshDrawPacket.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/MeshDrawPacket.h @@ -53,6 +53,7 @@ namespace AZ MeshDrawPacket( ModelLod& modelLod, size_t modelLodMeshIndex, + int32_t meshInfoIndex, Data::Instance materialOverride, Data::Instance objectSrg, const MaterialModelUvOverrideMap& materialModelUvMap = {}); @@ -119,6 +120,9 @@ namespace AZ // The index of the mesh within m_modelLod that is represented by the DrawPacket size_t m_modelLodMeshIndex; + // Compact LOD-stable index: lodIndex * 32 + meshIndex. See ModelDataInstance::GetMeshInfoIndex. + int32_t m_meshInfoIndex = -1; + // The per-object shader resource group Data::Instance m_objectSrg; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp index 132465b3a967..587e7cf1da0e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/MeshDrawPacket.cpp @@ -34,12 +34,14 @@ namespace AZ MeshDrawPacket::MeshDrawPacket( ModelLod& modelLod, size_t modelLodMeshIndex, + int32_t meshInfoIndex, Data::Instance materialOverride, Data::Instance objectSrg, const MaterialModelUvOverrideMap& materialModelUvMap ) : m_modelLod(&modelLod) , m_modelLodMeshIndex(modelLodMeshIndex) + , m_meshInfoIndex(meshInfoIndex) , m_objectSrg(objectSrg) , m_material(materialOverride) , m_materialModelUvMap(materialModelUvMap) @@ -441,6 +443,16 @@ namespace AZ drawSrg->SetConstant(index, aznumeric_cast(m_modelLodMeshIndex)); } + if (m_meshInfoIndex >= 0) + { + AZ::Name meshInfoNameIdx("m_meshInfoIndex"); + auto meshInfoConstIdx = drawSrg->FindShaderInputConstantIndex(meshInfoNameIdx); + if (meshInfoConstIdx.IsValid()) + { + drawSrg->SetConstant(meshInfoConstIdx, aznumeric_cast(m_meshInfoIndex)); + } + } + // TODO: Does it make sense to call Compile() in the case where both SetConstant() calls above fail? // Leaving it as always calling Compile() as precaution that there's code somewhere else that assumes // Compile() was already called on DrawSrg. From d9621d888c3a24f9582fffdfa8d7a89997cd03c0 Mon Sep 17 00:00:00 2001 From: Mateusz Wasilewski Date: Wed, 6 May 2026 15:31:28 +0200 Subject: [PATCH 2/2] Make mesh info index globally unique Signed-off-by: Mateusz Wasilewski --- .../Common/Code/Source/Mesh/MeshFeatureProcessor.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 5279a732cbd4..43a867ca26d7 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -3154,9 +3154,12 @@ namespace AZ int32_t ModelDataInstance::GetMeshInfoIndex(size_t modelLodIndex, size_t meshIndex) const { - // Stride must be >= max meshes per LOD; matches MaxSubmeshPerEntity in SegmentationFeatureProcessorInterface.h. - static constexpr int32_t MeshInfoIndexMeshesPerLod = 32; - return static_cast(modelLodIndex * MeshInfoIndexMeshesPerLod + meshIndex); + // Simplified version of the function from PR #19123 + // Indexes all submeshes in a globally unique way. + static constexpr uint32_t MeshInfoIndexMeshesPerLod = 32; + static constexpr uint32_t MeshInfoIndicesPerMesh = MeshInfoIndexMeshesPerLod * RPI::ModelLodAsset::LodCountMax; + return static_cast( + m_objectId.GetIndex() * MeshInfoIndicesPerMesh + modelLodIndex * MeshInfoIndexMeshesPerLod + meshIndex); } } // namespace Render