b53bf52e0d
* Fix code that deregisters the Atom Scene subsystem from the AzFramework Scene The AzFramework Scene subsystem API is a generic container based on the type of argument that is passed to it. It maintains a vector of typeids, and only one object of any type is stored at a time. The Bootstrap system component registers the Atom scene as a `ScenePtr` (aka `AZStd::shared_ptr<RPI:Scene>`) with the AzFramework Scene's generic subsystem. However, the component was previously deregistering the type by value, `RPI::Scene`. Since no subsystem for the type `RPI::Scene` was set, unsetting this type did nothing. The result was that the `RPI::Scene` object would still be around by the time that all the Atom `InstanceDatabse`s were being destroyed, resulting in a large number of errors reported about leaked instances during global shutdown. This fixes the above issue by passing the `m_defaultScene` as a parameter to `AzFramework::Scene::UnsetSubsystem`, the same value that is passed to `SetSubsystem`. This is better, because instead of providing explicit template arguments (which were specifying the incorrect type), this now allows the compiler to deduce the correct type, and the syntax is symmetric with the call to `SetSubsystem`. Signed-off-by: Chris Burel <burelc@amazon.com> * Correctly release the AWS API from the `HttpRequestManager` module This code was incorrectly assuming that `AWSNativeSDKInit::InitializationManager::Shutdown()` would be called automatically by the `InitializationManager` itself. However, all that `InitAwsApi()` does is create an `AZ::EnvironmentVariable`, which is a ref-counted type, and stores it in a global static. That global static is defined in a static library (namely `AWSNativeSDKInit`), which is linked in to the `HttpRequestManager` dynamic lib. Because it is a global static, it has to be explicitly cleared with the call to `Shutdown()`. Otherwise the destructor of the EnvironmentVariable doesn't happen until global destruction, by which time the allocator that is supplied to the AWS SDK has already been destroyed, and the shutdown of the AWS SDK attempts to use the already-destroyed allocator. Signed-off-by: Chris Burel <burelc@amazon.com> * Avoid blocking the remote console server thread if there are no connections The Remote console server runs in a separate thread. Previously, it would directly call `AzSock::Accept()` and block the server thread until some client connected to it. However, if no client connected, the thread would continue to be blocked, even if the game launcher tried to exit. This adds a check to see if there's a client on the socket before calling `Accept()`, to avoid the deadlock on launcher exit. Signed-off-by: Chris Burel <burelc@amazon.com> * Fix a log message to print one message per line Signed-off-by: Chris Burel <burelc@amazon.com> * Allow pumping the event loop to close the launcher window Events from the OS are handled in the game's main loop. The general loop looks like this: * Read events from the OS * Tick the game application One of the events that can come from the OS is that the window hosting the game is closed. When this event happens, many resources provided by the renderer are freed, and the game application's `shouldExit` bit is set. However, when the game's `Tick()` is called, there is lots of code that assumes the renderer is still there. To avoid crashing in the `Tick()` call, check if the game should exit after pumping the system events. Signed-off-by: Chris Burel <burelc@amazon.com> * Unload the level when exiting the launcher This ensures that any resources held onto by the level are freed before the launcher exits. Signed-off-by: Chris Burel <burelc@amazon.com> * Add an explicit bus `Disconnect()` call to `AZCoreLogSink` This is necessary because this bus has virtual functions and can be called from multiple threads. Signed-off-by: Chris Burel <burelc@amazon.com> * Allow normal cleanup to take place when exiting the game launcher Previously, global cleanup was side-stepped by calling `TerminateProcess` or `exit`, when quitting the game launcher. This is in contrast to the call to `_exit` on Linux and Mac when exiting the Editor. That leading `_` makes a big difference: the former runs object destruction, the latter does not. Instead of making the launcher exit with `_exit` on Linux, instead, remove that call and actually run all the atexit code. This does not modify the Editor's behavior however. It still uses `_exit` and `TerminateProcess`. Signed-off-by: Chris Burel <burelc@amazon.com>
439 lines
20 KiB
C++
439 lines
20 KiB
C++
/*
|
|
* 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 <BootstrapSystemComponent.h>
|
|
|
|
#include <AzCore/Asset/AssetCommon.h>
|
|
#include <AzCore/Component/ComponentApplicationBus.h>
|
|
#include <AzCore/Component/Entity.h>
|
|
#include <AzCore/NativeUI/NativeUIRequests.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
#include <AzCore/std/smart_ptr/make_shared.h>
|
|
|
|
#include <AzFramework/API/ApplicationAPI.h>
|
|
#include <AzFramework/Components/TransformComponent.h>
|
|
#include <AzFramework/Entity/GameEntityContextBus.h>
|
|
#include <AzFramework/Asset/AssetSystemBus.h>
|
|
|
|
#include <ISystem.h>
|
|
|
|
#include <Atom/RHI/RHISystemInterface.h>
|
|
|
|
#include <Atom/RPI.Reflect/Image/AttachmentImageAsset.h>
|
|
#include <Atom/RPI.Reflect/Asset/AssetUtils.h>
|
|
|
|
#include <Atom/RPI.Public/Pass/Pass.h>
|
|
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
|
#include <Atom/RPI.Public/RenderPipeline.h>
|
|
#include <Atom/RPI.Public/ViewportContextBus.h>
|
|
#include <Atom/RPI.Public/RPISystemInterface.h>
|
|
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
|
|
|
|
#include <Atom/Bootstrap/DefaultWindowBus.h>
|
|
#include <Atom/Bootstrap/BootstrapNotificationBus.h>
|
|
|
|
#include <Atom/RPI.Reflect/System/AnyAsset.h>
|
|
#include <AzCore/Console/IConsole.h>
|
|
#include <BootstrapSystemComponent_Traits_Platform.h>
|
|
|
|
static void OnFrameRateLimitChanged(const float& fpsLimit)
|
|
{
|
|
AZ::Render::Bootstrap::RequestBus::Broadcast(
|
|
&AZ::Render::Bootstrap::RequestBus::Events::SetFrameRateLimit, fpsLimit);
|
|
}
|
|
|
|
AZ_CVAR(AZ::CVarFixedString, r_default_pipeline_name, AZ_TRAIT_BOOTSTRAPSYSTEMCOMPONENT_PIPELINE_NAME, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Default Render pipeline name");
|
|
AZ_CVAR(float, r_fps_limit, 0, OnFrameRateLimitChanged, AZ::ConsoleFunctorFlags::Null, "The maximum framerate to render at, or 0 for unlimited");
|
|
|
|
namespace AZ
|
|
{
|
|
namespace Render
|
|
{
|
|
namespace Bootstrap
|
|
{
|
|
void BootstrapSystemComponent::Reflect(ReflectContext* context)
|
|
{
|
|
if (SerializeContext* serialize = azrtti_cast<SerializeContext*>(context))
|
|
{
|
|
serialize->Class<BootstrapSystemComponent, Component>()
|
|
->Version(1)
|
|
;
|
|
|
|
if (EditContext* ec = serialize->GetEditContext())
|
|
{
|
|
ec->Class<BootstrapSystemComponent>("Atom RPI", "Atom Renderer")
|
|
->ClassElement(Edit::ClassElements::EditorData, "")
|
|
->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System", 0xc94d118b))
|
|
->Attribute(Edit::Attributes::AutoExpand, true)
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
void BootstrapSystemComponent::GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided)
|
|
{
|
|
provided.push_back(AZ_CRC("BootstrapSystemComponent", 0xb8f32711));
|
|
}
|
|
|
|
void BootstrapSystemComponent::GetRequiredServices(ComponentDescriptor::DependencyArrayType& required)
|
|
{
|
|
required.push_back(AZ_CRC("RPISystem", 0xf2add773));
|
|
required.push_back(AZ_CRC("SceneSystemComponentService", 0xd8975435));
|
|
}
|
|
|
|
void BootstrapSystemComponent::GetDependentServices(ComponentDescriptor::DependencyArrayType& dependent)
|
|
{
|
|
dependent.push_back(AZ_CRC("ImGuiSystemComponent", 0x2f08b9a7));
|
|
dependent.push_back(AZ_CRC("PrimitiveSystemComponent", 0xc860fa59));
|
|
dependent.push_back(AZ_CRC("MeshSystemComponent", 0x21e5bbb6));
|
|
dependent.push_back(AZ_CRC("CoreLightsService", 0x91932ef6));
|
|
dependent.push_back(AZ_CRC("DynamicDrawService", 0x023c1673));
|
|
dependent.push_back(AZ_CRC("CommonService", 0x6398eec4));
|
|
}
|
|
|
|
void BootstrapSystemComponent::GetIncompatibleServices(ComponentDescriptor::DependencyArrayType& incompatible)
|
|
{
|
|
incompatible.push_back(AZ_CRC("BootstrapSystemComponent", 0xb8f32711));
|
|
}
|
|
|
|
BootstrapSystemComponent::BootstrapSystemComponent()
|
|
{
|
|
}
|
|
|
|
BootstrapSystemComponent::~BootstrapSystemComponent()
|
|
{
|
|
m_viewportContext.reset();
|
|
}
|
|
|
|
void BootstrapSystemComponent::Activate()
|
|
{
|
|
// Create a native window only if it's a launcher (or standalone)
|
|
// LY editor create its own window which we can get its handle through AzFramework::WindowSystemNotificationBus::Handler's OnWindowCreated() function
|
|
AZ::ApplicationTypeQuery appType;
|
|
ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType);
|
|
if (!appType.IsValid() || appType.IsGame())
|
|
{
|
|
// GFX TODO - investigate window creation being part of the GameApplication.
|
|
|
|
m_nativeWindow = AZStd::make_unique<AzFramework::NativeWindow>("O3DELauncher", AzFramework::WindowGeometry(0, 0, 1920, 1080));
|
|
AZ_Assert(m_nativeWindow, "Failed to create the game window\n");
|
|
|
|
m_nativeWindow->Activate();
|
|
|
|
m_windowHandle = m_nativeWindow->GetWindowHandle();
|
|
}
|
|
else
|
|
{
|
|
// Disable default scene creation for non-games projects
|
|
// This can be manually overridden via the DefaultWindowBus.
|
|
m_createDefaultScene = false;
|
|
}
|
|
|
|
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
|
|
TickBus::Handler::BusConnect();
|
|
|
|
// Listen for window system requests (e.g. requests for default window handle)
|
|
AzFramework::WindowSystemRequestBus::Handler::BusConnect();
|
|
|
|
// Listen for window system notifications (e.g. window being created by Editor)
|
|
AzFramework::WindowSystemNotificationBus::Handler::BusConnect();
|
|
|
|
Render::Bootstrap::DefaultWindowBus::Handler::BusConnect();
|
|
Render::Bootstrap::RequestBus::Handler::BusConnect();
|
|
}
|
|
|
|
void BootstrapSystemComponent::Deactivate()
|
|
{
|
|
Render::Bootstrap::RequestBus::Handler::BusDisconnect();
|
|
Render::Bootstrap::DefaultWindowBus::Handler::BusDisconnect();
|
|
|
|
AzFramework::WindowSystemRequestBus::Handler::BusDisconnect();
|
|
AzFramework::WindowSystemNotificationBus::Handler::BusDisconnect();
|
|
TickBus::Handler::BusDisconnect();
|
|
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
|
|
|
m_brdfTexture = nullptr;
|
|
RemoveRenderPipeline();
|
|
DestroyDefaultScene();
|
|
|
|
m_viewportContext.reset();
|
|
m_nativeWindow = nullptr;
|
|
m_windowHandle = nullptr;
|
|
}
|
|
|
|
void BootstrapSystemComponent::OnCatalogLoaded(const char* /*catalogFile*/)
|
|
{
|
|
if (m_isAssetCatalogLoaded)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_isAssetCatalogLoaded = true;
|
|
|
|
RPI::RPISystemInterface::Get()->InitializeSystemAssets();
|
|
|
|
if (!RPI::RPISystemInterface::Get()->IsInitialized())
|
|
{
|
|
AZ::OSString msgBoxMessage;
|
|
msgBoxMessage.append("RPI System could not initialize correctly. Check log for detail.");
|
|
|
|
AZ::NativeUI::NativeUIRequestBus::Broadcast(
|
|
&AZ::NativeUI::NativeUIRequestBus::Events::DisplayOkDialog, "O3DE Fatal Error", msgBoxMessage.c_str(), false);
|
|
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
|
|
|
|
return;
|
|
}
|
|
|
|
// In the case of the game we want to call create and register the scene as a soon as we can
|
|
// because a level could be loaded in autoexec.cfg and that will assert if there is no scene registered
|
|
// to get the feature processors for the components. So we can't wait until the tick (whereas the Editor wants to wait)
|
|
|
|
if (m_createDefaultScene)
|
|
{
|
|
CreateDefaultScene();
|
|
}
|
|
|
|
if (m_windowHandle)
|
|
{
|
|
CreateWindowContext();
|
|
if (m_createDefaultScene)
|
|
{
|
|
CreateDefaultRenderPipeline();
|
|
}
|
|
}
|
|
}
|
|
|
|
void BootstrapSystemComponent::OnWindowCreated(AzFramework::NativeWindowHandle windowHandle)
|
|
{
|
|
// only handle the first window (default) created
|
|
if (m_windowHandle == nullptr)
|
|
{
|
|
m_windowHandle = windowHandle;
|
|
|
|
if (m_isAssetCatalogLoaded)
|
|
{
|
|
CreateWindowContext();
|
|
if (m_createDefaultScene)
|
|
{
|
|
CreateDefaultRenderPipeline();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void BootstrapSystemComponent::CreateWindowContext()
|
|
{
|
|
RHI::Device* device = RHI::RHISystemInterface::Get()->GetDevice();
|
|
RPI::ViewportContextRequestsInterface::CreationParameters params;
|
|
params.device = device;
|
|
params.windowHandle = m_windowHandle;
|
|
params.renderScene = m_defaultScene;
|
|
// Setting the default ViewportContextID to an arbitrary and otherwise invalid (negative) value to ensure its uniqueness
|
|
params.id = -10;
|
|
|
|
auto viewContextManager = AZ::Interface<RPI::ViewportContextRequestsInterface>::Get();
|
|
m_viewportContext = viewContextManager->CreateViewportContext(
|
|
viewContextManager->GetDefaultViewportContextName(), params);
|
|
|
|
DefaultWindowNotificationBus::Broadcast(&DefaultWindowNotificationBus::Events::DefaultWindowCreated);
|
|
|
|
// Listen to window notification so we can request exit application when window closes
|
|
AzFramework::WindowNotificationBus::Handler::BusConnect(GetDefaultWindowHandle());
|
|
}
|
|
|
|
AZ::RPI::ScenePtr BootstrapSystemComponent::GetOrCreateAtomSceneFromAzScene(AzFramework::Scene* scene)
|
|
{
|
|
// Get or create a weak pointer to our scene
|
|
// If it's valid, we're done, if not we need to create an Atom scene and update our scene map
|
|
auto& atomSceneHandle = m_azSceneToAtomSceneMap[scene];
|
|
if (!atomSceneHandle.expired())
|
|
{
|
|
return atomSceneHandle.lock();
|
|
}
|
|
|
|
// Create and register a scene with all available feature processors
|
|
RPI::SceneDescriptor sceneDesc;
|
|
AZ::RPI::ScenePtr atomScene = RPI::Scene::CreateScene(sceneDesc);
|
|
atomScene->EnableAllFeatureProcessors();
|
|
atomScene->Activate();
|
|
|
|
// Register scene to RPI system so it will be processed/rendered per tick
|
|
RPI::RPISystemInterface::Get()->RegisterScene(atomScene);
|
|
scene->SetSubsystem(atomScene);
|
|
|
|
atomSceneHandle = atomScene;
|
|
|
|
return atomScene;
|
|
}
|
|
|
|
void BootstrapSystemComponent::CreateDefaultScene()
|
|
{
|
|
// Bind atomScene to the GameEntityContext's AzFramework::Scene
|
|
m_defaultFrameworkScene = AzFramework::SceneSystemInterface::Get()->GetScene(AzFramework::Scene::MainSceneName);
|
|
// This should never happen unless scene creation has changed.
|
|
AZ_Assert(m_defaultFrameworkScene, "Error: Scenes missing during system component initialization");
|
|
m_sceneRemovalHandler = AzFramework::Scene::RemovalEvent::Handler(
|
|
[this](AzFramework::Scene&, AzFramework::Scene::RemovalEventType eventType)
|
|
{
|
|
if (eventType == AzFramework::Scene::RemovalEventType::Zombified)
|
|
{
|
|
m_defaultFrameworkScene.reset();
|
|
}
|
|
});
|
|
m_defaultFrameworkScene->ConnectToEvents(m_sceneRemovalHandler);
|
|
m_defaultScene = GetOrCreateAtomSceneFromAzScene(m_defaultFrameworkScene.get());
|
|
}
|
|
|
|
bool BootstrapSystemComponent::EnsureDefaultRenderPipelineInstalledForScene(AZ::RPI::ScenePtr scene, AZ::RPI::ViewportContextPtr viewportContext)
|
|
{
|
|
// Create a render pipeline from the specified asset for the window context and add the pipeline to the scene.
|
|
// When running with no Asset Processor (for example in release), CompileAssetSync will return AssetStatus_Unknown.
|
|
AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown;
|
|
const AZ::CVarFixedString pipelineName = static_cast<AZ::CVarFixedString>(r_default_pipeline_name);
|
|
AzFramework::AssetSystemRequestBus::BroadcastResult(status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, pipelineName.data());
|
|
|
|
AZ_Assert(status == AzFramework::AssetSystem::AssetStatus_Compiled || status == AzFramework::AssetSystem::AssetStatus_Unknown, "Could not compile the default render pipeline at '%s'", pipelineName.c_str());
|
|
|
|
Data::Asset<RPI::AnyAsset> pipelineAsset = RPI::AssetUtils::LoadAssetByProductPath<RPI::AnyAsset>(pipelineName.data(), RPI::AssetUtils::TraceLevel::Error);
|
|
RPI::RenderPipelineDescriptor renderPipelineDescriptor = *RPI::GetDataFromAnyAsset<RPI::RenderPipelineDescriptor>(pipelineAsset);
|
|
renderPipelineDescriptor.m_name = AZStd::string::format("%s_%i", renderPipelineDescriptor.m_name.c_str(), viewportContext->GetId());
|
|
|
|
if (!scene->GetRenderPipeline(AZ::Name(renderPipelineDescriptor.m_name)))
|
|
{
|
|
RPI::RenderPipelinePtr renderPipeline = RPI::RenderPipeline::CreateRenderPipelineForWindow(renderPipelineDescriptor, *viewportContext->GetWindowContext().get());
|
|
pipelineAsset.Release();
|
|
scene->AddRenderPipeline(renderPipeline);
|
|
}
|
|
|
|
// As part of our initialization we need to create the BRDF texture generation pipeline
|
|
AZ::RPI::RenderPipelineDescriptor pipelineDesc;
|
|
pipelineDesc.m_mainViewTagName = "MainCamera";
|
|
pipelineDesc.m_name = AZStd::string::format("BRDFTexturePipeline_%i", viewportContext->GetId());
|
|
pipelineDesc.m_rootPassTemplate = "BRDFTexturePipeline";
|
|
pipelineDesc.m_executeOnce = true;
|
|
|
|
// Save a reference to the generated BRDF texture so it doesn't get deleted if all the passes refering to it get deleted and it's ref count goes to zero
|
|
if (!m_brdfTexture)
|
|
{
|
|
const AZStd::shared_ptr<RPI::PassTemplate> brdfTextureTemplate = RPI::PassSystemInterface::Get()->GetPassTemplate(Name("BRDFTextureTemplate"));
|
|
Data::Asset<RPI::AttachmentImageAsset> brdfImageAsset = RPI::AssetUtils::LoadAssetById<RPI::AttachmentImageAsset>(
|
|
brdfTextureTemplate->m_imageAttachments[0].m_assetRef.m_assetId, RPI::AssetUtils::TraceLevel::Error);
|
|
if (brdfImageAsset.IsReady())
|
|
{
|
|
m_brdfTexture = RPI::AttachmentImage::FindOrCreate(brdfImageAsset);
|
|
}
|
|
}
|
|
|
|
if (!scene->GetRenderPipeline(AZ::Name(pipelineDesc.m_name)))
|
|
{
|
|
RPI::RenderPipelinePtr brdfTexturePipeline = AZ::RPI::RenderPipeline::CreateRenderPipeline(pipelineDesc);
|
|
scene->AddRenderPipeline(brdfTexturePipeline);
|
|
}
|
|
|
|
// Send notification when the scene and its pipeline are ready.
|
|
// Use the first created pipeline's scene as our default scene for now to allow
|
|
// consumers waiting on scene availability to initialize.
|
|
if (!m_defaultSceneReady)
|
|
{
|
|
m_defaultScene = scene;
|
|
Render::Bootstrap::NotificationBus::Broadcast(
|
|
&Render::Bootstrap::NotificationBus::Handler::OnBootstrapSceneReady, m_defaultScene.get());
|
|
m_defaultSceneReady = true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
float BootstrapSystemComponent::GetFrameRateLimit() const
|
|
{
|
|
return r_fps_limit;
|
|
}
|
|
|
|
void BootstrapSystemComponent::SetFrameRateLimit(float fpsLimit)
|
|
{
|
|
r_fps_limit = fpsLimit;
|
|
if (m_viewportContext)
|
|
{
|
|
m_viewportContext->SetFpsLimit(r_fps_limit);
|
|
}
|
|
Render::Bootstrap::NotificationBus::Broadcast(
|
|
&Render::Bootstrap::NotificationBus::Events::OnFrameRateLimitChanged, fpsLimit);
|
|
}
|
|
|
|
void BootstrapSystemComponent::CreateDefaultRenderPipeline()
|
|
{
|
|
EnsureDefaultRenderPipelineInstalledForScene(m_defaultScene, m_viewportContext);
|
|
|
|
const auto pipeline = m_defaultScene->FindRenderPipelineForWindow(m_viewportContext->GetWindowHandle());
|
|
AZ_Error("AtomBootstrap", pipeline, "No pipeline found for the default viewport window! Did the default render pipeline fail to compile?");
|
|
if (pipeline)
|
|
{
|
|
m_renderPipelineId = pipeline->GetId();
|
|
}
|
|
}
|
|
|
|
void BootstrapSystemComponent::DestroyDefaultScene()
|
|
{
|
|
if (m_defaultScene)
|
|
{
|
|
RPI::RPISystemInterface::Get()->UnregisterScene(m_defaultScene);
|
|
|
|
// Unbind m_defaultScene to the GameEntityContext's AzFramework::Scene
|
|
if (m_defaultFrameworkScene)
|
|
{
|
|
m_defaultFrameworkScene->UnsetSubsystem(m_defaultScene);
|
|
}
|
|
|
|
m_defaultScene = nullptr;
|
|
m_defaultFrameworkScene = nullptr;
|
|
}
|
|
}
|
|
|
|
void BootstrapSystemComponent::RemoveRenderPipeline()
|
|
{
|
|
if (m_defaultScene && m_defaultScene->GetRenderPipeline(m_renderPipelineId))
|
|
{
|
|
m_defaultScene->RemoveRenderPipeline(m_renderPipelineId);
|
|
}
|
|
m_renderPipelineId = "";
|
|
}
|
|
|
|
void BootstrapSystemComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] ScriptTimePoint time)
|
|
{ }
|
|
|
|
int BootstrapSystemComponent::GetTickOrder()
|
|
{
|
|
return TICK_PRE_RENDER;
|
|
}
|
|
|
|
void BootstrapSystemComponent::OnWindowClosed()
|
|
{
|
|
m_windowHandle = nullptr;
|
|
m_viewportContext.reset();
|
|
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
|
|
AzFramework::WindowNotificationBus::Handler::BusDisconnect();
|
|
}
|
|
|
|
AzFramework::NativeWindowHandle BootstrapSystemComponent::GetDefaultWindowHandle()
|
|
{
|
|
return m_windowHandle;
|
|
}
|
|
|
|
AZStd::shared_ptr<RPI::WindowContext> BootstrapSystemComponent::GetDefaultWindowContext()
|
|
{
|
|
return m_viewportContext ? m_viewportContext->GetWindowContext() : nullptr;
|
|
}
|
|
|
|
void BootstrapSystemComponent::SetCreateDefaultScene(bool create)
|
|
{
|
|
m_createDefaultScene = create;
|
|
}
|
|
} // namespace Bootstrap
|
|
} // namespace Render
|
|
} // namespace AZ
|