PassTemplatesAutoLoader.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <RPI.Private/PassTemplatesAutoLoader.h>
  9. #include <AzCore/Serialization/EditContext.h>
  10. #include <AzCore/Settings/SettingsRegistry.h>
  11. #include <AzCore/Utils/Utils.h>
  12. #include <AzFramework/Gem/GemInfo.h>
  13. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  14. namespace AZ
  15. {
  16. namespace RPI
  17. {
  18. void PassTemplatesAutoLoader::Reflect(ReflectContext* context)
  19. {
  20. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  21. {
  22. serializeContext
  23. ->Class<PassTemplatesAutoLoader, Component>()
  24. ->Version(0)
  25. ;
  26. if (AZ::EditContext* ec = serializeContext->GetEditContext())
  27. {
  28. ec->Class<PassTemplatesAutoLoader>("PassTemplatesAutoLoader", "A service that loads PassTemplates.")
  29. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  30. ->Attribute(AZ::Edit::Attributes::AutoExpand, true)
  31. ;
  32. }
  33. }
  34. }
  35. void PassTemplatesAutoLoader::GetRequiredServices(ComponentDescriptor::DependencyArrayType& required)
  36. {
  37. required.push_back(AZ_CRC_CE("RPISystem"));
  38. }
  39. void PassTemplatesAutoLoader::GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided)
  40. {
  41. provided.push_back(AZ_CRC_CE("PassTemplatesAutoLoader"));
  42. }
  43. void PassTemplatesAutoLoader::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  44. {
  45. incompatible.push_back(AZ_CRC_CE("PassTemplatesAutoLoader"));
  46. }
  47. void PassTemplatesAutoLoader::Activate()
  48. {
  49. // Register the event handler.
  50. m_loadTemplatesHandler = AZ::RPI::PassSystemInterface::OnReadyLoadTemplatesEvent::Handler(
  51. [&]()
  52. {
  53. LoadPassTemplates();
  54. });
  55. AZ::RPI::PassSystemInterface::Get()->ConnectEvent(m_loadTemplatesHandler);
  56. }
  57. void PassTemplatesAutoLoader::Deactivate()
  58. {
  59. }
  60. void PassTemplatesAutoLoader::LoadPassTemplates()
  61. {
  62. auto* settingsRegistry = AZ::SettingsRegistry::Get();
  63. AZStd::vector<AzFramework::GemInfo> gemInfoList;
  64. if (!AzFramework::GetGemsInfo(gemInfoList, *settingsRegistry))
  65. {
  66. AZ_Warning(LogWindow, false, "%s Failed to get Gems info.\n", __FUNCTION__);
  67. return;
  68. }
  69. auto* passSystemInterface = AZ::RPI::PassSystemInterface::Get();
  70. AZStd::unordered_set<AZStd::string> loadedTemplates; // See CAVEAT below.
  71. auto loadFunc = [&](const AZStd::string& assetPath)
  72. {
  73. if (loadedTemplates.count(assetPath) > 0)
  74. {
  75. // CAVEAT: Most of the times Game Projects contain a Gem of the same name
  76. // inside of them, this is why we check first with @loadedTemplates before attempting to load
  77. // the PassTemplate asset located at <PROJECT_ROOT>/Passes/<PROJECT_NAME>/AutoLoadPassTemplates.azasset
  78. return;
  79. }
  80. const auto assetId = AssetUtils::GetAssetIdForProductPath(assetPath.c_str(), AssetUtils::TraceLevel::None);
  81. if (!assetId.IsValid())
  82. {
  83. // This is the most common scenario.
  84. return;
  85. }
  86. if (!passSystemInterface->LoadPassTemplateMappings(assetPath))
  87. {
  88. AZ_Error(LogWindow, false, "Failed to load PassTemplates at '%s'.\n", assetPath.c_str());
  89. return;
  90. }
  91. AZ_Printf(LogWindow, "Successfully load PassTemplates from '%s'.\n", assetPath.c_str());
  92. loadedTemplates.emplace(AZStd::move(assetPath));
  93. };
  94. for (const auto& gemInfo : gemInfoList)
  95. {
  96. AZStd::string assetPath = AZStd::string::format("Passes/%s/AutoLoadPassTemplates.azasset", gemInfo.m_gemName.c_str());
  97. loadFunc(assetPath);
  98. }
  99. // Besides the Gems, a Game Project can also provide PassTemplates.
  100. // <PROJECT_ROOT>/Assets/Passes/<PROJECT_NAME>/AutoLoadPassTemplates.azasset
  101. // <PROJECT_ROOT>/Passes/<PROJECT_NAME>/AutoLoadPassTemplates.azasset
  102. const auto projectName = AZ::Utils::GetProjectName(settingsRegistry);
  103. if (!projectName.empty())
  104. {
  105. {
  106. AZStd::string assetPath = AZStd::string::format("Passes/%s/AutoLoadPassTemplates.azasset", projectName.c_str());
  107. loadFunc(assetPath);
  108. }
  109. {
  110. AZStd::string assetPath = AZStd::string::format("Assets/Passes/%s/AutoLoadPassTemplates.azasset", projectName.c_str());
  111. loadFunc(assetPath);
  112. }
  113. }
  114. }
  115. } // namespace RPI
  116. } // namespace AZ