assetprocessor.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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. AZStd::string ToString() const
  174. {
  175. 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());
  176. }
  177. };
  178. //! JobDetails is an internal structure that is used to store job related information by the Asset Processor
  179. //! 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
  180. //! After which, the Job Entry is used to track and identify jobs.
  181. class JobDetails
  182. {
  183. public:
  184. JobEntry m_jobEntry;
  185. AZStd::string m_extraInformationForFingerprinting;
  186. const ScanFolderInfo* m_scanFolder; // the scan folder info the file was found in
  187. AZ::IO::Path m_intermediatePath; // The base/root path of the intermediate output folder
  188. AZ::IO::Path m_cachePath; // The base/root path of the cache folder, including the platform
  189. AZ::IO::Path m_relativePath; // Relative path portion of the output file. This can be overridden by the builder
  190. // UUID of the original source asset.
  191. // If this job is for an intermediate asset, the UUID is for the direct source which produced the intermediate.
  192. // If the original source asset is not using metadata files, this value will be empty.
  193. AZ::Uuid m_sourceUuid;
  194. AZStd::vector<JobDependencyInternal> m_jobDependencyList;
  195. // which files to include in the fingerprinting. (Not including job dependencies)
  196. SourceFilesForFingerprintingContainer m_fingerprintFiles;
  197. bool m_critical = false;
  198. int m_priority = -1;
  199. // indicates whether we need to check the server first for the outputs of this job
  200. // before we start processing locally
  201. bool m_checkServer = false;
  202. // Indicates whether this job needs to be processed irrespective of whether its fingerprint got modified or not.
  203. bool m_autoProcessJob = false;
  204. AssetBuilderSDK::AssetBuilderDesc m_assetBuilderDesc;
  205. AssetBuilderSDK::JobParameterMap m_jobParam;
  206. AZStd::vector<AZStd::string> m_warnings;
  207. // autoFail makes jobs which are added to the list and will automatically fail, and are used
  208. // to make sure that a "failure" shows up on the list so that the user can click to inspect the job and see why
  209. // it has failed instead of having a job fail mysteriously or be hard to find out why.
  210. // it is currently the only way for the job to be marked as a failure because of data integrity reasons after the builder
  211. // has already succeeded in actually making the asset data.
  212. // 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
  213. bool m_autoFail = false;
  214. // If true, this job declared a source dependency that could not be resolved.
  215. // There's a chance that the dependency might be fulfilled as part of processing other assets, if
  216. // an intermediate asset matches the missing dependency. If this is true, this job is treated as
  217. // lower priority than other jobs, so that there's a chance the dependency is resolved before this job runs.
  218. // If that dependency is resolved, then this job will be removed from the queue and re-added.
  219. // If the dependency is not resolved, then the job will run at the end of the queue still, in case the
  220. // builder is able to process the asset with the dependency gap, if the dependency was optional.
  221. bool m_hasMissingSourceDependency = false;
  222. AZStd::string ToString() const
  223. {
  224. return QString("%1 %2 %3").arg(m_jobEntry.GetAbsoluteSourcePath(), m_jobEntry.m_platformInfo.m_identifier.c_str(), m_jobEntry.m_jobKey).toUtf8().data();
  225. }
  226. bool operator==(const JobDetails& rhs) const
  227. {
  228. return ((m_jobEntry.GetAbsoluteSourcePath() == rhs.m_jobEntry.GetAbsoluteSourcePath()) &&
  229. (m_jobEntry.m_platformInfo.m_identifier == rhs.m_jobEntry.m_platformInfo.m_identifier) &&
  230. (m_jobEntry.m_jobKey == rhs.m_jobEntry.m_jobKey) &&
  231. m_jobEntry.m_builderGuid == rhs.m_jobEntry.m_builderGuid);
  232. }
  233. JobDetails() = default;
  234. };
  235. //! JobDesc struct is used for identifying jobs that need to be processed again
  236. //! because of job dependency declared on them by other jobs
  237. struct JobDesc
  238. {
  239. SourceAssetReference m_sourceAsset;
  240. AZStd::string m_jobKey;
  241. AZStd::string m_platformIdentifier;
  242. bool operator==(const JobDesc& rhs) const
  243. {
  244. return m_sourceAsset == rhs.m_sourceAsset
  245. && m_platformIdentifier == rhs.m_platformIdentifier
  246. && m_jobKey == rhs.m_jobKey;
  247. }
  248. JobDesc(SourceAssetReference sourceAsset, const AZStd::string& jobKey, const AZStd::string& platformIdentifier)
  249. : m_sourceAsset(AZStd::move(sourceAsset))
  250. , m_jobKey(jobKey)
  251. , m_platformIdentifier(platformIdentifier)
  252. {
  253. }
  254. AZStd::string ToString() const
  255. {
  256. AZStd::string lowerSourceName = m_sourceAsset.AbsolutePath().c_str();
  257. AZStd::to_lower(lowerSourceName.begin(), lowerSourceName.end());
  258. return AZStd::string::format("%s %s %s", lowerSourceName.c_str(), m_platformIdentifier.c_str(), m_jobKey.c_str());
  259. }
  260. };
  261. //! JobIndentifier is an internal structure that store all the data that can uniquely identify a job
  262. struct JobIndentifier
  263. {
  264. JobDesc m_jobDesc;
  265. AZ::Uuid m_builderUuid = AZ::Uuid::CreateNull();
  266. bool operator==(const JobIndentifier& rhs) const
  267. {
  268. return (m_jobDesc == rhs.m_jobDesc) && (m_builderUuid == rhs.m_builderUuid);
  269. }
  270. JobIndentifier(const JobDesc& jobDesc, const AZ::Uuid builderUuid)
  271. : m_jobDesc(jobDesc)
  272. , m_builderUuid(builderUuid)
  273. {
  274. }
  275. };
  276. } // namespace AssetProcessor
  277. namespace AZStd
  278. {
  279. template<>
  280. struct hash<AssetProcessor::JobDetails>
  281. {
  282. using argument_type = AssetProcessor::JobDetails;
  283. using result_type = size_t;
  284. result_type operator() (const argument_type& jobDetails) const
  285. {
  286. size_t h = 0;
  287. hash_combine(h, jobDetails.ToString());
  288. hash_combine(h, jobDetails.m_jobEntry.m_builderGuid);
  289. return h;
  290. }
  291. };
  292. template<>
  293. struct hash<AssetProcessor::JobDesc>
  294. {
  295. using argument_type = AssetProcessor::JobDesc;
  296. using result_type = size_t;
  297. result_type operator() (const argument_type& jobDesc) const
  298. {
  299. size_t h = 0;
  300. hash_combine(h, jobDesc.ToString());
  301. return h;
  302. }
  303. };
  304. template<>
  305. struct hash<AssetProcessor::JobIndentifier>
  306. {
  307. using argument_type = AssetProcessor::JobIndentifier;
  308. using result_type = size_t;
  309. result_type operator() (const argument_type& jobIndentifier) const
  310. {
  311. size_t h = 0;
  312. hash_combine(h, jobIndentifier.m_jobDesc);
  313. hash_combine(h, jobIndentifier.m_builderUuid);
  314. return h;
  315. }
  316. };
  317. }
  318. Q_DECLARE_METATYPE(AssetBuilderSDK::ProcessJobResponse)
  319. Q_DECLARE_METATYPE(AssetProcessor::JobEntry)
  320. Q_DECLARE_METATYPE(AssetProcessor::AssetProcessorStatusEntry)
  321. Q_DECLARE_METATYPE(AssetProcessor::JobDetails)
  322. Q_DECLARE_METATYPE(AssetProcessor::NetworkRequestID)
  323. Q_DECLARE_METATYPE(AssetProcessor::AssetScanningStatus)
  324. Q_DECLARE_METATYPE(AssetProcessor::AssetCatalogStatus)