ResourcePoolBuilder.cpp 9.6 KB

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