3
0

MaterialGraphCompiler.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. #pragma once
  9. #include <AtomToolsFramework/Graph/GraphCompiler.h>
  10. #include <AtomToolsFramework/Graph/GraphTemplateFileDataCacheRequestBus.h>
  11. #include <GraphModel/Model/Node.h>
  12. namespace MaterialCanvas
  13. {
  14. //! MaterialGraphCompiler traverses a material graph, searching for and splicing shader code snippets, variable values and definitions,
  15. //! and other information into complete, functional material types, materials, and shaders. Currently, the resulting files will be
  16. //! generated an output into the same folder location has the source graph.
  17. class MaterialGraphCompiler : public AtomToolsFramework::GraphCompiler
  18. {
  19. public:
  20. AZ_RTTI(MaterialGraphCompiler, "{570E3923-48C4-4B91-BC44-3145BE771E9B}", AtomToolsFramework::GraphCompiler);
  21. AZ_CLASS_ALLOCATOR(MaterialGraphCompiler, AZ::SystemAllocator);
  22. AZ_DISABLE_COPY_MOVE(MaterialGraphCompiler);
  23. static void Reflect(AZ::ReflectContext* context);
  24. MaterialGraphCompiler() = default;
  25. MaterialGraphCompiler(const AZ::Crc32& toolId);
  26. virtual ~MaterialGraphCompiler();
  27. // AtomToolsFramework::GraphCompiler overrides...
  28. AZStd::string GetGraphPath() const override;
  29. bool CompileGraph(GraphModel::GraphPtr graph, const AZStd::string& graphName, const AZStd::string& graphPath) override;
  30. private:
  31. void BuildSlotValueTable();
  32. void BuildDependencyTables();
  33. void BuildTemplatePathsForCurrentNode(const GraphModel::ConstNodePtr& currentNode);
  34. bool LoadTemplatesForCurrentNode();
  35. void DeleteExistingFilesForCurrentNode();
  36. void ClearFingerprintsForCurrentNode();
  37. void PreprocessTemplatesForCurrentNode();
  38. void BuildInstructionsForCurrentNode(const GraphModel::ConstNodePtr& currentNode);
  39. void BuildMaterialSrgForCurrentNode();
  40. bool BuildMaterialTypeForCurrentNode(const GraphModel::ConstNodePtr& currentNode);
  41. bool ExportTemplatesMatchingRegex(const AZStd::string& pattern);
  42. // Convert the template file path into a save file path based on the document name.
  43. AZStd::string GetOutputPathFromTemplatePath(const AZStd::string& templatePath) const;
  44. // Functions assisting with conversions between different vector and scalar types. Functions like these will eventually be moved out
  45. // of the document class so that they can be registered more flexibly and extensively.
  46. unsigned int GetVectorSize(const AZStd::any& slotValue) const;
  47. AZStd::any ConvertToScalar(const AZStd::any& slotValue) const;
  48. template<typename T>
  49. AZStd::any ConvertToVector(const AZStd::any& slotValue) const;
  50. AZStd::any ConvertToVector(const AZStd::any& slotValue, unsigned int score) const;
  51. // Returns the value of the slot or the slots incoming connection if present.
  52. AZStd::any GetValueFromSlot(GraphModel::ConstSlotPtr slot) const;
  53. // Returns the value for the corresponding slot or the slot providing its input, if connected.
  54. AZStd::any GetValueFromSlotOrConnection(GraphModel::ConstSlotPtr slot) const;
  55. // Convert special slot type names, like color, into one compatible with AZSL shader code.
  56. AZStd::string GetAzslTypeFromSlot(GraphModel::ConstSlotPtr slot) const;
  57. // Convert a stored slot value into a string representation that can be injected into AZSL shader code.
  58. AZStd::string GetAzslValueFromSlot(GraphModel::ConstSlotPtr slot) const;
  59. // Generate AZSL to insert/substitute members in the material SRG definition. The code for most data types is relatively small and
  60. // can be entered manually but SamplerState and other data types with several members need additional Handling transform the data
  61. // into the required format.
  62. AZStd::string GetAzslSrgMemberFromSlot(
  63. GraphModel::ConstNodePtr node, const AtomToolsFramework::DynamicNodeSlotConfig& slotConfig) const;
  64. // Creates a table of strings to search for and the values to replace them with for a specific node.
  65. AZStd::vector<AZStd::pair<AZStd::string, AZStd::string>> GetSubstitutionSymbolsFromNode(GraphModel::ConstNodePtr node) const;
  66. // Collect instructions from a slot and perform substitutions based on node and slot types, names, values, and connections.
  67. AZStd::vector<AZStd::string> GetInstructionsFromSlot(
  68. GraphModel::ConstNodePtr node,
  69. const AtomToolsFramework::DynamicNodeSlotConfig& slotConfig,
  70. const AZStd::vector<AZStd::pair<AZStd::string, AZStd::string>>& substitutionSymbols) const;
  71. // Determine if instructions contained on an input node should be used as part of code generation based on node connections.
  72. bool ShouldUseInstructionsFromInputNode(
  73. GraphModel::ConstNodePtr outputNode,
  74. GraphModel::ConstNodePtr inputNode,
  75. const AZStd::vector<AZStd::string>& inputSlotNames) const;
  76. // Build a list of all graph nodes sorted in execution order based on depth
  77. AZStd::vector<GraphModel::ConstNodePtr> GetAllNodesInExecutionOrder() const;
  78. // Build a list of all graph nodes That feed into specific slots an output node, sorted in execution order based on depth
  79. AZStd::vector<GraphModel::ConstNodePtr> GetInstructionNodesInExecutionOrder(
  80. GraphModel::ConstNodePtr outputNode, const AZStd::vector<AZStd::string>& inputSlotNames) const;
  81. // Generate AZSL instructions for an output node by evaluating all of the sorted graph nodes for connections to input slots
  82. AZStd::vector<AZStd::string> GetInstructionsFromConnectedNodes(
  83. GraphModel::ConstNodePtr outputNode,
  84. const AZStd::vector<AZStd::string>& inputSlotNames,
  85. AZStd::vector<GraphModel::ConstNodePtr>& instructionNodes) const;
  86. // Create a unique string identifier, from a node title and ID, that can be used for a file name or symbol in code
  87. AZStd::string GetSymbolNameFromNode(GraphModel::ConstNodePtr node) const;
  88. // Create a unique string identifier, from the node symbol name and slot title, that can be used as a variable name in code
  89. AZStd::string GetSymbolNameFromSlot(GraphModel::ConstSlotPtr slot) const;
  90. // Convert a material input node into AZSL lines of variables that can be injected into the material SRG
  91. AZStd::vector<AZStd::string> GetMaterialPropertySrgMemberFromSlot(
  92. GraphModel::ConstNodePtr node,
  93. const AtomToolsFramework::DynamicNodeSlotConfig& slotConfig,
  94. const AZStd::vector<AZStd::pair<AZStd::string, AZStd::string>>& substitutionSymbols) const;
  95. // Convert all material input nodes into AZSL lines of variables that can be injected into the material SRG
  96. AZStd::vector<AZStd::string> GetMaterialPropertySrgMemberFromNodes(const AZStd::vector<GraphModel::ConstNodePtr>& instructionNodes) const;
  97. // Creates and exports a material type source file by loading an existing template, replacing special tokens, and injecting
  98. // properties defined in material input nodes
  99. bool BuildMaterialTypeFromTemplate(
  100. GraphModel::ConstNodePtr templateNode,
  101. const AZStd::vector<GraphModel::ConstNodePtr>& instructionNodes,
  102. const AZStd::string& templateInputPath,
  103. const AZStd::string& templateOutputPath) const;
  104. // Returns the name that will be used to replace material graph name during any substitutions
  105. AZStd::string GetUniqueGraphName() const;
  106. // All slots and nodes will be visited to collect all of the unique include paths.
  107. AZStd::set<AZStd::string> m_includePaths;
  108. // There's probably no reason to distinguish between function and class definitions.
  109. // This could really be any globally defined function, class, struct, define.
  110. AZStd::vector<AZStd::string> m_classDefinitions;
  111. AZStd::vector<AZStd::string> m_functionDefinitions;
  112. // Container of unique node configurations IDs visited on the graph to collect include paths, class definitions, and function definitions.
  113. AZStd::unordered_set<AZ::Uuid> m_configIdsVisited;
  114. // Table of values for every slot, on every node, including values redirected from incoming connections, and values upgraded to
  115. // match types and sizes of values on related slots.
  116. AZStd::map<GraphModel::ConstSlotPtr, AZStd::any> m_slotValueTable;
  117. // This counter will be used as a suffix for graph name substitutions in case multiple template nodes are included in the same graph
  118. int m_templateNodeCount = 0;
  119. // Container of paths for template files that need to be evaluated and have products generated for the current node.
  120. AZStd::set<AZStd::string> m_templatePathsForCurrentNode;
  121. // Container of template source file data and lines they need to be transformed as part of compiling the graph.
  122. AZStd::list<AtomToolsFramework::GraphTemplateFileData> m_templateFileDataVecForCurrentNode;
  123. // A container of all nodes contributing instructions to the current node
  124. AZStd::mutex m_instructionNodesForCurrentNodeMutex;
  125. AZStd::vector<GraphModel::ConstNodePtr> m_instructionNodesForCurrentNode;
  126. };
  127. } // namespace MaterialCanvas