From 00062430a2788e21f61186f78d199b56aae5f316 Mon Sep 17 00:00:00 2001 From: Santora Date: Sat, 12 Jun 2021 11:52:46 -0700 Subject: [PATCH 1/2] Updated the usage of ShaderReloadDebugTracker to include the address of the object. This is necessary for debugging where multiple assets may be reloading at the same time. Also added a Printf function for generic messages at the current indent level. This is specifically in support of: ATOM-14613 Baseviewer MatertialHotReloadTest fails to change the color after turning blending on and off ATOM-15728 Shader Hot Reload Fails in Debug Build --- .../RPI.Public/Shader/ShaderReloadDebugTracker.h | 14 ++++++++++++++ .../Code/Source/RPI.Public/Material/Material.cpp | 9 +++++---- .../RPI/Code/Source/RPI.Public/Shader/Shader.cpp | 2 +- .../Source/RPI.Reflect/Material/MaterialAsset.cpp | 2 +- .../RPI.Reflect/Material/MaterialTypeAsset.cpp | 2 +- .../Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp | 4 ++-- 6 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h index dfda93dca3..8220d25eb8 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Shader/ShaderReloadDebugTracker.h @@ -57,6 +57,20 @@ namespace AZ } #endif } + + //! Prints a generic message at the appropriate indent level. + template + static void Printf([[maybe_unused]] const char* format, [[maybe_unused]] Args... args) + { +#ifdef AZ_ENABLE_SHADER_RELOAD_DEBUG_TRACKER + if (IsEnabled()) + { + const AZStd::string message = AZStd::string::format(format, args...); + + AZ_TracePrintf("ShaderReloadDebug", "%*s %s \n", s_indent, "", message.c_str()); + } +#endif + } //! Use this utility to call BeginSection(), and automatically call EndSection() when the object goes out of scope. class ScopedSection final diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp index 4a2718b9d5..eac1ee42e5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp @@ -97,6 +97,7 @@ namespace AZ ShaderReloadNotificationBus::MultiHandler::BusDisconnect(); for (auto& shaderItem : m_shaderCollection) { + ShaderReloadDebugTracker::Printf("(Material has ShaderAsset %p)", shaderItem.GetShaderAsset().Get()); ShaderReloadNotificationBus::MultiHandler::BusConnect(shaderItem.GetShaderAsset().GetId()); } @@ -226,7 +227,7 @@ namespace AZ // AssetBus overrides... void Material::OnAssetReloaded(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnAssetReloaded %s", asset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnAssetReloaded %s", this, asset.GetHint().c_str()); Data::Asset newMaterialAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; @@ -241,7 +242,7 @@ namespace AZ // MaterialReloadNotificationBus overrides... void Material::OnMaterialAssetReinitialized(const Data::Asset& materialAsset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnMaterialAssetReinitialized %s", materialAsset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str()); OnAssetReloaded(materialAsset); } @@ -249,7 +250,7 @@ namespace AZ // ShaderReloadNotificationBus overrides... void Material::OnShaderReinitialized([[maybe_unused]] const Shader& shader) { - ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnShaderReinitialized %s", shader.GetAsset().GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderReinitialized %s", this, shader.GetAsset().GetHint().c_str()); // Note that it might not be strictly necessary to reinitialize the entire material, we might be able to get away with // just bumping the m_currentChangeId or some other minor updates. But it's pretty hard to know what exactly needs to be // updated to correctly handle the reload, so it's safer to just reinitialize the whole material. @@ -269,7 +270,7 @@ namespace AZ void Material::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& /*shaderVariantId*/, ShaderVariantStableId shaderVariantStableId) { - ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnShaderVariantReinitialized %s variant %u", shader.GetAsset().GetHint().c_str(), shaderVariantStableId.GetIndex()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s variant %u", this, shader.GetAsset().GetHint().c_str(), shaderVariantStableId.GetIndex()); // Note that it would be better to check the shaderVariantId to see if that variant is relevant to this particular material before reinitializing it. // There could be hundreds or even thousands of variants for a shader, but only one of those variants will be used by any given material. So we could diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp index 7194c524ae..147f24d4f8 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Shader.cpp @@ -132,7 +132,7 @@ namespace AZ // AssetBus overrides void Shader::OnAssetReloaded(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("Shader::OnAssetReloaded %s", asset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Shader::OnAssetReloaded %s", this, asset.GetHint().c_str()); if (asset->GetId() == m_asset->GetId()) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp index 7e9e2ddb10..2e56c30652 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialAsset.cpp @@ -119,7 +119,7 @@ namespace AZ void MaterialAsset::OnAssetReloaded(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("MaterialAsset::OnAssetReloaded %s", asset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); Data::Asset newMaterialTypeAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp index 20adb63cb8..f7d0a83ac9 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Material/MaterialTypeAsset.cpp @@ -130,7 +130,7 @@ namespace AZ void MaterialTypeAsset::OnAssetReloaded(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("MaterialTypeAsset::OnAssetReloaded %s", asset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialTypeAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); // The order of asset reloads is non-deterministic. If the MaterialTypeAsset reloads before these // dependency assets, this will make sure the MaterialTypeAsset gets the latest ones when they reload. diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp index cf655d43f7..75d4a47bc0 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Shader/ShaderAsset.cpp @@ -381,7 +381,7 @@ namespace AZ // AssetBus overrides... void ShaderAsset::OnAssetReloaded(Data::Asset asset) { - ShaderReloadDebugTracker::ScopedSection reloadSection("ShaderAsset::OnAssetReloaded %s", asset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderAsset::OnAssetReloaded %s", this, asset.GetHint().c_str()); Data::Asset shaderVariantAsset = { asset.GetAs(), AZ::Data::AssetLoadBehavior::PreLoad }; AZ_Assert(shaderVariantAsset->GetStableId() == RootShaderVariantStableId, @@ -396,7 +396,7 @@ namespace AZ /// ShaderVariantFinderNotificationBus overrides void ShaderAsset::OnShaderVariantTreeAssetReady(Data::Asset shaderVariantTreeAsset, bool isError) { - ShaderReloadDebugTracker::ScopedSection reloadSection("ShaderAsset::OnShaderVariantTreeAssetReady %s", shaderVariantTreeAsset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderAsset::OnShaderVariantTreeAssetReady %s", this, shaderVariantTreeAsset.GetHint().c_str()); AZStd::unique_lock lock(m_variantTreeMutex); if (isError) From 406792606b1c335e138d4caf3770b6b19be737b7 Mon Sep 17 00:00:00 2001 From: Santora Date: Mon, 14 Jun 2021 13:04:15 -0700 Subject: [PATCH 2/2] I missed one spot that needs to print the address. --- Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp index eac1ee42e5..d9691ca175 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Material/Material.cpp @@ -261,7 +261,7 @@ namespace AZ { // TODO: I think we should make Shader handle OnShaderAssetReinitialized and treat it just like the shader reloaded. - ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnShaderAssetReinitialized %s", shaderAsset.GetHint().c_str()); + ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str()); // Note that it might not be strictly necessary to reinitialize the entire material, we might be able to get away with // just bumping the m_currentChangeId or some other minor updates. But it's pretty hard to know what exactly needs to be // updated to correctly handle the reload, so it's safer to just reinitialize the whole material.