assetprocessor.h 17 KB

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