ResourcePoolBuilder.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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. #include <ResourcePool/ResourcePoolBuilder.h>
  9. #include <AzCore/Serialization/Utils.h>
  10. #include <AzCore/std/smart_ptr/make_shared.h>
  11. #include <AzFramework/IO/LocalFileIO.h>
  12. #include <AzFramework/StringFunc/StringFunc.h>
  13. #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
  14. #include <AzCore/Serialization/Json/JsonUtils.h>
  15. #include <Atom/RHI.Reflect/BufferPoolDescriptor.h>
  16. #include <Atom/RHI.Reflect/ImagePoolDescriptor.h>
  17. #include <Atom/RPI.Reflect/ResourcePoolAssetCreator.h>
  18. #include <Atom/RPI.Reflect/Image/StreamingImagePoolAssetCreator.h>
  19. namespace AZ
  20. {
  21. AZ_TYPE_INFO_SPECIALIZE(RPI::ResourcePoolAssetType, "{09D35821-2D42-456B-B53C-C02BF387C5C4}");
  22. using namespace RPI;
  23. namespace RPI
  24. {
  25. // The file extension for the source file of resource pool Asset
  26. const char* s_sourcePoolAssetExt = "resourcepool";
  27. void ResourcePoolBuilder::RegisterBuilder()
  28. {
  29. AssetBuilderSDK::AssetBuilderDesc builderDescriptor;
  30. builderDescriptor.m_name = "Atom Resource Pool Asset Builder";
  31. builderDescriptor.m_version = 2; //ATOM-15196
  32. builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern(AZStd::string("*.") + s_sourcePoolAssetExt,
  33. AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
  34. builderDescriptor.m_busId = azrtti_typeid<ResourcePoolBuilder>();
  35. builderDescriptor.m_createJobFunction = AZStd::bind(&ResourcePoolBuilder::CreateJobs, this,
  36. AZStd::placeholders::_1, AZStd::placeholders::_2);
  37. builderDescriptor.m_processJobFunction = AZStd::bind(&ResourcePoolBuilder::ProcessJob, this,
  38. AZStd::placeholders::_1, AZStd::placeholders::_2);
  39. BusConnect(builderDescriptor.m_busId);
  40. AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDescriptor);
  41. }
  42. ResourcePoolBuilder::~ResourcePoolBuilder()
  43. {
  44. BusDisconnect();
  45. }
  46. void ResourcePoolBuilder::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response)
  47. {
  48. if (m_isShuttingDown)
  49. {
  50. response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown;
  51. return;
  52. }
  53. for (const AssetBuilderSDK::PlatformInfo& platformInfo : request.m_enabledPlatforms)
  54. {
  55. AssetBuilderSDK::JobDescriptor descriptor;
  56. descriptor.m_jobKey = "Atom Resource Pool";
  57. descriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
  58. descriptor.m_critical = false;
  59. response.m_createJobOutputs.push_back(descriptor);
  60. }
  61. response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
  62. }
  63. void ResourcePoolBuilder::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response)
  64. {
  65. AssetBuilderSDK::JobCancelListener jobCancelListener(request.m_jobId);
  66. if (jobCancelListener.IsCancelled())
  67. {
  68. response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Cancelled;
  69. return;
  70. }
  71. if (m_isShuttingDown)
  72. {
  73. response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Cancelled;
  74. return;
  75. }
  76. ResourcePoolSourceData poolSourceData;
  77. Outcome<void, AZStd::string> loadResult = AZ::JsonSerializationUtils::LoadObjectFromFile<ResourcePoolSourceData>(poolSourceData,
  78. request.m_fullPath);
  79. if (!loadResult.IsSuccess())
  80. {
  81. AZ_Error("PoolAssetProducer", false, "Failed to load source asset file %s", request.m_fullPath.c_str());
  82. AZ_Error("PoolAssetProducer", false, "Loading issues: %s", loadResult.GetError().c_str());
  83. response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
  84. return;
  85. }
  86. AZ_TracePrintf("AssetBuilder", "Load source data success\n");
  87. // Convert source format to asset used for runtime
  88. Data::AssetData* assetData = nullptr;
  89. const char* extension;
  90. Data::Asset<Data::AssetData> poolAsset;
  91. if (poolSourceData.m_poolType == ResourcePoolAssetType::StreamingImagePool)
  92. {
  93. extension = StreamingImagePoolAsset::Extension;
  94. poolAsset = CreateStreamingPoolAssetFromSource(poolSourceData);
  95. }
  96. else
  97. {
  98. extension = ResourcePoolAsset::Extension;
  99. poolAsset = CreatePoolAssetFromSource(poolSourceData);
  100. }
  101. assetData = poolAsset.GetData();
  102. if (!assetData)
  103. {
  104. AZ_Error("PoolAssetProducer", false, "Failed to create asset data");
  105. response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
  106. return;
  107. }
  108. AZ_TracePrintf("AssetBuilder", "Convert data success\n");
  109. // Get file name from source file path, then replace the extension to generate product file name
  110. AZStd::string destFileName;
  111. AzFramework::StringFunc::Path::GetFullFileName(request.m_fullPath.c_str(), destFileName);
  112. AzFramework::StringFunc::Path::ReplaceExtension(destFileName, extension);
  113. // Construct product full path
  114. AZStd::string destPath;
  115. AzFramework::StringFunc::Path::ConstructFull(request.m_tempDirPath.c_str(), destFileName.c_str(), destPath, true);
  116. // Save the asset to binary format for production
  117. bool result = AZ::Utils::SaveObjectToFile(destPath, AZ::DataStream::ST_BINARY, assetData, assetData->GetType(), nullptr);
  118. if (result == false)
  119. {
  120. AZ_Error("PoolAssetProducer", false, "Failed to save asset to cache")
  121. response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
  122. return;
  123. }
  124. AZ_TracePrintf("AssetBuilder", "Saved data to file %s \n", destPath.c_str());
  125. // Success. Save output product(s) to response
  126. AssetBuilderSDK::JobProduct jobProduct(destPath, assetData->GetType(), 0);
  127. jobProduct.m_dependenciesHandled = true; // This builder has no dependencies to output.
  128. response.m_outputProducts.push_back(jobProduct);
  129. response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
  130. }
  131. void ResourcePoolBuilder::ShutDown()
  132. {
  133. m_isShuttingDown = true;
  134. }
  135. Data::Asset<Data::AssetData> ResourcePoolBuilder::CreatePoolAssetFromSource(const ResourcePoolSourceData& sourceData)
  136. {
  137. ResourcePoolAssetCreator assetCreator;
  138. assetCreator.Begin(Data::AssetId(AZ::Uuid::CreateRandom()));
  139. assetCreator.SetPoolName(sourceData.m_poolName);
  140. switch (sourceData.m_poolType)
  141. {
  142. case ResourcePoolAssetType::BufferPool:
  143. {
  144. // [GFX TODO][ATOM-112] - Need to create pool descriptor based on device .
  145. AZStd::unique_ptr<RHI::BufferPoolDescriptor> bufferPoolDescriptor = AZStd::make_unique<RHI::BufferPoolDescriptor>();
  146. bufferPoolDescriptor->m_budgetInBytes = sourceData.m_budgetInBytes;
  147. bufferPoolDescriptor->m_heapMemoryLevel = sourceData.m_heapMemoryLevel;
  148. bufferPoolDescriptor->m_hostMemoryAccess = sourceData.m_hostMemoryAccess;
  149. bufferPoolDescriptor->m_bindFlags = sourceData.m_bufferPoolBindFlags;
  150. assetCreator.SetPoolDescriptor(AZStd::move(bufferPoolDescriptor));
  151. break;
  152. }
  153. case ResourcePoolAssetType::ImagePool:
  154. {
  155. AZStd::unique_ptr<RHI::ImagePoolDescriptor> imagePoolDescriptor = AZStd::make_unique<RHI::ImagePoolDescriptor>();
  156. imagePoolDescriptor->m_budgetInBytes = sourceData.m_budgetInBytes;
  157. imagePoolDescriptor->m_bindFlags = sourceData.m_imagePoolBindFlags;
  158. assetCreator.SetPoolDescriptor(AZStd::move(imagePoolDescriptor));
  159. break;
  160. }
  161. default:
  162. break;
  163. }
  164. Data::Asset<ResourcePoolAsset> poolAsset;
  165. if (assetCreator.End(poolAsset))
  166. {
  167. return poolAsset;
  168. }
  169. return {};
  170. }
  171. Data::Asset<Data::AssetData> ResourcePoolBuilder::CreateStreamingPoolAssetFromSource(const ResourcePoolSourceData& sourceData)
  172. {
  173. AZ_Assert(sourceData.m_poolType == ResourcePoolAssetType::StreamingImagePool, "Please use CreatePoolAssetFromSource for other type of pools");
  174. StreamingImagePoolAssetCreator assetCreator;
  175. assetCreator.Begin(Data::AssetId(AZ::Uuid::CreateRandom()));
  176. AZStd::unique_ptr<RHI::StreamingImagePoolDescriptor> poolDescriptor = AZStd::make_unique<RHI::StreamingImagePoolDescriptor>();
  177. poolDescriptor->m_budgetInBytes = sourceData.m_budgetInBytes;
  178. assetCreator.SetPoolDescriptor(AZStd::move(poolDescriptor));
  179. assetCreator.SetPoolName(sourceData.m_poolName);
  180. Data::Asset<StreamingImagePoolAsset> poolAsset;
  181. assetCreator.End(poolAsset);
  182. return poolAsset;
  183. }
  184. void ResourcePoolSourceData::Reflect(ReflectContext* context)
  185. {
  186. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  187. {
  188. serializeContext->Class<ResourcePoolSourceData>()
  189. ->Field("PoolName", &ResourcePoolSourceData::m_poolName)
  190. ->Field("PoolType", &ResourcePoolSourceData::m_poolType)
  191. ->Field("BudgetInBytes", &ResourcePoolSourceData::m_budgetInBytes)
  192. ->Field("BufferPoolHeapMemoryLevel", &ResourcePoolSourceData::m_heapMemoryLevel)
  193. ->Field("BufferPoolhostMemoryAccess", &ResourcePoolSourceData::m_hostMemoryAccess)
  194. ->Field("BufferPoolBindFlags", &ResourcePoolSourceData::m_bufferPoolBindFlags)
  195. ->Field("ImagePoolBindFlags", &ResourcePoolSourceData::m_imagePoolBindFlags)
  196. ;
  197. // register enum strings
  198. serializeContext->Enum<ResourcePoolAssetType>()
  199. ->Value("Unknown", ResourcePoolAssetType::Unknown)
  200. ->Value("BufferPool", ResourcePoolAssetType::BufferPool)
  201. ->Value("ImagePool", ResourcePoolAssetType::ImagePool)
  202. ->Value("StreamingImagePool", ResourcePoolAssetType::StreamingImagePool)
  203. ;
  204. }
  205. }
  206. } // namespace RPI_Builder
  207. } // namespace AZ