Fix for LYN-4594: [Atom][EMFX] Loading a saved level with entity and an actor component causes the editor to freeze. (DCO fixup) (#1878)

* Queue shader loads and register with the dynamic draw context after the shader is loaded to avoid a deadlock when there are multiple scenes processing at the same time.

Signed-off-by: amzn-tommy <waltont@amazon.com>

* Fixed AzCore case in AtomFont.h and two other files I found while searching

Signed-off-by: amzn-tommy <waltont@amazon.com>

* Switched to a utility that will both get the assetId and create the Asset, without calling GetAsset explicitely

Signed-off-by: amzn-tommy <waltont@amazon.com>

* Fixing typos in error message

Signed-off-by: amzn-tommy <waltont@amazon.com>
main
Tommy Walton 5 years ago committed by GitHub
parent 5b9647c11b
commit f177f671ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -16,6 +16,7 @@
#include <AzCore/std/containers/map.h>
#include <AzCore/std/smart_ptr/weak_ptr.h>
#include <AzCore/std/parallel/shared_mutex.h>
#include <AzCore/Asset/AssetCommon.h>
#include <map>
#include <AzFramework/Font/FontInterface.h>
@ -38,6 +39,7 @@ namespace AZ
class AtomFont
: public ICryFont
, public AzFramework::FontQueryInterface
, private Data::AssetBus::Handler
{
friend class FFont;
@ -122,6 +124,9 @@ namespace AZ
//! \param outputFullPath Full path to loaded font family, may need resolving with PathUtil::MakeGamePath.
XmlNodeRef LoadFontFamilyXml(const char* fontFamilyName, string& outputDirectory, string& outputFullPath);
// Data::AssetBus::Handler overrides...
void OnAssetReady(Data::Asset<Data::AssetData> asset) override;
private:
AzFramework::ISceneSystem::SceneEvent::Handler m_sceneEventHandler;

@ -29,6 +29,7 @@
#include <Atom/RPI.Public/RPIUtils.h>
#include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
// Static member definitions
const AZ::AtomFont::GlyphSize AZ::AtomFont::defaultGlyphSize = AZ::AtomFont::GlyphSize(ICryFont::defaultGlyphSizeX, ICryFont::defaultGlyphSizeY);
@ -349,30 +350,18 @@ AZ::AtomFont::AtomFont(ISystem* system)
#endif
AZ::Interface<AzFramework::FontQueryInterface>::Register(this);
// register font per viewport dynamic draw context.
// Queue a load for the font per viewport dynamic draw context shader, and wait for it to load
static const char* shaderFilepath = "Shaders/SimpleTextured.azshader";
AZ::AtomBridge::PerViewportDynamicDraw::Get()->RegisterDynamicDrawContext(
AZ::Name(AZ::AtomFontDynamicDrawContextName),
[](RPI::Ptr<RPI::DynamicDrawContext> drawContext)
{
Data::Instance<RPI::Shader> shader = AZ::RPI::LoadShader(shaderFilepath);
AZ::RPI::ShaderOptionList shaderOptions;
shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("false")));
shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("true")));
drawContext->InitShaderWithVariant(shader, &shaderOptions);
drawContext->InitVertexFormat(
{
{"POSITION", RHI::Format::R32G32B32_FLOAT},
{"COLOR", RHI::Format::B8G8R8A8_UNORM},
{"TEXCOORD0", RHI::Format::R32G32_FLOAT}
});
drawContext->EndInit();
});
Data::Asset<RPI::ShaderAsset> shaderAsset = RPI::AssetUtils::GetAssetByProductPath<RPI::ShaderAsset>(shaderFilepath, RPI::AssetUtils::TraceLevel::Assert);
shaderAsset.QueueLoad();
Data::AssetBus::Handler::BusConnect(shaderAsset.GetId());
}
AZ::AtomFont::~AtomFont()
{
Data::AssetBus::Handler::BusDisconnect();
AZ::Interface<AzFramework::FontQueryInterface>::Unregister(this);
m_defaultFontDrawInterface = nullptr;
@ -864,5 +853,36 @@ XmlNodeRef AZ::AtomFont::LoadFontFamilyXml(const char* fontFamilyName, string& o
return root;
}
void AZ::AtomFont::OnAssetReady(Data::Asset<Data::AssetData> asset)
{
Data::Asset<RPI::ShaderAsset> shaderAsset = asset;
AZ::AtomBridge::PerViewportDynamicDraw::Get()->RegisterDynamicDrawContext(
AZ::Name(AZ::AtomFontDynamicDrawContextName),
[shaderAsset](RPI::Ptr<RPI::DynamicDrawContext> drawContext)
{
AZ_Assert(shaderAsset->IsReady(), "Attempting to register the AtomFont"
" dynamic draw context before the shader asset is loaded. The shader should be loaded first"
" to avoid a blocking asset load and potential deadlock, since the DynamicDrawContext lambda"
" will be executed during scene processing and there may be multiple scenes executing in parallel.");
Data::Instance<RPI::Shader> shader = RPI::Shader::FindOrCreate(shaderAsset);
AZ::RPI::ShaderOptionList shaderOptions;
shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_useColorChannels"), AZ::Name("false")));
shaderOptions.push_back(AZ::RPI::ShaderOption(AZ::Name("o_clamp"), AZ::Name("true")));
drawContext->InitShaderWithVariant(shader, &shaderOptions);
drawContext->InitVertexFormat(
{
{"POSITION", RHI::Format::R32G32B32_FLOAT},
{"COLOR", RHI::Format::B8G8R8A8_UNORM},
{"TEXCOORD0", RHI::Format::R32G32_FLOAT}
});
drawContext->EndInit();
});
Data::AssetBus::Handler::BusDisconnect();
}
#endif

@ -27,6 +27,7 @@
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
#include <Atom/RPI.Reflect/Image/StreamingImageAssetCreator.h>
#include <Atom/RPI.Reflect/Image/ImageMipChainAssetCreator.h>
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
#include <Atom/RPI.Public/Image/StreamingImagePool.h>
#include <AtomBridge/PerViewportDynamicDrawInterface.h>
@ -87,6 +88,7 @@ namespace AZ::Render
void AtomViewportDisplayIconsSystemComponent::Deactivate()
{
Data::AssetBus::Handler::BusDisconnect();
Bootstrap::NotificationBus::Handler::BusDisconnect();
auto perViewportDynamicDrawInterface = AtomBridge::PerViewportDynamicDraw::Get();
@ -338,15 +340,32 @@ namespace AZ::Render
void AtomViewportDisplayIconsSystemComponent::OnBootstrapSceneReady([[maybe_unused]]AZ::RPI::Scene* bootstrapScene)
{
AtomBridge::PerViewportDynamicDraw::Get()->RegisterDynamicDrawContext(m_drawContextName, [](RPI::Ptr<RPI::DynamicDrawContext> drawContext)
{
auto shader = RPI::LoadShader(DrawContextShaderPath);
drawContext->InitShader(shader);
drawContext->InitVertexFormat(
{{"POSITION", RHI::Format::R32G32B32_FLOAT},
{"COLOR", RHI::Format::R8G8B8A8_UNORM},
{"TEXCOORD", RHI::Format::R32G32_FLOAT}});
drawContext->EndInit();
});
// Queue a load for the draw context shader, and wait for it to load
Data::Asset<RPI::ShaderAsset> shaderAsset = RPI::AssetUtils::GetAssetByProductPath<RPI::ShaderAsset>(DrawContextShaderPath, RPI::AssetUtils::TraceLevel::Assert);
shaderAsset.QueueLoad();
Data::AssetBus::Handler::BusConnect(shaderAsset.GetId());
}
void AtomViewportDisplayIconsSystemComponent::OnAssetReady(Data::Asset<Data::AssetData> asset)
{
// Once the shader is loaded, register it with the dynamic draw context
Data::Asset<RPI::ShaderAsset> shaderAsset = asset;
AtomBridge::PerViewportDynamicDraw::Get()->RegisterDynamicDrawContext(m_drawContextName, [shaderAsset](RPI::Ptr<RPI::DynamicDrawContext> drawContext)
{
AZ_Assert(shaderAsset->IsReady(), "Attempting to register the AtomViewportDisplayIconsSystemComponent"
" dynamic draw context before the shader asset is loaded. The shader should be loaded first"
" to avoid a blocking asset load and potential deadlock, since the DynamicDrawContext lambda"
" will be executed during scene processing and there may be multiple scenes executing in parallel.");
Data::Instance<RPI::Shader> shader = RPI::Shader::FindOrCreate(shaderAsset);
drawContext->InitShader(shader);
drawContext->InitVertexFormat(
{ {"POSITION", RHI::Format::R32G32B32_FLOAT},
{"COLOR", RHI::Format::R8G8B8A8_UNORM},
{"TEXCOORD", RHI::Format::R32G32_FLOAT} });
drawContext->EndInit();
});
Data::AssetBus::Handler::BusDisconnect();
}
} // namespace AZ::Render

@ -27,6 +27,7 @@ namespace AZ
: public AZ::Component
, public AzToolsFramework::EditorViewportIconDisplayInterface
, public AZ::Render::Bootstrap::NotificationBus::Handler
, private Data::AssetBus::Handler
{
public:
AZ_COMPONENT(AtomViewportDisplayIconsSystemComponent, "{AEC1D3E1-1D9A-437A-B4C6-CFAEE620C160}");
@ -51,6 +52,9 @@ namespace AZ
// AZ::Render::Bootstrap::NotificationBus::Handler overrides...
void OnBootstrapSceneReady(AZ::RPI::Scene* bootstrapScene) override;
// Data::AssetBus::Handler overrides...
void OnAssetReady(Data::Asset<Data::AssetData> asset) override;
private:
static constexpr const char* DrawContextShaderPath = "Shaders/TexturedIcon.azshader";
static constexpr QSize MinimumRenderedSvgSize = QSize(128, 128);

@ -8,7 +8,7 @@
#include <AzCore/Math/Vector3.h>
#include <IRenderAuxGeom.h>
#include <Azcore/Math/Color.h>
#include <AzCore/Math/Color.h>
namespace Blast
{

@ -8,7 +8,7 @@
#include <Atom/Feature/Mesh/MeshFeatureProcessorInterface.h>
#include <AzCore/std/containers/vector.h>
#include <Azcore/Math/Vector3.h>
#include <AzCore/Math/Vector3.h>
namespace Blast
{

Loading…
Cancel
Save