Merge branch 'development' into profiler_capture_api

Signed-off-by: AMZN-ScottR <24445312+AMZN-ScottR@users.noreply.github.com>
This commit is contained in:
AMZN-ScottR
2021-10-26 09:02:57 -07:00
96 changed files with 2384 additions and 401 deletions
@@ -65,8 +65,35 @@ namespace AZ
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides - Application is a singleton
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
typedef AZStd::recursive_mutex MutexType;
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
using MutexType = AZStd::recursive_mutex;
static constexpr bool EnableEventQueue = true;
using EventQueueMutexType = AZStd::mutex;
struct PostThreadDispatchInvoker
{
~PostThreadDispatchInvoker();
};
template <typename DispatchMutex>
struct ThreadDispatchLockGuard
{
ThreadDispatchLockGuard(DispatchMutex& contextMutex)
: m_lock{ contextMutex }
{}
ThreadDispatchLockGuard(DispatchMutex& contextMutex, AZStd::adopt_lock_t adopt_lock)
: m_lock{ contextMutex, adopt_lock }
{}
ThreadDispatchLockGuard(const ThreadDispatchLockGuard&) = delete;
ThreadDispatchLockGuard& operator=(const ThreadDispatchLockGuard&) = delete;
private:
PostThreadDispatchInvoker m_threadPolicyInvoker;
using LockType = AZStd::conditional_t<LocklessDispatch, AZ::Internal::NullLockGuard<DispatchMutex>, AZStd::scoped_lock<DispatchMutex>>;
LockType m_lock;
};
template <typename DispatchMutex, bool>
using DispatchLockGuard = ThreadDispatchLockGuard<DispatchMutex>;
//////////////////////////////////////////////////////////////////////////
virtual ~AssetCatalogRequests() = default;
@@ -200,6 +227,17 @@ namespace AZ
using AssetCatalogRequestBus = AZ::EBus<AssetCatalogRequests>;
inline AssetCatalogRequests::PostThreadDispatchInvoker::~PostThreadDispatchInvoker()
{
if (!AssetCatalogRequestBus::IsInDispatchThisThread())
{
if (AssetCatalogRequestBus::QueuedEventCount())
{
AssetCatalogRequestBus::ExecuteQueuedEvents();
}
}
}
/*
* Events that AssetManager listens for
*/
@@ -14,6 +14,7 @@
#include <AzCore/Casting/lossy_cast.h>
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Component/ComponentApplicationLifecycle.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/Debug/LocalFileEventLogger.h>
@@ -44,8 +45,6 @@
#include <AzCore/Module/Module.h>
#include <AzCore/Module/ModuleManager.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/Path/Path_fwd.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Driller/Driller.h>
@@ -506,6 +505,16 @@ namespace AZ
SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(*m_settingsRegistry, m_commandLine, executeRegDumpCommands);
SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(*m_settingsRegistry);
// The /O3DE/Application/LifecycleEvents array contains a valid set of lifecycle events
// Those lifecycle events are normally read from the <engine-root>/Registry
// which isn't merged until ComponentApplication::Create invokes MergeSettingsToRegistry
// So pre-populate the valid lifecycle even entries
ComponentApplicationLifecycle::RegisterEvent(*m_settingsRegistry, "SystemAllocatorCreated");
ComponentApplicationLifecycle::RegisterEvent(*m_settingsRegistry, "SettingsRegistryAvailable");
ComponentApplicationLifecycle::RegisterEvent(*m_settingsRegistry, "ConsoleAvailable");
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "SystemAllocatorCreated", R"({})");
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "SettingsRegistryAvailable", R"({})");
// Create the Module Manager
m_moduleManager = AZStd::make_unique<ModuleManager>();
@@ -520,6 +529,7 @@ namespace AZ
m_ownsConsole = true;
m_console->LinkDeferredFunctors(AZ::ConsoleFunctorBase::GetDeferredHead());
m_settingsRegistryConsoleFunctors = AZ::SettingsRegistryConsoleUtils::RegisterAzConsoleCommands(*m_settingsRegistry, *m_console);
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "ConsoleAvailable", R"({})");
}
}
@@ -551,6 +561,7 @@ namespace AZ
{
AZ::Interface<AZ::IConsole>::Unregister(m_console);
delete m_console;
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "ConsoleUnavailable", R"({})");
}
m_moduleManager.reset();
@@ -558,6 +569,8 @@ namespace AZ
if (AZ::SettingsRegistry::Get() == m_settingsRegistry.get())
{
SettingsRegistry::Unregister(m_settingsRegistry.get());
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "SettingsRegistryUnavailable", R"({})");
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "SystemAllocatorPendingDestruction", R"({})");
}
m_settingsRegistry.reset();
@@ -672,6 +685,8 @@ namespace AZ
ReflectionEnvironment::GetReflectionManager()->Reflect(azrtti_typeid(this), [this](ReflectContext* context) {Reflect(context); });
RegisterCoreComponents();
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "ReflectionManagerAvailable", R"({})");
TickBus::AllowFunctionQueuing(true);
SystemTickBus::AllowFunctionQueuing(true);
@@ -691,6 +706,7 @@ namespace AZ
// Load the actual modules
LoadModules();
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "GemsLoaded", R"({})");
// Execute user.cfg after modules have been loaded but before processing any command-line overrides
AZ::IO::FixedMaxPath platformCachePath;
@@ -756,12 +772,14 @@ namespace AZ
m_entities.rehash(0); // force free all memory
DestroyReflectionManager();
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "ReflectionManagerUnavailable", R"({})");
static_cast<SettingsRegistryImpl*>(m_settingsRegistry.get())->ClearNotifiers();
static_cast<SettingsRegistryImpl*>(m_settingsRegistry.get())->ClearMergeEvents();
// Uninit and unload any dynamic modules.
m_moduleManager->UnloadModules();
ComponentApplicationLifecycle::SignalEvent(*m_settingsRegistry, "GemsUnloaded", R"({})");
NameDictionary::Destroy();
@@ -175,6 +175,8 @@ namespace AZ
bool m_loadDynamicModules = true;
//! Used by test fixtures to ensure reflection occurs to edit context.
bool m_createEditContext = false;
//! Indicates whether the AssetCatalog.xml should be loaded by default in Application::StartCommon
bool m_loadAssetCatalog = true;
};
ComponentApplication();
@@ -356,7 +358,7 @@ namespace AZ
/// Calculates the root directory of the engine.
void CalculateEngineRoot();
/// Calculates the directory where the bootstrap.cfg file resides.
/// Deprecated: The term "AppRoot" has no meaning
void CalculateAppRoot();
template<typename Iterator>
@@ -0,0 +1,87 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Component/ComponentApplicationLifecycle.h>
#include <AzCore/Settings/SettingsRegistryVisitorUtils.h>
namespace AZ::ComponentApplicationLifecycle
{
bool ValidateEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName)
{
using FixedValueString = SettingsRegistryInterface::FixedValueString;
using Type = SettingsRegistryInterface::Type;
FixedValueString eventRegistrationKey{ ApplicationLifecycleEventRegistrationKey };
eventRegistrationKey += '/';
eventRegistrationKey += eventName;
return settingsRegistry.GetType(eventRegistrationKey) == Type::Object;
}
bool SignalEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName, AZStd::string_view eventValue)
{
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
using Format = AZ::SettingsRegistryInterface::Format;
if (!ValidateEvent(settingsRegistry, eventName))
{
AZ_Warning("ComponentApplicationLifecycle", false, R"(Cannot signal event %.*s. Name does is not a field of object "%.*s".)"
R"( Please make sure the entry exists in the '<engine-root>/Registry/application_lifecycle_events.setreg")"
" or in *.setreg within the project", AZ_STRING_ARG(eventName), AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey));
return false;
}
auto eventRegistrationKey = FixedValueString::format("%.*s/%.*s", AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey),
AZ_STRING_ARG(eventName));
return settingsRegistry.MergeSettings(eventValue, Format::JsonMergePatch, eventRegistrationKey);
}
bool RegisterEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName)
{
using FixedValueString = SettingsRegistryInterface::FixedValueString;
using Format = AZ::SettingsRegistryInterface::Format;
if (!ValidateEvent(settingsRegistry, eventName))
{
FixedValueString eventRegistrationKey{ ApplicationLifecycleEventRegistrationKey };
eventRegistrationKey += '/';
eventRegistrationKey += eventName;
return settingsRegistry.MergeSettings(R"({})", Format::JsonMergePatch, eventRegistrationKey);
}
return true;
}
bool RegisterHandler(AZ::SettingsRegistryInterface& settingsRegistry, AZ::SettingsRegistryInterface::NotifyEventHandler& handler,
AZ::SettingsRegistryInterface::NotifyCallback callback, AZStd::string_view eventName)
{
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
using Type = AZ::SettingsRegistryInterface::Type;
using NotifyEventHandler = AZ::SettingsRegistryInterface::NotifyEventHandler;
if (!ValidateEvent(settingsRegistry, eventName))
{
AZ_Warning("ComponentApplicationLifecycle", false, R"(Cannot register event %.*s. Name does is not a field of object "%.*s".)"
R"( Please make sure the entry exists in the '<engine-root>/Registry/application_lifecycle_events.setreg")"
" or in *.setreg within the project", AZ_STRING_ARG(eventName), AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey));
return false;
}
auto eventNameRegistrationKey = FixedValueString::format("%.*s/%.*s", AZ_STRING_ARG(ApplicationLifecycleEventRegistrationKey),
AZ_STRING_ARG(eventName));
auto lifecycleCallback = [callback = AZStd::move(callback), eventNameRegistrationKey](AZStd::string_view path, Type type)
{
if (path == eventNameRegistrationKey)
{
callback(path, type);
}
};
handler = NotifyEventHandler(AZStd::move(lifecycleCallback));
settingsRegistry.RegisterNotifier(handler);
return true;
}
}
@@ -0,0 +1,54 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/std/string/string_view.h>
namespace AZ::ComponentApplicationLifecycle
{
//! Root Key where lifecycle events should be registered under
inline constexpr AZStd::string_view ApplicationLifecycleEventRegistrationKey = "/O3DE/Runtime/Application/LifecycleEvents";
//! Validates that the event @eventName is stored in the array at ApplicationLifecycleEventRegistrationKey
//! @param settingsRegistry registry where @eventName will be searched
//! @param eventName name of key that validated that exists as an element in the ApplicationLifecycleEventRegistrationKey array
//! @return true if the @eventName was found in the ApplicationLifecycleEventRegistrationKey array
bool ValidateEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName);
//! Wrapper around setting a value underneath the ApplicationLifecycleEventRegistrationKey
//! It validates if the @eventName is is part of the ApplicationLifecycleEventRegistrationKey array
//! It then appends the @eventName to the ApplicationLifecycleEventRegistrationKey merges the @eventValue into
//! the SettingsRegistry at that key
//! NOTE: This function should only be invoked from ComponentApplication and its derived classes
//! @param settingsRegistry registry where eventName should be set
//! @param eventName name of key underneath the ApplicationLifecycleEventRegistrationKey to signal
//! @param eventValue JSON Object that will be merged into the SettingsRegistry at <ApplicationLifecycleEventRootKey>/<eventName>
//! @return true if the eventValue was successfully merged at the <ApplicationLifecycleEventRootKey>/<eventName>
bool SignalEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName, AZStd::string_view eventValue);
//! Register that the event @eventName is stored in the array at ApplicationLifecycleEventRegistrationKey
//! @param settingsRegistry registry where @eventName will be searched
//! @param eventName name of key that will be stored in the ApplicationLifecycleEventRegistrationKey array
//! @return true if the event passed validation or the eventName was stored in the ApplicationLifecycleEventRegistrationKey array
bool RegisterEvent(AZ::SettingsRegistryInterface& settingsRegistry, AZStd::string_view eventName);
//! Wrapper around registering the NotifyEventHandler with the SettingsRegistry for the specified event
//! It validates if the @eventName is is part of the ApplicationLifecycleEventRegistrationKey array and if
//! so moves the @callback into @handler and then registers the handler with the SettingsRegistry NotifyEvent
//! @param settingsRegistry registry where handler will be registered
//! @param handler handler where callback will be moved into and then registered with the SettingsRegistry
//! if the specified @eventName passes validation
//! @param callback will be moved into the handler if the specified @eventName is valid
//! @param eventName name of key underneath the ApplicationLifecycleEventRegistrationKey to register
//! @return true if the handler was registered with the SettingsRegistry NotifyEvent
bool RegisterHandler(AZ::SettingsRegistryInterface& settingsRegistry, AZ::SettingsRegistryInterface::NotifyEventHandler& handler,
AZ::SettingsRegistryInterface::NotifyCallback callback, AZStd::string_view eventName);
}
@@ -262,6 +262,6 @@ static constexpr AZ::ThreadSafety ConsoleThreadSafety<_TYPE, std::enable_if_t<st
//! @param _FLAGS a set of AzFramework::ConsoleFunctorFlags used to mutate behaviour
//! @param _DESC a description of the cvar
#define AZ_CONSOLEFREEFUNC_4(_NAME, _FUNCTION, _FLAGS, _DESC) \
inline AZ::ConsoleFunctor<void, false> Functor##_FUNCTION(#_FUNCTION, _DESC, _FLAGS | AZ::ConsoleFunctorFlags::DontDuplicate, AZ::TypeId::CreateNull(), &_FUNCTION)
inline AZ::ConsoleFunctor<void, false> Functor##_FUNCTION(_NAME, _DESC, _FLAGS | AZ::ConsoleFunctorFlags::DontDuplicate, AZ::TypeId::CreateNull(), &_FUNCTION)
#define AZ_CONSOLEFREEFUNC(...) AZ_MACRO_SPECIALIZE(AZ_CONSOLEFREEFUNC_, AZ_VA_NUM_ARGS(__VA_ARGS__), (__VA_ARGS__))
@@ -10,16 +10,13 @@
#include <AzCore/Module/Internal/ModuleManagerSearchPathTool.h>
#include <AzCore/Module/Module.h>
#include <AzCore/RTTI/AttributeReader.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/ComponentApplicationLifecycle.h>
#include <AzCore/NativeUI/NativeUIRequests.h>
#include <AzCore/Script/ScriptSystemBus.h>
#include <AzCore/Script/ScriptContext.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/smart_ptr/make_shared.h>
@@ -221,11 +218,16 @@ namespace AZ
}
}
AZStd::string componentNamesArray = R"({ "SystemComponents":[)";
const char* comma = "";
// For all system components, deactivate
for (auto componentIt = m_systemComponents.rbegin(); componentIt != m_systemComponents.rend(); ++componentIt)
{
ModuleEntity::DeactivateComponent(**componentIt);
componentNamesArray += AZStd::string::format(R"(%s"%s")", comma, (*componentIt)->RTTI_GetTypeName());
comma = ", ";
}
componentNamesArray += R"(]})";
// For all modules that we created an entity for, set them to "Init" (meaning not Activated)
for (auto& moduleData : m_ownedModules)
@@ -239,6 +241,13 @@ namespace AZ
// Since the system components have been deactivated clear out the vector.
m_systemComponents.clear();
// Signal that the System Components have deactivated
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
AZ::ComponentApplicationLifecycle::SignalEvent(*settingsRegistry, "SystemComponentsDeactivated", componentNamesArray);
}
}
//=========================================================================
@@ -284,7 +293,11 @@ namespace AZ
{
// Split the tag list
AZStd::vector<AZStd::string_view> tagList;
AZStd::tokenize<AZStd::string_view>(tags, ",", tagList);
auto TokenizeTags = [&tagList](AZStd::string_view token)
{
tagList.push_back(token);
};
AZ::StringFunc::TokenizeVisitor(tags, TokenizeTags, ',');
m_systemComponentTags.resize(tagList.size());
AZStd::transform(tagList.begin(), tagList.end(), m_systemComponentTags.begin(), [](const AZStd::string_view& tag)
@@ -737,11 +750,17 @@ namespace AZ
}
}
AZStd::string componentNamesArray = R"({ "SystemComponents":[)";
const char* comma = "";
// Activate the entities in the appropriate order
for (Component* component : componentsToActivate)
{
ModuleEntity::ActivateComponent(*component);
componentNamesArray += AZStd::string::format(R"(%s"%s")", comma, component->RTTI_GetTypeName());
comma = ", ";
}
componentNamesArray += R"(]})";
// Done activating; set state to active
for (auto& moduleData : modulesToInit)
@@ -755,5 +774,12 @@ namespace AZ
// Save the activated components for deactivation later
m_systemComponents.insert(m_systemComponents.end(), componentsToActivate.begin(), componentsToActivate.end());
// Signal that the System Components are activated
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
AZ::ComponentApplicationLifecycle::SignalEvent(*settingsRegistry, "SystemComponentsActivated",
componentNamesArray);
}
}
} // namespace AZ
@@ -15,20 +15,20 @@
namespace AZ::SettingsRegistryScriptUtils::Internal
{
static void RegisterScriptProxyForNotify(SettingsRegistryScriptProxy& settingsRegistryProxy)
static void RegisterScriptProxyForNotify(SettingsRegistryInterface* settingsRegistry,
SettingsRegistryScriptProxy::NotifyEventProxy* notifyEventProxy)
{
if (settingsRegistryProxy.IsValid())
if (settingsRegistry != nullptr)
{
auto ForwardSettingsUpdateToProxyEvent = [&settingsRegistryProxy](AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
auto ForwardSettingsUpdateToProxyEvent = [notifyEventProxy](AZStd::string_view path, AZ::SettingsRegistryInterface::Type)
{
if (settingsRegistryProxy.m_notifyEventProxy)
if (notifyEventProxy)
{
settingsRegistryProxy.m_notifyEventProxy->m_scriptNotifyEvent.Signal(path);
notifyEventProxy->m_scriptNotifyEvent.Signal(path);
}
};
// Register the forwarding function with the BehaviorContext
settingsRegistryProxy.m_notifyEventProxy->m_settingsUpdatedHandler =
settingsRegistryProxy.m_settingsRegistry->RegisterNotifier(ForwardSettingsUpdateToProxyEvent);
notifyEventProxy->m_settingsUpdatedHandler = settingsRegistry->RegisterNotifier(ForwardSettingsUpdateToProxyEvent);
}
}
@@ -37,7 +37,7 @@ namespace AZ::SettingsRegistryScriptUtils::Internal
: m_settingsRegistry(AZStd::move(settingsRegistry))
, m_notifyEventProxy(AZStd::make_shared<NotifyEventProxy>())
{
RegisterScriptProxyForNotify(*this);
RegisterScriptProxyForNotify(m_settingsRegistry.get(), m_notifyEventProxy.get());
}
// Raw AZ::SettingsRegistryInterface pointer is not owned by the proxy, so it's deleter is a no-op
@@ -45,7 +45,7 @@ namespace AZ::SettingsRegistryScriptUtils::Internal
: m_settingsRegistry(settingsRegistry, [](AZ::SettingsRegistryInterface*) {})
, m_notifyEventProxy(AZStd::make_shared<NotifyEventProxy>())
{
RegisterScriptProxyForNotify(*this);
RegisterScriptProxyForNotify(m_settingsRegistry.get(), m_notifyEventProxy.get());
}
// SettingsRegistryScriptProxy function that determines if the SettingsRegistry object is valid
@@ -41,6 +41,8 @@ set(FILES
Component/ComponentApplication.cpp
Component/ComponentApplication.h
Component/ComponentApplicationBus.h
Component/ComponentApplicationLifecycle.cpp
Component/ComponentApplicationLifecycle.h
Component/ComponentBus.cpp
Component/ComponentBus.h
Component/ComponentExport.h