MaterialCanvasApplication.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  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 <Atom/RHI.Reflect/SamplerState.h>
  9. #include <Atom/RHI/Factory.h>
  10. #include <Atom/RPI.Edit/Shader/ShaderSourceData.h>
  11. #include <Atom/RPI.Reflect/Image/StreamingImageAsset.h>
  12. #include <AtomToolsFramework/Document/AtomToolsAnyDocument.h>
  13. #include <AtomToolsFramework/Document/AtomToolsDocumentSystemRequestBus.h>
  14. #include <AtomToolsFramework/Graph/DynamicNode/DynamicNodeUtil.h>
  15. #include <AtomToolsFramework/Graph/GraphDocument.h>
  16. #include <AtomToolsFramework/Graph/GraphDocumentView.h>
  17. #include <AtomToolsFramework/Util/Util.h>
  18. #include <AzCore/Math/Color.h>
  19. #include <AzCore/Math/Vector2.h>
  20. #include <AzCore/Math/Vector3.h>
  21. #include <AzCore/Math/Vector4.h>
  22. #include <AzCore/RTTI/RTTI.h>
  23. #include <AzCore/Utils/Utils.h>
  24. #include <AzCore/std/smart_ptr/make_shared.h>
  25. #include <Document/MaterialGraphCompiler.h>
  26. #include <GraphModel/Model/DataType.h>
  27. #include <MaterialCanvasApplication.h>
  28. #include <Window/MaterialCanvasMainWindow.h>
  29. #include <QLabel>
  30. #if defined(EXTERNAL_CRASH_REPORTING)
  31. #include <ToolsCrashHandler.h>
  32. #endif
  33. void InitMaterialCanvasResources()
  34. {
  35. // Must register qt resources from other modules
  36. Q_INIT_RESOURCE(MaterialCanvas);
  37. Q_INIT_RESOURCE(InspectorWidget);
  38. Q_INIT_RESOURCE(AtomToolsAssetBrowser);
  39. Q_INIT_RESOURCE(GraphView);
  40. }
  41. namespace MaterialCanvas
  42. {
  43. static const char* GetBuildTargetName()
  44. {
  45. #if !defined(LY_CMAKE_TARGET)
  46. #error "LY_CMAKE_TARGET must be defined in order to add this source file to a CMake executable target"
  47. #endif
  48. return LY_CMAKE_TARGET;
  49. }
  50. MaterialCanvasApplication::MaterialCanvasApplication(int* argc, char*** argv)
  51. : Base(GetBuildTargetName(), argc, argv)
  52. {
  53. #if defined(EXTERNAL_CRASH_REPORTING)
  54. CrashHandler::ToolsCrashHandler::InitCrashHandler("MaterialCanvas", {});
  55. #endif
  56. InitMaterialCanvasResources();
  57. QApplication::setOrganizationName("O3DE");
  58. QApplication::setApplicationName("O3DE Material Canvas");
  59. QApplication::setWindowIcon(QIcon(":/Icons/application.svg"));
  60. AzToolsFramework::EditorWindowRequestBus::Handler::BusConnect();
  61. AZ::RHI::FactoryManagerNotificationBus::Handler::BusConnect();
  62. AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusConnect(m_toolId);
  63. }
  64. MaterialCanvasApplication::~MaterialCanvasApplication()
  65. {
  66. AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect();
  67. AzToolsFramework::EditorWindowRequestBus::Handler::BusDisconnect();
  68. AZ::RHI::FactoryManagerNotificationBus::Handler::BusDisconnect();
  69. m_window.reset();
  70. }
  71. void MaterialCanvasApplication::Reflect(AZ::ReflectContext* context)
  72. {
  73. Base::Reflect(context);
  74. MaterialGraphCompiler::Reflect(context);
  75. if (auto serialize = azrtti_cast<AZ::SerializeContext*>(context))
  76. {
  77. serialize->RegisterGenericType<AZStd::array<AZ::Vector2, 2>>();
  78. serialize->RegisterGenericType<AZStd::array<AZ::Vector3, 3>>();
  79. serialize->RegisterGenericType<AZStd::array<AZ::Vector4, 3>>();
  80. serialize->RegisterGenericType<AZStd::array<AZ::Vector4, 4>>();
  81. }
  82. }
  83. const char* MaterialCanvasApplication::GetCurrentConfigurationName() const
  84. {
  85. #if defined(_RELEASE)
  86. return "ReleaseMaterialCanvas";
  87. #elif defined(_DEBUG)
  88. return "DebugMaterialCanvas";
  89. #else
  90. return "ProfileMaterialCanvas";
  91. #endif
  92. }
  93. void MaterialCanvasApplication::StartCommon(AZ::Entity* systemEntity)
  94. {
  95. Base::StartCommon(systemEntity);
  96. InitDynamicNodeManager();
  97. InitDynamicNodeEditData();
  98. InitSharedGraphContext();
  99. InitGraphViewSettings();
  100. InitMaterialGraphDocumentType();
  101. InitMaterialGraphNodeDocumentType();
  102. InitShaderSourceDataDocumentType();
  103. InitMainWindow();
  104. InitDefaultDocument();
  105. }
  106. void MaterialCanvasApplication::Destroy()
  107. {
  108. // Save all of the graph view configuration settings to the settings registry.
  109. AtomToolsFramework::SetSettingsObject("/O3DE/Atom/GraphView/ViewSettings", m_graphViewSettingsPtr);
  110. m_graphViewSettingsPtr.reset();
  111. m_window.reset();
  112. m_viewportSettingsSystem.reset();
  113. m_graphContext.reset();
  114. m_graphTemplateFileDataCache.reset();
  115. m_dynamicNodeManager.reset();
  116. ApplyShaderBuildSettings();
  117. Base::Destroy();
  118. }
  119. AZStd::vector<AZStd::string> MaterialCanvasApplication::GetCriticalAssetFilters() const
  120. {
  121. return AZStd::vector<AZStd::string>({ "passes/", "config/", "MaterialEditor/", "MaterialCanvas/" });
  122. }
  123. QWidget* MaterialCanvasApplication::GetAppMainWindow()
  124. {
  125. return m_window.get();
  126. }
  127. void MaterialCanvasApplication::FactoryRegistered()
  128. {
  129. ApplyShaderBuildSettings();
  130. }
  131. void MaterialCanvasApplication::InitDynamicNodeManager()
  132. {
  133. // Instantiate the dynamic node manager to register all dynamic node configurations and data types used in this tool
  134. m_dynamicNodeManager.reset(aznew AtomToolsFramework::DynamicNodeManager(m_toolId));
  135. // Creating default sampler state with settings common to pre-existing material types.
  136. AZ::RHI::SamplerState defaultSamplerState{};
  137. defaultSamplerState.m_filterMin = AZ::RHI::FilterMode::Linear;
  138. defaultSamplerState.m_filterMag = AZ::RHI::FilterMode::Linear;
  139. defaultSamplerState.m_filterMip = AZ::RHI::FilterMode::Linear;
  140. defaultSamplerState.m_anisotropyMax = 16;
  141. // Register all data types required by Material Canvas nodes with the dynamic node manager
  142. m_dynamicNodeManager->RegisterDataTypes({
  143. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("bool"), bool{}, "bool"),
  144. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("int"), int32_t{}, "int"),
  145. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("uint"), uint32_t{}, "uint"),
  146. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("float"), float{}, "float"),
  147. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("float2"), AZ::Vector2{}, "float2"),
  148. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("float3"), AZ::Vector3{}, "float3"),
  149. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("float4"), AZ::Vector4{}, "float4"),
  150. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("float2x2"), AZStd::array<AZ::Vector2, 2>{ AZ::Vector2(1.0f, 0.0f), AZ::Vector2(0.0f, 1.0f) }, "float2x2"),
  151. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("float3x3"), AZStd::array<AZ::Vector3, 3>{ AZ::Vector3(1.0f, 0.0f, 0.0f), AZ::Vector3(0.0f, 1.0f, 0.0f), AZ::Vector3(0.0f, 0.0f, 1.0f) }, "float3x3"),
  152. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("float4x3"), AZStd::array<AZ::Vector4, 3>{ AZ::Vector4(1.0f, 0.0f, 0.0f, 0.0f), AZ::Vector4(0.0f, 1.0f, 0.0f, 0.0f), AZ::Vector4(0.0f, 0.0f, 1.0f, 0.0f) }, "float4x3"),
  153. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("float4x4"), AZStd::array<AZ::Vector4, 4>{ AZ::Vector4(1.0f, 0.0f, 0.0f, 0.0f), AZ::Vector4(0.0f, 1.0f, 0.0f, 0.0f), AZ::Vector4(0.0f, 0.0f, 1.0f, 0.0f), AZ::Vector4(0.0f, 0.0f, 0.0f, 1.0f) }, "float4x4"),
  154. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("color"), AZ::Color::CreateOne(), "color"),
  155. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("string"), AZStd::string{}, "string"),
  156. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("image"), AZ::Data::Asset<AZ::RPI::StreamingImageAsset>{ AZ::Data::AssetLoadBehavior::NoLoad }, "image"),
  157. AZStd::make_shared<GraphModel::DataType>(AZ_CRC_CE("sampler"), defaultSamplerState, "sampler"),
  158. });
  159. // Search the project and gems for dynamic node configurations and register them with the manager
  160. m_dynamicNodeManager->LoadConfigFiles("materialgraphnode");
  161. }
  162. void MaterialCanvasApplication::InitDynamicNodeEditData()
  163. {
  164. // Registering custom property handlers for dynamic node configuration settings. The settings are just a map of string data.
  165. // Recognized settings will need special controls for selecting files or editing large blocks of text without taking up much real
  166. // estate in the property editor. In the future, this will likely be replaced with a more specialized node configuration editor.
  167. AZ::Edit::ElementData editData;
  168. editData.m_elementId = AZ_CRC_CE("MultilineStringDialog");
  169. m_dynamicNodeManager->RegisterEditDataForSetting("instructions", editData);
  170. m_dynamicNodeManager->RegisterEditDataForSetting("classDefinitions", editData);
  171. m_dynamicNodeManager->RegisterEditDataForSetting("functionDefinitions", editData);
  172. m_dynamicNodeManager->RegisterEditDataForSetting("materialPropertySrgMember", editData);
  173. m_dynamicNodeManager->RegisterEditDataForSetting("materialPropertyDescription", editData);
  174. editData = {};
  175. editData.m_elementId = AZ::Edit::UIHandlers::LineEdit;
  176. m_dynamicNodeManager->RegisterEditDataForSetting("materialPropertyName", editData);
  177. m_dynamicNodeManager->RegisterEditDataForSetting("materialPropertyDisplayName", editData);
  178. m_dynamicNodeManager->RegisterEditDataForSetting("materialPropertyConnectionName", editData);
  179. m_dynamicNodeManager->RegisterEditDataForSetting("materialPropertyGroupName", editData);
  180. m_dynamicNodeManager->RegisterEditDataForSetting("materialPropertyGroup", editData);
  181. editData = {};
  182. editData.m_elementId = AZ::Edit::UIHandlers::ComboBox;
  183. AtomToolsFramework::AddEditDataAttribute(
  184. editData, AZ::Edit::Attributes::StringList, AZStd::vector<AZStd::string>{ "", "0", "1", "2", "3", "4" });
  185. m_dynamicNodeManager->RegisterEditDataForSetting("materialPropertyMinVectorSize", editData);
  186. editData = {};
  187. editData.m_elementId = AZ::Edit::UIHandlers::ComboBox;
  188. AtomToolsFramework::AddEditDataAttribute(
  189. editData,
  190. AZ::Edit::Attributes::StringList,
  191. AZStd::vector<AZStd::string>{ "None", "ShaderInput", "ShaderOption", "ShaderEnabled", "InternalProperty", "" });
  192. m_dynamicNodeManager->RegisterEditDataForSetting("materialPropertyConnectionType", editData);
  193. editData = {};
  194. editData.m_elementId = AZ_CRC_CE("StringFilePath");
  195. AtomToolsFramework::AddEditDataAttribute(editData, AZ_CRC_CE("Title"), AZStd::string("Template File"));
  196. AtomToolsFramework::AddEditDataAttribute(
  197. editData, AZ_CRC_CE("Extensions"), AZStd::vector<AZStd::string>{ "azsl", "azsli", "material", "materialtype", "shader" });
  198. m_dynamicNodeManager->RegisterEditDataForSetting("templatePaths", editData);
  199. editData = {};
  200. editData.m_elementId = AZ_CRC_CE("StringFilePath");
  201. AtomToolsFramework::AddEditDataAttribute(editData, AZ_CRC_CE("Title"), AZStd::string("Include File"));
  202. AtomToolsFramework::AddEditDataAttribute(editData, AZ_CRC_CE("Extensions"), AZStd::vector<AZStd::string>{ "azsli" });
  203. m_dynamicNodeManager->RegisterEditDataForSetting("includePaths", editData);
  204. }
  205. void MaterialCanvasApplication::InitSharedGraphContext()
  206. {
  207. // Each graph document creates its own graph context but we want to use a shared graph context instead to avoid data duplication
  208. m_graphContext = AZStd::make_shared<GraphModel::GraphContext>(
  209. "Material Graph", ".materialgraph", m_dynamicNodeManager->GetRegisteredDataTypes());
  210. m_graphContext->CreateModuleGraphManager();
  211. }
  212. void MaterialCanvasApplication::InitGraphViewSettings()
  213. {
  214. // This configuration data is passed through the main window and graph views to setup translation data, styling, and node palettes
  215. m_graphViewSettingsPtr = AtomToolsFramework::GetSettingsObject(
  216. "/O3DE/Atom/GraphView/ViewSettings", AZStd::make_shared<AtomToolsFramework::GraphViewSettings>());
  217. // Initialize the application specific graph view settings that are not serialized.
  218. m_graphViewSettingsPtr->m_translationPath = "@products@/materialcanvas/translation/materialcanvas_en_us.qm";
  219. m_graphViewSettingsPtr->m_styleManagerPath = "MaterialCanvas/StyleSheet/materialcanvas_style.json";
  220. m_graphViewSettingsPtr->m_nodeMimeType = "MaterialCanvas/node-palette-mime-event";
  221. m_graphViewSettingsPtr->m_nodeSaveIdentifier = "MaterialCanvas/ContextMenu";
  222. m_graphViewSettingsPtr->m_createNodeTreeItemsFn = [](const AZ::Crc32& toolId)
  223. {
  224. GraphCanvas::GraphCanvasTreeItem* rootTreeItem = {};
  225. AtomToolsFramework::DynamicNodeManagerRequestBus::EventResult(
  226. rootTreeItem, toolId, &AtomToolsFramework::DynamicNodeManagerRequestBus::Events::CreateNodePaletteTree);
  227. return rootTreeItem;
  228. };
  229. // Initialize the default group preset names and colors needed by the graph canvas view to create node groups.
  230. const AZStd::map<AZStd::string, AZ::Color> defaultGroupPresets = AtomToolsFramework::GetSettingsObject(
  231. "/O3DE/Atom/GraphView/DefaultGroupPresets",
  232. AZStd::map<AZStd::string, AZ::Color>{ { "Logic", AZ::Color(0.188f, 0.972f, 0.243f, 1.0f) },
  233. { "Function", AZ::Color(0.396f, 0.788f, 0.788f, 1.0f) },
  234. { "Output", AZ::Color(0.866f, 0.498f, 0.427f, 1.0f) },
  235. { "Input", AZ::Color(0.396f, 0.788f, 0.549f, 1.0f) } });
  236. // Connect the graph view settings to the required buses so that they can be accessed throughout the application.
  237. m_graphViewSettingsPtr->Initialize(m_toolId, defaultGroupPresets);
  238. }
  239. void MaterialCanvasApplication::InitMaterialGraphDocumentType()
  240. {
  241. // Initialize system to asynchronously report material and shader related asset processing status for open documents
  242. m_assetStatusReporterSystem.reset(aznew AtomToolsFramework::AssetStatusReporterSystem(m_toolId));
  243. // Initialize system to load and store material graph template files and only reload them if modified
  244. m_graphTemplateFileDataCache.reset(aznew AtomToolsFramework::GraphTemplateFileDataCache(m_toolId));
  245. // Acquiring default Material Canvas document type info so that it can be customized before registration
  246. auto documentTypeInfo = AtomToolsFramework::GraphDocument::BuildDocumentTypeInfo(
  247. "Material Graph",
  248. { "materialgraph" },
  249. { "materialgraphtemplate" },
  250. AtomToolsFramework::GetPathWithoutAlias(AtomToolsFramework::GetSettingsValue<AZStd::string>(
  251. "/O3DE/Atom/MaterialCanvas/DefaultMaterialGraphTemplate",
  252. "@gemroot:MaterialCanvas@/Assets/MaterialCanvas/GraphData/blank_graph.materialgraphtemplate")),
  253. m_graphContext,
  254. [toolId = m_toolId](){ return AZStd::make_shared<MaterialGraphCompiler>(toolId); });
  255. // Overriding documentview factory function to create graph view
  256. documentTypeInfo.m_documentViewFactoryCallback = [this](const AZ::Crc32& toolId, const AZ::Uuid& documentId)
  257. {
  258. m_window->AddDocumentTab(
  259. documentId, aznew AtomToolsFramework::GraphDocumentView(toolId, documentId, m_graphViewSettingsPtr, m_window.get()));
  260. return true;
  261. };
  262. AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
  263. m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, documentTypeInfo);
  264. }
  265. void MaterialCanvasApplication::InitMaterialGraphNodeDocumentType()
  266. {
  267. // Register document type for editing Material Canvas node configurations. This document type does not have a central view widget
  268. // and will show a label directing users to the inspector.
  269. auto documentTypeInfo = AtomToolsFramework::AtomToolsAnyDocument::BuildDocumentTypeInfo(
  270. "Material Graph Node Config",
  271. { "materialgraphnode" },
  272. { "materialgraphnodetemplate" },
  273. AZStd::any(AtomToolsFramework::DynamicNodeConfig()),
  274. AZ::Uuid::CreateNull()); // Null ID because JSON file contains type info and can be loaded directly into AZStd::any
  275. documentTypeInfo.m_documentViewFactoryCallback = [this]([[maybe_unused]] const AZ::Crc32& toolId, const AZ::Uuid& documentId)
  276. {
  277. auto viewWidget = new QLabel("Material Graph Node Config properties can be edited in the inspector.", m_window.get());
  278. viewWidget->setAlignment(Qt::AlignCenter);
  279. return m_window->AddDocumentTab(documentId, viewWidget);
  280. };
  281. AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
  282. m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, documentTypeInfo);
  283. }
  284. void MaterialCanvasApplication::InitShaderSourceDataDocumentType()
  285. {
  286. // Register document type for editing shader source data files. This document type does not have a central view
  287. // and will display a label widget that directs users to edit using the inspector.
  288. auto documentTypeInfo = AtomToolsFramework::AtomToolsAnyDocument::BuildDocumentTypeInfo(
  289. "Shader Source Data",
  290. { "shader" },
  291. {},
  292. AZStd::any(AZ::RPI::ShaderSourceData()),
  293. AZ::RPI::ShaderSourceData::TYPEINFO_Uuid()); // Supplying ID because it is not included in the JSON file
  294. documentTypeInfo.m_documentViewFactoryCallback = [this]([[maybe_unused]] const AZ::Crc32& toolId, const AZ::Uuid& documentId)
  295. {
  296. auto viewWidget = new QLabel("Shader Source Data properties can be edited in the inspector.", m_window.get());
  297. viewWidget->setAlignment(Qt::AlignCenter);
  298. return m_window->AddDocumentTab(documentId, viewWidget);
  299. };
  300. AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Event(
  301. m_toolId, &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::RegisterDocumentType, documentTypeInfo);
  302. }
  303. void MaterialCanvasApplication::InitMainWindow()
  304. {
  305. m_viewportSettingsSystem.reset(aznew AtomToolsFramework::EntityPreviewViewportSettingsSystem(m_toolId));
  306. m_window.reset(aznew MaterialCanvasMainWindow(m_toolId, m_graphViewSettingsPtr));
  307. m_window->show();
  308. }
  309. void MaterialCanvasApplication::InitDefaultDocument()
  310. {
  311. // Create an untitled, empty graph document as soon as the application starts so the user can begin creating immediately.
  312. if (AtomToolsFramework::GetSettingsValue("/O3DE/Atom/MaterialCanvas/CreateDefaultDocumentOnStart", true))
  313. {
  314. AZ::Uuid documentId = AZ::Uuid::CreateNull();
  315. AtomToolsFramework::AtomToolsDocumentSystemRequestBus::EventResult(
  316. documentId,
  317. m_toolId,
  318. &AtomToolsFramework::AtomToolsDocumentSystemRequestBus::Handler::CreateDocumentFromTypeName,
  319. "Material Graph");
  320. AtomToolsFramework::AtomToolsDocumentNotificationBus::Event(
  321. m_toolId, &AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::OnDocumentOpened, documentId);
  322. }
  323. }
  324. void MaterialCanvasApplication::ApplyShaderBuildSettings()
  325. {
  326. // If faster shader build settings are enabled, copy a settings registry file stub into the user settings folder. This will
  327. // override AP and shader build settings, disabling shaders and shader variant building for inactive platforms and RHI. Copying any
  328. // of these settings files requires restarting the application and the asset processor for the changes to be picked up.
  329. if (auto fileIO = AZ::IO::FileIOBase::GetInstance())
  330. {
  331. const AZ::IO::FixedMaxPath materialCanvasGemPath = AZ::Utils::GetGemPath("MaterialCanvas");
  332. const auto settingsPathStub(
  333. materialCanvasGemPath / AZ::SettingsRegistryInterface::RegistryFolder / "user_minimal_shader_build.setregstub");
  334. const auto settingsPathDx12Stub(
  335. materialCanvasGemPath / AZ::SettingsRegistryInterface::RegistryFolder / "user_minimal_shader_build_dx12.setregstub");
  336. const AZ::IO::FixedMaxPath projectPath = AZ::Utils::GetProjectPath();
  337. const auto settingsPath(
  338. projectPath / AZ::SettingsRegistryInterface::DevUserRegistryFolder / "user_minimal_shader_build.setreg");
  339. const auto settingsPathDx12(
  340. projectPath / AZ::SettingsRegistryInterface::DevUserRegistryFolder / "user_minimal_shader_build_dx12.setreg");
  341. const bool enableFasterShaderBuilds =
  342. AtomToolsFramework::GetSettingsValue<bool>("/O3DE/Atom/MaterialCanvas/EnableFasterShaderBuilds", false);
  343. if (enableFasterShaderBuilds)
  344. {
  345. // Windows is the only platform with multiple, non-null RHI, supporting Vulkan and DX12. If DX12 is the active RHI then it
  346. // will require copying its own settings file. Settings files for inactive RHI will be deleted from the user folder.
  347. if (const AZ::Name apiName = AZ::RHI::Factory::Get().GetName(); apiName == AZ::Name("dx12"))
  348. {
  349. fileIO->Copy(settingsPathDx12Stub.c_str(), settingsPathDx12.c_str());
  350. fileIO->Remove(settingsPath.c_str());
  351. }
  352. else
  353. {
  354. fileIO->Copy(settingsPathStub.c_str(), settingsPath.c_str());
  355. fileIO->Remove(settingsPathDx12.c_str());
  356. }
  357. }
  358. else
  359. {
  360. fileIO->Remove(settingsPath.c_str());
  361. fileIO->Remove(settingsPathDx12.c_str());
  362. }
  363. }
  364. }
  365. } // namespace MaterialCanvas