Fixed ATOM-14613 Baseviewer MatertialHotReloadTest fails to change the color after turning blending on and off
The problem was... After a MaterialAsset reload, there could be two different versions of the MaterialAsset in memory: the old one and the reloaded one. The old one is still connected to buses and can send reinitialization messages when other things reload or reinitialize. So when the shader asset reloaded, both the old and new MaterialAsset were sending reinitialization messages. Material::OnMaterialAssetReinitialized was using the materialAsset parameter to initialize the Material, and the latest call to OnMaterialAssetReinitialized was for the *old* MaterialAsset. The solution is to use the m_materialAsset member when reinitializing the Material. I also added checks in a couple places to skip unnecessary reinitialization, and added comments in the bus headers to warn developers about this issue. Testing: Added a new step to ASV's MaterialHotReloadTest.bv.lua script for the error scenario, and this now passes. Ran ASV full test suite, both dx12 and vulkan, only known issues occurred.
This commit is contained in:
@@ -115,12 +115,19 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialAsset::OnMaterialTypeAssetReinitialized(const Data::Asset<MaterialTypeAsset>&)
|
||||
void MaterialAsset::OnMaterialTypeAssetReinitialized(const Data::Asset<MaterialTypeAsset>& materialTypeAsset)
|
||||
{
|
||||
// MaterialAsset doesn't need to reinitialize any of its own data when MaterialTypeAsset reinitializes,
|
||||
// because all it depends on is the MaterialTypeAsset reference, rather than the data inside it.
|
||||
// Ultimately it's the Material that cares about these changes, so we just forward any signal we get.
|
||||
MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset<MaterialAsset>{this, AZ::Data::AssetLoadBehavior::PreLoad});
|
||||
// When reloads occur, it's possible for old Asset objects to hang around and report reinitialization,
|
||||
// so we can reduce unnecessary reinitialization in that case.
|
||||
if (materialTypeAsset.Get() == m_materialTypeAsset.Get())
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnMaterialTypeAssetReinitialized %s", this, materialTypeAsset.GetHint().c_str());
|
||||
|
||||
// MaterialAsset doesn't need to reinitialize any of its own data when MaterialTypeAsset reinitializes,
|
||||
// because all it depends on is the MaterialTypeAsset reference, rather than the data inside it.
|
||||
// Ultimately it's the Material that cares about these changes, so we just forward any signal we get.
|
||||
MaterialReloadNotificationBus::Event(GetId(), &MaterialReloadNotifications::OnMaterialAssetReinitialized, Data::Asset<MaterialAsset>{this, AZ::Data::AssetLoadBehavior::PreLoad});
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialAsset::ReinitializeMaterialTypeAsset(Data::Asset<Data::AssetData> asset)
|
||||
|
||||
Reference in New Issue
Block a user