assetprocessor.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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 <QPair>
  10. #include <QMetaType>
  11. #include <AzCore/Math/Uuid.h>
  12. #include <AzCore/Math/Crc.h>
  13. #include <QString>
  14. #include <QList>
  15. #include <QSet>
  16. #include <AssetBuilderSDK/AssetBuilderBusses.h>
  17. #include <AssetBuilderSDK/AssetBuilderSDK.h>
  18. #include <AzCore/std/containers/vector.h>
  19. #include <AzCore/std/containers/map.h>
  20. #include <AzCore/std/containers/set.h>
  21. #include <AzCore/Asset/AssetCommon.h>
  22. #include <AzCore/IO/Path/Path.h>
  23. #include <AzFramework/Asset/AssetRegistry.h>
  24. #include <AzCore/Math/Crc.h>
  25. #include <native/AssetManager/assetScanFolderInfo.h>
  26. #include <AzFramework/StringFunc/StringFunc.h>
  27. #include "AssetProcessor_Traits_Platform.h"
  28. #include <AssetManager/SourceAssetReference.h>
  29. namespace AssetProcessor
  30. {
  31. // global settings for Asset Processor, they usually come from the engine config file
  32. // but individual gems, projects, and users can override them.
  33. constexpr const char* AssetProcessorSettingsKey{ "/Amazon/AssetProcessor/Settings" };
  34. constexpr const char* DebugChannel = "Debug"; //Use this channel name if you want to write the message to the log file only.
  35. constexpr const char* ConsoleChannel = "AssetProcessor";// Use this channel name if you want to write the message to both the console and the log file.
  36. constexpr const char* FENCE_FILE_EXTENSION = "fence"; //fence file extension
  37. constexpr const char* AutoFailReasonKey = "failreason"; // the key to look in for auto-fail reason.
  38. constexpr const char* AutoFailLogFile = "faillogfile"; // if this is provided, this is a complete log of the failure and will be added after the failreason.
  39. constexpr const char* AutoFailOmitFromDatabaseKey = "failreason_omitFromDatabase"; // if set in your job info hash, your job will not be tracked by the database.
  40. const unsigned int g_RetriesForFenceFile = 5; // number of retries for fencing
  41. constexpr int RetriesForJobLostConnection = ASSETPROCESSOR_TRAIT_ASSET_BUILDER_LOST_CONNECTION_RETRIES; // number of times to retry a job when a network error due to network issues or a crashed AssetBuilder process is determined to have caused a job failure
  42. [[maybe_unused]] constexpr const char* IntermediateAssetsFolderName = "Intermediate Assets"; // name of the intermediate assets folder
  43. // Even though AP can handle files with path length greater than window's legacy path length limit, we have some 3rdparty sdk's
  44. // which do not handle this case, therefore we will make AP warn about jobs whose either source file or output file name exceeds the windows legacy path length limit
  45. // on all platforms
  46. #define ASSETPROCESSOR_WARN_PATH_LEN 260
  47. //! a shared convenience typedef for requests that have come over the network
  48. //! The first element is the connection id it came from and the second element is the serial number
  49. //! which can be used to send a response.
  50. typedef QPair<quint32, quint32> NetworkRequestID;
  51. //! a shared convenience typedef for Escalating Jobs
  52. //! The first element is the jobRunKey of the job and the second element is the escalation
  53. typedef QList<QPair<AZ::s64, int> > JobIdEscalationList;
  54. //! A map which is used to keep absolute paths --> Database Paths of source files.
  55. //! This is intentionally a map (not unordered_map) in order to ensure order is stable, and to eliminate duplicates.
  56. typedef AZStd::map<AZStd::string, AZStd::string> SourceFilesForFingerprintingContainer;
  57. //! A shared convenience typedef for tracking a source path and a scan folder ID together.
  58. typedef AZStd::pair<AZStd::string, AZ::s64> SourceAndScanID;
  59. enum AssetScanningStatus
  60. {
  61. Unknown,
  62. Started,
  63. InProgress,
  64. Completed,
  65. Stopped
  66. };
  67. //! This enum stores all the different job escalation values
  68. enum JobEscalation
  69. {
  70. ProcessAssetRequestSyncEscalation = 200, //!< Used when the Sync Compile Asset (blocking compile) is requested
  71. ProcessAssetRequestStatusEscalation = 150, //!< Used when the Get Status is called on a specific asset, but not sync compile.
  72. AssetJobRequestEscalation = 100, //!< Used when the user is asking about a specific job, but not syncing
  73. CriticalDependencyEscalation = 50, //!< Used when it is discovered that a critical job depends on this job.
  74. DefaultEscalation = 0
  75. };
  76. //! This enum stores all the different asset processor status values
  77. enum AssetProcessorStatus
  78. {
  79. Initializing_Gems,
  80. Initializing_Builders,
  81. Scanning_Started,
  82. Analyzing_Jobs,
  83. Processing_Jobs,
  84. };
  85. enum AssetCatalogStatus
  86. {
  87. RequiresSaving,
  88. UpToDate
  89. };
  90. //! AssetProcessorStatusEntry stores all the necessary information related to AssetProcessorStatus
  91. struct AssetProcessorStatusEntry
  92. {
  93. AssetProcessorStatus m_status;
  94. unsigned int m_count = 0;
  95. QString m_extraInfo; //this can be used to send any other info like name etc
  96. explicit AssetProcessorStatusEntry(AssetProcessorStatus status, unsigned int count = 0, QString extraInfo = QString())
  97. : m_status(status)
  98. , m_count(count)
  99. , m_extraInfo(extraInfo)
  100. {
  101. }
  102. AssetProcessorStatusEntry() = default;
  103. };
  104. struct AssetRecognizer;
  105. //! JobEntry is an internal structure that is used to uniquely identify a specific job and keeps track of it as it flows through the AP system
  106. //! It prevents us from having to copy the entire of JobDetails, which is a very heavy structure.
  107. //! In general, communication ABOUT jobs will have the JobEntry as the key
  108. class JobEntry
  109. {
  110. public:
  111. // note that QStrings are ref-counted copy-on-write, so a move operation will not be beneficial unless this struct gains considerable heap allocated fields.
  112. SourceAssetReference m_sourceAssetReference;
  113. AZ::Uuid m_builderGuid = AZ::Uuid::CreateNull(); //! the builder that will perform the job
  114. AssetBuilderSDK::PlatformInfo m_platformInfo;
  115. AZ::Uuid m_sourceFileUUID = AZ::Uuid::CreateNull(); ///< The actual UUID of the source being processed
  116. QString m_jobKey; // JobKey is used when a single input file, for a single platform, for a single builder outputs many separate jobs
  117. AZ::u32 m_computedFingerprint = 0; // what the fingerprint was at the time of job creation.
  118. qint64 m_computedFingerprintTimeStamp = 0; // stores the number of milliseconds since the universal coordinated time when the fingerprint was computed.
  119. AZ::u64 m_jobRunKey = 0;
  120. AZ::s64 m_failureCauseSourceId = AzToolsFramework::AssetDatabase::InvalidEntryId; // Id of the source that caused this job to fail (typically due to a conflict).
  121. AZ::u32 m_failureCauseFingerprint = 0; // Fingerprint of the job that caused this job to fail. Used to prevent infinite retry loops.
  122. bool m_checkExclusiveLock = true; ///< indicates whether we need to check the input file for exclusive lock before we process this job
  123. bool m_addToDatabase = true; ///< If false, this is just a UI job, and should not affect the database.
  124. QString GetAbsoluteSourcePath() const
  125. {
  126. return m_sourceAssetReference.AbsolutePath().c_str();
  127. }
  128. AZ::u32 GetHash() const
  129. {
  130. AZ::Crc32 crc(m_sourceAssetReference.ScanFolderPath().c_str());
  131. crc.Add(m_sourceAssetReference.RelativePath().c_str());
  132. crc.Add(m_platformInfo.m_identifier.c_str());
  133. crc.Add(m_jobKey.toUtf8().constData());
  134. crc.Add(m_builderGuid.ToString<AZStd::string>().c_str());
  135. return crc;
  136. }
  137. JobEntry() = default;
  138. JobEntry(SourceAssetReference sourceAssetReference, const AZ::Uuid& builderGuid, const AssetBuilderSDK::PlatformInfo& platformInfo, QString jobKey, AZ::u32 computedFingerprint, AZ::u64 jobRunKey, const AZ::Uuid &sourceUuid, bool addToDatabase = true)
  139. : m_sourceAssetReference(AZStd::move(sourceAssetReference))
  140. , m_builderGuid(builderGuid)
  141. , m_platformInfo(platformInfo)
  142. , m_jobKey(jobKey)
  143. , m_computedFingerprint(computedFingerprint)
  144. , m_jobRunKey(jobRunKey)
  145. , m_addToDatabase(addToDatabase)
  146. , m_sourceFileUUID(sourceUuid)
  147. {
  148. }
  149. };
  150. //! This is an internal structure that hold all the information related to source file Dependency
  151. struct SourceFileDependencyInternal
  152. {
  153. AZStd::string m_sourceWatchFolder; // this is the absolute path to the watch folder.
  154. AZStd::string m_relativeSourcePath; // this is a pure relative path, not a database path
  155. AZ::Uuid m_sourceUUID;
  156. AZ::Uuid m_builderId;
  157. AssetBuilderSDK::SourceFileDependency m_sourceFileDependency; // this is the raw data captured from the builder.
  158. AZStd::string ToString() const
  159. {
  160. return AZStd::string::format(" %s %s %s", m_sourceUUID.ToString<AZStd::string>().c_str(), m_builderId.ToString<AZStd::string>().c_str(), m_relativeSourcePath.c_str());
  161. }
  162. };
  163. //! JobDependencyInternal is an internal structure that is used to store job dependency related info
  164. //! for later processing once we have resolved all the job dependency.
  165. struct JobDependencyInternal
  166. {
  167. JobDependencyInternal(const AssetBuilderSDK::JobDependency& jobDependency)
  168. :m_jobDependency(jobDependency)
  169. {
  170. }
  171. AZStd::set<AZ::Uuid> m_builderUuidList;// ordered set because we have to use dependent jobs fingerprint in some sorted order.
  172. AssetBuilderSDK::JobDependency m_jobDependency;
  173. // Set to true if the source file is missing at the time of job creation.
  174. // Updated to false later when the dependency appears.
  175. bool m_isMissingSource = false;
  176. AZStd::string ToString() const
  177. {
  178. return AZStd::string::format("%s %s %s", m_jobDependency.m_sourceFile.m_sourceFileDependencyPath.c_str(), m_jobDependency.m_jobKey.c_str(), m_jobDependency.m_platformIdentifier.c_str());
  179. }
  180. };
  181. //! JobDetails is an internal structure that is used to store job related information by the Asset Processor
  182. //! Its heavy, since it contains the parameter map and the builder desc so is expensive to copy and in general only used to create jobs
  183. //! After which, the Job Entry is used to track and identify jobs.
  184. class JobDetails
  185. {
  186. public:
  187. JobEntry m_jobEntry;
  188. AZStd::string m_extraInformationForFingerprinting;
  189. const ScanFolderInfo* m_scanFolder; // the scan folder info the file was found in
  190. AZ::IO::Path m_intermediatePath; // The base/root path of the intermediate output folder
  191. AZ::IO::Path m_cachePath; // The base/root path of the cache folder, including the platform
  192. AZ::IO::Path m_relativePath; // Relative path portion of the output file. This can be overridden by the builder
  193. // UUID of the original source asset.
  194. // If this job is for an intermediate asset, the UUID is for the direct source which produced the intermediate.
  195. // If the original source asset is not using metadata files, this value will be empty.
  196. AZ::Uuid m_sourceUuid;
  197. AZStd::vector<JobDependencyInternal> m_jobDependencyList;
  198. // which files to include in the fingerprinting. (Not including job dependencies)
  199. SourceFilesForFingerprintingContainer m_fingerprintFiles;
  200. bool m_critical = false;
  201. int m_priority = -1;
  202. // indicates whether we need to check the server first for the outputs of this job
  203. // before we start processing locally
  204. bool m_checkServer = false;
  205. // Indicates whether this job needs to be processed irrespective of whether its fingerprint got modified or not.
  206. bool m_autoProcessJob = false;
  207. AssetBuilderSDK::AssetBuilderDesc m_assetBuilderDesc;
  208. AssetBuilderSDK::JobParameterMap m_jobParam;
  209. AZStd::vector<AZStd::string> m_warnings;
  210. // autoFail makes jobs which are added to the list and will automatically fail, and are used
  211. // to make sure that a "failure" shows up on the list so that the user can click to inspect the job and see why
  212. // it has failed instead of having a job fail mysteriously or be hard to find out why.
  213. // it is currently the only way for the job to be marked as a failure because of data integrity reasons after the builder
  214. // has already succeeded in actually making the asset data.
  215. // if you set a job to "auto fail" it will check the m_jobParam map for a AZ_CRC(AutoFailReasonKey) and use that, if present, for fail information
  216. bool m_autoFail = false;
  217. AZStd::string ToString() const
  218. {
  219. return QString("%1 %2 %3").arg(m_jobEntry.GetAbsoluteSourcePath(), m_jobEntry.m_platformInfo.m_identifier.c_str(), m_jobEntry.m_jobKey).toUtf8().data();
  220. }
  221. bool operator==(const JobDetails& rhs) const
  222. {
  223. return ((m_jobEntry.GetAbsoluteSourcePath() == rhs.m_jobEntry.GetAbsoluteSourcePath()) &&
  224. (m_jobEntry.m_platformInfo.m_identifier == rhs.m_jobEntry.m_platformInfo.m_identifier) &&
  225. (m_jobEntry.m_jobKey == rhs.m_jobEntry.m_jobKey) &&
  226. m_jobEntry.m_builderGuid == rhs.m_jobEntry.m_builderGuid);
  227. }
  228. JobDetails() = default;
  229. bool HasMissingSourceDependency() const
  230. {
  231. for (const auto& jobDependency : m_jobDependencyList)
  232. {
  233. if (jobDependency.m_isMissingSource)
  234. {
  235. return true;
  236. }
  237. }
  238. return false;
  239. }
  240. };
  241. //! JobDesc struct is used for identifying jobs that need to be processed again
  242. //! because of job dependency declared on them by other jobs
  243. struct JobDesc
  244. {
  245. SourceAssetReference m_sourceAsset;
  246. AZStd::string m_jobKey;
  247. AZStd::string m_platformIdentifier;
  248. bool operator==(const JobDesc& rhs) const
  249. {
  250. return m_sourceAsset == rhs.m_sourceAsset
  251. && m_platformIdentifier == rhs.m_platformIdentifier
  252. && m_jobKey == rhs.m_jobKey;
  253. }
  254. JobDesc(SourceAssetReference sourceAsset, const AZStd::string& jobKey, const AZStd::string& platformIdentifier)
  255. : m_sourceAsset(AZStd::move(sourceAsset))
  256. , m_jobKey(jobKey)
  257. , m_platformIdentifier(platformIdentifier)
  258. {
  259. }
  260. AZStd::string ToString() const
  261. {
  262. AZStd::string lowerSourceName = m_sourceAsset.AbsolutePath().c_str();
  263. AZStd::to_lower(lowerSourceName.begin(), lowerSourceName.end());
  264. return AZStd::string::format("%s %s %s", lowerSourceName.c_str(), m_platformIdentifier.c_str(), m_jobKey.c_str());
  265. }
  266. };
  267. //! JobIndentifier is an internal structure that store all the data that can uniquely identify a job
  268. struct JobIndentifier
  269. {
  270. JobDesc m_jobDesc;
  271. AZ::Uuid m_builderUuid = AZ::Uuid::CreateNull();
  272. bool operator==(const JobIndentifier& rhs) const
  273. {
  274. return (m_jobDesc == rhs.m_jobDesc) && (m_builderUuid == rhs.m_builderUuid);
  275. }
  276. JobIndentifier(const JobDesc& jobDesc, const AZ::Uuid builderUuid)
  277. : m_jobDesc(jobDesc)
  278. , m_builderUuid(builderUuid)
  279. {
  280. }
  281. };
  282. } // namespace AssetProcessor
  283. namespace AZStd
  284. {
  285. template<>
  286. struct hash<AssetProcessor::JobDetails>
  287. {
  288. using argument_type = AssetProcessor::JobDetails;
  289. using result_type = size_t;
  290. result_type operator() (const argument_type& jobDetails) const
  291. {
  292. size_t h = 0;
  293. hash_combine(h, jobDetails.ToString());
  294. hash_combine(h, jobDetails.m_jobEntry.m_builderGuid);
  295. return h;
  296. }
  297. };
  298. template<>
  299. struct hash<AssetProcessor::JobDesc>
  300. {
  301. using argument_type = AssetProcessor::JobDesc;
  302. using result_type = size_t;
  303. result_type operator() (const argument_type& jobDesc) const
  304. {
  305. size_t h = 0;
  306. hash_combine(h, jobDesc.ToString());
  307. return h;
  308. }
  309. };
  310. template<>
  311. struct hash<AssetProcessor::JobIndentifier>
  312. {
  313. using argument_type = AssetProcessor::JobIndentifier;
  314. using result_type = size_t;
  315. result_type operator() (const argument_type& jobIndentifier) const
  316. {
  317. size_t h = 0;
  318. hash_combine(h, jobIndentifier.m_jobDesc);
  319. hash_combine(h, jobIndentifier.m_builderUuid);
  320. return h;
  321. }
  322. };
  323. }
  324. Q_DECLARE_METATYPE(AssetBuilderSDK::ProcessJobResponse)
  325. Q_DECLARE_METATYPE(AssetProcessor::JobEntry)
  326. Q_DECLARE_METATYPE(AssetProcessor::AssetProcessorStatusEntry)
  327. Q_DECLARE_METATYPE(AssetProcessor::JobDetails)
  328. Q_DECLARE_METATYPE(AssetProcessor::NetworkRequestID)
  329. Q_DECLARE_METATYPE(AssetProcessor::AssetScanningStatus)
  330. Q_DECLARE_METATYPE(AssetProcessor::AssetCatalogStatus)