1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876 |
- /*
- * 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 <SampleComponentManager.h>
- #include <SampleComponentConfig.h>
- #include <Atom/Component/DebugCamera/CameraComponent.h>
- #include <Atom/Component/DebugCamera/NoClipControllerComponent.h>
- #include <Atom/Component/DebugCamera/ArcBallControllerComponent.h>
- #include <Atom/Feature/AuxGeom/AuxGeomFeatureProcessor.h>
- #include <Atom/Feature/ImGui/ImGuiUtils.h>
- #include <Atom/Feature/ImGui/SystemBus.h>
- #include <Atom/Feature/Mesh/MeshFeatureProcessor.h>
- #include <Atom/Feature/PostProcessing/PostProcessingConstants.h>
- #include <Atom/Feature/SkinnedMesh/SkinnedMeshInputBuffers.h>
- #include <Atom/RPI.Public/Pass/Pass.h>
- #include <Atom/RPI.Public/Pass/ParentPass.h>
- #include <Atom/RPI.Public/Pass/PassSystemInterface.h>
- #include <Atom/RPI.Public/Pass/RenderPass.h>
- #include <Atom/RPI.Public/Pass/Specific/SwapChainPass.h>
- #include <Atom/RPI.Public/RenderPipeline.h>
- #include <Atom/RPI.Public/RPISystemInterface.h>
- #include <Atom/RPI.Public/Scene.h>
- #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
- #include <Atom/RPI.Reflect/Image/AttachmentImageAsset.h>
- #include <Atom/RPI.Reflect/Image/AttachmentImageAssetCreator.h>
- #include <Atom/RPI.Reflect/Shader/IShaderVariantFinder.h>
- #include <Atom/RHI/Factory.h>
- #include <Atom/RHI/RHISystemInterface.h>
- #include <Atom/RHI/RHIMemoryStatisticsInterface.h>
- #include <Atom/RHI/RHIUtils.h>
- #include <Atom/RHI.Reflect/AliasedHeapEnums.h>
- #include <Automation/ScriptManager.h>
- #include <RHI/AlphaToCoverageExampleComponent.h>
- #include <RHI/AsyncComputeExampleComponent.h>
- #include <RHI/BasicRHIComponent.h>
- #include <RHI/ComputeExampleComponent.h>
- #include <RHI/CopyQueueComponent.h>
- #include <RHI/DualSourceBlendingComponent.h>
- #include <RHI/IndirectRenderingExampleComponent.h>
- #include <RHI/InputAssemblyExampleComponent.h>
- #include <RHI/SubpassExampleComponent.h>
- #include <RHI/MRTExampleComponent.h>
- #include <RHI/MSAAExampleComponent.h>
- #include <RHI/MultiThreadComponent.h>
- #include <RHI/MultiViewportSwapchainComponent.h>
- #include <RHI/MultipleViewsComponent.h>
- #include <RHI/QueryExampleComponent.h>
- #include <RHI/StencilExampleComponent.h>
- #include <RHI/SwapchainExampleComponent.h>
- #include <RHI/SphericalHarmonicsExampleComponent.h>
- #include <RHI/Texture3dExampleComponent.h>
- #include <RHI/TextureArrayExampleComponent.h>
- #include <RHI/TextureExampleComponent.h>
- #include <RHI/TextureMapExampleComponent.h>
- #include <RHI/TriangleExampleComponent.h>
- #include <RHI/XRExampleComponent.h>
- #include <RHI/TrianglesConstantBufferExampleComponent.h>
- #include <RHI/BindlessPrototypeExampleComponent.h>
- #include <RHI/RayTracingExampleComponent.h>
- #include <RHI/MatrixAlignmentTestExampleComponent.h>
- #include <RHI/VariableRateShadingExampleComponent.h>
- #include <Performance/100KDrawable_SingleView_ExampleComponent.h>
- #include <Performance/100KDraw_10KDrawable_MultiView_ExampleComponent.h>
- #include <AreaLightExampleComponent.h>
- #include <AssetLoadTestComponent.h>
- #include <AuxGeomExampleComponent.h>
- #include <BakedShaderVariantExampleComponent.h>
- #include <SponzaBenchmarkComponent.h>
- #include <BloomExampleComponent.h>
- #include <CheckerboardExampleComponent.h>
- #include <CullingAndLodExampleComponent.h>
- #include <DecalExampleComponent.h>
- #include <DepthOfFieldExampleComponent.h>
- #include <DynamicDrawExampleComponent.h>
- #include <DynamicMaterialTestComponent.h>
- #include <ExposureExampleComponent.h>
- #include <EyeMaterialExampleComponent.h>
- #include <SceneReloadSoakTestComponent.h>
- #include <LightCullingExampleComponent.h>
- #include <MeshExampleComponent.h>
- #include <MSAA_RPI_ExampleComponent.h>
- #include <MultiRenderPipelineExampleComponent.h>
- #include <MultiSceneExampleComponent.h>
- #include <ParallaxMappingExampleComponent.h>
- #include <RayTracingIntersectionShaderExampleComponent.h>
- #include <RenderTargetTextureExampleComponent.h>
- #include <SceneReloadSoakTestComponent.h>
- #include <ShadowExampleComponent.h>
- #include <ShadowedSponzaExampleComponent.h>
- #include <SkinnedMeshExampleComponent.h>
- #include <SsaoExampleComponent.h>
- #include <StreamingImageExampleComponent.h>
- #include <RootConstantsExampleComponent.h>
- #include <MultiViewSingleSceneAuxGeomExampleComponent.h>
- #include <TonemappingExampleComponent.h>
- #include <TransparencyExampleComponent.h>
- #include <DiffuseGIExampleComponent.h>
- #include <SSRExampleComponent.h>
- #include <XRRPIExampleComponent.h>
- #include <ShaderReloadTestComponent.h>
- #include <ReadbackExampleComponent.h>
- #include <Atom/Bootstrap/DefaultWindowBus.h>
- #include <AzCore/Component/Entity.h>
- #include <AzCore/Debug/Profiler.h>
- #include <AzCore/Debug/ProfilerBus.h>
- #include <AzCore/IO/IStreamerProfiler.h>
- #include <AzCore/Serialization/SerializeContext.h>
- #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
- #include <AzCore/std/smart_ptr/make_shared.h>
- #include <AzCore/std/algorithm.h>
- #include <AzFramework/API/ApplicationAPI.h>
- #include <AzFramework/Components/ConsoleBus.h>
- #include <AzFramework/Components/TransformComponent.h>
- #include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
- #include <AzFramework/Entity/GameEntityContextBus.h>
- #include <AzFramework/Scene/Scene.h>
- #include <AzFramework/Scene/SceneSystemInterface.h>
- #include <Passes/RayTracingAmbientOcclusionPass.h>
- #include <Utils/Utils.h>
- #include <Profiler/ProfilerImGuiBus.h>
- #include "ExampleComponentBus.h"
- #include <EntityUtilityFunctions.h>
- namespace Platform
- {
- const char* GetPipelineName();
- }
- namespace AtomSampleViewer
- {
- namespace
- {
- constexpr const char* PassTreeToolName = "PassTree";
- constexpr const char* CpuProfilerToolName = "CPU Profiler";
- constexpr const char* GpuProfilerToolName = "GPU Profiler";
- constexpr const char* FileIoProfilerToolName = "File IO Profiler";
- constexpr const char* TransientAttachmentProfilerToolName = "Transient Attachment Profiler";
- constexpr const char* SampleSetting = "/O3DE/AtomSampleViewer/Sample";
- }
- bool IsValidNumMSAASamples(int16_t numSamples)
- {
- return (numSamples == 1) || (numSamples == 2) || (numSamples == 4) || (numSamples == 8);
- }
- template <typename T>
- static SampleEntry NewRHISample(const AZStd::string& name)
- {
- return NewSample<T>(SamplePipelineType::RHI, "RHI", name);
- }
- template <typename T>
- static SampleEntry NewRHISample(const AZStd::string& name, AZStd::function<bool()> isSupportedFunction)
- {
- SampleEntry entry = NewSample<T>(SamplePipelineType::RHI, "RHI", name, isSupportedFunction);
- entry.m_isSupportedFunc = isSupportedFunction;
- return entry;
- }
- template <typename T>
- static SampleEntry NewRPISample(const AZStd::string& name)
- {
- return NewSample<T>(SamplePipelineType::RPI, "RPI", name);
- }
- template <typename T>
- static SampleEntry NewRPISample(const AZStd::string& name, AZStd::function<bool()> isSupportedFunction)
- {
- return NewSample<T>(SamplePipelineType::RPI, "RPI", name, isSupportedFunction);
- }
- template <typename T>
- static SampleEntry NewFeaturesSample(const AZStd::string& name)
- {
- return NewSample<T>(SamplePipelineType::RPI, "Features", name);
- }
- template <typename T>
- static SampleEntry NewFeaturesSample(const AZStd::string& name, AZStd::function<bool()> isSupportedFunction)
- {
- return NewSample<T>(SamplePipelineType::RPI, "Features", name, isSupportedFunction);
- }
- template <typename T>
- static SampleEntry NewPerfSample(const AZStd::string& name)
- {
- return NewSample<T>(SamplePipelineType::RPI, "Performance", name);
- }
- template <typename T>
- static SampleEntry NewPerfSample(const AZStd::string& name, AZStd::function<bool()> isSupportedFunction)
- {
- return NewSample<T>(SamplePipelineType::RPI, "Performance", name, isSupportedFunction);
- }
- static AZStd::string GetTargetSampleName()
- {
- //Check command line option
- const AzFramework::CommandLine* commandLine = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(commandLine, &AzFramework::ApplicationRequests::GetCommandLine);
- if (commandLine->HasSwitch("sample"))
- {
- AZStd::string targetSampleName = commandLine->GetSwitchValue("sample", 0);
- return targetSampleName;
- }
- //Check settings registry
- if (AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get())
- {
- if (AZStd::string targetSampleName;
- settingsRegistry->Get(targetSampleName, SampleSetting))
- {
- return targetSampleName;
- }
- }
- return {};
- }
- void SampleComponentManager::Reflect(AZ::ReflectContext* context)
- {
- if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
- {
- serializeContext->Class<SampleComponentManager, AZ::Component>()
- ->Version(0)
- ;
- // This registration matches ShaderOptionValuesSourceData, which is needed by ImGuiShaderUtils, to support
- // generating JSON for shader variants.
- serializeContext->RegisterGenericType<AZStd::unordered_map<Name, Name>>();
- }
- }
- void SampleComponentManager::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
- {
- required.push_back(AZ_CRC("PrototypeLmbrCentralService", 0xe35e6de0));
- }
- void SampleComponentManager::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
- {
- provided.push_back(AZ_CRC_CE("SampleComponentManagerService"));
- }
- void SampleComponentManager::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
- {
- dependent.push_back(AZ_CRC("AzFrameworkConfigurationSystemComponentService", 0xcc49c96e)); // Ensures a scene is created for the GameEntityContext
- }
- AZStd::vector<SampleEntry> SampleComponentManager::GetSamples()
- {
- return {
- NewRHISample<AlphaToCoverageExampleComponent>("AlphaToCoverage"),
- NewRHISample<AsyncComputeExampleComponent>("AsyncCompute"),
- NewRHISample<BindlessPrototypeExampleComponent>("BindlessPrototype"),
- NewRHISample<ComputeExampleComponent>("Compute"),
- NewRHISample<CopyQueueComponent>("CopyQueue"),
- NewRHISample<DualSourceBlendingComponent>("DualSourceBlending", []() {return Utils::GetRHIDevice()->GetFeatures().m_dualSourceBlending; }),
- NewRHISample<IndirectRenderingExampleComponent>("IndirectRendering", []() {return Utils::GetRHIDevice()->GetFeatures().m_indirectCommandTier > RHI::IndirectCommandTiers::Tier0; }),
- NewRHISample<InputAssemblyExampleComponent>("InputAssembly"),
- NewRHISample<MSAAExampleComponent>("MSAA"),
- NewRHISample<MultipleViewsComponent>("MultipleViews"),
- NewRHISample<MRTExampleComponent>("MultiRenderTarget"),
- NewRHISample<MultiThreadComponent>("MultiThread"),
- NewRHISample<MultiViewportSwapchainComponent>("MultiViewportSwapchainComponent", [] { return IsMultiViewportSwapchainSampleSupported(); }),
- NewRHISample<QueryExampleComponent>("Queries"),
- NewRHISample<RayTracingExampleComponent>("RayTracing", []() {return Utils::GetRHIDevice()->GetFeatures().m_rayTracing; }),
- NewRHISample<SphericalHarmonicsExampleComponent>("SphericalHarmonics"),
- NewRHISample<StencilExampleComponent>("Stencil"),
- NewRHISample<SubpassExampleComponent>("Subpass", []() {return Utils::GetRHIDevice()->GetFeatures().m_renderTargetSubpassInputSupport != AZ::RHI::SubpassInputSupportType::NotSupported; }),
- NewRHISample<SwapchainExampleComponent>("Swapchain"),
- NewRHISample<TextureExampleComponent>("Texture"),
- NewRHISample<Texture3dExampleComponent>("Texture3d"),
- NewRHISample<TextureArrayExampleComponent>("TextureArray"),
- NewRHISample<TextureMapExampleComponent>("TextureMap"),
- NewRHISample<TriangleExampleComponent>("Triangle"),
- NewRHISample<TrianglesConstantBufferExampleComponent>("TrianglesConstantBuffer"),
- NewRHISample<XRExampleComponent>("OpenXr", []() { return AZ::RHI::RHISystemInterface::Get()->GetXRSystem() != nullptr; }),
- NewRHISample<MatrixAlignmentTestExampleComponent>("MatrixAlignmentTest"),
- NewRHISample<VariableRateShadingExampleComponent>("VariableRateShading", []() { return Utils::GetRHIDevice()->GetFeatures().m_shadingRateTypeMask != RHI::ShadingRateTypeFlags::None; }),
- NewRPISample<AssetLoadTestComponent>("AssetLoadTest"),
- NewRPISample<AuxGeomExampleComponent>("AuxGeom"),
- NewRPISample<BakedShaderVariantExampleComponent>("BakedShaderVariant"),
- NewRPISample<SponzaBenchmarkComponent>("SponzaBenchmark"),
- NewRPISample<CullingAndLodExampleComponent>("CullingAndLod"),
- NewRPISample<DecalExampleComponent>("Decals"),
- NewRPISample<DynamicDrawExampleComponent>("DynamicDraw"),
- NewRPISample<DynamicMaterialTestComponent>("DynamicMaterialTest"),
- NewRPISample<MeshExampleComponent>("Mesh"),
- NewRPISample<MSAA_RPI_ExampleComponent>("MSAA"),
- NewRPISample<MultiRenderPipelineExampleComponent>("MultiRenderPipeline"),
- NewRPISample<MultiSceneExampleComponent>("MultiScene"),
- NewRPISample<MultiViewSingleSceneAuxGeomExampleComponent>("MultiViewSingleSceneAuxGeom"),
- NewRPISample<ReadbackExampleComponent>("Readback"),
- NewRPISample<RenderTargetTextureExampleComponent>("RenderTargetTexture"),
- NewRPISample<RootConstantsExampleComponent>("RootConstants"),
- NewRPISample<SceneReloadSoakTestComponent>("SceneReloadSoakTest"),
- NewRPISample<StreamingImageExampleComponent>("StreamingImage"),
- NewRPISample<ShaderReloadTestComponent>("ShaderReloadTest"),
- NewFeaturesSample<AreaLightExampleComponent>("AreaLight"),
- NewFeaturesSample<BloomExampleComponent>("Bloom"),
- NewFeaturesSample<CheckerboardExampleComponent>("Checkerboard", []() {return (Utils::GetRHIDevice()->GetPhysicalDevice().GetDescriptor().m_vendorId != RHI::VendorId::ARM && Utils::GetRHIDevice()->GetPhysicalDevice().GetDescriptor().m_vendorId != RHI::VendorId::Qualcomm); }),
- NewFeaturesSample<DepthOfFieldExampleComponent>("DepthOfField"),
- NewFeaturesSample<DiffuseGIExampleComponent>("DiffuseGI", []() {return Utils::GetRHIDevice()->GetFeatures().m_rayTracing; }),
- NewFeaturesSample<ExposureExampleComponent>("Exposure"),
- NewFeaturesSample<EyeMaterialExampleComponent>("EyeMaterial"),
- NewFeaturesSample<LightCullingExampleComponent>("LightCulling"),
- NewFeaturesSample<ParallaxMappingExampleComponent>("Parallax"),
- NewFeaturesSample<RayTracingIntersectionShaderExampleComponent>("RayTracingIntersectionShader", []() { return Utils::GetRHIDevice()->GetFeatures().m_rayTracing; }),
- NewFeaturesSample<ShadowExampleComponent>("Shadow"),
- NewFeaturesSample<ShadowedSponzaExampleComponent>("ShadowedSponza"),
- NewFeaturesSample<SkinnedMeshExampleComponent>("SkinnedMesh"),
- NewFeaturesSample<SsaoExampleComponent>("SSAO"),
- NewFeaturesSample<SSRExampleComponent>("SSR"),
- NewFeaturesSample<XRRPIExampleComponent>("OpenXR", []() { return AZ::RPI::RPISystemInterface::Get()->GetXRSystem() != nullptr; }),
- NewFeaturesSample<TonemappingExampleComponent>("Tonemapping"),
- NewFeaturesSample<TransparencyExampleComponent>("Transparency"),
- NewPerfSample<_100KDrawableExampleComponent>("100KDrawable_SingleView"),
- NewPerfSample<_100KDraw10KDrawableExampleComponent>("100KDraw_10KDrawable_MultiView"),
- };
- }
- void SampleComponentManager::RegisterSampleComponent(const SampleEntry& sample)
- {
- if (AZStd::find(m_availableSamples.begin(), m_availableSamples.end(), sample) == m_availableSamples.end())
- {
- m_availableSamples.push_back(sample);
- m_groupedSamples[sample.m_parentMenuName].push_back(static_cast<int32_t>(m_availableSamples.size() - 1));
- }
- }
- ScriptManager* SampleComponentManager::GetScriptManagerInstance()
- {
- AZ_Assert(m_scriptManager, "Script Manager is nullptr");
- return m_scriptManager.get();
- }
- ScriptableImGui* SampleComponentManager::GetScriptableImGuiInstance()
- {
- AZ_Assert(m_scriptableImGui, "Scriptable ImGui is nullptr");
- return m_scriptableImGui.get();
- }
- SampleComponentManager::SampleComponentManager()
- : m_imguiFrameCaptureSaver("@user@/frame_capture.xml")
- {
- m_imGuiFrameTimer = AZStd::make_unique<ImGuiHistogramQueue>(FrameTimeDefaultLogSize, FrameTimeDefaultLogSize, 250.0f);
- m_exampleEntity = aznew AZ::Entity();
- m_entityContextId = AzFramework::EntityContextId::CreateNull();
- }
- SampleComponentManager::~SampleComponentManager()
- {
- m_exampleEntity = nullptr;
- m_cameraEntity = nullptr;
- m_windowContext = nullptr;
- m_availableSamples.clear();
- }
- void SampleComponentManager::Init()
- {
- AZStd::vector<SampleEntry> samples = GetSamples();
- for (const SampleEntry& sample : samples)
- {
- RegisterSampleComponent(sample);
- }
- m_scriptManager = AZStd::make_unique<ScriptManager>();
- m_scriptableImGui = AZStd::make_unique<ScriptableImGui>();
- }
- void SampleComponentManager::Activate()
- {
- // We can only initialize this component after the asset catalog has been loaded.
- AzFramework::AssetCatalogEventBus::Handler::BusConnect();
- AZ::Render::ImGuiSystemNotificationBus::Handler::BusConnect();
- SampleComponentSingletonRequestBus::Handler::BusConnect();
- auto* passSystem = AZ::RPI::PassSystemInterface::Get();
- AZ_Assert(passSystem, "Cannot get the pass system.");
- passSystem->AddPassCreator(Name("RayTracingAmbientOcclusionPass"), &AZ::Render::RayTracingAmbientOcclusionPass::Create);
- }
- void SampleComponentManager::ActivateInternal()
- {
- using namespace AZ;
- AZ::ApplicationTypeQuery appType;
- ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType);
- if (!appType.IsValid() || !appType.IsGame())
- {
- return;
- }
- // 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
- // LoadCatalog call in AtomSampleViewer system component. Although load the same asset catalog twice doesn't seem to cause other issue.
- if (m_wasActivated)
- {
- return;
- }
- Render::Bootstrap::DefaultWindowBus::BroadcastResult(m_windowContext, &Render::Bootstrap::DefaultWindowBus::Events::GetDefaultWindowContext);
- AzFramework::GameEntityContextRequestBus::BroadcastResult(m_entityContextId, &AzFramework::GameEntityContextRequestBus::Events::GetGameEntityContextId);
- CreateDefaultCamera();
- // Add customized pass classes
- auto* passSystem = RPI::PassSystemInterface::Get();
- passSystem->AddPassCreator(Name("RHISamplePass"), &AtomSampleViewer::RHISamplePass::Create);
- // Use scene and render pipeline for RHI samples as default scene and render pipeline
- CreateSceneForRHISample();
- m_exampleEntity->Init();
- m_exampleEntity->Activate();
- m_isSampleSupported.resize(m_availableSamples.size());
- for (size_t i = 0; i < m_availableSamples.size(); ++i)
- {
- // Assume that the sample is supported if no m_isSupportedFunc is provided.
- m_isSampleSupported[i] = m_availableSamples[i].m_isSupportedFunc ? m_availableSamples[i].m_isSupportedFunc() : true;
- }
- AZ_Printf("SampleComponentManager", "Available Samples -------------------------\n");
- for (size_t i = 0; i < m_availableSamples.size(); ++i)
- {
- AZStd::string printStr = "\t[" + m_availableSamples[i].m_fullName + "]";
- if (!m_isSampleSupported[i])
- {
- printStr += " Not Supported ";
- }
- if (i < 9)
- {
- printStr += AZStd::string::format("\tctrl+%lu", i + 1);
- }
- printStr += "\n";
- AZ_Printf("SampleComponentManager", printStr.data());
- }
- AZ_Printf("SampleComponentManager", "-------------------------------------------\n");
- AzFramework::InputChannelEventListener::BusConnect();
- TickBus::Handler::BusConnect();
- bool targetSampleFound = false;
- if (AZStd::string targetSampleName = GetTargetSampleName();
- !targetSampleName.empty())
- {
- AZStd::to_lower(targetSampleName.begin(), targetSampleName.end());
- for (int32_t i = 0; i < m_availableSamples.size(); ++i)
- {
- AZStd::string sampleName = m_availableSamples[i].m_fullName;
- AZStd::to_lower(sampleName.begin(), sampleName.end());
- if (sampleName == targetSampleName)
- {
- if (m_isSampleSupported[i])
- {
- if (m_availableSamples[i].m_contentWarning.empty())
- {
- m_selectedSampleIndex = i;
- m_sampleChangeRequest = true;
- }
- else
- {
- m_contentWarningDialog.OpenPopupConfirmation(
- m_availableSamples[i].m_contentWarningTitle,
- m_availableSamples[i].m_contentWarning,
- [this, i]() {
- m_selectedSampleIndex = i;
- m_sampleChangeRequest = true;
- });
- }
- targetSampleFound = true;
- }
- break;
- }
- }
- AZ_Warning("SampleComponentManager", targetSampleFound, "Failed find target sample %s", targetSampleName.c_str());
- }
- const AzFramework::CommandLine* commandLine = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(commandLine, &AzFramework::ApplicationRequests::GetCommandLine);
- if (commandLine->HasSwitch("timingSamples"))
- {
- AZStd::string timingSamplesStr = commandLine->GetSwitchValue("timingSamples", 0);
- int timingSamplesCount = 0;
- if (AZ::StringFunc::LooksLikeInt(timingSamplesStr.c_str(), &timingSamplesCount))
- {
- timingSamplesCount = AZStd::clamp<int>(timingSamplesCount, FrameTimeMinLogSize, FrameTimeMaxLogSize);
- m_imGuiFrameTimer = AZStd::make_unique<ImGuiHistogramQueue>(timingSamplesCount, timingSamplesCount, 250.0f);
- }
- }
- // Set default screenshot folder to relative path 'Screenshots'
- AZ::IO::Path screenshotFolder = "Screenshots";
- // Get folder from command line if it exists
- static const char* screenshotFolderFlagName = "screenshotFolder";
- if (commandLine->HasSwitch(screenshotFolderFlagName))
- {
- screenshotFolder = commandLine->GetSwitchValue(screenshotFolderFlagName, 0);
- }
- // Make the screenshot directory relative to the Writeable Storage Path
- // The Path::operator/ smartly knows how to concatenate two absolute paths
- // i.e <absolute path1> / <absolute path2> = <absolute path2>
- auto settingsRegistry = AZ::SettingsRegistry::Get();
- AZ::IO::Path writableStoragePath;
- settingsRegistry->Get(writableStoragePath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_DevWriteStorage);
- screenshotFolder = writableStoragePath / screenshotFolder;
- m_imguiFrameCaptureSaver.SetDefaultFolder(screenshotFolder.Native());
- m_imguiFrameCaptureSaver.SetDefaultFileName("screenshot");
- m_imguiFrameCaptureSaver.SetAvailableExtensions({ "png", "ppm", "dds" });
- m_imguiFrameCaptureSaver.Activate();
- SampleComponentManagerRequestBus::Handler::BusConnect();
- m_scriptManager->Activate();
- m_wasActivated = true;
- SampleComponentManagerNotificationBus::Broadcast(&SampleComponentManagerNotificationBus::Events::OnSampleManagerActivated);
- }
- void SampleComponentManager::Deactivate()
- {
- DestroyEntity(m_cameraEntity);
- AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
- AZ::Render::ImGuiSystemNotificationBus::Handler::BusDisconnect();
- m_scriptManager->Deactivate();
- m_imguiFrameCaptureSaver.Deactivate();
- SampleComponentSingletonRequestBus::Handler::BusDisconnect();
- SampleComponentManagerRequestBus::Handler::BusDisconnect();
- AZ::TickBus::Handler::BusDisconnect();
- AzFramework::InputChannelEventListener::Disconnect();
- Render::ImGuiSystemRequestBus::Broadcast(&Render::ImGuiSystemRequests::PopActiveContext);
- m_imguiPassTree.Reset();
- m_imguiFrameGraphVisualizer.Reset();
- m_windowContext = nullptr;
- m_brdfTexture.reset();
- ReleaseRHIScene();
- ReleaseRPIScene();
- }
- void SampleComponentManager::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
- {
- if (auto* xrSystem = AZ::RPI::RPISystemInterface::Get()->GetXRSystem())
- {
- EnableRenderPipeline(xrSystem->GetRHIXRRenderingInterface()->IsDefaultRenderPipelineEnabledOnHost());
- //Only enable XR pipelines if the XR drivers indicate we have accurate pose information from the device
- EnableXrPipelines(xrSystem->ShouldRender());
- }
- if (m_imGuiFrameTimer)
- {
- m_imGuiFrameTimer->PushValue(deltaTime * 1000.0f);
- }
- bool screenshotRequest = false;
- if (m_ctrlModifierLDown || m_ctrlModifierRDown)
- {
- if (m_alphanumericQDown)
- {
- RequestExit();
- return;
- }
- if (m_alphanumericTDown && m_canCaptureRADTM)
- {
- #ifdef AZ_PROFILE_TELEMETRY
- Utils::ToggleRadTMCapture();
- m_canCaptureRADTM = false;
- #endif
- }
- else if (!m_alphanumericTDown)
- {
- m_canCaptureRADTM = true;
- }
- if (m_alphanumericPDown)
- {
- screenshotRequest = true;
- }
- }
- // Request a frame capture only once per key press, even if the keys are held down for multiple ticks.
- if (screenshotRequest)
- {
- ++m_screenshotKeyDownCount;
- if (m_screenshotKeyDownCount == 1)
- {
- RequestFrameCapture(m_imguiFrameCaptureSaver.GetNextAutoSaveFilePath(), true);
- }
- }
- else
- {
- m_screenshotKeyDownCount = 0;
- }
- RenderImGui(deltaTime);
- // SampleChange needs to happen after RenderImGui as some of the samples create sidebars on a separate ImGui context
- // which can interfere with m_imguiContext in the first frame
- if (m_sampleChangeRequest && m_canSwitchSample)
- {
- SampleChange();
- m_canSwitchSample = false;
- }
- else if (m_escapeDown && m_canSwitchSample)
- {
- Reset();
- m_canSwitchSample = false;
- Utils::ReportScriptableAction("OpenSample('')");
- }
- // 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
- if (!m_sampleChangeRequest && !m_escapeDown)
- {
- m_canSwitchSample = true;
- }
- // Since the event has been handled, clear the request
- m_sampleChangeRequest = false;
- m_escapeDown = false;
- m_scriptManager->TickScript(deltaTime);
- if (m_isFrameCapturePending)
- {
- if (m_countdownForFrameCapture > 0)
- {
- m_countdownForFrameCapture--;
- }
- else if (m_countdownForFrameCapture == 0)
- {
- AZ::Render::FrameCaptureOutcome capOutcome;
- AZ::Render::FrameCaptureRequestBus::BroadcastResult(capOutcome, &AZ::Render::FrameCaptureRequestBus::Events::CaptureScreenshot, m_frameCaptureFilePath);
- if (capOutcome.IsSuccess()) // if unsuccessfull leave state to attempt again next tick
- {
- m_frameCaptureId = capOutcome.GetValue();
- AZ::Render::FrameCaptureNotificationBus::Handler::BusConnect(m_frameCaptureId);
- m_countdownForFrameCapture = -1; // Don't call CaptureScreenshot again
- }
- else
- {
- m_frameCaptureId = AZ::Render::InvalidFrameCaptureId;
- }
- }
- }
- }
- bool SampleComponentManager::OnInputChannelEventFiltered(const AzFramework::InputChannel& inputChannel)
- {
- const size_t samplesAvailableCount = m_availableSamples.size();
- AZStd::vector<AzFramework::InputChannelId> sampleInputMapping;
- sampleInputMapping.reserve(samplesAvailableCount);
- for (size_t i = 0; i < samplesAvailableCount; ++i)
- {
- switch (i)
- {
- case 0:
- sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric1);
- break;
- case 1:
- sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric2);
- break;
- case 2:
- sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric3);
- break;
- case 3:
- sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric4);
- break;
- case 4:
- sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric5);
- break;
- case 5:
- sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric6);
- break;
- case 6:
- sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric7);
- break;
- case 7:
- sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric8);
- break;
- case 8:
- sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric9);
- break;
- case 9:
- sampleInputMapping.push_back(AzFramework::InputDeviceKeyboard::Key::Alphanumeric0);
- break;
- default:
- break;
- }
- }
- const AzFramework::InputChannelId& inputChannelId = inputChannel.GetInputChannelId();
- switch (inputChannel.GetState())
- {
- case AzFramework::InputChannel::State::Began:
- case AzFramework::InputChannel::State::Updated:
- {
- if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::ModifierCtrlL)
- {
- m_ctrlModifierLDown = true;
- }
- else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::ModifierCtrlR)
- {
- m_ctrlModifierRDown = true;
- }
- else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericQ)
- {
- m_alphanumericQDown = true;
- }
- else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericT)
- {
- m_alphanumericTDown = true;
- }
- else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericP)
- {
- m_alphanumericPDown = true;
- }
- else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::Escape)
- {
- m_escapeDown = true;
- }
- break;
- }
- case AzFramework::InputChannel::State::Ended:
- {
- if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::ModifierCtrlL)
- {
- m_ctrlModifierLDown = false;
- }
- else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::ModifierCtrlR)
- {
- m_ctrlModifierRDown = false;
- }
- else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericQ)
- {
- m_alphanumericQDown = false;
- }
- else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericT)
- {
- m_alphanumericTDown = false;
- }
- else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::AlphanumericP)
- {
- m_alphanumericPDown = false;
- }
- else if (inputChannelId == AzFramework::InputDeviceKeyboard::Key::Escape)
- {
- m_escapeDown = false;
- }
- break;
- }
- default:
- {
- break;
- }
- }
- return false;
- }
- void SampleComponentManager::RenderImGui(float deltaTime)
- {
- if (!m_isImGuiAvailable)
- {
- return;
- }
- ShowMenuBar();
- if (m_exitRequested)
- {
- return;
- }
- if (m_showResizeViewportDialog)
- {
- ShowResizeViewportDialog();
- }
- if (m_showFramerateHistogram)
- {
- ShowFramerateHistogram(deltaTime);
- }
- if (m_showFrameCaptureDialog)
- {
- ShowFrameCaptureDialog();
- }
- if (m_showImGuiMetrics)
- {
- ImGui::ShowMetricsWindow(&m_showImGuiMetrics);
- }
- if (m_showSampleHelper)
- {
- ShowSampleHelper();
- }
- if (m_showAbout)
- {
- ShowAboutWindow();
- }
- if (m_showPassTree)
- {
- ShowPassTreeWindow();
- }
- if (m_showFrameGraphVisualizer)
- {
- ShowFrameGraphVisualizerWindow();
- }
- if (m_showCullingDebugWindow)
- {
- AZ::RPI::Scene* rpiScene = AZ::RPI::RPISystemInterface::Get()->GetSceneByName(AZ::Name("RPI"));
- if (rpiScene)
- {
- AZ::Render::ImGuiDrawCullingDebug(m_showCullingDebugWindow, rpiScene);
- }
- }
- if (m_showCpuProfiler)
- {
- ShowCpuProfilerWindow();
- }
- if (m_showGpuProfiler)
- {
- ShowGpuProfilerWindow();
- }
- if (m_showFileIoProfiler)
- {
- ShowFileIoProfilerWindow();
- }
- if (m_showTransientAttachmentProfiler)
- {
- ShowTransientAttachmentProfilerWindow();
- }
- m_scriptManager->TickImGui();
- m_contentWarningDialog.TickPopup();
- }
- void SampleComponentManager::ShowMenuBar()
- {
- if (ImGui::BeginMainMenuBar())
- {
- // If imgui doesn't have enough room to render a menu, it will fall back to the safe area which
- // is typically 3 pixels. This causes the menu to overlap the menu bar, and makes it easy to
- // accidentally select the first item on that menu bar. By altering the safe area temporarily
- // while drawing the menu, this problem can be avoided.
-
- ImVec2 cachedSafeArea = ImGui::GetStyle().DisplaySafeAreaPadding;
- ImGui::GetStyle().DisplaySafeAreaPadding = ImVec2(cachedSafeArea.x, cachedSafeArea.y + 16.0f);
- if (ImGui::BeginMenu("File"))
- {
- if (ImGui::MenuItem("Exit", "Ctrl-Q"))
- {
- RequestExit();
- }
- if (ImGui::MenuItem("Capture Frame...", "Ctrl-P"))
- {
- m_showFrameCaptureDialog = true;
- }
- ImGui::EndMenu();
- }
- if (ImGui::BeginMenu("View"))
- {
- if (Utils::SupportsResizeClientArea() && ImGui::MenuItem("Resize Viewport..."))
- {
- m_showResizeViewportDialog = true;
- }
- if (Utils::SupportsToggleFullScreenOfDefaultWindow() && ImGui::MenuItem("Toggle Full Screen"))
- {
- Utils::ToggleFullScreenOfDefaultWindow();
- }
- if (ImGui::MenuItem("Frame Time Histogram"))
- {
- m_showFramerateHistogram = !m_showFramerateHistogram;
- }
- if (ImGui::MenuItem("ImGui Metrics"))
- {
- m_showImGuiMetrics = !m_showImGuiMetrics;
- }
- if (ImGui::MenuItem("Sample Helper"))
- {
- m_showSampleHelper = !m_showSampleHelper;
- }
- if (ImGui::MenuItem("Frame Graph Visualizer"))
- {
- m_showFrameGraphVisualizer = !m_showFrameGraphVisualizer;
- }
- ImGui::EndMenu();
- }
- if (ImGui::BeginMenu("Samples"))
- {
- for (auto&& [parentMenuName, samples] : m_groupedSamples)
- {
- if (ImGui::BeginMenu(parentMenuName.c_str()))
- {
- for (int32_t index : samples)
- {
- SampleEntry& sample = m_availableSamples[index];
- const char* sampleName = sample.m_sampleName.c_str();
- bool enabled = m_isSampleSupported[index];
- if (ImGui::MenuItem(sampleName, nullptr, false, enabled))
- {
- Utils::ReportScriptableAction("OpenSample('%s')", sample.m_sampleName.c_str());
- if (sample.m_contentWarning.empty())
- {
- m_sampleChangeRequest = true;
- m_selectedSampleIndex = index;
- }
- else
- {
- m_contentWarningDialog.OpenPopupConfirmation(
- sample.m_contentWarningTitle,
- sample.m_contentWarning,
- [this, index]() {
- m_sampleChangeRequest = true;
- m_selectedSampleIndex = index;
- });
- }
- }
- }
- ImGui::EndMenu();
- }
- }
- ImGui::EndMenu();
- }
- #ifdef AZ_PROFILE_TELEMETRY
- if (ImGui::BeginMenu("RADTelemetry"))
- {
- if (ImGui::MenuItem("Toggle Capture", "Ctrl-T"))
- {
- Utils::ToggleRadTMCapture();
- }
- ImGui::EndMenu();
- }
- #endif // AZ_PROFILE_TELEMETRY
- if (ImGui::BeginMenu("Automation"))
- {
- const char* AutomationContentWarningTitle = AtomSampleComponent::CommonPhotosensitiveWarningTitle;
- const char* AutomationContentWarning = "Running automated scripts will trigger flashing images that could cause seizures or other adverse effects in photosensitive individuals.";
- if (ImGui::MenuItem("Run Script..."))
- {
- m_contentWarningDialog.OpenPopupConfirmation(
- AutomationContentWarningTitle,
- AutomationContentWarning,
- [this]() {
- m_scriptManager->OpenScriptRunnerDialog();
- });
- }
- if (ImGui::MenuItem("Run Precommit Wizard..."))
- {
- m_contentWarningDialog.OpenPopupConfirmation(
- AutomationContentWarningTitle,
- AutomationContentWarning,
- [this]() {
- m_scriptManager->OpenPrecommitWizard();
- });
- }
- ImGui::EndMenu();
- }
- if (ImGui::BeginMenu("Pass"))
- {
- if (ImGui::MenuItem(PassTreeToolName))
- {
- m_showPassTree = !m_showPassTree;
- Utils::ReportScriptableAction("ShowTool('%s', %s)", PassTreeToolName, m_showPassTree?"true":"false");
- }
- ImGui::EndMenu();
- }
- if (ImGui::BeginMenu("Culling"))
- {
- if (ImGui::MenuItem("Culling Debug Window"))
- {
- m_showCullingDebugWindow = !m_showCullingDebugWindow;
- }
- ImGui::EndMenu();
- }
- if (ImGui::BeginMenu("Profile"))
- {
- if (ImGui::MenuItem(CpuProfilerToolName))
- {
- m_showCpuProfiler = !m_showCpuProfiler;
- if (auto profilerSystem = AZ::Debug::ProfilerSystemInterface::Get(); profilerSystem)
- {
- profilerSystem->SetActive(m_showCpuProfiler);
- }
- Utils::ReportScriptableAction("ShowTool('%s', %s)", CpuProfilerToolName, m_showCpuProfiler ? "true" : "false");
- }
- if (AZ::IO::StreamerProfiler::Get() != nullptr)
- {
- if (ImGui::MenuItem(FileIoProfilerToolName))
- {
- m_showFileIoProfiler = !m_showFileIoProfiler;
- Utils::ReportScriptableAction(
- "ShowTool('%s', %s)", FileIoProfilerToolName, m_showFileIoProfiler ? "true" : "false");
- }
- }
- if (ImGui::MenuItem(GpuProfilerToolName))
- {
- m_showGpuProfiler = !m_showGpuProfiler;
- Utils::ReportScriptableAction("ShowTool('%s', %s)", GpuProfilerToolName, m_showGpuProfiler ? "true" : "false");
- }
- if (ImGui::MenuItem(TransientAttachmentProfilerToolName))
- {
- m_showTransientAttachmentProfiler = !m_showTransientAttachmentProfiler;
- AZ::RHI::RHISystemInterface::Get()->ModifyFrameSchedulerStatisticsFlags(
- AZ::RHI::FrameSchedulerStatisticsFlags::GatherTransientAttachmentStatistics,
- m_showTransientAttachmentProfiler);
- Utils::ReportScriptableAction("ShowTool('%s', %s)", TransientAttachmentProfilerToolName, m_showTransientAttachmentProfiler ? "true" : "false");
- }
- ImGui::EndMenu();
- }
- if (ImGui::BeginMenu("Help"))
- {
- if (ImGui::MenuItem("About"))
- {
- m_showAbout = !m_showAbout;
- }
- ImGui::EndMenu();
- }
- // Restore original safe area.
- ImGui::GetStyle().DisplaySafeAreaPadding = cachedSafeArea;
- ImGui::EndMainMenuBar();
- }
- }
- void SampleComponentManager::ShowSampleHelper()
- {
- if (ImGui::Begin("Sample Helper", &m_showSampleHelper, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings))
- {
- if (ImGui::Button("Reset"))
- {
- //Removes the existing sample component and
- //resets the selection index
- Reset();
- CameraReset();
- m_selectedSampleIndex = -1;
- }
- ImGui::SameLine();
- if (ImGui::Button("Reset Sample"))
- {
- //Force a sample change event when the selection index
- //hasn't changed. This resets the sample component.
- SampleChange();
- }
- ImGui::SameLine();
- if (ImGui::Button("Reset Camera"))
- {
- CameraReset();
- }
- }
- ImGui::End();
- }
- void SampleComponentManager::ShowAboutWindow()
- {
- if (ImGui::Begin("About", &m_showAbout, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings))
- {
- ImGui::Text("RHI API: %s", AZ::RHI::Factory::Get().GetName().GetCStr());
- }
- ImGui::End();
- }
- void SampleComponentManager::ShowPassTreeWindow()
- {
- m_imguiPassTree.Draw(m_showPassTree, AZ::RPI::PassSystemInterface::Get()->GetRootPass().get());
- }
- void SampleComponentManager::ShowFrameGraphVisualizerWindow()
- {
- AZ::RHI::Device* rhiDevice = Utils::GetRHIDevice().get();
- m_imguiFrameGraphVisualizer.Init(rhiDevice);
- m_imguiFrameGraphVisualizer.Draw(m_showFrameGraphVisualizer);
- }
- void SampleComponentManager::ShowCpuProfilerWindow()
- {
- if (auto profilerImGui = Profiler::ProfilerImGuiInterface::Get(); profilerImGui)
- {
- profilerImGui->ShowCpuProfilerWindow(m_showCpuProfiler);
- }
- }
- void SampleComponentManager::ShowFileIoProfilerWindow()
- {
- if (auto profilerImGui = AZ::IO::StreamerProfiler::Get(); profilerImGui)
- {
- profilerImGui->DrawStatistics(m_showFileIoProfiler);
- }
- }
- void SampleComponentManager::ShowGpuProfilerWindow()
- {
- m_imguiGpuProfiler.Draw(m_showGpuProfiler, AZ::RPI::PassSystemInterface::Get()->GetRootPass());
- }
- void SampleComponentManager::ShowTransientAttachmentProfilerWindow()
- {
- auto* transientStats = AZ::RHI::RHIMemoryStatisticsInterface::Get()->GetTransientAttachmentStatistics();
- if (transientStats)
- {
- m_showTransientAttachmentProfiler = m_imguiTransientAttachmentProfiler.Draw(*transientStats);
- }
- }
- void SampleComponentManager::ShowResizeViewportDialog()
- {
- static int size[2] = { 0, 0 };
- if (size[0] <= 0)
- {
- size[0] = aznumeric_cast<int>(m_windowContext->GetViewport().m_maxX - m_windowContext->GetViewport().m_minX);
- }
- if (size[1] <= 0)
- {
- size[1] = aznumeric_cast<int>(m_windowContext->GetViewport().m_maxY - m_windowContext->GetViewport().m_minY);
- }
- bool dialogWasOpen = m_showResizeViewportDialog;
- if (ImGui::Begin("Resize Viewport", &m_showResizeViewportDialog, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings))
- {
- ImGui::InputInt2("Size", size);
- if (ImGui::Button("Resize"))
- {
- Utils::ResizeClientArea(size[0], size[1], AzFramework::WindowPosOptions());
- Utils::ReportScriptableAction("ResizeViewport(%d, %d)", size[0], size[1]);
- // Re-initialize the size fields on the next frame so we can see whether the
- // correct size was achieved (should be the same values the user entered)...
- size[0] = 0;
- size[1] = 0;
- }
- }
- ImGui::End();
- if (dialogWasOpen && !m_showResizeViewportDialog)
- {
- // Re-initialize the size fields next time the dialog is shown...
- size[0] = 0;
- size[1] = 0;
- }
- }
- void SampleComponentManager::ShowFramerateHistogram(float deltaTime)
- {
- if (m_imGuiFrameTimer && ImGui::Begin("Frame Time Histogram", &m_showFramerateHistogram, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings))
- {
- ImGuiHistogramQueue::WidgetSettings settings;
- settings.m_reportInverse = false;
- settings.m_units = "ms";
- m_imGuiFrameTimer->Tick(deltaTime * 1000.0f, settings);
- }
- ImGui::End();
- }
- void SampleComponentManager::RequestFrameCapture(const AZStd::string& filePath, bool hideImGui)
- {
- AZ_Assert(false == m_isFrameCapturePending, "Frame capture already in progress");
- AZ_Assert(AZ::Render::InvalidFrameCaptureId == m_frameCaptureId, "Unfinished frame capture detected");
- m_isFrameCapturePending = true;
- m_hideImGuiDuringFrameCapture = hideImGui;
- m_frameCaptureFilePath = filePath;
- // Don't continue the script while a frame capture is pending in case subsequent changes
- // interfere with the pending capture.
- ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::PauseScript);
- if (m_hideImGuiDuringFrameCapture)
- {
- AZ::Render::ImGuiSystemRequestBus::Broadcast(&AZ::Render::ImGuiSystemRequestBus::Events::HideAllImGuiPasses);
- // We also hide Open 3D Engine's debug text
- AzFramework::ConsoleRequestBus::Broadcast(&AzFramework::ConsoleRequests::ExecuteConsoleCommand, "r_DisplayInfo 0");
- // The ExecuteConsoleCommand request is handled in a deferred manner, so we have to delay the screenshot a bit.
- m_countdownForFrameCapture = 1;
- }
- else
- {
- m_countdownForFrameCapture = 0;
- }
- }
- void SampleComponentManager::OnFrameCaptureFinished(AZ::Render::FrameCaptureResult /*result*/, const AZStd::string& /*info*/)
- {
- AZ::Render::FrameCaptureNotificationBus::Handler::BusDisconnect();
- if (m_hideImGuiDuringFrameCapture)
- {
- AZ::Render::ImGuiSystemRequestBus::Broadcast(&AZ::Render::ImGuiSystemRequestBus::Events::ShowAllImGuiPasses);
- // We also show Open 3D Engine's debug text
- AzFramework::ConsoleRequestBus::Broadcast(&AzFramework::ConsoleRequests::ExecuteConsoleCommand, "r_DisplayInfo 1");
- }
- ScriptRunnerRequestBus::Broadcast(&ScriptRunnerRequests::ResumeScript);
- m_isFrameCapturePending = false;
- }
- bool SampleComponentManager::IsFrameCapturePending()
- {
- return m_isFrameCapturePending;
- }
- void SampleComponentManager::RunMainTestSuite(const AZStd::string& suiteFilePath, bool exitOnTestEnd, int randomSeed)
- {
- if (m_scriptManager)
- {
- m_scriptManager->RunMainTestSuite(suiteFilePath, exitOnTestEnd, randomSeed);
- }
- }
- void SampleComponentManager::SetNumMSAASamples(int16_t numMSAASamples)
- {
- AZ_Assert(IsValidNumMSAASamples(numMSAASamples), "Invalid MSAA sample setting");
- m_numMsaaSamples = numMSAASamples;
- }
- int16_t SampleComponentManager::GetNumMSAASamples()
- {
- return m_numMsaaSamples;
- }
- void SampleComponentManager::SetDefaultNumMSAASamples(int16_t defaultNumMsaaSamples)
- {
- m_defaultNumMsaaSamples = defaultNumMsaaSamples;
- }
- int16_t SampleComponentManager::GetDefaultNumMSAASamples()
- {
- return m_defaultNumMsaaSamples;
- }
- void SampleComponentManager::ResetNumMSAASamples()
- {
- m_numMsaaSamples = m_defaultNumMsaaSamples;
- }
- void SampleComponentManager::ResetRPIScene()
- {
- ReleaseRPIScene();
- SwitchSceneForRPISample();
- }
- void SampleComponentManager::ClearRPIScene()
- {
- ReleaseRPIScene();
- }
- void SampleComponentManager::EnableRenderPipeline(bool value)
- {
- if (m_renderPipeline)
- {
- if (value)
- {
- m_renderPipeline->AddToRenderTick();
- }
- else
- {
- m_renderPipeline->RemoveFromRenderTick();
- }
- }
- }
- void SampleComponentManager::EnableXrPipelines(bool value)
- {
- for (RPI::RenderPipelinePtr xrPipeline : m_xrPipelines)
- {
- if (xrPipeline)
- {
- if (value)
- {
- xrPipeline->AddToRenderTick();
- }
- else
- {
- xrPipeline->RemoveFromRenderTick();
- }
- }
- }
- }
- void SampleComponentManager::ShowFrameCaptureDialog()
- {
- static bool requestCaptureOnNextFrame = false;
- static bool hideImGuiFromFrameCapture = true;
- if (requestCaptureOnNextFrame)
- {
- requestCaptureOnNextFrame = false;
- RequestFrameCapture(m_imguiFrameCaptureSaver.GetSaveFilePath(), hideImGuiFromFrameCapture);
- }
- else if (!m_isFrameCapturePending) // Hide this dialog while taking a capture
- {
- if (ImGui::Begin("Frame Capture", &m_showFrameCaptureDialog))
- {
- ImGui::Checkbox("Hide ImGui", &hideImGuiFromFrameCapture);
- ImGuiSaveFilePath::WidgetSettings settings;
- settings.m_labels.m_filePath = "File Path (.png, .ppm, or .dds):";
- m_imguiFrameCaptureSaver.Tick(settings);
- if (ImGui::Button("Capture"))
- {
- // Don't actually do the capture until the next frame, so we can hide this dialog first
- requestCaptureOnNextFrame = true;
- if (hideImGuiFromFrameCapture)
- {
- Utils::ReportScriptableAction("CaptureScreenshot('%s')", m_imguiFrameCaptureSaver.GetSaveFilePath().c_str());
- }
- else
- {
- Utils::ReportScriptableAction("CaptureScreenshotWithImGui('%s')", m_imguiFrameCaptureSaver.GetSaveFilePath().c_str());
- }
- }
- }
- ImGui::End();
- }
- }
- void SampleComponentManager::RequestExit()
- {
- AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::ExitMainLoop);
- AZ::TickBus::Handler::BusDisconnect();
- AzFramework::InputChannelEventListener::Disconnect();
- m_exitRequested = true;
- }
- void SampleComponentManager::ShutdownActiveSample()
- {
- m_exampleEntity->Deactivate();
- // Pointer to all the passes within m_rhiSamplePasses must be nullified before all the samples within m_activeSamples are destroyed.
- SetRHISamplePass(nullptr);
- for (AZ::Component* activeComponent : m_activeSamples)
- {
- if (activeComponent != nullptr)
- {
- // Disable the camera controller just in case the active sample enabled it and didn't disable in Deactivate().
- AZ::Debug::CameraControllerRequestBus::Event(m_cameraEntity->GetId(), &AZ::Debug::CameraControllerRequestBus::Events::Disable);
- m_exampleEntity->RemoveComponent(activeComponent);
- delete activeComponent;
- }
- }
- m_activeSamples.clear();
- // Force a reset of the shader variant finder to get more consistent testing of samples every time they are run, rather
- // than the first time for each sample being "special".
- auto variantFinder = AZ::Interface<AZ::RPI::IShaderVariantFinder>::Get();
- variantFinder->Reset();
- }
- void SampleComponentManager::Reset()
- {
- ShutdownActiveSample();
- m_exampleEntity->Activate();
- // Reset to RHI sample pipeline
- SwitchSceneForRHISample();
- SetRHISamplePass(nullptr);
- }
- void SampleComponentManager::CreateDefaultCamera()
- {
- if (m_cameraEntity)
- {
- return;
- }
- // A camera entity will be created by the entity context request bus so that the component for this entity can use a feature processor.
- AzFramework::EntityContextRequestBus::EventResult(m_cameraEntity, m_entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "CameraEntity");
- //Add debug camera and controller components
- AZ::Debug::CameraComponentConfig cameraConfig(m_windowContext);
- cameraConfig.m_fovY = AZ::Constants::QuarterPi;
- cameraConfig.m_depthFar = 1000.0f;
- m_cameraEntity->CreateComponent(azrtti_typeid<AZ::Debug::CameraComponent>())
- ->SetConfiguration(cameraConfig);
- m_cameraEntity->CreateComponent(azrtti_typeid<AzFramework::TransformComponent>());
- m_cameraEntity->CreateComponent(azrtti_typeid<AZ::Debug::ArcBallControllerComponent>());
- m_cameraEntity->CreateComponent(azrtti_typeid<AZ::Debug::NoClipControllerComponent>());
- m_cameraEntity->Activate();
- m_scriptManager->SetCameraEntity(m_cameraEntity);
- }
- void SampleComponentManager::SetupImGuiContext()
- {
- AdjustImGuiFontScale();
- // Add imgui context
- Render::ImGuiSystemRequestBus::BroadcastResult(m_isImGuiAvailable, &Render::ImGuiSystemRequests::PushActiveContextFromDefaultPass);
- 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.");
- }
- void SampleComponentManager::ActiveImGuiContextChanged(ImGuiContext* context)
- {
- ImGui::SetCurrentContext(context);
- }
- bool SampleComponentManager::OpenSample(const AZStd::string& sampleName)
- {
- for (int32_t i = 0; i < m_availableSamples.size(); i++)
- {
- if (m_availableSamples[i].m_parentMenuName + '/' + m_availableSamples[i].m_sampleName == sampleName)
- {
- if (!m_availableSamples[i].m_isSupportedFunc || m_availableSamples[i].m_isSupportedFunc())
- {
- m_selectedSampleIndex = i;
- m_sampleChangeRequest = true;
- return true;
- }
- else
- {
- AZ_Error("SampleComponentManager", false, "Sample '%s' is not supported on this platform.", sampleName.c_str());
- }
- }
- }
- return false;
- }
- bool SampleComponentManager::ShowTool(const AZStd::string& toolName, bool enable)
- {
- if (toolName == PassTreeToolName)
- {
- m_showPassTree = enable;
- return true;
- }
- else if (toolName == CpuProfilerToolName)
- {
- m_showCpuProfiler = enable;
- return true;
- }
- else if (toolName == FileIoProfilerToolName)
- {
- m_showFileIoProfiler = enable;
- return true;
- }
- else if (toolName == GpuProfilerToolName)
- {
- m_showGpuProfiler = enable;
- return true;
- }
- else if (toolName == TransientAttachmentProfilerToolName)
- {
- m_showTransientAttachmentProfiler = enable;
- return true;
- }
- return false;
- }
- void SampleComponentManager::SampleChange()
- {
- if (m_selectedSampleIndex == -1)
- {
- return;
- }
- ShutdownActiveSample();
- // Reset the camera *before* activating the sample, because the sample's Activate() function might
- // want to reposition the camera.
- CameraReset();
- const SampleEntry& sampleEntry = m_availableSamples[m_selectedSampleIndex];
- // Create scene and render pipeline before create sample component
- if (sampleEntry.m_pipelineType == SamplePipelineType::RHI)
- {
- SwitchSceneForRHISample();
- }
- else if (sampleEntry.m_pipelineType == SamplePipelineType::RPI)
- {
- SwitchSceneForRPISample();
- }
- SampleComponentConfig config(m_windowContext, m_cameraEntity->GetId(), m_entityContextId);
- // special setup for RHI samples
- if (sampleEntry.m_pipelineType == SamplePipelineType::RHI)
- {
- for (AZ::RPI::Ptr<RHISamplePass> samplePass : m_rhiSamplePasses)
- {
- BasicRHIComponent* rhiSampleComponent = static_cast<BasicRHIComponent*>(m_exampleEntity->CreateComponent(sampleEntry.m_sampleUuid));
- rhiSampleComponent->SetConfiguration(config);
- rhiSampleComponent->SetViewIndex(samplePass->GetViewIndex());
- if (rhiSampleComponent->IsSupportedRHISamplePipeline())
- {
- samplePass->SetRHISample(rhiSampleComponent);
- }
- else
- {
- samplePass->SetRHISample(nullptr);
- }
- m_activeSamples.push_back(rhiSampleComponent);
- }
- }
- else
- {
- AZ::Component* newComponent = m_exampleEntity->CreateComponent(sampleEntry.m_sampleUuid);
- newComponent->SetConfiguration(config);
- m_activeSamples.push_back(newComponent);
- }
-
- m_exampleEntity->Activate();
- // Even though this is done in CameraReset(), the example component wasn't activated at the time so we have to send this event again.
- ExampleComponentRequestBus::Event(m_exampleEntity->GetId(), &ExampleComponentRequestBus::Events::ResetCamera);
- }
- void SampleComponentManager::CameraReset()
- {
- // Reset the camera transform. Some examples do not use a controller or use a controller that doesn't override the whole transform.
- // Set to a transform that is 5 units away from the origin and looking at the origin along the Y axis.
- const AZ::EntityId cameraEntityId = m_cameraEntity->GetId();
- AZ::TransformBus::Event(cameraEntityId, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, -5.0f, 0.0f)));
- AZ::Debug::CameraControllerRequestBus::Event(cameraEntityId, &AZ::Debug::CameraControllerRequestBus::Events::Reset);
- // Tell the current example to reset the camera, any example that controls the camera and preserves controller state should implement this event
- ExampleComponentRequestBus::Event(m_exampleEntity->GetId(), &ExampleComponentRequestBus::Events::ResetCamera);
- }
- void SampleComponentManager::CreateSceneForRHISample()
- {
- // Create and register the rhi scene with only feature processors required for AtomShimRenderer (only for AtomSampleViewerLauncher)
- RPI::SceneDescriptor sceneDesc;
- sceneDesc.m_nameId = AZ::Name("RHI");
- sceneDesc.m_featureProcessorNames.push_back("AZ::Render::AuxGeomFeatureProcessor");
- m_rhiScene = RPI::Scene::CreateScene(sceneDesc);
- m_rhiScene->Activate();
- auto* xrSystem = AZ::RHI::RHISystemInterface::Get()->GetXRSystem();
- const bool createDefaultRenderPipeline = !xrSystem || xrSystem->IsDefaultRenderPipelineNeeded();
- if (createDefaultRenderPipeline)
- {
- RPI::RenderPipelineDescriptor pipelineDesc;
- pipelineDesc.m_name = "RHISamplePipeline";
- pipelineDesc.m_rootPassTemplate = "RHISamplePipelineTemplate";
- // Add view to pipeline since there are few RHI samples are using ViewSrg
- pipelineDesc.m_mainViewTagName = "MainCamera";
- m_renderPipeline = RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineDesc, *m_windowContext.get());
- m_rhiScene->AddRenderPipeline(m_renderPipeline);
- m_renderPipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId());
- // Get RHISamplePass
- AZ::RPI::PassFilter passFilter = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("RHISamplePass"), m_renderPipeline.get());
- m_rhiSamplePasses.push_back(azrtti_cast<RHISamplePass*>(AZ::RPI::PassSystemInterface::Get()->FindFirstPass(passFilter)));
- // Enable or disable default pipeline on host while there is an xr system.
- if (xrSystem)
- {
- EnableRenderPipeline(xrSystem->IsDefaultRenderPipelineEnabledOnHost());
- }
- }
- if (xrSystem)
- {
- RPI::RenderPipelineDescriptor xrPipelineDesc;
- xrPipelineDesc.m_mainViewTagName = "MainCamera";
- // Build the pipeline for left eye
- xrPipelineDesc.m_name = "RHISamplePipelineXRLeft";
- xrPipelineDesc.m_rootPassTemplate = "RHISamplePipelineXRLeftTemplate";
- RPI::RenderPipelinePtr renderPipelineLeft = RPI::RenderPipeline::CreateRenderPipelineForWindow(xrPipelineDesc, *m_windowContext.get(), AZ::RPI::ViewType::XrLeft);
- // Build the pipeline for right eye
- xrPipelineDesc.m_name = "RHISamplePipelineXRRight";
- xrPipelineDesc.m_rootPassTemplate = "RHISamplePipelineXRRightTemplate";
- RPI::RenderPipelinePtr renderPipelineRight = RPI::RenderPipeline::CreateRenderPipelineForWindow(xrPipelineDesc, *m_windowContext.get(), AZ::RPI::ViewType::XrRight);
- //Add both the pipelines to the scene
- m_rhiScene->AddRenderPipeline(renderPipelineLeft);
- m_rhiScene->AddRenderPipeline(renderPipelineRight);
- renderPipelineLeft->SetDefaultViewFromEntity(m_cameraEntity->GetId());
- renderPipelineRight->SetDefaultViewFromEntity(m_cameraEntity->GetId());
-
- // Set the correct view index for the RHI sample passes
- AZ::RPI::PassFilter rhiSamplePassFilterLeft = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("RHISamplePass"), renderPipelineLeft.get());
- AZ::RPI::Ptr<RHISamplePass> rhiSamplePassLeft = azrtti_cast<RHISamplePass*>(AZ::RPI::PassSystemInterface::Get()->FindFirstPass(rhiSamplePassFilterLeft));
- rhiSamplePassLeft->SetViewIndex(0);
- m_rhiSamplePasses.push_back(rhiSamplePassLeft);
- AZ::RPI::PassFilter rhiSamplePassFilterRight = AZ::RPI::PassFilter::CreateWithPassName(AZ::Name("RHISamplePass"), renderPipelineRight.get());
- AZ::RPI::Ptr<RHISamplePass> rhiSamplePassRight = azrtti_cast<RHISamplePass*>(AZ::RPI::PassSystemInterface::Get()->FindFirstPass(rhiSamplePassFilterRight));
- rhiSamplePassRight->SetViewIndex(1);
- m_rhiSamplePasses.push_back(rhiSamplePassRight);
- //Cache the pipelines in case we want to enable/disable them
- m_xrPipelines.push_back(renderPipelineLeft);
- m_xrPipelines.push_back(renderPipelineRight);
- //Disable XR pipelines by default
- EnableXrPipelines(false);
- }
- // Register the RHi scene
- RPI::RPISystemInterface::Get()->RegisterScene(m_rhiScene);
- // Setup imGui since a new render pipeline with imgui pass was created
- SetupImGuiContext();
- }
- void SampleComponentManager::ReleaseRHIScene()
- {
- if (m_rhiScene)
- {
- m_rhiSamplePasses.clear();
- m_xrPipelines.clear();
- m_renderPipeline = nullptr;
- RPI::RPISystemInterface::Get()->UnregisterScene(m_rhiScene);
- m_rhiScene = nullptr;
- }
- }
- void SampleComponentManager::SwitchSceneForRHISample()
- {
- ReleaseRPIScene();
- ReleaseRHIScene();
- CreateSceneForRHISample();
- }
- void SampleComponentManager::CreateSceneForRPISample()
- {
- // set pipeline MSAA samples
- AZ_Assert(IsValidNumMSAASamples(m_numMsaaSamples), "Invalid MSAA sample setting");
- const bool isNonMsaaPipeline = (m_numMsaaSamples == 1);
- const char* supervariantName = isNonMsaaPipeline ? AZ::RPI::NoMsaaSupervariantName : "";
- AZ::RPI::ShaderSystemInterface::Get()->SetSupervariantName(AZ::Name(supervariantName));
- // Create and register a scene with all available feature processors
- RPI::SceneDescriptor sceneDesc;
- sceneDesc.m_nameId = AZ::Name("RPI");
- m_rpiScene = RPI::Scene::CreateScene(sceneDesc);
- m_rpiScene->EnableAllFeatureProcessors();
- // Bind m_rpiScene to the GameEntityContext's AzFramework::Scene so the RPI Scene can be found by the entity context
- auto sceneSystem = AzFramework::SceneSystemInterface::Get();
- AZ_Assert(sceneSystem, "SampleComponentManager requires an implementation of the scene system.");
- AZStd::shared_ptr<AzFramework::Scene> mainScene = sceneSystem->GetScene(AzFramework::Scene::MainSceneName);
- AZ_Assert(mainScene, "Main scene missing during system component initialization"); // This should never happen unless scene creation has changed.
- // Add RPI::Scene as a sub system for the default AzFramework Scene
- [[maybe_unused]] bool result = mainScene->SetSubsystem(m_rpiScene);
- AZ_Assert(result, "SampleComponentManager failed to register the RPI scene with the general scene.");
- m_rpiScene->Activate();
- // Register scene to RPI system so it will be processed/rendered per tick
- RPI::RPISystemInterface::Get()->RegisterScene(m_rpiScene);
-
-
- auto* xrSystem = AZ::RHI::RHISystemInterface::Get()->GetXRSystem();
- const bool createDefaultRenderPipeline = !xrSystem || xrSystem->IsDefaultRenderPipelineNeeded();
- if (createDefaultRenderPipeline)
- {
- // Create MainPipeline as its render pipeline
- RPI::RenderPipelineDescriptor pipelineDesc;
- pipelineDesc.m_name = "RPISamplePipeline";
- pipelineDesc.m_rootPassTemplate = GetRootPassTemplateName();
- pipelineDesc.m_materialPipelineTag = GetMaterialPipelineName();
- pipelineDesc.m_mainViewTagName = "MainCamera";
- pipelineDesc.m_allowModification = true;
- pipelineDesc.m_renderSettings.m_multisampleState.m_samples = static_cast<uint16_t>(m_numMsaaSamples);
- m_renderPipeline = RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineDesc, *m_windowContext.get());
- m_rpiScene->AddRenderPipeline(m_renderPipeline);
- m_renderPipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId());
- // Enable or disable default pipeline on host while there is an xr system.
- if (xrSystem)
- {
- EnableRenderPipeline(xrSystem->IsDefaultRenderPipelineEnabledOnHost());
- }
- }
- if (xrSystem)
- {
- RPI::RenderPipelineDescriptor xrPipelineDesc;
- xrPipelineDesc.m_mainViewTagName = "MainCamera";
- xrPipelineDesc.m_renderSettings.m_multisampleState.m_samples = static_cast<uint16_t>(m_numMsaaSamples);
- // Build the pipeline for left eye
- xrPipelineDesc.m_name = "RPISamplePipelineXRLeft";
- xrPipelineDesc.m_materialPipelineTag = "MultiViewPipeline";
- xrPipelineDesc.m_rootPassTemplate = "MultiViewPipelineTemplate";
- RPI::RenderPipelinePtr renderPipelineLeft = RPI::RenderPipeline::CreateRenderPipelineForWindow(xrPipelineDesc, *m_windowContext.get(), AZ::RPI::ViewType::XrLeft);
- // Build the pipeline for right eye
- xrPipelineDesc.m_name = "RHISamplePipelineXRRight";
- xrPipelineDesc.m_materialPipelineTag = "MultiViewPipeline";
- xrPipelineDesc.m_rootPassTemplate = "MultiViewPipelineTemplate";
- RPI::RenderPipelinePtr renderPipelineRight = RPI::RenderPipeline::CreateRenderPipelineForWindow(xrPipelineDesc, *m_windowContext.get(), AZ::RPI::ViewType::XrRight);
- //Add both the pipelines to the scene
- m_rpiScene->AddRenderPipeline(renderPipelineLeft);
- m_rpiScene->AddRenderPipeline(renderPipelineRight);
- renderPipelineLeft->SetDefaultStereoscopicViewFromEntity(m_cameraEntity->GetId(), RPI::ViewType::XrLeft); //Left eye
- renderPipelineRight->SetDefaultStereoscopicViewFromEntity(m_cameraEntity->GetId(), RPI::ViewType::XrRight); //Right eye
- //Cache the pipelines in case we want to enable/disable them
- m_xrPipelines.push_back(renderPipelineLeft);
- m_xrPipelines.push_back(renderPipelineRight);
- // Disable XR pipelines by default
- EnableXrPipelines(false);
- }
- // As part of our initialization we need to create the BRDF texture generation pipeline
- AZ::RPI::RenderPipelineDescriptor brdfPipelineDesc;
- brdfPipelineDesc.m_mainViewTagName = "MainCamera";
- brdfPipelineDesc.m_name = "BRDFTexturePipeline";
- brdfPipelineDesc.m_rootPassTemplate = "BRDFTexturePipeline";
- brdfPipelineDesc.m_executeOnce = true;
-
- RPI::RenderPipelinePtr brdfTexturePipeline = AZ::RPI::RenderPipeline::CreateRenderPipeline(brdfPipelineDesc);
- m_rpiScene->AddRenderPipeline(brdfTexturePipeline);
-
- // Save a reference to the generated BRDF texture so it doesn't get deleted if all the passes referring to it get deleted and it's ref count goes to zero
- if (!m_brdfTexture)
- {
- const AZStd::shared_ptr<const 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);
- }
- }
- // Setup imGui since a new render pipeline with imgui pass was created
- SetupImGuiContext();
- }
- void SampleComponentManager::ReleaseRPIScene()
- {
- if (m_rpiScene)
- {
- m_xrPipelines.clear();
- m_renderPipeline = nullptr;
- RPI::RPISystemInterface::Get()->UnregisterScene(m_rpiScene);
- auto sceneSystem = AzFramework::SceneSystemInterface::Get();
- AZ_Assert(sceneSystem, "Scene system was destroyed before SampleComponentManager was able to unregister the RPI scene.");
- AZStd::shared_ptr<AzFramework::Scene> scene = sceneSystem->GetScene(AzFramework::Scene::MainSceneName);
- AZ_Assert(scene, "The main scene wasn't found in the scene system.");
- [[maybe_unused]] bool result = scene->UnsetSubsystem(m_rpiScene);
- AZ_Assert(result, "SampleComponentManager failed to unregister its RPI scene from the general scene.");
-
- m_rpiScene = nullptr;
- }
- }
- void SampleComponentManager::SwitchSceneForRPISample()
- {
- ReleaseRHIScene();
- ReleaseRPIScene();
- CreateSceneForRPISample();
- }
- // AzFramework::AssetCatalogEventBus::Handler overrides ...
- void SampleComponentManager::OnCatalogLoaded([[maybe_unused]] const char* catalogFile)
- {
- AZ::TickBus::QueueFunction([&]()
- {
- ActivateInternal();
- });
- }
-
- void SampleComponentManager::SetRHISamplePass(BasicRHIComponent* sampleComponent)
- {
- for (AZ::RPI::Ptr<RHISamplePass> samplePass : m_rhiSamplePasses)
- {
- samplePass->SetRHISample(sampleComponent);
- }
- }
- } // namespace AtomSampleViewer
|