3
0

ShaderManagementConsoleApplication.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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 <AssetDatabase/AssetDatabaseConnection.h>
  9. #include <Atom/RPI.Edit/Common/AssetUtils.h>
  10. #include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
  11. #include <Atom/RPI.Public/Material/Material.h>
  12. #include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
  13. #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
  14. #include <ShaderManagementConsoleApplication.h>
  15. #include <Document/ShaderManagementConsoleDocument.h>
  16. #include <Window/ShaderManagementConsoleTableView.h>
  17. #include <Window/ShaderManagementConsoleWindow.h>
  18. void InitShaderManagementConsoleResources()
  19. {
  20. // Must register qt resources from other modules
  21. Q_INIT_RESOURCE(ShaderManagementConsole);
  22. Q_INIT_RESOURCE(InspectorWidget);
  23. Q_INIT_RESOURCE(AtomToolsAssetBrowser);
  24. }
  25. namespace ShaderManagementConsole
  26. {
  27. static const char* GetBuildTargetName()
  28. {
  29. #if !defined(LY_CMAKE_TARGET)
  30. #error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target"
  31. #endif
  32. return LY_CMAKE_TARGET;
  33. }
  34. ShaderManagementConsoleApplication::ShaderManagementConsoleApplication(int* argc, char*** argv)
  35. : Base(GetBuildTargetName(), argc, argv)
  36. {
  37. InitShaderManagementConsoleResources();
  38. QApplication::setOrganizationName("O3DE");
  39. QApplication::setApplicationName("O3DE Shader Management Console");
  40. QApplication::setWindowIcon(QIcon(":/Icons/application.svg"));
  41. AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect();
  42. ShaderManagementConsoleRequestBus::Handler::BusConnect();
  43. }
  44. ShaderManagementConsoleApplication::~ShaderManagementConsoleApplication()
  45. {
  46. AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect();
  47. ShaderManagementConsoleRequestBus::Handler::BusDisconnect();
  48. m_window.reset();
  49. }
  50. void ShaderManagementConsoleApplication::Reflect(AZ::ReflectContext* context)
  51. {
  52. Base::Reflect(context);
  53. ShaderManagementConsoleDocument::Reflect(context);
  54. if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
  55. {
  56. behaviorContext->EBus<ShaderManagementConsoleRequestBus>("ShaderManagementConsoleRequestBus")
  57. ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
  58. ->Attribute(AZ::Script::Attributes::Category, "Editor")
  59. ->Attribute(AZ::Script::Attributes::Module, "shadermanagementconsole")
  60. ->Event("GetSourceAssetInfo", &ShaderManagementConsoleRequestBus::Events::GetSourceAssetInfo)
  61. ->Event("FindMaterialAssetsUsingShader", &ShaderManagementConsoleRequestBus::Events::FindMaterialAssetsUsingShader)
  62. ->Event("GetMaterialInstanceShaderItems", &ShaderManagementConsoleRequestBus::Events::GetMaterialInstanceShaderItems)
  63. ->Event("GetAllMaterialAssetIds", &ShaderManagementConsoleRequestBus::Events::GetAllMaterialAssetIds)
  64. ->Event("GetFullSourcePathFromRelativeProductPath", &ShaderManagementConsoleRequestBus::Events::GetFullSourcePathFromRelativeProductPath)
  65. ->Event("GenerateRelativeSourcePath", &ShaderManagementConsoleRequestBus::Events::GenerateRelativeSourcePath);
  66. }
  67. }
  68. const char* ShaderManagementConsoleApplication::GetCurrentConfigurationName() const
  69. {
  70. #if defined(_RELEASE)
  71. return "ReleaseShaderManagementConsole";
  72. #elif defined(_DEBUG)
  73. return "DebugShaderManagementConsole";
  74. #else
  75. return "ProfileShaderManagementConsole";
  76. #endif
  77. }
  78. void ShaderManagementConsoleApplication::StartCommon(AZ::Entity* systemEntity)
  79. {
  80. Base::StartCommon(systemEntity);
  81. // Overriding default document type info to provide a custom view
  82. auto documentTypeInfo = ShaderManagementConsoleDocument::BuildDocumentTypeInfo();
  83. documentTypeInfo.m_documentViewFactoryCallback = [this](const AZ::Crc32& toolId, const AZ::Uuid& documentId) {
  84. return m_window->AddDocumentTab(documentId, new ShaderManagementConsoleTableView(toolId, documentId, m_window.get()));
  85. };
  86. AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
  87. m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, documentTypeInfo);
  88. m_window.reset(aznew ShaderManagementConsoleWindow(m_toolId));
  89. m_window->show();
  90. }
  91. void ShaderManagementConsoleApplication::Destroy()
  92. {
  93. m_window.reset();
  94. Base::Destroy();
  95. }
  96. AZStd::vector<AZStd::string> ShaderManagementConsoleApplication::GetCriticalAssetFilters() const
  97. {
  98. return AZStd::vector<AZStd::string>({ "passes/", "config/" });
  99. }
  100. QWidget* ShaderManagementConsoleApplication::GetAppMainWindow()
  101. {
  102. return m_window.get();
  103. }
  104. AZ::Data::AssetInfo ShaderManagementConsoleApplication::GetSourceAssetInfo(const AZStd::string& sourceAssetFileName)
  105. {
  106. bool result = false;
  107. AZ::Data::AssetInfo assetInfo;
  108. AZStd::string watchFolder;
  109. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
  110. result,
  111. &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath,
  112. sourceAssetFileName.c_str(),
  113. assetInfo,
  114. watchFolder);
  115. AZ_Error(nullptr, result, "Failed to get the asset info for the file: %s.", sourceAssetFileName.c_str());
  116. return assetInfo;
  117. }
  118. AZStd::vector<AZ::Data::AssetId> ShaderManagementConsoleApplication::FindMaterialAssetsUsingShader(const AZStd::string& shaderFilePath)
  119. {
  120. AzToolsFramework::AssetDatabase::AssetDatabaseConnection assetDatabaseConnection;
  121. assetDatabaseConnection.OpenDatabase();
  122. // Find all material types that reference shaderFilePath
  123. AZStd::list<AZStd::string> materialTypeSources;
  124. bool foundSourceInfo = false;
  125. AZStd::string watchFolder;
  126. AZ::Data::AssetInfo shaderAssetInfo;
  127. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
  128. foundSourceInfo,
  129. &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath,
  130. shaderFilePath.c_str(),
  131. shaderAssetInfo,
  132. watchFolder);
  133. if (!foundSourceInfo)
  134. {
  135. AZ_Error("FindMaterialAssetsUsingShader", false, "Failed to find source file info %s.", shaderFilePath.c_str());
  136. return {};
  137. }
  138. assetDatabaseConnection.QuerySourceDependencyByDependsOnSource(
  139. shaderAssetInfo.m_assetId.m_guid, shaderAssetInfo.m_relativePath.c_str(), watchFolder.c_str(), AzToolsFramework::AssetDatabase::SourceFileDependencyEntry::DEP_Any,
  140. [&](AzToolsFramework::AssetDatabase::SourceFileDependencyEntry& sourceFileDependencyEntry)
  141. {
  142. AZStd::string relativeSourcePath;
  143. assetDatabaseConnection.QuerySourceBySourceGuid(
  144. sourceFileDependencyEntry.m_sourceGuid,
  145. [&relativeSourcePath](AzToolsFramework::AssetDatabase::SourceDatabaseEntry& entry)
  146. {
  147. relativeSourcePath = entry.m_sourceName;
  148. return false;
  149. });
  150. if (AzFramework::StringFunc::Path::IsExtension(relativeSourcePath.c_str(), AZ::RPI::MaterialTypeSourceData::Extension))
  151. {
  152. materialTypeSources.push_back(relativeSourcePath);
  153. }
  154. return true;
  155. });
  156. // Find all materials that reference any of the material types using this shader
  157. AZ::Data::AssetInfo materialTypeSourceAssetInfo;
  158. AZStd::list<AzToolsFramework::AssetDatabase::ProductDatabaseEntry> productDependencies;
  159. for (const auto& materialTypeSource : materialTypeSources)
  160. {
  161. bool result = false;
  162. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
  163. result, &AzToolsFramework::AssetSystem::AssetSystemRequest::GetSourceInfoBySourcePath, materialTypeSource.c_str(),
  164. materialTypeSourceAssetInfo, watchFolder);
  165. if (result)
  166. {
  167. assetDatabaseConnection.QueryDirectReverseProductDependenciesBySourceGuidSubId(
  168. materialTypeSourceAssetInfo.m_assetId.m_guid, materialTypeSourceAssetInfo.m_assetId.m_subId,
  169. [&](AzToolsFramework::AssetDatabase::ProductDatabaseEntry& entry)
  170. {
  171. if (AzFramework::StringFunc::Path::IsExtension(entry.m_productName.c_str(), AZ::RPI::MaterialAsset::Extension))
  172. {
  173. productDependencies.push_back(entry);
  174. }
  175. return true;
  176. });
  177. }
  178. }
  179. AZStd::vector<AZ::Data::AssetId> results;
  180. results.reserve(productDependencies.size());
  181. for (const auto& product : productDependencies)
  182. {
  183. assetDatabaseConnection.QueryCombinedByProductID(
  184. product.m_productID,
  185. [&](AzToolsFramework::AssetDatabase::CombinedDatabaseEntry& combined)
  186. {
  187. results.push_back({ combined.m_sourceGuid, combined.m_subID });
  188. return false;
  189. },
  190. {});
  191. }
  192. return results;
  193. }
  194. AZStd::vector<AZ::RPI::ShaderCollection::Item> ShaderManagementConsoleApplication::GetMaterialInstanceShaderItems(
  195. const AZ::Data::AssetId& materialAssetId)
  196. {
  197. auto materialAsset =
  198. AZ::RPI::AssetUtils::LoadAssetById<AZ::RPI::MaterialAsset>(materialAssetId, AZ::RPI::AssetUtils::TraceLevel::Error);
  199. if (!materialAsset.IsReady())
  200. {
  201. AZ_Error(
  202. "ShaderManagementConsole", false, "Failed to load material asset from asset id: %s",
  203. materialAssetId.ToFixedString().c_str());
  204. return AZStd::vector<AZ::RPI::ShaderCollection::Item>();
  205. }
  206. auto materialInstance = AZ::RPI::Material::Create(materialAsset);
  207. if (!materialInstance)
  208. {
  209. AZ_Error(
  210. "ShaderManagementConsole", false, "Failed to create material instance from asset: %s",
  211. materialAsset.ToString<AZStd::string>().c_str());
  212. return AZStd::vector<AZ::RPI::ShaderCollection::Item>();
  213. }
  214. AZStd::vector<AZ::RPI::ShaderCollection::Item> shaderItems;
  215. materialInstance->ForAllShaderItems(
  216. [&](const AZ::Name&, const AZ::RPI::ShaderCollection::Item& shaderItem)
  217. {
  218. shaderItems.push_back(shaderItem);
  219. return true;
  220. });
  221. return shaderItems;
  222. }
  223. AZStd::vector<AZ::Data::AssetId> ShaderManagementConsoleApplication::GetAllMaterialAssetIds()
  224. {
  225. AZStd::vector<AZ::Data::AssetId> assetIds;
  226. AZ::Data::AssetCatalogRequests::AssetEnumerationCB collectAssetsCb =
  227. [&]([[maybe_unused]] const AZ::Data::AssetId id, const AZ::Data::AssetInfo& info)
  228. {
  229. if (info.m_assetType == AZ::RPI::MaterialAsset::RTTI_Type())
  230. {
  231. assetIds.push_back(id);
  232. }
  233. };
  234. AZ::Data::AssetCatalogRequestBus::Broadcast(
  235. &AZ::Data::AssetCatalogRequestBus::Events::EnumerateAssets, nullptr, collectAssetsCb, nullptr);
  236. return assetIds;
  237. }
  238. AZStd::string ShaderManagementConsoleApplication::GetFullSourcePathFromRelativeProductPath(const AZStd::string& relativeProductPath)
  239. {
  240. AZStd::string fullSourcePath;
  241. bool fullPathFound = false;
  242. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
  243. fullPathFound,
  244. &AzToolsFramework::AssetSystem::AssetSystemRequest::GetFullSourcePathFromRelativeProductPath,
  245. relativeProductPath,
  246. fullSourcePath);
  247. if (fullPathFound)
  248. {
  249. return fullSourcePath;
  250. }
  251. else
  252. {
  253. AZ_Error(
  254. "GetFullSourcePathFromRelativeProductPath",
  255. false,
  256. "Failed to get full sorece path for relative product path %s.",
  257. relativeProductPath.c_str());
  258. }
  259. return "";
  260. }
  261. AZStd::string ShaderManagementConsoleApplication::GenerateRelativeSourcePath(const AZStd::string& fullShaderPath)
  262. {
  263. bool pathFound = false;
  264. AZStd::string relativePath, rootFolder;
  265. AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
  266. pathFound,
  267. &AzToolsFramework::AssetSystemRequestBus::Events::GenerateRelativeSourcePath,
  268. fullShaderPath,
  269. relativePath,
  270. rootFolder);
  271. if (pathFound)
  272. {
  273. return relativePath;
  274. }
  275. else
  276. {
  277. AZ_Error("GenerateRelativeSourcePath", false, "Can not find a relative path from the shader: '%s'.", fullShaderPath.c_str());
  278. return "";
  279. }
  280. }
  281. } // namespace ShaderManagementConsole