SampleComponentManager.cpp 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512
  1. /*
  2. * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
  3. * its licensors.
  4. *
  5. * For complete copyright and license terms please see the LICENSE at the root of this
  6. * distribution (the "License"). All use of this software is governed by the License,
  7. * or, if provided, by the license below or the license accompanying this file. Do not
  8. * remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
  9. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. *
  11. */
  12. #include <SampleComponentManager.h>
  13. #include <SampleComponentConfig.h>
  14. #include <Atom/Component/DebugCamera/CameraComponent.h>
  15. #include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
  16. #include <Atom/Component/DebugCamera/ArcBallControllerComponent.h>
  17. #include <Atom/Feature/AuxGeom/AuxGeomFeatureProcessor.h>
  18. #include <Atom/Feature/ImGui/ImGuiUtils.h>
  19. #include <Atom/Feature/ImGui/SystemBus.h>
  20. #include <Atom/Feature/Mesh/MeshFeatureProcessor.h>
  21. #include <Atom/Feature/PostProcessing/PostProcessingConstants.h>
  22. #include <Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h>
  23. #include <Atom/RPI.Public/Pass/Pass.h>
  24. #include <Atom/RPI.Public/Pass/ParentPass.h>
  25. #include <Atom/RPI.Public/Pass/PassSystemInterface.h>
  26. #include <Atom/RPI.Public/Pass/RenderPass.h>
  27. #include <Atom/RPI.Public/Pass/Specific/SwapChainPass.h>
  28. #include <Atom/RPI.Public/RenderPipeline.h>
  29. #include <Atom/RPI.Public/RPISystemInterface.h>
  30. #include <Atom/RPI.Public/Scene.h>
  31. #include <Atom/RPI.Reflect/Shader/IShaderVariantFinder.h>
  32. #include <Atom/RHI/Factory.h>
  33. #include <Atom/RHI/RHISystemInterface.h>
  34. #include <Atom/RHI.Reflect/AliasedHeapEnums.h>
  35. #include <Automation/ScriptManager.h>
  36. #include <RHI/AlphaToCoverageExampleComponent.h>
  37. #include <RHI/AsyncComputeExampleComponent.h>
  38. #include <RHI/BasicRHIComponent.h>
  39. #include <RHI/ComputeExampleComponent.h>
  40. #include <RHI/CopyQueueComponent.h>
  41. #include <RHI/DualSourceBlendingComponent.h>
  42. #include <RHI/IndirectRenderingExampleComponent.h>
  43. #include <RHI/InputAssemblyExampleComponent.h>
  44. #include <RHI/SubpassExampleComponent.h>
  45. #include <RHI/MRTExampleComponent.h>
  46. #include <RHI/MSAAExampleComponent.h>
  47. #include <RHI/MultiThreadComponent.h>
  48. #include <RHI/MultiViewportSwapchainComponent.h>
  49. #include <RHI/MultipleViewsComponent.h>
  50. #include <RHI/QueryExampleComponent.h>
  51. #include <RHI/StencilExampleComponent.h>
  52. #include <RHI/SwapchainExampleComponent.h>
  53. #include <RHI/SphericalHarmonicsExampleComponent.h>
  54. #include <RHI/Texture3dExampleComponent.h>
  55. #include <RHI/TextureArrayExampleComponent.h>
  56. #include <RHI/TextureExampleComponent.h>
  57. #include <RHI/TextureMapExampleComponent.h>
  58. #include <RHI/TriangleExampleComponent.h>
  59. #include <RHI/TrianglesConstantBufferExampleComponent.h>
  60. #include <RHI/BindlessPrototypeExampleComponent.h>
  61. #include <RHI/RayTracingExampleComponent.h>
  62. #include <AreaLightExampleComponent.h>
  63. #include <AssetLoadTestComponent.h>
  64. #include <AuxGeomExampleComponent.h>
  65. #include <BistroBenchmarkComponent.h>
  66. #include <BloomExampleComponent.h>
  67. #include <CheckerboardExampleComponent.h>
  68. #include <CullingAndLodExampleComponent.h>
  69. #include <DecalExampleComponent.h>
  70. #include <DepthOfFieldExampleComponent.h>
  71. #include <DynamicDrawExampleComponent.h>
  72. #include <DynamicMaterialTestComponent.h>
  73. #include <MaterialHotReloadTestComponent.h>
  74. #include <ExposureExampleComponent.h>
  75. #include <SceneReloadSoakTestComponent.h>
  76. #include <LightCullingExampleComponent.h>
  77. #include <MeshExampleComponent.h>
  78. #include <MSAA_RPI_ExampleComponent.h>
  79. #include <MultiRenderPipelineExampleComponent.h>
  80. #include <MultiSceneExampleComponent.h>
  81. #include <ParallaxMappingExampleComponent.h>
  82. #include <SceneReloadSoakTestComponent.h>
  83. #include <ShadingExampleComponent.h>
  84. #include <ShadowExampleComponent.h>
  85. #include <ShadowedBistroExampleComponent.h>
  86. #include <SkinnedMeshExampleComponent.h>
  87. #include <SsaoExampleComponent.h>
  88. #include <StreamingImageExampleComponent.h>
  89. #include <RootConstantsExampleComponent.h>
  90. #include <MultiViewSingleSceneAuxGeomExampleComponent.h>
  91. #include <TonemappingExampleComponent.h>
  92. #include <TransparencyExampleComponent.h>
  93. #include <DiffuseGIExampleComponent.h>
  94. #include <SSRExampleComponent.h>
  95. #include <Atom/Bootstrap/DefaultWindowBus.h>
  96. #include <AzCore/Component/Entity.h>
  97. #include <AzCore/Debug/Profiler.h>
  98. #include <AzCore/Serialization/SerializeContext.h>
  99. #include <AzCore/std/smart_ptr/make_shared.h>
  100. #include <AzCore/std/algorithm.h>
  101. #include <AzFramework/API/ApplicationAPI.h>
  102. #include <AzFramework/Components/ConsoleBus.h>
  103. #include <AzFramework/Components/TransformComponent.h>
  104. #include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
  105. #include <AzFramework/Entity/GameEntityContextBus.h>
  106. #include <AzFramework/Scene/Scene.h>
  107. #include <AzFramework/Scene/SceneSystemBus.h>
  108. #include <Passes/RayTracingAmbientOcclusionPass.h>
  109. #include <Utils/Utils.h>
  110. #include "ExampleComponentBus.h"
  111. namespace Platform
  112. {
  113. const char* GetPipelineName();
  114. }
  115. namespace AtomSampleViewer
  116. {
  117. namespace
  118. {
  119. const char* PassTreeToolName = "PassTree";
  120. const char* CpuProfilerToolName = "CPU Profiler";
  121. const char* GpuProfilerToolName = "GPU Profiler";
  122. const char* TransientAttachmentProfilerToolName = "Transient Attachment Profiler";
  123. }
  124. SampleEntry SampleEntry::NewRHISample(const AZStd::string& name, const AZ::Uuid& uuid)
  125. {
  126. SampleEntry entry;
  127. entry.m_sampleName = name;
  128. entry.m_sampleUuid = uuid;
  129. entry.m_pipelineType = SamplePipelineType::RHI;
  130. return entry;
  131. }
  132. SampleEntry SampleEntry::NewRHISample(const AZStd::string& name, const AZ::Uuid& uuid, AZStd::function<bool()> isSupportedFunction)
  133. {
  134. SampleEntry entry;
  135. entry.m_sampleName = name;
  136. entry.m_sampleUuid = uuid;
  137. entry.m_pipelineType = SamplePipelineType::RHI;
  138. entry.m_isSupportedFunc = isSupportedFunction;
  139. return entry;
  140. }
  141. SampleEntry SampleEntry::NewRPISample(const AZStd::string& name, const AZ::Uuid& uuid)
  142. {
  143. SampleEntry entry;
  144. entry.m_sampleName = name;
  145. entry.m_sampleUuid = uuid;
  146. entry.m_pipelineType = SamplePipelineType::RPI;
  147. return entry;
  148. }
  149. SampleEntry SampleEntry::NewRPISample(const AZStd::string& name, const AZ::Uuid& uuid, AZStd::function<bool()> isSupportedFunction)
  150. {
  151. SampleEntry entry;
  152. entry.m_sampleName = name;
  153. entry.m_sampleUuid = uuid;
  154. entry.m_pipelineType = SamplePipelineType::RPI;
  155. entry.m_isSupportedFunc = isSupportedFunction;
  156. return entry;
  157. }
  158. void SampleComponentManager::Reflect(AZ::ReflectContext* context)
  159. {
  160. if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  161. {
  162. serializeContext->Class<SampleComponentManager, AZ::Component>()
  163. ->Version(0)
  164. ;
  165. }
  166. }
  167. void SampleComponentManager::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  168. {
  169. required.push_back(AZ_CRC("PrototypeLmbrCentralService", 0xe35e6de0));
  170. }
  171. void SampleComponentManager::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
  172. {
  173. dependent.push_back(AZ_CRC("AzFrameworkConfigurationSystemComponentService", 0xcc49c96e)); // Ensures a scene is created for the GameEntityContext
  174. }
  175. void SampleComponentManager::RegisterSampleComponent(const SampleEntry& sample)
  176. {
  177. if (AZStd::find(m_availableSamples.begin(), m_availableSamples.end(), sample) == m_availableSamples.end())
  178. {
  179. m_availableSamples.push_back(sample);
  180. }
  181. }
  182. SampleComponentManager::SampleComponentManager()
  183. : m_imguiFrameCaptureSaver("@user@/frame_capture.xml")
  184. , m_imGuiFrameTimer(FrameTimeLogSize, FrameTimeLogSize)
  185. {
  186. m_exampleEntity = aznew AZ::Entity();
  187. m_entityContextId = AzFramework::EntityContextId::CreateNull();
  188. memset(m_alphanumericNumbersDown, 0, s_alphanumericCount);
  189. }
  190. SampleComponentManager::~SampleComponentManager()
  191. {
  192. m_exampleEntity = nullptr;
  193. m_cameraEntity = nullptr;
  194. m_windowContext = nullptr;
  195. m_availableSamples.clear();
  196. }
  197. void SampleComponentManager::Init()
  198. {
  199. auto isSupportedFunc = []()
  200. {
  201. return SampleComponentManager::IsMultiViewportSwapchainSampleSupported();
  202. };
  203. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/AlphaToCoverage", azrtti_typeid<AlphaToCoverageExampleComponent>() ));
  204. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/AsyncCompute", azrtti_typeid<AsyncComputeExampleComponent>() ) );
  205. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/BindlessPrototype", azrtti_typeid<BindlessPrototypeExampleComponent>() ));
  206. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/Compute", azrtti_typeid<ComputeExampleComponent>() ));
  207. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/CopyQueue", azrtti_typeid<CopyQueueComponent>() ));
  208. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/DualSourceBlending", azrtti_typeid<DualSourceBlendingComponent>(), []() {return Utils::GetRHIDevice()->GetFeatures().m_dualSourceBlending; } ));
  209. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/IndirectRendering", azrtti_typeid<IndirectRenderingExampleComponent>(), []() {return Utils::GetRHIDevice()->GetFeatures().m_indirectCommandTier > RHI::IndirectCommandTiers::Tier0; } ));
  210. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/InputAssembly", azrtti_typeid<InputAssemblyExampleComponent>()));
  211. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/MSAA", azrtti_typeid<MSAAExampleComponent>() ));
  212. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/MultipleViews", azrtti_typeid<MultipleViewsComponent>() ));
  213. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/MultiRenderTarget", azrtti_typeid<MRTExampleComponent>() ));
  214. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/MultiThread", azrtti_typeid<MultiThreadComponent>() ));
  215. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/MultiViewportSwapchainComponent", azrtti_typeid<MultiViewportSwapchainComponent>(), isSupportedFunc ));
  216. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/Queries", azrtti_typeid<QueryExampleComponent>() ));
  217. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/RayTracing", azrtti_typeid<RayTracingExampleComponent>(), []() {return Utils::GetRHIDevice()->GetFeatures().m_rayTracing; } ));
  218. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/SphericalHarmonics", azrtti_typeid<SphericalHarmonicsExampleComponent>() ));
  219. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/Stencil", azrtti_typeid<StencilExampleComponent>() ));
  220. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/Subpass", azrtti_typeid<SubpassExampleComponent>(), []() {return Utils::GetRHIDevice()->GetFeatures().m_renderTargetSubpassInputSupport != AZ::RHI::SubpassInputSupportType::NotSupported; } ));
  221. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/Swapchain", azrtti_typeid<SwapchainExampleComponent>() ));
  222. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/Texture", azrtti_typeid<TextureExampleComponent>() ));
  223. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/Texture3d", azrtti_typeid<Texture3dExampleComponent>() ));
  224. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/TextureArray", azrtti_typeid<TextureArrayExampleComponent>() ));
  225. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/TextureMap", azrtti_typeid<TextureMapExampleComponent>() ));
  226. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/Triangle", azrtti_typeid<TriangleExampleComponent>() ));
  227. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRHISample( "RHI/TrianglesConstantBuffer", azrtti_typeid<TrianglesConstantBufferExampleComponent>() ));
  228. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/AssetLoadTest", azrtti_typeid<AssetLoadTestComponent>() ));
  229. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/AuxGeom", azrtti_typeid<AuxGeomExampleComponent>() ));
  230. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/BistroBenchmark", azrtti_typeid<BistroBenchmarkComponent>() ));
  231. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/CullingAndLod", azrtti_typeid<CullingAndLodExampleComponent>() ));
  232. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/Decals", azrtti_typeid<DecalExampleComponent>() ));
  233. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/DynamicDraw", azrtti_typeid<DynamicDrawExampleComponent>() ));
  234. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/DynamicMaterialTest", azrtti_typeid<DynamicMaterialTestComponent>() ));
  235. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/MaterialHotReloadTest", azrtti_typeid<MaterialHotReloadTestComponent>() ));
  236. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/Mesh", azrtti_typeid<MeshExampleComponent>() ));
  237. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/MSAA", azrtti_typeid<MSAA_RPI_ExampleComponent>() ));
  238. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/MultiRenderPipeline", azrtti_typeid<MultiRenderPipelineExampleComponent>() ));
  239. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/MultiScene", azrtti_typeid<MultiSceneExampleComponent>() ));
  240. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/MultiViewSingleSceneAuxGeom", azrtti_typeid<MultiViewSingleSceneAuxGeomExampleComponent>() ));
  241. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/RootConstants", azrtti_typeid<RootConstantsExampleComponent>() ));
  242. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/SceneReloadSoakTest", azrtti_typeid<SceneReloadSoakTestComponent>() ));
  243. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/Shading", azrtti_typeid<ShadingExampleComponent>() ));
  244. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "RPI/StreamingImage", azrtti_typeid<StreamingImageExampleComponent>() ));
  245. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/AreaLight", azrtti_typeid<AreaLightExampleComponent>() ));
  246. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/Bloom", azrtti_typeid<BloomExampleComponent>() ));
  247. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/Checkerboard", azrtti_typeid<CheckerboardExampleComponent>() ));
  248. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/DepthOfField", azrtti_typeid<DepthOfFieldExampleComponent>() ));
  249. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/DiffuseGI", azrtti_typeid<DiffuseGIExampleComponent>(), []() {return Utils::GetRHIDevice()->GetFeatures().m_rayTracing; }));
  250. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/Exposure", azrtti_typeid<ExposureExampleComponent>() ));
  251. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/LightCulling", azrtti_typeid<LightCullingExampleComponent>() ));
  252. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/Parallax", azrtti_typeid<ParallaxMappingExampleComponent>() ));
  253. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/Shadow", azrtti_typeid<ShadowExampleComponent>() ));
  254. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/ShadowedBistro", azrtti_typeid<ShadowedBistroExampleComponent>() ));
  255. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/SkinnedMesh", azrtti_typeid<SkinnedMeshExampleComponent>() ));
  256. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/SSAO", azrtti_typeid<SsaoExampleComponent>()));
  257. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/SSR", azrtti_typeid<SSRExampleComponent>()));
  258. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/Tonemapping", azrtti_typeid<TonemappingExampleComponent>() ));
  259. SampleComponentManager::RegisterSampleComponent(SampleEntry::NewRPISample( "Features/Transparency", azrtti_typeid<TransparencyExampleComponent>() ));
  260. m_scriptManager = AZStd::make_unique<ScriptManager>();
  261. }
  262. void SampleComponentManager::Activate()
  263. {
  264. // We can only initialize this component after the asset catalog has been loaded.
  265. AzFramework::AssetCatalogEventBus::Handler::BusConnect();
  266. AZ::Render::ImGuiSystemNotificationBus::Handler::BusConnect();
  267. auto* passSystem = AZ::RPI::PassSystemInterface::Get();
  268. AZ_Assert(passSystem, "Cannot get the pass system.");
  269. passSystem->AddPassCreator(Name("RayTracingAmbientOcclusionPass"), &AZ::Render::RayTracingAmbientOcclusionPass::Create);
  270. }
  271. void SampleComponentManager::ActivateInternal()
  272. {
  273. using namespace AZ;
  274. AZ::ApplicationTypeQuery appType;
  275. ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType);
  276. if (!appType.IsValid() || appType.IsEditor())
  277. {
  278. return;
  279. }
  280. // ActivateInternal() may get called twice because the OnCatalogLoaded was called twice When run AtomSampleViewer launcher. One of those two events is from ly launcher framework and the other one is from
  281. // LoadCatalog call in AtomSampleViewer system component. Although load the same asset catalog twice doesn't seem to cause other issue.
  282. if (m_wasActivated)
  283. {
  284. return;
  285. }
  286. Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_windowContext, &Render::Bootstrap::DefaultWindowBus::Events::GetDefaultWindowContext);
  287. AzFramework::GameEntityContextRequestBus::BroadcastResult(m_entityContextId, &AzFramework::GameEntityContextRequestBus::Events::GetGameEntityContextId);
  288. CreateDefaultCamera();
  289. // Add customized pass classes
  290. auto* passSystem = RPI::PassSystemInterface::Get();
  291. passSystem->AddPassCreator(Name("RHISamplePass"), &AtomSampleViewer::RHISamplePass::Create);
  292. // Use scene and render pipeline for RHI samples as default scene and render pipeline
  293. CreateSceneForRHISample();
  294. m_exampleEntity->Init();
  295. m_exampleEntity->Activate();
  296. m_isSampleSupported.resize(m_availableSamples.size());
  297. for (size_t i = 0; i < m_availableSamples.size(); ++i)
  298. {
  299. // Assume that the sample is supported if no m_isSupportedFunc is provided.
  300. m_isSampleSupported[i] = m_availableSamples[i].m_isSupportedFunc ? m_availableSamples[i].m_isSupportedFunc() : true;
  301. }
  302. AZ_Printf("SampleComponentManager", "Available Samples -------------------------\n");
  303. for (size_t i = 0; i < m_availableSamples.size(); ++i)
  304. {
  305. AZStd::string printStr = "\t[" + m_availableSamples[i].m_sampleName + "]";
  306. if (!m_isSampleSupported[i])
  307. {
  308. printStr += " Not Supported ";
  309. }
  310. if (i < 9)
  311. {
  312. printStr += AZStd::string::format("\tctrl+%lu", i + 1);
  313. }
  314. printStr += "\n";
  315. AZ_Printf("SampleComponentManager", printStr.data());
  316. }
  317. AZ_Printf("SampleComponentManager", "-------------------------------------------\n");
  318. AzFramework::InputChannelEventListener::BusConnect();
  319. TickBus::Handler::BusConnect();
  320. bool targetSampleFound = false;
  321. const AzFramework::CommandLine* commandLine = nullptr;
  322. AzFramework::ApplicationRequests::Bus::BroadcastResult(commandLine, &AzFramework::ApplicationRequests::GetCommandLine);
  323. if (commandLine->HasSwitch("sample"))
  324. {
  325. AZStd::string targetSampleName = commandLine->GetSwitchValue("sample", 0);
  326. AZStd::to_lower(targetSampleName.begin(), targetSampleName.end());
  327. for (int32_t i = 0; i < m_availableSamples.size(); ++i)
  328. {
  329. AZStd::string sampleName = m_availableSamples[i].m_sampleName;
  330. AZStd::to_lower(sampleName.begin(), sampleName.end());
  331. if (sampleName == targetSampleName)
  332. {
  333. if (m_isSampleSupported[i])
  334. {
  335. targetSampleFound = true;
  336. m_selectedSampleIndex = i;
  337. m_sampleChangeRequest = true;
  338. }
  339. break;
  340. }
  341. }
  342. AZ_Warning("SampleComponentManager", targetSampleFound, "Failed find target sample %s", targetSampleName.c_str());
  343. }
  344. // Set default screenshot folder to relative path 'Screenshots'
  345. AZStd::string screenshotFolder = "Screenshots";
  346. // Get folder from command line if it exists
  347. static const char* screenshotFolderFlagName = "screenshotFolder";
  348. if (commandLine->HasSwitch(screenshotFolderFlagName))
  349. {
  350. screenshotFolder = commandLine->GetSwitchValue(screenshotFolderFlagName, 0);
  351. AzFramework::StringFunc::Path::Normalize(screenshotFolder);
  352. }
  353. if (AzFramework::StringFunc::Path::IsRelative(screenshotFolder.c_str()))
  354. {
  355. const char* engineRoot = nullptr;
  356. AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
  357. AzFramework::StringFunc::Path::Join(engineRoot, screenshotFolder.c_str(), screenshotFolder, true, false);
  358. }
  359. m_imguiFrameCaptureSaver.SetDefaultFolder(screenshotFolder);
  360. m_imguiFrameCaptureSaver.SetDefaultFileName("screenshot");
  361. m_imguiFrameCaptureSaver.SetAvailableExtensions({"ppm", "dds"});
  362. m_imguiFrameCaptureSaver.Activate();
  363. SampleComponentManagerRequestBus::Handler::BusConnect();
  364. m_scriptManager->Activate();
  365. m_wasActivated = true;
  366. SampleComponentManagerNotificationBus::Broadcast(&SampleComponentManagerNotificationBus::Events::OnSampleManagerActivated);
  367. }
  368. void SampleComponentManager::Deactivate()
  369. {
  370. AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
  371. AZ::Render::ImGuiSystemNotificationBus::Handler::BusDisconnect();
  372. m_scriptManager->Deactivate();
  373. m_imguiFrameCaptureSaver.Deactivate();
  374. SampleComponentManagerRequestBus::Handler::BusDisconnect();
  375. AZ::TickBus::Handler::BusDisconnect();
  376. AzFramework::InputChannelEventListener::Disconnect();
  377. Render::ImGuiSystemRequestBus::Broadcast(&Render::ImGuiSystemRequests::PopActiveContext);
  378. m_imguiPassTree.Reset();
  379. m_imguiFrameGraphVisualizer.Reset();
  380. m_windowContext = nullptr;
  381. ReleaseRHIScene();
  382. ReleaseRPIScene();
  383. }
  384. void SampleComponentManager::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
  385. {
  386. m_simulateTime += deltaTime;
  387. m_deltaTime = deltaTime;
  388. m_imGuiFrameTimer.PushValue(deltaTime);
  389. bool screenshotRequest = false;
  390. if (m_ctrlModifierLDown || m_ctrlModifierRDown)
  391. {
  392. if (m_alphanumericQDown)
  393. {
  394. RequestExit();
  395. return;
  396. }
  397. if (m_alphanumericTDown && m_canCaptureRADTM)
  398. {
  399. #ifdef AZ_PROFILE_TELEMETRY
  400. Utils::ToggleRadTMCapture();
  401. m_canCaptureRADTM = false;
  402. #endif
  403. }
  404. else if (!m_alphanumericTDown)
  405. {
  406. m_canCaptureRADTM = true;
  407. }
  408. if (m_alphanumericPDown)
  409. {
  410. screenshotRequest = true;
  411. }
  412. for (size_t i = 0; i < m_availableSamples.size(); ++i)
  413. {
  414. if (m_alphanumericNumbersDown[i] && i < s_alphanumericCount && m_isSampleSupported[i])
  415. {
  416. m_sampleChangeRequest = true;
  417. m_selectedSampleIndex = static_cast<int32_t>(i);
  418. break;
  419. }
  420. }
  421. }
  422. // Request a frame capture only once per key press, even if the keys are held down for multiple ticks.
  423. if (screenshotRequest)
  424. {
  425. ++m_screenshotKeyDownCount;
  426. if (m_screenshotKeyDownCount == 1)
  427. {
  428. RequestFrameCapture(m_imguiFrameCaptureSaver.GetNextAutoSaveFilePath(), true);
  429. }
  430. }
  431. else
  432. {
  433. m_screenshotKeyDownCount = 0;
  434. }
  435. RenderImGui(deltaTime);
  436. // SampleChange needs to happen after RenderImGui as some of the samples create sidebars on a separate ImGui context
  437. // which can interfere with m_imguiContext in the first frame
  438. if (m_sampleChangeRequest && m_canSwitchSample)
  439. {
  440. SampleChange();
  441. m_canSwitchSample = false;
  442. }
  443. else if (m_escapeDown && m_canSwitchSample)
  444. {
  445. Reset();
  446. m_canSwitchSample = false;
  447. Utils::ReportScriptableAction("OpenSample('')");
  448. }
  449. // Once a SampleChange/Reset request has been handled, it will not be handled again until there has been at least one frame where the sample hasn't changed
  450. if (!m_sampleChangeRequest && !m_escapeDown)
  451. {
  452. m_canSwitchSample = true;
  453. }
  454. // Since the event has been handled, clear the request
  455. m_sampleChangeRequest = false;
  456. m_escapeDown = false;
  457. m_scriptManager->TickScript(deltaTime);
  458. if (m_isFrameCapturePending)
  459. {
  460. if (m_countdownForFrameCapture > 0)
  461. {
  462. m_countdownForFrameCapture--;
  463. }
  464. else if (m_countdownForFrameCapture == 0)
  465. {
  466. AZ::Render::FrameCaptureNotificationBus::Handler::BusConnect();
  467. AZ::Render::FrameCaptureRequestBus::Broadcast(&AZ::Render::FrameCaptureRequestBus::Events::CaptureScreenshot, m_frameCaptureFilePath);
  468. m_countdownForFrameCapture = -1; // Don't call CaptureScreenshot again
  469. }
  470. }
  471. }
  472. bool SampleComponentManager::OnInputChannelEventFiltered(const AzFramework::InputChannel& inputChannel)
  473. {
  474. const size_t samplesAvailableCount = m_availableSamples.size();
  475. AZStd::vector<AzFramework::InputChannelId> sampleInputMapping;
  476. sampleInputMapping.reserve(samplesAvailableCount);
  477. for (size_t i = 0; i < samplesAvailableCount; ++i)
  478. {
  479. switch (i)
  480. {
  481. case 0:
  482. sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric1);
  483. break;
  484. case 1:
  485. sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric2);
  486. break;
  487. case 2:
  488. sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric3);
  489. break;
  490. case 3:
  491. sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric4);
  492. break;
  493. case 4:
  494. sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric5);
  495. break;
  496. case 5:
  497. sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric6);
  498. break;
  499. case 6:
  500. sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric7);
  501. break;
  502. case 7:
  503. sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric8);
  504. break;
  505. case 8:
  506. sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric9);
  507. break;
  508. case 9:
  509. sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric0);
  510. break;
  511. default:
  512. break;
  513. }
  514. }
  515. const AzFramework::InputChannelId& inputChannelId = inputChannel.GetInputChannelId();
  516. switch (inputChannel.GetState())
  517. {
  518. case AzFramework::InputChannel::State::Began:
  519. case AzFramework::InputChannel::State::Updated:
  520. {
  521. if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::ModifierCtrlL)
  522. {
  523. m_ctrlModifierLDown = true;
  524. }
  525. else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::ModifierCtrlR)
  526. {
  527. m_ctrlModifierRDown = true;
  528. }
  529. else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericQ)
  530. {
  531. m_alphanumericQDown = true;
  532. }
  533. else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericT)
  534. {
  535. m_alphanumericTDown = true;
  536. }
  537. else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericP)
  538. {
  539. m_alphanumericPDown = true;
  540. }
  541. else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::Escape)
  542. {
  543. m_escapeDown = true;
  544. }
  545. for (size_t i = 0; i < samplesAvailableCount; ++i)
  546. {
  547. if ((i < s_alphanumericCount) && (inputChannelId == sampleInputMapping[i]))
  548. {
  549. m_alphanumericNumbersDown[i] = true;
  550. }
  551. }
  552. break;
  553. }
  554. case AzFramework::InputChannel::State::Ended:
  555. {
  556. if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::ModifierCtrlL)
  557. {
  558. m_ctrlModifierLDown = false;
  559. }
  560. else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::ModifierCtrlR)
  561. {
  562. m_ctrlModifierRDown = false;
  563. }
  564. else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericQ)
  565. {
  566. m_alphanumericQDown = false;
  567. }
  568. else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericT)
  569. {
  570. m_alphanumericTDown = false;
  571. }
  572. else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericP)
  573. {
  574. m_alphanumericPDown = false;
  575. }
  576. else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::Escape)
  577. {
  578. m_escapeDown = false;
  579. }
  580. for (size_t i = 0; i < samplesAvailableCount; ++i)
  581. {
  582. if ((i < s_alphanumericCount) && (inputChannelId == sampleInputMapping[i]))
  583. {
  584. m_alphanumericNumbersDown[i] = false;
  585. }
  586. }
  587. break;
  588. }
  589. default:
  590. {
  591. break;
  592. }
  593. }
  594. return false;
  595. }
  596. void SampleComponentManager::RenderImGui(float deltaTime)
  597. {
  598. if (!m_isImGuiAvailable)
  599. {
  600. return;
  601. }
  602. ShowMenuBar();
  603. if (m_exitRequested)
  604. {
  605. return;
  606. }
  607. if (m_showResizeViewportDialog)
  608. {
  609. ShowResizeViewportDialog();
  610. }
  611. if (m_showFramerateHistogram)
  612. {
  613. ShowFramerateHistogram(deltaTime);
  614. }
  615. if (m_showFrameCaptureDialog)
  616. {
  617. ShowFrameCaptureDialog();
  618. }
  619. if (m_showImGuiMetrics)
  620. {
  621. ImGui::ShowMetricsWindow(&m_showImGuiMetrics);
  622. }
  623. if (m_showSampleHelper)
  624. {
  625. ShowSampleHelper();
  626. }
  627. if (m_showAbout)
  628. {
  629. ShowAboutWindow();
  630. }
  631. if (m_showPassTree)
  632. {
  633. ShowPassTreeWindow();
  634. }
  635. if (m_showFrameGraphVisualizer)
  636. {
  637. ShowFrameGraphVisualizerWindow();
  638. }
  639. if (m_showCullingDebugWindow)
  640. {
  641. AZ::RPI::Scene* defaultScene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get();
  642. AZ::Render::ImGuiDrawCullingDebug(m_showCullingDebugWindow, defaultScene);
  643. }
  644. if (m_showCpuProfiler)
  645. {
  646. ShowCpuProfilerWindow();
  647. }
  648. if (m_showGpuProfiler)
  649. {
  650. ShowGpuProfilerWindow();
  651. }
  652. if (m_showTransientAttachmentProfiler)
  653. {
  654. ShowTransientAttachmentProfilerWindow();
  655. }
  656. if (m_showShaderMetrics)
  657. {
  658. ShowShaderMetricsWindow();
  659. }
  660. m_scriptManager->TickImGui();
  661. }
  662. void SampleComponentManager::ShowMenuBar()
  663. {
  664. if (ImGui::BeginMainMenuBar())
  665. {
  666. if (ImGui::BeginMenu("File"))
  667. {
  668. if (ImGui::MenuItem("Exit", "Ctrl-Q"))
  669. {
  670. RequestExit();
  671. return;
  672. }
  673. if (ImGui::MenuItem("Capture Frame...", "Ctrl-P"))
  674. {
  675. m_showFrameCaptureDialog = true;
  676. }
  677. ImGui::EndMenu();
  678. }
  679. if (ImGui::BeginMenu("View"))
  680. {
  681. if (Utils::SupportsResizeClientArea() && ImGui::MenuItem("Resize Viewport..."))
  682. {
  683. m_showResizeViewportDialog = true;
  684. }
  685. if (Utils::SupportsToggleFullScreenOfDefaultWindow() && ImGui::MenuItem("Toggle Full Screen"))
  686. {
  687. Utils::ToggleFullScreenOfDefaultWindow();
  688. }
  689. if (ImGui::MenuItem("Framerate Histogram"))
  690. {
  691. m_showFramerateHistogram = !m_showFramerateHistogram;
  692. }
  693. if (ImGui::MenuItem("ImGui Metrics"))
  694. {
  695. m_showImGuiMetrics = !m_showImGuiMetrics;
  696. }
  697. if (ImGui::MenuItem("Sample Helper"))
  698. {
  699. m_showSampleHelper = !m_showSampleHelper;
  700. }
  701. if (ImGui::MenuItem("Frame Graph Visualizer"))
  702. {
  703. m_showFrameGraphVisualizer = !m_showFrameGraphVisualizer;
  704. }
  705. if (ImGui::MenuItem("Shader Metrics"))
  706. {
  707. m_showShaderMetrics = !m_showShaderMetrics;
  708. }
  709. ImGui::EndMenu();
  710. }
  711. if (ImGui::BeginMenu("Samples"))
  712. {
  713. for (int32_t i = 0; i < m_availableSamples.size(); i++)
  714. {
  715. const char* sampleName = m_availableSamples[i].m_sampleName.c_str();
  716. bool enabled = m_isSampleSupported[i];
  717. if (i < s_alphanumericCount)
  718. {
  719. const AZStd::string hotkeyName = AZStd::string::format("Ctrl-%d: ", (i + 1) % 10);
  720. if (ImGui::MenuItem(sampleName, hotkeyName.c_str(), false, enabled))
  721. {
  722. m_selectedSampleIndex = i;
  723. m_sampleChangeRequest = true;
  724. }
  725. }
  726. else
  727. {
  728. if (ImGui::MenuItem(sampleName, nullptr, false, enabled))
  729. {
  730. m_selectedSampleIndex = i;
  731. m_sampleChangeRequest = true;
  732. }
  733. }
  734. }
  735. if (m_sampleChangeRequest)
  736. {
  737. Utils::ReportScriptableAction("OpenSample('%s')", m_availableSamples[m_selectedSampleIndex].m_sampleName.c_str());
  738. }
  739. ImGui::EndMenu();
  740. }
  741. #ifdef AZ_PROFILE_TELEMETRY
  742. if (ImGui::BeginMenu("RADTelemetry"))
  743. {
  744. if (ImGui::MenuItem("Toggle Capture", "Ctrl-T"))
  745. {
  746. Utils::ToggleRadTMCapture();
  747. }
  748. ImGui::EndMenu();
  749. }
  750. #endif // AZ_PROFILE_TELEMETRY
  751. if (ImGui::BeginMenu("Automation"))
  752. {
  753. if (ImGui::MenuItem("Run Script..."))
  754. {
  755. m_scriptManager->OpenScriptRunnerDialog();
  756. }
  757. ImGui::EndMenu();
  758. }
  759. if (ImGui::BeginMenu("Pass"))
  760. {
  761. if (ImGui::MenuItem(PassTreeToolName))
  762. {
  763. m_showPassTree = !m_showPassTree;
  764. Utils::ReportScriptableAction("ShowTool('%s', %s)", PassTreeToolName, m_showPassTree?"true":"false");
  765. }
  766. ImGui::EndMenu();
  767. }
  768. if (ImGui::BeginMenu("Culling"))
  769. {
  770. if (ImGui::MenuItem("Culling Debug Window"))
  771. {
  772. m_showCullingDebugWindow = !m_showCullingDebugWindow;
  773. }
  774. ImGui::EndMenu();
  775. }
  776. if (ImGui::BeginMenu("Profile"))
  777. {
  778. if (ImGui::MenuItem(CpuProfilerToolName))
  779. {
  780. m_showCpuProfiler = !m_showCpuProfiler;
  781. AZ::RHI::RHISystemInterface::Get()->ModifyFrameSchedulerStatisticsFlags(
  782. AZ::RHI::FrameSchedulerStatisticsFlags::GatherCpuTimingStatistics,
  783. m_showCpuProfiler);
  784. AZ::RHI::CpuProfiler::Get()->SetProfilerEnabled(m_showCpuProfiler);
  785. Utils::ReportScriptableAction("ShowTool('%s', %s)", CpuProfilerToolName, m_showCpuProfiler ? "true" : "false");
  786. }
  787. if (ImGui::MenuItem(GpuProfilerToolName))
  788. {
  789. m_showGpuProfiler = !m_showGpuProfiler;
  790. Utils::ReportScriptableAction("ShowTool('%s', %s)", GpuProfilerToolName, m_showGpuProfiler ? "true" : "false");
  791. }
  792. if (ImGui::MenuItem(TransientAttachmentProfilerToolName))
  793. {
  794. m_showTransientAttachmentProfiler = !m_showTransientAttachmentProfiler;
  795. AZ::RHI::RHISystemInterface::Get()->ModifyFrameSchedulerStatisticsFlags(
  796. AZ::RHI::FrameSchedulerStatisticsFlags::GatherTransientAttachmentStatistics,
  797. m_showTransientAttachmentProfiler);
  798. Utils::ReportScriptableAction("ShowTool('%s', %s)", TransientAttachmentProfilerToolName, m_showTransientAttachmentProfiler ? "true" : "false");
  799. }
  800. ImGui::EndMenu();
  801. }
  802. if (ImGui::BeginMenu("Help"))
  803. {
  804. if (ImGui::MenuItem("About"))
  805. {
  806. m_showAbout = !m_showAbout;
  807. }
  808. ImGui::EndMenu();
  809. }
  810. ImGui::EndMainMenuBar();
  811. }
  812. }
  813. void SampleComponentManager::ShowSampleHelper()
  814. {
  815. if (ImGui::Begin("Sample Helper", &m_showSampleHelper, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings))
  816. {
  817. if (ImGui::Button("Reset"))
  818. {
  819. //Removes the existing sample component and
  820. //resets the selection index
  821. Reset();
  822. CameraReset();
  823. m_selectedSampleIndex = -1;
  824. }
  825. ImGui::SameLine();
  826. if (ImGui::Button("Reset Sample"))
  827. {
  828. //Force a sample change event when the selection index
  829. //hasn't changed. This resets the sample component.
  830. SampleChange();
  831. }
  832. ImGui::SameLine();
  833. if (ImGui::Button("Reset Camera"))
  834. {
  835. CameraReset();
  836. }
  837. }
  838. ImGui::End();
  839. }
  840. void SampleComponentManager::ShowAboutWindow()
  841. {
  842. if (ImGui::Begin("About", &m_showAbout, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings))
  843. {
  844. ImGui::Text("RHI API: %s", AZ::RHI::Factory::Get().GetName().GetCStr());
  845. }
  846. ImGui::End();
  847. }
  848. void SampleComponentManager::ShowPassTreeWindow()
  849. {
  850. m_imguiPassTree.Draw(m_showPassTree, AZ::RPI::PassSystemInterface::Get()->GetRootPass().get());
  851. }
  852. void SampleComponentManager::ShowFrameGraphVisualizerWindow()
  853. {
  854. AZ::RHI::Device* rhiDevice = Utils::GetRHIDevice().get();
  855. m_imguiFrameGraphVisualizer.Init(rhiDevice);
  856. m_imguiFrameGraphVisualizer.Draw(m_showFrameGraphVisualizer);
  857. }
  858. void SampleComponentManager::ShowCpuProfilerWindow()
  859. {
  860. const AZ::RHI::CpuTimingStatistics* stats = AZ::RHI::RHISystemInterface::Get()->GetCpuTimingStatistics();
  861. if (stats)
  862. {
  863. m_imguiCpuProfiler.Draw(m_showCpuProfiler, *stats);
  864. }
  865. }
  866. void SampleComponentManager::ShowGpuProfilerWindow()
  867. {
  868. m_imguiGpuProfiler.Draw(m_showGpuProfiler, AZ::RPI::PassSystemInterface::Get()->GetRootPass());
  869. }
  870. void SampleComponentManager::ShowTransientAttachmentProfilerWindow()
  871. {
  872. auto* transientStats = AZ::RHI::RHISystemInterface::Get()->GetTransientAttachmentStatistics();
  873. if (transientStats)
  874. {
  875. m_showTransientAttachmentProfiler = m_imguiTransientAttachmentProfiler.Draw(*transientStats);
  876. }
  877. }
  878. void SampleComponentManager::ShowShaderMetricsWindow()
  879. {
  880. m_imguiShaderMetrics.Draw(m_showShaderMetrics, AZ::RPI::ShaderMetricsSystemInterface::Get()->GetMetrics());
  881. }
  882. void SampleComponentManager::ShowResizeViewportDialog()
  883. {
  884. static int size[2] = { 0, 0 };
  885. if (size[0] <= 0)
  886. {
  887. size[0] = aznumeric_cast<int>(m_windowContext->GetViewport().m_maxX - m_windowContext->GetViewport().m_minX);
  888. }
  889. if (size[1] <= 0)
  890. {
  891. size[1] = aznumeric_cast<int>(m_windowContext->GetViewport().m_maxY - m_windowContext->GetViewport().m_minY);
  892. }
  893. bool dialogWasOpen = m_showResizeViewportDialog;
  894. if (ImGui::Begin("Resize Viewport", &m_showResizeViewportDialog, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings))
  895. {
  896. ImGui::InputInt2("Size", size);
  897. if (ImGui::Button("Resize"))
  898. {
  899. Utils::ResizeClientArea(size[0], size[1]);
  900. Utils::ReportScriptableAction("ResizeViewport(%d, %d)", size[0], size[1]);
  901. // Re-initialize the size fields on the next frame so we can see whether the
  902. // correct size was achieved (should be the same values the user entered)...
  903. size[0] = 0;
  904. size[1] = 0;
  905. }
  906. }
  907. ImGui::End();
  908. if (dialogWasOpen && !m_showResizeViewportDialog)
  909. {
  910. // Re-initialize the size fields next time the dialog is shown...
  911. size[0] = 0;
  912. size[1] = 0;
  913. }
  914. }
  915. void SampleComponentManager::ShowFramerateHistogram(float deltaTime)
  916. {
  917. if (ImGui::Begin("Framerate Histogram", &m_showFramerateHistogram, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings))
  918. {
  919. ImGuiHistogramQueue::WidgetSettings settings;
  920. settings.m_reportInverse = true;
  921. settings.m_units = "fps";
  922. m_imGuiFrameTimer.Tick(deltaTime, settings);
  923. }
  924. ImGui::End();
  925. }
  926. void SampleComponentManager::RequestFrameCapture(const AZStd::string& filePath, bool hideImGui)
  927. {
  928. AZ_Assert(false == m_isFrameCapturePending, "Frame capture already in progress");
  929. m_isFrameCapturePending = true;
  930. m_hideImGuiDuringFrameCapture = hideImGui;
  931. m_frameCaptureFilePath = filePath;
  932. // Don't continue the script while a frame capture is pending in case subsequent changes
  933. // interfere with the pending capture.
  934. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::PauseScript);
  935. if (m_hideImGuiDuringFrameCapture)
  936. {
  937. AZ::Render::ImGuiSystemRequestBus::Broadcast(&AZ::Render::ImGuiSystemRequestBus::Events::HideAllImGuiPasses);
  938. // We also hide lumberyard's debug text
  939. AzFramework::ConsoleRequestBus::Broadcast(&AzFramework::ConsoleRequests::ExecuteConsoleCommand, "r_DisplayInfo 0");
  940. // The ExecuteConsoleCommand request is handled in a deferred manner, so we have to delay the screenshot a bit.
  941. m_countdownForFrameCapture = 1;
  942. }
  943. else
  944. {
  945. m_countdownForFrameCapture = 0;
  946. }
  947. }
  948. void SampleComponentManager::OnCaptureFinished(AZ::Render::FrameCaptureResult /*result*/, const AZStd::string& /*info*/)
  949. {
  950. AZ::Render::FrameCaptureNotificationBus::Handler::BusDisconnect();
  951. if (m_hideImGuiDuringFrameCapture)
  952. {
  953. AZ::Render::ImGuiSystemRequestBus::Broadcast(&AZ::Render::ImGuiSystemRequestBus::Events::ShowAllImGuiPasses);
  954. // We also show lumberyard's debug text
  955. AzFramework::ConsoleRequestBus::Broadcast(&AzFramework::ConsoleRequests::ExecuteConsoleCommand, "r_DisplayInfo 1");
  956. }
  957. ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::ResumeScript);
  958. m_isFrameCapturePending = false;
  959. }
  960. bool SampleComponentManager::IsFrameCapturePending()
  961. {
  962. return m_isFrameCapturePending;
  963. }
  964. void SampleComponentManager::RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd)
  965. {
  966. if (m_scriptManager)
  967. {
  968. m_scriptManager->RunMainTestSuite(suiteFilePath, exitOnTestEnd);
  969. }
  970. }
  971. void SampleComponentManager::ShowFrameCaptureDialog()
  972. {
  973. static bool requestCaptureOnNextFrame = false;
  974. static bool hideImGuiFromFrameCapture = true;
  975. if (requestCaptureOnNextFrame)
  976. {
  977. requestCaptureOnNextFrame = false;
  978. RequestFrameCapture(m_imguiFrameCaptureSaver.GetSaveFilePath(), hideImGuiFromFrameCapture);
  979. }
  980. else if (!m_isFrameCapturePending) // Hide this dialog while taking a capture
  981. {
  982. if (ImGui::Begin("Frame Capture", &m_showFrameCaptureDialog))
  983. {
  984. ImGui::Checkbox("Hide ImGui", &hideImGuiFromFrameCapture);
  985. ImGuiSaveFilePath::WidgetSettings settings;
  986. settings.m_labels.m_filePath = "File Path (.ppm or .dds):";
  987. m_imguiFrameCaptureSaver.Tick(settings);
  988. if (ImGui::Button("Capture"))
  989. {
  990. // Don't actually do the capture until the next frame, so we can hide this dialog first
  991. requestCaptureOnNextFrame = true;
  992. if (hideImGuiFromFrameCapture)
  993. {
  994. Utils::ReportScriptableAction("CaptureScreenshot('%s')", m_imguiFrameCaptureSaver.GetSaveFilePath().c_str());
  995. }
  996. else
  997. {
  998. Utils::ReportScriptableAction("CaptureScreenshotWithImGui('%s')", m_imguiFrameCaptureSaver.GetSaveFilePath().c_str());
  999. }
  1000. }
  1001. }
  1002. ImGui::End();
  1003. }
  1004. }
  1005. void SampleComponentManager::RequestExit()
  1006. {
  1007. AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
  1008. AZ::TickBus::Handler::BusDisconnect();
  1009. AzFramework::InputChannelEventListener::Disconnect();
  1010. m_exitRequested = true;
  1011. }
  1012. void SampleComponentManager::ShutdownActiveSample()
  1013. {
  1014. m_exampleEntity->Deactivate();
  1015. // Pointer to the m_activeSample must be nullified before m_activeSample is destroyed.
  1016. if (m_rhiSamplePass)
  1017. {
  1018. m_rhiSamplePass->SetRHISample(nullptr);
  1019. }
  1020. if (m_activeSample != nullptr)
  1021. {
  1022. // Disable the camera controller just in case the active sample enabled it and didn't disable in Deactivate().
  1023. AZ::Debug::CameraControllerRequestBus::Event(m_cameraEntity->GetId(), &AZ::Debug::CameraControllerRequestBus::Events::Disable);
  1024. m_exampleEntity->RemoveComponent(m_activeSample);
  1025. delete m_activeSample;
  1026. }
  1027. m_activeSample = nullptr;
  1028. // Force a reset of the shader variant finder to get more consistent testing of samples every time they are run, rather
  1029. // than the first time for each sample being "special".
  1030. auto variantFinder = AZ::Interface<AZ::RPI::IShaderVariantFinder>::Get();
  1031. variantFinder->Reset();
  1032. }
  1033. void SampleComponentManager::Reset()
  1034. {
  1035. ShutdownActiveSample();
  1036. m_exampleEntity->Activate();
  1037. // Reset to RHI sample pipeline
  1038. SwitchSceneForRHISample();
  1039. m_rhiSamplePass->SetRHISample(nullptr);
  1040. }
  1041. void SampleComponentManager::CreateDefaultCamera()
  1042. {
  1043. if (m_cameraEntity)
  1044. {
  1045. return;
  1046. }
  1047. // A camera entity will be created by the entity context request bus so that the component for this entity can use a feature processor.
  1048. AzFramework::EntityContextRequestBus::EventResult(m_cameraEntity, m_entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "CameraEntity");
  1049. //Add debug camera and controller components
  1050. AZ::Debug::CameraComponentConfig cameraConfig(m_windowContext);
  1051. cameraConfig.m_fovY = AZ::Constants::QuarterPi;
  1052. m_cameraEntity->CreateComponent(azrtti_typeid<AZ::Debug::CameraComponent>())
  1053. ->SetConfiguration(cameraConfig);
  1054. m_cameraEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
  1055. m_cameraEntity->CreateComponent(azrtti_typeid<AZ::Debug::ArcBallControllerComponent>());
  1056. m_cameraEntity->CreateComponent(azrtti_typeid<AZ::Debug::NoClipControllerComponent>());
  1057. m_cameraEntity->Activate();
  1058. m_scriptManager->SetCameraEntity(m_cameraEntity);
  1059. }
  1060. void SampleComponentManager::SetupImGuiContext()
  1061. {
  1062. AdjustImGuiFontScale();
  1063. // Add imgui context
  1064. Render::ImGuiSystemRequestBus::BroadcastResult(m_isImGuiAvailable, &Render::ImGuiSystemRequests::PushActiveContextFromDefaultPass);
  1065. AZ_Assert(m_isImGuiAvailable, "Unable set default imgui context to active. Does your pipeline have an ImGui pass marked as default? Your pass assets may need to be rebuilt.");
  1066. }
  1067. void SampleComponentManager::ActiveImGuiContextChanged(ImGuiContext* context)
  1068. {
  1069. ImGui::SetCurrentContext(context);
  1070. }
  1071. bool SampleComponentManager::OpenSample(const AZStd::string& sampleName)
  1072. {
  1073. for (int32_t i = 0; i < m_availableSamples.size(); i++)
  1074. {
  1075. if (m_availableSamples[i].m_sampleName == sampleName)
  1076. {
  1077. if (!m_availableSamples[i].m_isSupportedFunc || m_availableSamples[i].m_isSupportedFunc())
  1078. {
  1079. m_selectedSampleIndex = i;
  1080. m_sampleChangeRequest = true;
  1081. return true;
  1082. }
  1083. else
  1084. {
  1085. AZ_Error("SampleComponentManager", false, "Sample '%s' is not supported on this platform.", sampleName.c_str());
  1086. }
  1087. }
  1088. }
  1089. return false;
  1090. }
  1091. bool SampleComponentManager::ShowTool(const AZStd::string& toolName, bool enable)
  1092. {
  1093. if (toolName == PassTreeToolName)
  1094. {
  1095. m_showPassTree = enable;
  1096. return true;
  1097. }
  1098. else if (toolName == CpuProfilerToolName)
  1099. {
  1100. m_showCpuProfiler = enable;
  1101. return true;
  1102. }
  1103. else if (toolName == GpuProfilerToolName)
  1104. {
  1105. m_showGpuProfiler = enable;
  1106. return true;
  1107. }
  1108. else if (toolName == TransientAttachmentProfilerToolName)
  1109. {
  1110. m_showTransientAttachmentProfiler = enable;
  1111. return true;
  1112. }
  1113. return false;
  1114. }
  1115. void SampleComponentManager::SampleChange()
  1116. {
  1117. if (m_selectedSampleIndex == -1)
  1118. {
  1119. return;
  1120. }
  1121. ShutdownActiveSample();
  1122. // Reset the camera *before* activating the sample, because the sample's Activate() function might
  1123. // want to reposition the camera.
  1124. CameraReset();
  1125. const SampleEntry& sampleEntry = m_availableSamples[m_selectedSampleIndex];
  1126. SampleComponentConfig config(m_windowContext, m_cameraEntity->GetId(), m_entityContextId);
  1127. m_activeSample = m_exampleEntity->CreateComponent(sampleEntry.m_sampleUuid);
  1128. m_activeSample->SetConfiguration(config);
  1129. if (sampleEntry.m_pipelineType == SamplePipelineType::RHI)
  1130. {
  1131. SwitchSceneForRHISample();
  1132. BasicRHIComponent* rhiSampleComponent = static_cast<BasicRHIComponent*>(m_activeSample);
  1133. if (rhiSampleComponent->IsSupportedRHISamplePipeline())
  1134. {
  1135. m_rhiSamplePass->SetRHISample(rhiSampleComponent);
  1136. }
  1137. else
  1138. {
  1139. m_rhiSamplePass->SetRHISample(nullptr);
  1140. }
  1141. }
  1142. else if (sampleEntry.m_pipelineType == SamplePipelineType::RPI)
  1143. {
  1144. SwitchSceneForRPISample();
  1145. }
  1146. m_exampleEntity->Activate();
  1147. // Even though this is done in CameraReset(), the example component wasn't activated at the time so we have to send this event again.
  1148. ExampleComponentRequestBus::Event(m_exampleEntity->GetId(), &ExampleComponentRequestBus::Events::ResetCamera);
  1149. }
  1150. void SampleComponentManager::CameraReset()
  1151. {
  1152. // Reset the camera transform. Some examples do not use a controller or use a controller that doesn't override the whole transform.
  1153. // Set to a transform that is 5 units away from the origin and looking at the origin along the Y axis.
  1154. const AZ::EntityId cameraEntityId = m_cameraEntity->GetId();
  1155. AZ::TransformBus::Event(cameraEntityId, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, -5.0f, 0.0f)));
  1156. AZ::Debug::CameraControllerRequestBus::Event(cameraEntityId, &AZ::Debug::CameraControllerRequestBus::Events::Reset);
  1157. // Tell the current example to reset the camera, any example that controls the camera and preserves controller state should implement this event
  1158. ExampleComponentRequestBus::Event(m_exampleEntity->GetId(), &ExampleComponentRequestBus::Events::ResetCamera);
  1159. }
  1160. void SampleComponentManager::CreateSceneForRHISample()
  1161. {
  1162. // Create and register the rhi scene with only feature processors required for AtomShimRenderer (only for AtomSampleViewerLauncher)
  1163. RPI::SceneDescriptor sceneDesc;
  1164. sceneDesc.m_featureProcessorNames.push_back("AuxGeomFeatureProcessor");
  1165. m_rhiScene = RPI::Scene::CreateScene(sceneDesc);
  1166. m_rhiScene->Activate();
  1167. RPI::RenderPipelineDescriptor pipelineDesc;
  1168. pipelineDesc.m_name = "RHISamplePipeline";
  1169. pipelineDesc.m_rootPassTemplate = "RHISamplePipelineTemplate";
  1170. // Add view to pipeline since there are few RHI samples are using ViewSrg
  1171. pipelineDesc.m_mainViewTagName = "MainCamera";
  1172. RPI::RenderPipelinePtr renderPipeline = RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineDesc, *m_windowContext.get());
  1173. m_rhiScene->AddRenderPipeline(renderPipeline);
  1174. renderPipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId());
  1175. RPI::RPISystemInterface::Get()->RegisterScene(m_rhiScene);
  1176. // Get RHISamplePass
  1177. m_rhiSamplePass = azrtti_cast<RHISamplePass*>(renderPipeline->GetRootPass()->FindPassByNameRecursive(AZ::Name("RHISamplePass")).get());
  1178. // Setup imGui since a new render pipeline with imgui pass was created
  1179. SetupImGuiContext();
  1180. }
  1181. void SampleComponentManager::ReleaseRHIScene()
  1182. {
  1183. if (m_rhiScene)
  1184. {
  1185. m_rhiSamplePass = nullptr;
  1186. RPI::RPISystemInterface::Get()->UnregisterScene(m_rhiScene);
  1187. m_rhiScene = nullptr;
  1188. }
  1189. }
  1190. void SampleComponentManager::SwitchSceneForRHISample()
  1191. {
  1192. ReleaseRPIScene();
  1193. if (!m_rhiScene)
  1194. {
  1195. CreateSceneForRHISample();
  1196. }
  1197. }
  1198. void SampleComponentManager::CreateSceneForRPISample()
  1199. {
  1200. // Create and register a scene with all available feature processors
  1201. RPI::SceneDescriptor sceneDesc;
  1202. m_rpiScene = RPI::Scene::CreateScene(sceneDesc);
  1203. m_rpiScene->EnableAllFeatureProcessors();
  1204. // Setup scene srg modification callback.
  1205. RPI::ShaderResourceGroupCallback callback = [this](RPI::ShaderResourceGroup* srg)
  1206. {
  1207. if (srg == nullptr)
  1208. {
  1209. return;
  1210. }
  1211. bool needCompile = false;
  1212. RHI::ShaderInputConstantIndex timeIndex = srg->FindShaderInputConstantIndex(Name{ "m_time" });
  1213. if (timeIndex.IsValid())
  1214. {
  1215. srg->SetConstant(timeIndex, m_simulateTime);
  1216. needCompile = true;
  1217. }
  1218. RHI::ShaderInputConstantIndex deltaTimeIndex = srg->FindShaderInputConstantIndex(Name{ "m_deltaTime" });
  1219. if (deltaTimeIndex.IsValid())
  1220. {
  1221. srg->SetConstant(deltaTimeIndex, m_deltaTime);
  1222. needCompile = true;
  1223. }
  1224. if (needCompile)
  1225. {
  1226. srg->Compile();
  1227. }
  1228. };
  1229. m_rpiScene->SetShaderResourceGroupCallback(callback);
  1230. // Bind m_rpiScene to the GameEntityContext's AzFramework::Scene so the RPI Scene can be found by the entity context
  1231. AZStd::vector<AzFramework::Scene*> scenes;
  1232. AzFramework::SceneSystemRequestBus::BroadcastResult(scenes, &AzFramework::SceneSystemRequests::GetAllScenes);
  1233. AZ_Assert(scenes.size() > 0, "Error: Scenes missing during system component initialization"); // This should never happen unless scene creation has changed.
  1234. // Add RPI::Scene as a sub system for the default AzFramework Scene
  1235. const uint32_t DefaultAzSceneIndex = 0;
  1236. scenes[DefaultAzSceneIndex]->SetSubsystem(m_rpiScene.get());
  1237. m_rpiScene->Activate();
  1238. // Register scene to RPI system so it will be processed/rendered per tick
  1239. RPI::RPISystemInterface::Get()->RegisterScene(m_rpiScene);
  1240. // Create MainPipeline as its render pipeline
  1241. RPI::RenderPipelineDescriptor pipelineDesc;
  1242. pipelineDesc.m_name = "RPISamplePipeline";
  1243. pipelineDesc.m_rootPassTemplate = GetRootPassTemplateName();
  1244. pipelineDesc.m_mainViewTagName = "MainCamera";
  1245. pipelineDesc.m_renderSettings.m_multisampleState.m_samples = 4;
  1246. RPI::RenderPipelinePtr renderPipeline = RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineDesc, *m_windowContext.get());
  1247. m_rpiScene->AddRenderPipeline(renderPipeline);
  1248. renderPipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId());
  1249. // As part of our initialization we need to create the BRDF texture generation pipeline
  1250. AZ::RPI::RenderPipelineDescriptor brdfPipelineDesc;
  1251. brdfPipelineDesc.m_mainViewTagName = "MainCamera";
  1252. brdfPipelineDesc.m_name = "BRDFTexturePipeline";
  1253. brdfPipelineDesc.m_rootPassTemplate = "BRDFTexturePipeline";
  1254. brdfPipelineDesc.m_executeOnce = true;
  1255. RPI::RenderPipelinePtr brdfTexturePipeline = AZ::RPI::RenderPipeline::CreateRenderPipeline(brdfPipelineDesc);
  1256. m_rpiScene->AddRenderPipeline(brdfTexturePipeline);
  1257. // Setup imGui since a new render pipeline with imgui pass was created
  1258. SetupImGuiContext();
  1259. }
  1260. void SampleComponentManager::ReleaseRPIScene()
  1261. {
  1262. if (m_rpiScene)
  1263. {
  1264. RPI::RPISystemInterface::Get()->UnregisterScene(m_rpiScene);
  1265. AZStd::vector<AzFramework::Scene*> scenes;
  1266. AzFramework::SceneSystemRequestBus::BroadcastResult(scenes, &AzFramework::SceneSystemRequests::GetAllScenes);
  1267. scenes[0]->UnsetSubsystem<RPI::Scene>();
  1268. m_rpiScene = nullptr;
  1269. }
  1270. }
  1271. void SampleComponentManager::SwitchSceneForRPISample()
  1272. {
  1273. ReleaseRHIScene();
  1274. if (!m_rpiScene)
  1275. {
  1276. CreateSceneForRPISample();
  1277. }
  1278. }
  1279. // AzFramework::AssetCatalogEventBus::Handler overrides ...
  1280. void SampleComponentManager::OnCatalogLoaded([[maybe_unused]] const char* catalogFile)
  1281. {
  1282. AZ::TickBus::QueueFunction([&]()
  1283. {
  1284. ActivateInternal();
  1285. });
  1286. }
  1287. } // namespace AtomSampleViewer