assetprocessor.h 17 KB

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