AssetBuilderComponent.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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 <AssetBuilderSDK/AssetBuilderBusses.h>
  10. #include <AssetBuilderSDK/AssetBuilderSDK.h>
  11. #include <AzCore/Component/Component.h>
  12. #include <AzCore/std/parallel/binary_semaphore.h>
  13. #include <AzFramework/Network/SocketConnection.h>
  14. #include <AzToolsFramework/Application/ToolsApplication.h>
  15. #include <AzToolsFramework/API/AssetDatabaseBus.h>
  16. #include "AssetBuilderInfo.h"
  17. //! This bus is used to signal to the AssetBuilderComponent to start up and execute while providing a return code
  18. class BuilderBusTraits
  19. : public AZ::EBusTraits
  20. {
  21. public:
  22. static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
  23. static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
  24. typedef AZStd::recursive_mutex MutexType;
  25. virtual ~BuilderBusTraits() = default;
  26. virtual bool Run() = 0;
  27. };
  28. typedef AZ::EBus<BuilderBusTraits> BuilderBus;
  29. //! Main component of the AssetBuilder that handles interfacing with the AssetProcessor and the Builder module(s)
  30. //! In resident mode, the component will keep the application up and running indefinitely while accepting job requests from the AP network connection
  31. //! The other mods (create, process) will read a job from an `input` file and write the response to the `output` file and then terminate
  32. class AssetBuilderComponent
  33. : public AZ::Component,
  34. public BuilderBus::Handler,
  35. public AssetBuilderSDK::AssetBuilderBus::Handler,
  36. public AzFramework::EngineConnectionEvents::Bus::Handler,
  37. public AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler
  38. {
  39. public:
  40. AZ_COMPONENT(AssetBuilderComponent, "{04332899-5d73-4d41-86b7-b1017d349673}")
  41. static void Reflect(AZ::ReflectContext* context);
  42. bool DoHelloPing();
  43. AssetBuilderComponent() = default;
  44. ~AssetBuilderComponent() override = default;
  45. void PrintHelp();
  46. // AZ::Component overrides
  47. void Activate() override;
  48. void Deactivate() override;
  49. // BuilderBus Handler
  50. bool Run() override;
  51. // AssetBuilderBus Handler
  52. bool FindBuilderInformation(const AZ::Uuid& builderGuid, AssetBuilderSDK::AssetBuilderDesc& descriptionOut) override;
  53. void RegisterBuilderInformation(const AssetBuilderSDK::AssetBuilderDesc& builderDesc) override;
  54. void RegisterComponentDescriptor(AZ::ComponentDescriptor* descriptor) override;
  55. //EngineConnectionEvents Handler
  56. void Disconnected(AzFramework::SocketConnection* connection) override;
  57. static bool IsInDebugMode(const AzFramework::CommandLine& commandLine);
  58. //AssetDatabaseRequestsBus Handler
  59. bool GetAssetDatabaseLocation(AZStd::string& location) override;
  60. protected:
  61. AZ_DISABLE_COPY_MOVE(AssetBuilderComponent);
  62. enum class JobType
  63. {
  64. Create,
  65. Process
  66. };
  67. //! Describes a job request that came in from the network connection
  68. struct Job
  69. {
  70. JobType m_jobType;
  71. AZ::u32 m_requestSerial;
  72. AZStd::unique_ptr<AzFramework::AssetSystem::BaseAssetProcessorMessage> m_netRequest;
  73. AZStd::unique_ptr<AzFramework::AssetSystem::BaseAssetProcessorMessage> m_netResponse;
  74. };
  75. //! Reads a command line parameter and places it in the outValue parameter. Returns false if the value is empty, true otherwise
  76. //! If required is true, an AZ_Error message is output
  77. bool GetParameter(const char* paramName, AZStd::string& outValue, bool required = true) const;
  78. //! Returns the platform specific extension for dynamic libraries
  79. static const char* GetLibraryExtension();
  80. bool ConnectToAssetProcessor();
  81. bool SendRegisteredBuildersToAp();
  82. bool LoadBuilders(const AZStd::string& builderFolder);
  83. bool LoadBuilder(const AZStd::string& filePath);
  84. void UnloadBuilders();
  85. //! Hooks up net job request handling and keeps the AssetBuilder running indefinitely
  86. bool RunInResidentMode(bool sendRegistration);
  87. bool RunDebugTask(AZStd::string&& debugFile, bool runCreateJobs, bool runProcessJob);
  88. bool RunOneShotTask(const AZStd::string& task);
  89. template<typename TNetRequest, typename TNetResponse>
  90. void ResidentJobHandler(AZ::u32 serial, const void* data, AZ::u32 dataLength, JobType jobType);
  91. void CreateJobsResidentHandler(AZ::u32 typeId, AZ::u32 serial, const void* data, AZ::u32 dataLength);
  92. void ProcessJobResidentHandler(AZ::u32 typeId, AZ::u32 serial, const void* data, AZ::u32 dataLength);
  93. bool IsBuilderForFile(const AZStd::string& filePath, const AssetBuilderSDK::AssetBuilderDesc& builderDescription) const;
  94. //! Run by a separate thread to avoid blocking the net recv thread
  95. //! Handles calling the appropriate builder job function for the incoming job
  96. void JobThread();
  97. void ProcessJob(const AssetBuilderSDK::ProcessJobFunction& job, const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& outResponse);
  98. //! If needed looks at collected data and updates the result code from the job accordingly.
  99. void UpdateResultCode(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response) const;
  100. //! Handles reading the request from file, passing it to the specified function and writing the response to file
  101. template<typename TRequest, typename TResponse>
  102. bool HandleTask(const AZStd::string& inputFilePath, const AZStd::string& outputFilePath, const AZStd::function<void(const TRequest& request, TResponse& response)>& handlerFunc);
  103. //! Flush the File Streamer cache to ensure that there aren't stale file handles or data between asset job runs.
  104. void FlushFileStreamerCache();
  105. //! Map used to look up the asset builder to handle a request
  106. AZStd::unordered_map<AZ::Uuid, AZStd::unique_ptr<AssetBuilderSDK::AssetBuilderDesc>> m_assetBuilderDescMap;
  107. //! List of loaded builders
  108. AZStd::vector<AZStd::unique_ptr<AssetBuilder::ExternalModuleAssetBuilderInfo>> m_assetBuilderInfoList;
  109. //! Currently loading builder
  110. AssetBuilder::ExternalModuleAssetBuilderInfo* m_currentAssetBuilder = nullptr;
  111. //! Thread for running a job, so we don't block the network thread while doing work
  112. AZStd::thread_desc m_jobThreadDesc;
  113. AZStd::thread m_jobThread;
  114. //! Indicates if resident mode is up and running
  115. AZStd::atomic<bool> m_running{};
  116. //! Main thread will wait on this event in resident mode. Releasing it will shut down the application
  117. AZStd::binary_semaphore m_mainEvent;
  118. //! Use to signal a new job is ready to be processed
  119. AZStd::binary_semaphore m_jobEvent;
  120. //! Lock for m_queuedJob
  121. AZStd::mutex m_jobMutex;
  122. //! Stored job that is waiting to be picked up for processing by the job thread
  123. AZStd::unique_ptr<Job> m_queuedJob;
  124. AZStd::string m_gameName;
  125. AZStd::string m_projectPath;
  126. AZStd::string m_gameCache;
  127. };