RayTracingFeatureProcessor.cpp 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602
  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 <Atom/Feature/RayTracing/RayTracingPass.h>
  9. #include <Atom/RHI/Factory.h>
  10. #include <Atom/RHI/RHISystemInterface.h>
  11. #include <Atom/RHI/RayTracingAccelerationStructure.h>
  12. #include <Atom/RHI/RayTracingCompactionQueryPool.h>
  13. #include <Atom/RPI.Public/Pass/PassFilter.h>
  14. #include <Atom/RPI.Public/Scene.h>
  15. #include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
  16. #include <Atom/RPI.Reflect/Asset/AssetUtils.h>
  17. #include <CoreLights/CapsuleLightFeatureProcessor.h>
  18. #include <CoreLights/DirectionalLightFeatureProcessor.h>
  19. #include <CoreLights/DiskLightFeatureProcessor.h>
  20. #include <CoreLights/PointLightFeatureProcessor.h>
  21. #include <CoreLights/QuadLightFeatureProcessor.h>
  22. #include <CoreLights/SimplePointLightFeatureProcessor.h>
  23. #include <CoreLights/SimpleSpotLightFeatureProcessor.h>
  24. #include <ImageBasedLights/ImageBasedLightFeatureProcessor.h>
  25. #include <RayTracing/RayTracingFeatureProcessor.h>
  26. namespace AZ
  27. {
  28. namespace Render
  29. {
  30. void RayTracingFeatureProcessor::Reflect(ReflectContext* context)
  31. {
  32. if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
  33. {
  34. serializeContext
  35. ->Class<RayTracingFeatureProcessor, FeatureProcessor>()
  36. ->Version(1);
  37. }
  38. }
  39. void RayTracingFeatureProcessor::Activate()
  40. {
  41. auto deviceMask{RHI::RHISystemInterface::Get()->GetRayTracingSupport()};
  42. m_rayTracingEnabled = (deviceMask != RHI::MultiDevice::NoDevices);
  43. if (!m_rayTracingEnabled)
  44. {
  45. return;
  46. }
  47. m_transformServiceFeatureProcessor = GetParentScene()->GetFeatureProcessor<TransformServiceFeatureProcessorInterface>();
  48. // initialize the ray tracing buffer pools
  49. m_bufferPools = aznew RHI::RayTracingBufferPools;
  50. m_bufferPools->Init(deviceMask);
  51. auto deviceCount = RHI::RHISystemInterface::Get()->GetDeviceCount();
  52. for (auto deviceIndex{0}; deviceIndex < deviceCount; ++deviceIndex)
  53. {
  54. if ((AZStd::to_underlying(deviceMask) >> deviceIndex) & 1)
  55. {
  56. m_meshBufferIndices[deviceIndex] = {};
  57. m_materialTextureIndices[deviceIndex] = {};
  58. m_meshInfos[deviceIndex] = {};
  59. m_materialInfos[deviceIndex] = {};
  60. m_proceduralGeometryMaterialInfos[deviceIndex] = {};
  61. }
  62. }
  63. // create TLAS attachmentId
  64. AZStd::string uuidString = AZ::Uuid::CreateRandom().ToString<AZStd::string>();
  65. m_tlasAttachmentId = RHI::AttachmentId(AZStd::string::format("RayTracingTlasAttachmentId_%s", uuidString.c_str()));
  66. // create the TLAS object
  67. m_tlas = aznew RHI::RayTracingTlas;
  68. // load the RayTracingSrg asset asset
  69. m_rayTracingSrgAsset = RPI::AssetUtils::LoadCriticalAsset<RPI::ShaderAsset>("shaderlib/atom/features/rayTracing/raytracingsrgs.azshader");
  70. if (!m_rayTracingSrgAsset.IsReady())
  71. {
  72. AZ_Assert(false, "Failed to load RayTracingSrg asset");
  73. return;
  74. }
  75. // create the RayTracingSceneSrg
  76. m_rayTracingSceneSrg = RPI::ShaderResourceGroup::Create(m_rayTracingSrgAsset, Name("RayTracingSceneSrg"));
  77. AZ_Assert(m_rayTracingSceneSrg, "Failed to create RayTracingSceneSrg");
  78. // create the RayTracingMaterialSrg
  79. const AZ::Name rayTracingMaterialSrgName("RayTracingMaterialSrg");
  80. m_rayTracingMaterialSrg = RPI::ShaderResourceGroup::Create(m_rayTracingSrgAsset, Name("RayTracingMaterialSrg"));
  81. AZ_Assert(m_rayTracingMaterialSrg, "Failed to create RayTracingMaterialSrg");
  82. // Setup RayTracingCompactionQueryPool
  83. {
  84. auto rpiDesc = RPI::RPISystemInterface::Get()->GetDescriptor();
  85. RHI::RayTracingCompactionQueryPoolDescriptor desc;
  86. desc.m_deviceMask = RHI::RHISystemInterface::Get()->GetRayTracingSupport();
  87. desc.m_budget = rpiDesc.m_rayTracingSystemDescriptor.m_rayTracingCompactionQueryPoolSize;
  88. desc.m_readbackBufferPool = AZ::RPI::BufferSystemInterface::Get()->GetCommonBufferPool(RPI::CommonBufferPoolType::ReadBack);
  89. desc.m_copyBufferPool = AZ::RPI::BufferSystemInterface::Get()->GetCommonBufferPool(RPI::CommonBufferPoolType::ReadWrite);
  90. m_compactionQueryPool = aznew RHI::RayTracingCompactionQueryPool;
  91. m_compactionQueryPool->Init(desc);
  92. }
  93. EnableSceneNotification();
  94. }
  95. void RayTracingFeatureProcessor::Deactivate()
  96. {
  97. DisableSceneNotification();
  98. }
  99. RayTracingFeatureProcessor::ProceduralGeometryTypeHandle RayTracingFeatureProcessor::RegisterProceduralGeometryType(
  100. const AZStd::string& name,
  101. const Data::Instance<RPI::Shader>& intersectionShader,
  102. const AZStd::string& intersectionShaderName,
  103. const AZStd::unordered_map<int, uint32_t>& bindlessBufferIndices)
  104. {
  105. ProceduralGeometryTypeHandle geometryTypeHandle;
  106. {
  107. ProceduralGeometryType proceduralGeometryType;
  108. proceduralGeometryType.m_name = AZ::Name(name);
  109. proceduralGeometryType.m_intersectionShader = intersectionShader;
  110. proceduralGeometryType.m_intersectionShaderName = AZ::Name(intersectionShaderName);
  111. proceduralGeometryType.m_bindlessBufferIndices = bindlessBufferIndices;
  112. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  113. geometryTypeHandle = m_proceduralGeometryTypes.insert(proceduralGeometryType);
  114. }
  115. m_proceduralGeometryTypeRevision++;
  116. return geometryTypeHandle;
  117. }
  118. void RayTracingFeatureProcessor::SetProceduralGeometryTypeBindlessBufferIndex(
  119. ProceduralGeometryTypeWeakHandle geometryTypeHandle, const AZStd::unordered_map<int, uint32_t>& bindlessBufferIndices)
  120. {
  121. if (!m_rayTracingEnabled)
  122. {
  123. return;
  124. }
  125. geometryTypeHandle->m_bindlessBufferIndices = bindlessBufferIndices;
  126. m_proceduralGeometryInfoBufferNeedsUpdate = true;
  127. }
  128. void RayTracingFeatureProcessor::AddProceduralGeometry(
  129. ProceduralGeometryTypeWeakHandle geometryTypeHandle,
  130. const Uuid& uuid,
  131. const Aabb& aabb,
  132. const SubMeshMaterial& material,
  133. RHI::RayTracingAccelerationStructureInstanceInclusionMask instanceMask,
  134. uint32_t localInstanceIndex)
  135. {
  136. if (!m_rayTracingEnabled)
  137. {
  138. return;
  139. }
  140. RHI::Ptr<AZ::RHI::RayTracingBlas> rayTracingBlas = aznew AZ::RHI::RayTracingBlas;
  141. RHI::RayTracingBlasDescriptor blasDescriptor;
  142. blasDescriptor.m_aabb = aabb;
  143. rayTracingBlas->CreateBuffers(m_deviceMask, &blasDescriptor, *m_bufferPools);
  144. ProceduralGeometry proceduralGeometry;
  145. proceduralGeometry.m_uuid = uuid;
  146. proceduralGeometry.m_typeHandle = geometryTypeHandle;
  147. proceduralGeometry.m_aabb = aabb;
  148. proceduralGeometry.m_instanceMask = static_cast<uint32_t>(instanceMask);
  149. proceduralGeometry.m_blas = rayTracingBlas;
  150. proceduralGeometry.m_localInstanceIndex = localInstanceIndex;
  151. MeshBlasInstance meshBlasInstance;
  152. meshBlasInstance.m_count = 1;
  153. SubMeshBlasInstance subMeshBlasInstance;
  154. subMeshBlasInstance.m_blas = rayTracingBlas;
  155. meshBlasInstance.m_subMeshes.push_back(AZStd::move(subMeshBlasInstance));
  156. MaterialInfo materialInfo;
  157. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  158. m_proceduralGeometryLookup.emplace(uuid, m_proceduralGeometry.size());
  159. m_proceduralGeometry.push_back(proceduralGeometry);
  160. auto deviceCount = RHI::RHISystemInterface::Get()->GetDeviceCount();
  161. for (auto deviceIndex{0}; deviceIndex < deviceCount; ++deviceIndex)
  162. {
  163. m_proceduralGeometryMaterialInfos[deviceIndex].emplace_back();
  164. ConvertMaterial(m_proceduralGeometryMaterialInfos[deviceIndex].back(), material, deviceIndex);
  165. }
  166. m_blasInstanceMap.emplace(Data::AssetId(uuid), meshBlasInstance);
  167. RHI::MultiDeviceObject::IterateDevices(
  168. m_deviceMask,
  169. [&](int deviceIndex)
  170. {
  171. m_blasToBuild[deviceIndex].insert(Data::AssetId(uuid));
  172. return true;
  173. });
  174. geometryTypeHandle->m_instanceCount++;
  175. m_revision++;
  176. m_proceduralGeometryInfoBufferNeedsUpdate = true;
  177. m_materialInfoBufferNeedsUpdate = true;
  178. m_indexListNeedsUpdate = true;
  179. }
  180. void RayTracingFeatureProcessor::SetProceduralGeometryTransform(
  181. const Uuid& uuid, const Transform& transform, const Vector3& nonUniformScale)
  182. {
  183. if (!m_rayTracingEnabled)
  184. {
  185. return;
  186. }
  187. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  188. if (auto it = m_proceduralGeometryLookup.find(uuid); it != m_proceduralGeometryLookup.end())
  189. {
  190. m_proceduralGeometry[it->second].m_transform = transform;
  191. m_proceduralGeometry[it->second].m_nonUniformScale = nonUniformScale;
  192. }
  193. m_revision++;
  194. }
  195. void RayTracingFeatureProcessor::SetProceduralGeometryLocalInstanceIndex(const Uuid& uuid, uint32_t localInstanceIndex)
  196. {
  197. if (!m_rayTracingEnabled)
  198. {
  199. return;
  200. }
  201. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  202. if (auto it = m_proceduralGeometryLookup.find(uuid); it != m_proceduralGeometryLookup.end())
  203. {
  204. m_proceduralGeometry[it->second].m_localInstanceIndex = localInstanceIndex;
  205. }
  206. m_proceduralGeometryInfoBufferNeedsUpdate = true;
  207. }
  208. void RayTracingFeatureProcessor::SetProceduralGeometryMaterial(
  209. const Uuid& uuid, const RayTracingFeatureProcessor::SubMeshMaterial& material)
  210. {
  211. if (!m_rayTracingEnabled)
  212. {
  213. return;
  214. }
  215. auto deviceCount = RHI::RHISystemInterface::Get()->GetDeviceCount();
  216. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  217. for (auto deviceIndex{0}; deviceIndex < deviceCount; ++deviceIndex)
  218. {
  219. if (auto it = m_proceduralGeometryLookup.find(uuid); it != m_proceduralGeometryLookup.end())
  220. {
  221. ConvertMaterial(m_proceduralGeometryMaterialInfos[deviceIndex][it->second], material, deviceIndex);
  222. }
  223. }
  224. m_materialInfoBufferNeedsUpdate = true;
  225. }
  226. void RayTracingFeatureProcessor::RemoveProceduralGeometry(const Uuid& uuid)
  227. {
  228. if (!m_rayTracingEnabled)
  229. {
  230. return;
  231. }
  232. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  233. size_t materialInfoIndex = m_proceduralGeometryLookup[uuid];
  234. m_proceduralGeometry[materialInfoIndex].m_typeHandle->m_instanceCount--;
  235. if (materialInfoIndex < m_proceduralGeometry.size() - 1)
  236. {
  237. m_proceduralGeometryLookup[m_proceduralGeometry.back().m_uuid] = m_proceduralGeometryLookup[uuid];
  238. m_proceduralGeometry[materialInfoIndex] = m_proceduralGeometry.back();
  239. for (auto& [deviceIndex, materialInfos] : m_proceduralGeometryMaterialInfos)
  240. {
  241. materialInfos[materialInfoIndex] = materialInfos.back();
  242. }
  243. }
  244. m_proceduralGeometry.pop_back();
  245. for (auto& [deviceIndex, materialInfos] : m_proceduralGeometryMaterialInfos)
  246. {
  247. materialInfos.pop_back();
  248. }
  249. m_proceduralGeometryLookup.erase(uuid);
  250. RemoveBlasInstance(uuid);
  251. m_revision++;
  252. m_proceduralGeometryInfoBufferNeedsUpdate = true;
  253. m_materialInfoBufferNeedsUpdate = true;
  254. m_indexListNeedsUpdate = true;
  255. }
  256. int RayTracingFeatureProcessor::GetProceduralGeometryCount(ProceduralGeometryTypeWeakHandle geometryTypeHandle) const
  257. {
  258. return geometryTypeHandle->m_instanceCount;
  259. }
  260. void RayTracingFeatureProcessor::AddMesh(const AZ::Uuid& uuid, const Mesh& rayTracingMesh, const SubMeshVector& subMeshes)
  261. {
  262. if (!m_rayTracingEnabled)
  263. {
  264. return;
  265. }
  266. // lock the mutex to protect the mesh and BLAS lists
  267. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  268. // check to see if we already have this mesh
  269. MeshMap::iterator itMesh = m_meshes.find(uuid);
  270. if (itMesh != m_meshes.end())
  271. {
  272. AZ_Assert(false, "AddMesh called on an existing Mesh, call RemoveMesh first");
  273. return;
  274. }
  275. // add the mesh
  276. m_meshes.insert(AZStd::make_pair(uuid, rayTracingMesh));
  277. Mesh& mesh = m_meshes[uuid];
  278. // add the subMeshes to the end of the global subMesh vector
  279. // Note 1: the MeshInfo and MaterialInfo vectors are parallel with the subMesh vector
  280. // Note 2: the list of indices for the subMeshes in the global vector are stored in the parent Mesh
  281. IndexVector subMeshIndices;
  282. uint32_t subMeshGlobalIndex = aznumeric_cast<uint32_t>(m_subMeshes.size());
  283. for (uint32_t subMeshIndex = 0; subMeshIndex < subMeshes.size(); ++subMeshIndex, ++subMeshGlobalIndex)
  284. {
  285. SubMesh& subMesh = m_subMeshes.emplace_back(subMeshes[subMeshIndex]);
  286. subMesh.m_mesh = &mesh;
  287. subMesh.m_subMeshIndex = subMeshIndex;
  288. subMesh.m_globalIndex = subMeshGlobalIndex;
  289. // add to the list of global subMeshIndices, which will be stored in the Mesh
  290. subMeshIndices.push_back(subMeshGlobalIndex);
  291. // add MeshInfo and MaterialInfo entries
  292. for (auto& [deviceIndex, meshInfos] : m_meshInfos)
  293. {
  294. meshInfos.emplace_back();
  295. }
  296. for (auto& [deviceIndex, materialInfos] : m_materialInfos)
  297. {
  298. materialInfos.emplace_back();
  299. }
  300. }
  301. mesh.m_subMeshIndices = subMeshIndices;
  302. // search for an existing BLAS instance entry for this mesh using the assetId
  303. BlasInstanceMap::iterator itMeshBlasInstance = m_blasInstanceMap.find(mesh.m_assetId);
  304. if (itMeshBlasInstance == m_blasInstanceMap.end())
  305. {
  306. // make a new BLAS map entry for this mesh
  307. MeshBlasInstance meshBlasInstance;
  308. meshBlasInstance.m_count = 1;
  309. meshBlasInstance.m_subMeshes.reserve(mesh.m_subMeshIndices.size());
  310. meshBlasInstance.m_isSkinnedMesh = mesh.m_isSkinnedMesh;
  311. itMeshBlasInstance = m_blasInstanceMap.insert({ mesh.m_assetId, meshBlasInstance }).first;
  312. // Note: the build flags are set to be the same for each BLAS created for the mesh
  313. RHI::RayTracingAccelerationStructureBuildFlags buildFlags =
  314. CreateRayTracingAccelerationStructureBuildFlags(mesh.m_isSkinnedMesh);
  315. auto rpiDesc = RPI::RPISystemInterface::Get()->GetDescriptor();
  316. if (mesh.m_subMeshIndices.size() > rpiDesc.m_rayTracingSystemDescriptor.m_rayTracingCompactionQueryPoolSize)
  317. {
  318. AZ_Warning(
  319. "RaytracingFeatureProcessor",
  320. false,
  321. "CompactionQueryPool is not large enough for model %s.\n"
  322. "Pool size: %d\n"
  323. "Num meshes in model: %d\n"
  324. "Raytracing Acceleration Structure Compaction will be disabled for this model\n"
  325. "Consider increasing the size of the pool through the registry setting "
  326. "O3DE/Atom/RPI/Initialization/RayTracingSystemDescriptor/RayTracingCompactionQueryPoolSize",
  327. mesh.m_assetId.ToFixedString().c_str(),
  328. rpiDesc.m_rayTracingSystemDescriptor.m_rayTracingCompactionQueryPoolSize,
  329. mesh.m_subMeshIndices.size());
  330. buildFlags = buildFlags & ~RHI::RayTracingAccelerationStructureBuildFlags::ENABLE_COMPACTION;
  331. }
  332. for (uint32_t subMeshIndex = 0; subMeshIndex < mesh.m_subMeshIndices.size(); ++subMeshIndex)
  333. {
  334. const SubMesh& subMesh = m_subMeshes[mesh.m_subMeshIndices[subMeshIndex]];
  335. SubMeshBlasInstance subMeshBlasInstance;
  336. RHI::RayTracingBlasDescriptor& blasDescriptor = subMeshBlasInstance.m_blasDescriptor;
  337. blasDescriptor.m_buildFlags = buildFlags;
  338. RHI::RayTracingGeometry& blasGeometry = blasDescriptor.m_geometries.emplace_back();
  339. blasGeometry.m_vertexFormat = subMesh.m_positionFormat;
  340. blasGeometry.m_vertexBuffer = subMesh.m_positionVertexBufferView;
  341. blasGeometry.m_indexBuffer = subMesh.m_indexBufferView;
  342. itMeshBlasInstance->second.m_subMeshes.push_back(subMeshBlasInstance);
  343. }
  344. m_blasToCreate.insert(mesh.m_assetId);
  345. }
  346. else
  347. {
  348. itMeshBlasInstance->second.m_count++;
  349. }
  350. AZ_Error(
  351. "RaytracingFeatureProcessor",
  352. itMeshBlasInstance->second.m_subMeshes.size() == mesh.m_subMeshIndices.size(),
  353. "AddMesh: The number of submeshes given does match the number of submeshes in the mesh (%d vs %d)",
  354. itMeshBlasInstance->second.m_subMeshes.size(),
  355. mesh.m_subMeshIndices.size());
  356. for (uint32_t subMeshIndex = 0; subMeshIndex < mesh.m_subMeshIndices.size(); ++subMeshIndex)
  357. {
  358. m_subMeshes[mesh.m_subMeshIndices[subMeshIndex]].m_blasInstanceId = { mesh.m_assetId, subMeshIndex };
  359. }
  360. AZ::Transform noScaleTransform = mesh.m_transform;
  361. noScaleTransform.ExtractUniformScale();
  362. AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform);
  363. rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose();
  364. Matrix3x4 worldInvTranspose3x4 = Matrix3x4::CreateFromMatrix3x3(rotationMatrix);
  365. Matrix3x4 reflectionProbeModelToWorld3x4 = Matrix3x4::CreateFromTransform(mesh.m_reflectionProbe.m_modelToWorld);
  366. // store the mesh buffers and material textures in the resource lists
  367. for (uint32_t subMeshIndex : mesh.m_subMeshIndices)
  368. {
  369. SubMesh& subMesh = m_subMeshes[subMeshIndex];
  370. AZ_Assert(subMesh.m_indexShaderBufferView.get(), "RayTracing Mesh IndexBuffer cannot be null");
  371. AZ_Assert(subMesh.m_positionShaderBufferView.get(), "RayTracing Mesh PositionBuffer cannot be null");
  372. AZ_Assert(subMesh.m_normalShaderBufferView.get(), "RayTracing Mesh NormalBuffer cannot be null");
  373. for (auto& [deviceIndex, meshInfos] : m_meshInfos)
  374. {
  375. MeshInfo& meshInfo = meshInfos[subMesh.m_globalIndex];
  376. worldInvTranspose3x4.StoreToRowMajorFloat12(meshInfo.m_worldInvTranspose.data());
  377. meshInfo.m_bufferFlags = subMesh.m_bufferFlags;
  378. meshInfo.m_indexByteOffset = subMesh.m_indexBufferView.GetByteOffset();
  379. meshInfo.m_positionByteOffset = subMesh.m_positionVertexBufferView.GetByteOffset();
  380. meshInfo.m_normalByteOffset = subMesh.m_normalVertexBufferView.GetByteOffset();
  381. meshInfo.m_tangentByteOffset =
  382. subMesh.m_tangentShaderBufferView ? subMesh.m_tangentVertexBufferView.GetByteOffset() : 0;
  383. meshInfo.m_bitangentByteOffset =
  384. subMesh.m_bitangentShaderBufferView ? subMesh.m_bitangentVertexBufferView.GetByteOffset() : 0;
  385. meshInfo.m_uvByteOffset = subMesh.m_uvShaderBufferView ? subMesh.m_uvVertexBufferView.GetByteOffset() : 0;
  386. meshInfo.m_indexFormat = subMesh.m_indexBufferView.GetIndexFormat();
  387. meshInfo.m_positionFormat = subMesh.m_positionFormat;
  388. meshInfo.m_normalFormat = subMesh.m_normalFormat;
  389. meshInfo.m_uvFormat = subMesh.m_uvFormat;
  390. meshInfo.m_tangentFormat = subMesh.m_tangentFormat;
  391. meshInfo.m_bitangentFormat = subMesh.m_bitangentFormat;
  392. auto& materialInfos{ m_materialInfos[deviceIndex] };
  393. MaterialInfo& materialInfo = materialInfos[subMesh.m_globalIndex];
  394. ConvertMaterial(materialInfo, subMesh.m_material, deviceIndex);
  395. auto& meshBufferIndices = m_meshBufferIndices[deviceIndex];
  396. // add mesh buffers
  397. meshInfo.m_bufferStartIndex = meshBufferIndices.AddEntry(
  398. {
  399. #if USE_BINDLESS_SRG
  400. subMesh.m_indexShaderBufferView.get() ? subMesh.m_indexShaderBufferView->GetDeviceBufferView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex,
  401. subMesh.m_positionShaderBufferView.get() ? subMesh.m_positionShaderBufferView->GetDeviceBufferView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex,
  402. subMesh.m_normalShaderBufferView.get() ? subMesh.m_normalShaderBufferView->GetDeviceBufferView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex,
  403. subMesh.m_tangentShaderBufferView.get() ? subMesh.m_tangentShaderBufferView->GetDeviceBufferView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex,
  404. subMesh.m_bitangentShaderBufferView.get() ? subMesh.m_bitangentShaderBufferView->GetDeviceBufferView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex,
  405. subMesh.m_uvShaderBufferView.get() ? subMesh.m_uvShaderBufferView->GetDeviceBufferView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex
  406. #else
  407. m_meshBuffers.AddResource(subMesh.m_indexShaderBufferView.get()),
  408. m_meshBuffers.AddResource(subMesh.m_positionShaderBufferView.get()),
  409. m_meshBuffers.AddResource(subMesh.m_normalShaderBufferView.get()),
  410. m_meshBuffers.AddResource(subMesh.m_tangentShaderBufferView.get()),
  411. m_meshBuffers.AddResource(subMesh.m_bitangentShaderBufferView.get()),
  412. m_meshBuffers.AddResource(subMesh.m_uvShaderBufferView.get())
  413. #endif
  414. });
  415. // add reflection probe data
  416. if (mesh.m_reflectionProbe.m_reflectionProbeCubeMap.get())
  417. {
  418. materialInfo.m_reflectionProbeCubeMapIndex = mesh.m_reflectionProbe.m_reflectionProbeCubeMap->GetImageView()->GetDeviceImageView(deviceIndex)->GetBindlessReadIndex();
  419. if (materialInfo.m_reflectionProbeCubeMapIndex != InvalidIndex)
  420. {
  421. reflectionProbeModelToWorld3x4.StoreToRowMajorFloat12(materialInfo.m_reflectionProbeData.m_modelToWorld.data());
  422. reflectionProbeModelToWorld3x4.GetInverseFull().StoreToRowMajorFloat12(materialInfo.m_reflectionProbeData.m_modelToWorldInverse.data());
  423. mesh.m_reflectionProbe.m_outerObbHalfLengths.StoreToFloat3(materialInfo.m_reflectionProbeData.m_outerObbHalfLengths.data());
  424. mesh.m_reflectionProbe.m_innerObbHalfLengths.StoreToFloat3(materialInfo.m_reflectionProbeData.m_innerObbHalfLengths.data());
  425. materialInfo.m_reflectionProbeData.m_useReflectionProbe = true;
  426. materialInfo.m_reflectionProbeData.m_useParallaxCorrection = mesh.m_reflectionProbe.m_useParallaxCorrection;
  427. materialInfo.m_reflectionProbeData.m_exposure = mesh.m_reflectionProbe.m_exposure;
  428. }
  429. }
  430. }
  431. }
  432. m_revision++;
  433. m_subMeshCount += aznumeric_cast<uint32_t>(subMeshes.size());
  434. m_meshInfoBufferNeedsUpdate = true;
  435. m_materialInfoBufferNeedsUpdate = true;
  436. m_indexListNeedsUpdate = true;
  437. }
  438. void RayTracingFeatureProcessor::RemoveMesh(const AZ::Uuid& uuid)
  439. {
  440. if (!m_rayTracingEnabled)
  441. {
  442. return;
  443. }
  444. // lock the mutex to protect the mesh and BLAS lists
  445. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  446. MeshMap::iterator itMesh = m_meshes.find(uuid);
  447. if (itMesh != m_meshes.end())
  448. {
  449. Mesh& mesh = itMesh->second;
  450. // decrement the count from the BLAS instances, and check to see if we can remove them
  451. BlasInstanceMap::iterator itBlas = m_blasInstanceMap.find(mesh.m_assetId);
  452. if (itBlas != m_blasInstanceMap.end())
  453. {
  454. itBlas->second.m_count--;
  455. if (itBlas->second.m_count == 0)
  456. {
  457. if (itBlas->second.m_isSkinnedMesh)
  458. {
  459. --m_skinnedMeshCount;
  460. }
  461. RemoveBlasInstance(mesh.m_assetId);
  462. }
  463. }
  464. // remove the SubMeshes
  465. for (auto& subMeshIndex : mesh.m_subMeshIndices)
  466. {
  467. SubMesh& subMesh = m_subMeshes[subMeshIndex];
  468. uint32_t globalIndex = subMesh.m_globalIndex;
  469. for (auto& [deviceIndex, meshInfos] : m_meshInfos)
  470. {
  471. MeshInfo& meshInfo = meshInfos[globalIndex];
  472. auto& meshBufferIndices = m_meshBufferIndices[deviceIndex];
  473. meshBufferIndices.RemoveEntry(meshInfo.m_bufferStartIndex);
  474. }
  475. for (auto& [deviceIndex, materialTextureIndices] : m_materialTextureIndices)
  476. {
  477. MaterialInfo& materialInfo = m_materialInfos[deviceIndex][globalIndex];
  478. materialTextureIndices.RemoveEntry(materialInfo.m_textureStartIndex);
  479. }
  480. #if !USE_BINDLESS_SRG
  481. m_meshBuffers.RemoveResource(subMesh.m_indexShaderBufferView.get());
  482. m_meshBuffers.RemoveResource(subMesh.m_positionShaderBufferView.get());
  483. m_meshBuffers.RemoveResource(subMesh.m_normalShaderBufferView.get());
  484. m_meshBuffers.RemoveResource(subMesh.m_tangentShaderBufferView.get());
  485. m_meshBuffers.RemoveResource(subMesh.m_bitangentShaderBufferView.get());
  486. m_meshBuffers.RemoveResource(subMesh.m_uvShaderBufferView.get());
  487. m_materialTextures.RemoveResource(subMesh.m_material.m_baseColorImageView.get());
  488. m_materialTextures.RemoveResource(subMesh.m_material.m_normalImageView.get());
  489. m_materialTextures.RemoveResource(subMesh.m_material.m_metallicImageView.get());
  490. m_materialTextures.RemoveResource(subMesh.m_material.m_roughnessImageView.get());
  491. m_materialTextures.RemoveResource(subMesh.m_material.m_emissiveImageView.get());
  492. #endif
  493. if (globalIndex < m_subMeshes.size() - 1)
  494. {
  495. // the subMesh we're removing is in the middle of the global lists, remove by swapping the last element to its position in the list
  496. m_subMeshes[globalIndex] = m_subMeshes.back();
  497. for (auto& [deviceIndex, meshInfos] : m_meshInfos)
  498. {
  499. auto& materialInfos{ m_materialInfos[deviceIndex] };
  500. meshInfos[globalIndex] = meshInfos.back();
  501. materialInfos[globalIndex] = materialInfos.back();
  502. }
  503. // update the global index for the swapped subMesh
  504. m_subMeshes[globalIndex].m_globalIndex = globalIndex;
  505. // update the global index in the parent Mesh' subMesh list
  506. Mesh* swappedSubMeshParent = m_subMeshes[globalIndex].m_mesh;
  507. uint32_t swappedSubMeshIndex = m_subMeshes[globalIndex].m_subMeshIndex;
  508. swappedSubMeshParent->m_subMeshIndices[swappedSubMeshIndex] = globalIndex;
  509. }
  510. m_subMeshes.pop_back();
  511. for (auto& [deviceIndex, meshInfos] : m_meshInfos)
  512. {
  513. auto& materialInfos{ m_materialInfos[deviceIndex] };
  514. meshInfos.pop_back();
  515. materialInfos.pop_back();
  516. }
  517. }
  518. // remove from the Mesh list
  519. m_subMeshCount -= aznumeric_cast<uint32_t>(mesh.m_subMeshIndices.size());
  520. m_meshes.erase(itMesh);
  521. m_revision++;
  522. // reset all data structures if all meshes were removed (i.e., empty scene)
  523. if (m_subMeshCount == 0)
  524. {
  525. m_meshes.clear();
  526. m_subMeshes.clear();
  527. m_blasInstanceMap.clear();
  528. for (auto& [deviceIndex, meshInfos] : m_meshInfos)
  529. {
  530. meshInfos.clear();
  531. }
  532. for (auto& [deviceIndex, materialInfos] : m_materialInfos)
  533. {
  534. materialInfos.clear();
  535. }
  536. for (auto& [deviceIndex, meshBufferIndices] : m_meshBufferIndices)
  537. {
  538. meshBufferIndices.Reset();
  539. }
  540. for (auto& [deviceIndex, materialTextureIndices] : m_materialTextureIndices)
  541. {
  542. materialTextureIndices.Reset();
  543. }
  544. #if !USE_BINDLESS_SRG
  545. m_meshBuffers.Reset();
  546. m_materialTextures.Reset();
  547. #endif
  548. }
  549. }
  550. m_meshInfoBufferNeedsUpdate = true;
  551. m_materialInfoBufferNeedsUpdate = true;
  552. m_indexListNeedsUpdate = true;
  553. }
  554. void RayTracingFeatureProcessor::SetMeshTransform(const AZ::Uuid& uuid, const AZ::Transform transform, const AZ::Vector3 nonUniformScale)
  555. {
  556. if (!m_rayTracingEnabled)
  557. {
  558. return;
  559. }
  560. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  561. MeshMap::iterator itMesh = m_meshes.find(uuid);
  562. if (itMesh != m_meshes.end())
  563. {
  564. Mesh& mesh = itMesh->second;
  565. mesh.m_transform = transform;
  566. mesh.m_nonUniformScale = nonUniformScale;
  567. m_revision++;
  568. // create a world inverse transpose 3x4 matrix
  569. AZ::Transform noScaleTransform = mesh.m_transform;
  570. noScaleTransform.ExtractUniformScale();
  571. AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform);
  572. rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose();
  573. Matrix3x4 worldInvTranspose3x4 = Matrix3x4::CreateFromMatrix3x3(rotationMatrix);
  574. // update all MeshInfos for this Mesh with the new transform
  575. for (const auto& subMeshIndex : mesh.m_subMeshIndices)
  576. {
  577. for (auto& [deviceIndex, meshInfos] : m_meshInfos)
  578. {
  579. MeshInfo& meshInfo = meshInfos[subMeshIndex];
  580. worldInvTranspose3x4.StoreToRowMajorFloat12(meshInfo.m_worldInvTranspose.data());
  581. }
  582. }
  583. m_meshInfoBufferNeedsUpdate = true;
  584. }
  585. }
  586. void RayTracingFeatureProcessor::SetMeshReflectionProbe(const AZ::Uuid& uuid, const Mesh::ReflectionProbe& reflectionProbe)
  587. {
  588. if (!m_rayTracingEnabled)
  589. {
  590. return;
  591. }
  592. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  593. MeshMap::iterator itMesh = m_meshes.find(uuid);
  594. if (itMesh != m_meshes.end())
  595. {
  596. Mesh& mesh = itMesh->second;
  597. // update the Mesh reflection probe data
  598. mesh.m_reflectionProbe = reflectionProbe;
  599. // update all of the subMeshes
  600. const Data::Instance<RPI::Image>& reflectionProbeCubeMap = reflectionProbe.m_reflectionProbeCubeMap;
  601. Matrix3x4 reflectionProbeModelToWorld3x4 = Matrix3x4::CreateFromTransform(mesh.m_reflectionProbe.m_modelToWorld);
  602. for (auto& subMeshIndex : mesh.m_subMeshIndices)
  603. {
  604. SubMesh& subMesh = m_subMeshes[subMeshIndex];
  605. uint32_t globalIndex = subMesh.m_globalIndex;
  606. for (auto& [deviceIndex, materialInfos] : m_materialInfos)
  607. {
  608. MaterialInfo& materialInfo = materialInfos[globalIndex];
  609. materialInfo.m_reflectionProbeCubeMapIndex = reflectionProbeCubeMap.get()
  610. ? reflectionProbeCubeMap->GetImageView()->GetDeviceImageView(deviceIndex)->GetBindlessReadIndex()
  611. : InvalidIndex;
  612. if (materialInfo.m_reflectionProbeCubeMapIndex != InvalidIndex)
  613. {
  614. reflectionProbeModelToWorld3x4.StoreToRowMajorFloat12(materialInfo.m_reflectionProbeData.m_modelToWorld.data());
  615. reflectionProbeModelToWorld3x4.GetInverseFull().StoreToRowMajorFloat12(materialInfo.m_reflectionProbeData.m_modelToWorldInverse.data());
  616. mesh.m_reflectionProbe.m_outerObbHalfLengths.StoreToFloat3(materialInfo.m_reflectionProbeData.m_outerObbHalfLengths.data());
  617. mesh.m_reflectionProbe.m_innerObbHalfLengths.StoreToFloat3(materialInfo.m_reflectionProbeData.m_innerObbHalfLengths.data());
  618. materialInfo.m_reflectionProbeData.m_useReflectionProbe = true;
  619. materialInfo.m_reflectionProbeData.m_useParallaxCorrection = mesh.m_reflectionProbe.m_useParallaxCorrection;
  620. materialInfo.m_reflectionProbeData.m_exposure = mesh.m_reflectionProbe.m_exposure;
  621. }
  622. else
  623. {
  624. materialInfo.m_reflectionProbeData.m_useReflectionProbe = false;
  625. }
  626. }
  627. }
  628. m_materialInfoBufferNeedsUpdate = true;
  629. }
  630. }
  631. void RayTracingFeatureProcessor::SetMeshMaterials(const AZ::Uuid& uuid, const SubMeshMaterialVector& subMeshMaterials)
  632. {
  633. if (!m_rayTracingEnabled)
  634. {
  635. return;
  636. }
  637. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  638. MeshMap::iterator itMesh = m_meshes.find(uuid);
  639. if (itMesh != m_meshes.end())
  640. {
  641. Mesh& mesh = itMesh->second;
  642. AZ_Assert(
  643. subMeshMaterials.size() == mesh.m_subMeshIndices.size(),
  644. "The size of subMeshes in SetMeshMaterial must be the same as in AddMesh");
  645. for (auto& subMeshIndex : mesh.m_subMeshIndices)
  646. {
  647. const SubMesh& subMesh = m_subMeshes[subMeshIndex];
  648. for (auto& [deviceIndex, materialInfos] : m_materialInfos)
  649. {
  650. ConvertMaterial(materialInfos[subMesh.m_globalIndex], subMeshMaterials[subMesh.m_subMeshIndex], deviceIndex);
  651. }
  652. }
  653. m_materialInfoBufferNeedsUpdate = true;
  654. m_indexListNeedsUpdate = true;
  655. }
  656. }
  657. void RayTracingFeatureProcessor::Render(const RenderPacket&)
  658. {
  659. m_frameIndex++;
  660. }
  661. void RayTracingFeatureProcessor::BeginFrame(int deviceIndex)
  662. {
  663. if (deviceIndex == RHI::MultiDevice::InvalidDeviceIndex)
  664. {
  665. deviceIndex = RHI::MultiDevice::DefaultDeviceIndex;
  666. }
  667. bool updatedDeviceMask = false;
  668. if (!RHI::CheckBit(m_deviceMask, deviceIndex))
  669. {
  670. for (auto& [assetId, blasInstance] : m_blasInstanceMap)
  671. {
  672. m_blasToCreate.insert(assetId);
  673. }
  674. m_deviceMask = RHI::SetBit(m_deviceMask, deviceIndex);
  675. updatedDeviceMask = true;
  676. m_revision++;
  677. // Make sure the map entries are present so we don't have a race condition in MarkBlasInstance*
  678. m_uncompactedBlasEnqueuedForDeletion.insert(deviceIndex);
  679. m_blasEnqueuedForCompact.insert(deviceIndex);
  680. }
  681. if (m_updatedFrameIndex == m_frameIndex)
  682. {
  683. if (!updatedDeviceMask)
  684. {
  685. // Make sure the update is only called once per frame
  686. // When multiple devices are present a RayTracingAccelerationStructurePass is created per device
  687. // Thus this function is called once for each device
  688. return;
  689. }
  690. }
  691. else
  692. {
  693. m_compactionQueryPool->BeginFrame(m_frameIndex);
  694. }
  695. m_updatedFrameIndex = m_frameIndex;
  696. UpdateBlasInstances();
  697. if (m_tlasRevision != m_revision)
  698. {
  699. m_tlasRevision = m_revision;
  700. // create the TLAS descriptor
  701. AZStd::unordered_map<int, RHI::DeviceRayTracingTlasDescriptor> tlasDescriptor;
  702. RHI::MultiDeviceObject::IterateDevices(
  703. m_deviceMask,
  704. [&](int deviceIndex)
  705. {
  706. // Create all device descriptors. This is needed if no Blas instances are present
  707. tlasDescriptor[deviceIndex];
  708. return true;
  709. });
  710. uint32_t instanceIndex = 0;
  711. for (auto& subMesh : m_subMeshes)
  712. {
  713. RHI::MultiDeviceObject::IterateDevices(
  714. m_deviceMask,
  715. [&](int deviceIndex)
  716. {
  717. auto meshIt = m_blasInstanceMap.find(subMesh.m_blasInstanceId.first);
  718. if (meshIt == m_blasInstanceMap.end())
  719. {
  720. return false;
  721. }
  722. if (subMesh.m_blasInstanceId.second >= meshIt->second.m_subMeshes.size())
  723. {
  724. return false;
  725. }
  726. const auto& blasInstance = meshIt->second.m_subMeshes[subMesh.m_blasInstanceId.second];
  727. RHI::RayTracingBlas* blas = blasInstance.m_compactBlas.get();
  728. if (blas == nullptr || !RHI::CheckBit(blas->GetDeviceMask(), deviceIndex))
  729. {
  730. blas = blasInstance.m_blas.get();
  731. if (blas && !RHI::CheckBit(blas->GetDeviceMask(), deviceIndex))
  732. {
  733. // This might happen if the number of BLAS created per frame is limited
  734. blas = nullptr;
  735. }
  736. }
  737. if (blas)
  738. {
  739. RHI::DeviceRayTracingTlasInstance& tlasInstance = tlasDescriptor[deviceIndex].m_instances.emplace_back();
  740. tlasInstance.m_instanceID = instanceIndex;
  741. tlasInstance.m_instanceMask = subMesh.m_mesh->m_instanceMask;
  742. tlasInstance.m_hitGroupIndex = 0;
  743. tlasInstance.m_blas = blas->GetDeviceRayTracingBlas(deviceIndex);
  744. tlasInstance.m_transform = subMesh.m_mesh->m_transform;
  745. tlasInstance.m_nonUniformScale = subMesh.m_mesh->m_nonUniformScale;
  746. tlasInstance.m_transparent = subMesh.m_material.m_irradianceColor.GetA() < 1.0f;
  747. }
  748. return true;
  749. });
  750. instanceIndex++;
  751. }
  752. unsigned proceduralHitGroupIndex = 1; // Hit group 0 is used for normal meshes
  753. AZStd::unordered_map<Name, unsigned> geometryTypeMap;
  754. geometryTypeMap.reserve(m_proceduralGeometryTypes.size());
  755. for (auto it = m_proceduralGeometryTypes.cbegin(); it != m_proceduralGeometryTypes.cend(); ++it)
  756. {
  757. geometryTypeMap[it->m_name] = proceduralHitGroupIndex++;
  758. }
  759. for (const auto& proceduralGeometry : m_proceduralGeometry)
  760. {
  761. RHI::MultiDeviceObject::IterateDevices(
  762. m_deviceMask,
  763. [&](int deviceIndex)
  764. {
  765. RHI::DeviceRayTracingTlasInstance& tlasInstance = tlasDescriptor[deviceIndex].m_instances.emplace_back();
  766. tlasInstance.m_instanceID = instanceIndex;
  767. tlasInstance.m_instanceMask = proceduralGeometry.m_instanceMask;
  768. tlasInstance.m_hitGroupIndex = geometryTypeMap[proceduralGeometry.m_typeHandle->m_name];
  769. tlasInstance.m_blas = proceduralGeometry.m_blas->GetDeviceRayTracingBlas(deviceIndex);
  770. tlasInstance.m_transform = proceduralGeometry.m_transform;
  771. tlasInstance.m_nonUniformScale = proceduralGeometry.m_nonUniformScale;
  772. return true;
  773. });
  774. instanceIndex++;
  775. }
  776. // create the TLAS buffers based on the descriptor
  777. RHI::Ptr<RHI::RayTracingTlas>& rayTracingTlas = m_tlas;
  778. rayTracingTlas->CreateBuffers(m_deviceMask, tlasDescriptor, *m_bufferPools);
  779. }
  780. // update and compile the RayTracingSceneSrg and RayTracingMaterialSrg
  781. // Note: the timing of this update is very important, it needs to be updated after the TLAS is allocated so it can
  782. // be set on the RayTracingSceneSrg for this frame, and the ray tracing mesh data in the RayTracingSceneSrg must
  783. // exactly match the TLAS. Any mismatch in this data may result in a TDR.
  784. UpdateRayTracingSrgs();
  785. }
  786. uint32_t RayTracingFeatureProcessor::GetBuiltRevision(int deviceIndex) const
  787. {
  788. auto it = m_builtRevisions.find(deviceIndex);
  789. if (it != m_builtRevisions.end())
  790. {
  791. return it->second;
  792. }
  793. else
  794. {
  795. return 0;
  796. }
  797. }
  798. void RayTracingFeatureProcessor::SetBuiltRevision(int deviceIndex, uint32_t revision)
  799. {
  800. m_builtRevisions[deviceIndex] = revision;
  801. }
  802. void RayTracingFeatureProcessor::UpdateRayTracingSrgs()
  803. {
  804. AZ_PROFILE_SCOPE(AzRender, "RayTracingFeatureProcessor::UpdateRayTracingSrgs");
  805. if (!m_tlas->GetTlasBuffer())
  806. {
  807. return;
  808. }
  809. if (m_rayTracingSceneSrg->IsQueuedForCompile() || m_rayTracingMaterialSrg->IsQueuedForCompile())
  810. {
  811. //[GFX TODO][ATOM-14792] AtomSampleViewer: Reset scene and feature processors before switching to sample
  812. return;
  813. }
  814. // lock the mutex to protect the mesh and BLAS lists
  815. AZStd::unique_lock<AZStd::mutex> lock(m_mutex);
  816. if (HasMeshGeometry())
  817. {
  818. UpdateMeshInfoBuffer();
  819. }
  820. if (HasProceduralGeometry())
  821. {
  822. UpdateProceduralGeometryInfoBuffer();
  823. }
  824. if (HasGeometry())
  825. {
  826. UpdateMaterialInfoBuffer();
  827. UpdateIndexLists();
  828. }
  829. UpdateRayTracingSceneSrg();
  830. UpdateRayTracingMaterialSrg();
  831. }
  832. const void RayTracingFeatureProcessor::MarkBlasInstanceForCompaction(int deviceIndex, Data::AssetId assetId)
  833. {
  834. auto it = m_blasInstanceMap.find(assetId);
  835. if (RHI::Validation::IsEnabled())
  836. {
  837. if (it != m_blasInstanceMap.end())
  838. {
  839. for ([[maybe_unused]] auto& subMeshInstance : it->second.m_subMeshes)
  840. {
  841. AZ_Assert(
  842. subMeshInstance.m_compactionSizeQuery, "Enqueuing a Blas without an compaction size query for compaction");
  843. }
  844. }
  845. }
  846. m_blasEnqueuedForCompact[deviceIndex][assetId].m_frameIndex =
  847. static_cast<int>(m_frameIndex + RHI::Limits::Device::FrameCountMax);
  848. }
  849. const void RayTracingFeatureProcessor::MarkBlasInstanceAsCompactionEnqueued(int deviceIndex, Data::AssetId assetId)
  850. {
  851. auto it = m_blasInstanceMap.find(assetId);
  852. if (RHI::Validation::IsEnabled())
  853. {
  854. if (it != m_blasInstanceMap.end())
  855. {
  856. for ([[maybe_unused]] auto& subMeshInstance : it->second.m_subMeshes)
  857. {
  858. AZ_Assert(subMeshInstance.m_compactBlas, "Marking a Blas without a compacted Blas as enqueued for compaction");
  859. }
  860. }
  861. }
  862. m_uncompactedBlasEnqueuedForDeletion[deviceIndex][assetId].m_frameIndex =
  863. static_cast<int>(m_frameIndex + RHI::Limits::Device::FrameCountMax);
  864. }
  865. void RayTracingFeatureProcessor::UpdateBlasInstances()
  866. {
  867. bool changed = false;
  868. auto rpiDesc = RPI::RPISystemInterface::Get()->GetDescriptor();
  869. {
  870. uint32_t numModelBlasCreated = 0;
  871. uint32_t numCompactionQueriesEnqueued = 0;
  872. AZStd::unordered_set<Data::AssetId> toRemoveFromCreateList;
  873. for (auto assetId : m_blasToCreate)
  874. {
  875. auto it = m_blasInstanceMap.find(assetId);
  876. if (it == m_blasInstanceMap.end())
  877. {
  878. toRemoveFromCreateList.insert(assetId);
  879. continue;
  880. }
  881. auto& instance = it->second;
  882. {
  883. int numSubmeshesWithCompactionQuery = 0;
  884. for (auto& subMeshInstance : instance.m_subMeshes)
  885. {
  886. // create the BLAS object and store it in the BLAS list
  887. if (RHI::CheckBitsAny(
  888. subMeshInstance.m_blasDescriptor.m_buildFlags,
  889. RHI::RayTracingAccelerationStructureBuildFlags::ENABLE_COMPACTION))
  890. {
  891. numSubmeshesWithCompactionQuery++;
  892. }
  893. }
  894. if (numCompactionQueriesEnqueued + numSubmeshesWithCompactionQuery >
  895. rpiDesc.m_rayTracingSystemDescriptor.m_rayTracingCompactionQueryPoolSize)
  896. {
  897. break;
  898. }
  899. }
  900. RHI::MultiDevice::DeviceMask createdOnDevices{};
  901. for (auto& subMeshInstance : instance.m_subMeshes)
  902. {
  903. // create the BLAS object and store it in the BLAS list
  904. if (RHI::CheckBitsAny(
  905. subMeshInstance.m_blasDescriptor.m_buildFlags,
  906. RHI::RayTracingAccelerationStructureBuildFlags::ENABLE_COMPACTION))
  907. {
  908. if (subMeshInstance.m_compactionSizeQuery)
  909. {
  910. RHI::MultiDeviceObject::IterateDevices(
  911. m_deviceMask & ~subMeshInstance.m_compactionSizeQuery->GetDeviceMask(),
  912. [&](int deviceIndex)
  913. {
  914. m_compactionQueryPool->AddDeviceToQuery(deviceIndex, subMeshInstance.m_compactionSizeQuery.get());
  915. return true;
  916. });
  917. }
  918. else
  919. {
  920. subMeshInstance.m_compactionSizeQuery = aznew RHI::RayTracingCompactionQuery;
  921. m_compactionQueryPool->InitQuery(m_deviceMask, subMeshInstance.m_compactionSizeQuery.get());
  922. }
  923. numCompactionQueriesEnqueued++;
  924. }
  925. if (subMeshInstance.m_blas)
  926. {
  927. createdOnDevices = m_deviceMask & ~subMeshInstance.m_blas->GetDeviceMask();
  928. RHI::MultiDeviceObject::IterateDevices(
  929. createdOnDevices,
  930. [&](int deviceIndex)
  931. {
  932. subMeshInstance.m_blas->AddDevice(deviceIndex, *m_bufferPools);
  933. return true;
  934. });
  935. }
  936. else
  937. {
  938. subMeshInstance.m_blas = aznew RHI::RayTracingBlas;
  939. subMeshInstance.m_blas->CreateBuffers(m_deviceMask, &subMeshInstance.m_blasDescriptor, *m_bufferPools);
  940. createdOnDevices = m_deviceMask;
  941. }
  942. }
  943. if (instance.m_isSkinnedMesh)
  944. {
  945. if (createdOnDevices ==
  946. m_deviceMask) // If it's not the full device mask, a new device was added, not a new blas instance
  947. {
  948. ++m_skinnedMeshCount;
  949. m_skinnedBlasIds.insert(assetId);
  950. }
  951. }
  952. else if (createdOnDevices != RHI::MultiDevice::NoDevices)
  953. {
  954. RHI::MultiDeviceObject::IterateDevices(
  955. createdOnDevices,
  956. [&](int deviceIndex)
  957. {
  958. m_blasToBuild[deviceIndex].insert(assetId);
  959. return true;
  960. });
  961. }
  962. toRemoveFromCreateList.insert(assetId);
  963. changed = true;
  964. numModelBlasCreated++;
  965. if (rpiDesc.m_rayTracingSystemDescriptor.m_maxBlasCreatedPerFrame > 0 &&
  966. numModelBlasCreated >= static_cast<uint32_t>(rpiDesc.m_rayTracingSystemDescriptor.m_maxBlasCreatedPerFrame))
  967. {
  968. break;
  969. }
  970. }
  971. for (auto& toRemove : toRemoveFromCreateList)
  972. {
  973. m_blasToCreate.erase(toRemove);
  974. }
  975. }
  976. // Check which Blas are ready for compaction and create compacted acceleration structures for them
  977. for (auto& [deviceIndex, blasEnqueuedForCompact] : m_blasEnqueuedForCompact)
  978. {
  979. AZStd::unordered_set<Data::AssetId> toDelete;
  980. for (const auto& [assetId, frameEvent] : blasEnqueuedForCompact)
  981. {
  982. if (frameEvent.m_frameIndex <= m_frameIndex)
  983. {
  984. auto it = m_blasInstanceMap.find(assetId);
  985. if (it != m_blasInstanceMap.end())
  986. {
  987. // Limit the number of blas we enqueue per frame to the size of the compaction query pool
  988. for (int subMeshIdx = 0; subMeshIdx < it->second.m_subMeshes.size(); subMeshIdx++)
  989. {
  990. auto& subMeshInstance = it->second.m_subMeshes[subMeshIdx];
  991. AZ_Assert(
  992. !subMeshInstance.m_compactBlas ||
  993. !RHI::CheckBit(subMeshInstance.m_compactBlas->GetDeviceMask(), deviceIndex),
  994. "Trying to compact a Blas twice");
  995. auto deviceMask = RHI::SetBit(RHI::MultiDevice::DeviceMask{}, deviceIndex);
  996. if (subMeshInstance.m_compactBlas)
  997. {
  998. auto size =
  999. subMeshInstance.m_compactionSizeQuery->GetDeviceRayTracingCompactionQuery(deviceIndex)->GetResult();
  1000. subMeshInstance.m_compactBlas->AddDeviceCompacted(
  1001. deviceIndex, *subMeshInstance.m_blas, size, *m_bufferPools);
  1002. }
  1003. else
  1004. {
  1005. AZStd::unordered_map<int, uint64_t> sizes;
  1006. sizes[deviceIndex] =
  1007. subMeshInstance.m_compactionSizeQuery->GetDeviceRayTracingCompactionQuery(deviceIndex)->GetResult();
  1008. subMeshInstance.m_compactBlas = aznew RHI::RayTracingBlas;
  1009. subMeshInstance.m_compactBlas->CreateCompactedBuffers(
  1010. deviceMask, *subMeshInstance.m_blas, sizes, *m_bufferPools);
  1011. }
  1012. if (RHI::ResetBits(subMeshInstance.m_compactionSizeQuery->GetDeviceMask(), deviceMask) ==
  1013. RHI::MultiDevice::DeviceMask{})
  1014. {
  1015. subMeshInstance.m_compactionSizeQuery = {};
  1016. }
  1017. else
  1018. {
  1019. m_compactionQueryPool->RemoveDeviceFromQuery(deviceIndex, subMeshInstance.m_compactionSizeQuery.get());
  1020. }
  1021. changed = true;
  1022. }
  1023. m_blasToCompact[deviceIndex].insert(assetId);
  1024. }
  1025. toDelete.insert(assetId);
  1026. }
  1027. }
  1028. for (auto& assetId : toDelete)
  1029. {
  1030. blasEnqueuedForCompact.erase(assetId);
  1031. }
  1032. }
  1033. // Check which uncompacted Blas can be deleted, and delete them
  1034. for (auto& [deviceIndex, uncompactedBlasEnqueuedForDeletion] : m_uncompactedBlasEnqueuedForDeletion)
  1035. {
  1036. AZStd::unordered_set<Data::AssetId> toDelete;
  1037. for (const auto& [assetId, frameEvent] : uncompactedBlasEnqueuedForDeletion)
  1038. {
  1039. if (frameEvent.m_frameIndex <= m_frameIndex)
  1040. {
  1041. auto it = m_blasInstanceMap.find(assetId);
  1042. if (it != m_blasInstanceMap.end())
  1043. {
  1044. for (auto& subMeshInstance : it->second.m_subMeshes)
  1045. {
  1046. AZ_Assert(
  1047. subMeshInstance.m_compactBlas, "Deleting a uncompacted Blas from a submesh without a compacted one");
  1048. if (subMeshInstance.m_blas->GetDeviceMask() == RHI::SetBit(RHI::MultiDevice::NoDevices, deviceIndex))
  1049. {
  1050. subMeshInstance.m_blas = {};
  1051. }
  1052. else
  1053. {
  1054. subMeshInstance.m_blas->RemoveDevice(deviceIndex);
  1055. }
  1056. changed = true;
  1057. }
  1058. }
  1059. toDelete.insert(assetId);
  1060. }
  1061. }
  1062. for (auto& assetId : toDelete)
  1063. {
  1064. uncompactedBlasEnqueuedForDeletion.erase(assetId);
  1065. }
  1066. }
  1067. if (changed)
  1068. {
  1069. m_revision++;
  1070. }
  1071. }
  1072. void RayTracingFeatureProcessor::UpdateMeshInfoBuffer()
  1073. {
  1074. if (m_meshInfoBufferNeedsUpdate)
  1075. {
  1076. AZStd::unordered_map<int, const void*> rawMeshInfos;
  1077. for (auto& [deviceIndex, meshInfos] : m_meshInfos)
  1078. {
  1079. rawMeshInfos[deviceIndex] = meshInfos.data();
  1080. }
  1081. size_t meshInfoByteCount = m_meshInfos.begin()->second.size() * sizeof(MeshInfo);
  1082. m_meshInfoGpuBuffer.AdvanceCurrentBufferAndUpdateData(rawMeshInfos, meshInfoByteCount);
  1083. m_meshInfoBufferNeedsUpdate = false;
  1084. }
  1085. }
  1086. void RayTracingFeatureProcessor::UpdateProceduralGeometryInfoBuffer()
  1087. {
  1088. if (!m_proceduralGeometryInfoBufferNeedsUpdate)
  1089. {
  1090. return;
  1091. }
  1092. AZStd::unordered_map<int, AZStd::vector<uint32_t>> proceduralGeometryInfos;
  1093. for (const auto& proceduralGeometry : m_proceduralGeometry)
  1094. {
  1095. for (auto& [deviceIndex, bindlessBufferIndex] : proceduralGeometry.m_typeHandle->m_bindlessBufferIndices)
  1096. {
  1097. auto& proceduralGeometryInfo = proceduralGeometryInfos[deviceIndex];
  1098. if (proceduralGeometryInfo.empty())
  1099. {
  1100. proceduralGeometryInfo.reserve(m_proceduralGeometry.size() * 2);
  1101. }
  1102. proceduralGeometryInfo.push_back(bindlessBufferIndex);
  1103. proceduralGeometryInfo.push_back(proceduralGeometry.m_localInstanceIndex);
  1104. }
  1105. }
  1106. AZStd::unordered_map<int, const void*> rawProceduralGeometryInfos;
  1107. for (auto& [deviceIndex, proceduralGeometryInfo] : proceduralGeometryInfos)
  1108. {
  1109. rawProceduralGeometryInfos[deviceIndex] = proceduralGeometryInfo.data();
  1110. }
  1111. m_proceduralGeometryInfoGpuBuffer.AdvanceCurrentBufferAndUpdateData(
  1112. rawProceduralGeometryInfos, m_proceduralGeometry.size() * 2 * sizeof(uint32_t));
  1113. m_proceduralGeometryInfoBufferNeedsUpdate = false;
  1114. }
  1115. void RayTracingFeatureProcessor::UpdateMaterialInfoBuffer()
  1116. {
  1117. if (m_materialInfoBufferNeedsUpdate)
  1118. {
  1119. m_materialInfoGpuBuffer.AdvanceCurrentElement();
  1120. m_materialInfoGpuBuffer.CreateOrResizeCurrentBufferWithElementCount<MaterialInfo>(
  1121. m_subMeshCount + m_proceduralGeometryMaterialInfos.begin()->second.size());
  1122. m_materialInfoGpuBuffer.UpdateCurrentBufferData(m_materialInfos);
  1123. m_materialInfoGpuBuffer.UpdateCurrentBufferData(m_proceduralGeometryMaterialInfos, m_subMeshCount);
  1124. m_materialInfoBufferNeedsUpdate = false;
  1125. }
  1126. }
  1127. void RayTracingFeatureProcessor::UpdateIndexLists()
  1128. {
  1129. if (m_indexListNeedsUpdate)
  1130. {
  1131. #if !USE_BINDLESS_SRG
  1132. // resolve to the true indices using the indirection list
  1133. // Note: this is done on the CPU to avoid double-indirection in the shader
  1134. AZStd::unordered_map<int, IndexVector> resolvedMeshBufferIndicesMap;
  1135. for (const auto& [deviceIndex, meshBufferIndices] : m_meshBufferIndices)
  1136. {
  1137. IndexVector& resolvedMeshBufferIndices = resolvedMeshBufferIndicesMap[deviceIndex];
  1138. resolvedMeshBufferIndices.resize(meshBufferIndices.GetIndexList().size());
  1139. uint32_t resolvedMeshBufferIndex = 0;
  1140. for (auto& meshBufferIndex : meshBufferIndices.GetIndexList())
  1141. {
  1142. if (!meshBufferIndices.IsValidIndex(meshBufferIndex))
  1143. {
  1144. resolvedMeshBufferIndices[resolvedMeshBufferIndex++] = InvalidIndex;
  1145. }
  1146. else
  1147. {
  1148. resolvedMeshBufferIndices[resolvedMeshBufferIndex++] = m_meshBuffers.GetIndirectionList()[meshBufferIndex];
  1149. }
  1150. }
  1151. }
  1152. m_meshBufferIndicesGpuBuffer.AdvanceCurrentBufferAndUpdateData(resolvedMeshBufferIndicesMap);
  1153. #else
  1154. AZStd::unordered_map<int, const void*> rawMeshData;
  1155. for (auto& [deviceIndex, meshBufferIndices] : m_meshBufferIndices)
  1156. {
  1157. rawMeshData[deviceIndex] = meshBufferIndices.GetIndexList().data();
  1158. }
  1159. size_t newMeshBufferIndicesByteCount = m_meshBufferIndices.begin()->second.GetIndexList().size() * sizeof(uint32_t);
  1160. m_meshBufferIndicesGpuBuffer.AdvanceCurrentBufferAndUpdateData(rawMeshData, newMeshBufferIndicesByteCount);
  1161. #endif
  1162. #if !USE_BINDLESS_SRG
  1163. // resolve to the true indices using the indirection list
  1164. // Note: this is done on the CPU to avoid double-indirection in the shader
  1165. AZStd::unordered_map<int, IndexVector> resolvedMaterialTextureIndicesMap;
  1166. for (const auto& [deviceIndex, materialTextureIndices] : m_materialTextureIndices)
  1167. {
  1168. IndexVector& resolvedMaterialTextureIndices = resolvedMaterialTextureIndicesMap[deviceIndex];
  1169. resolvedMaterialTextureIndices.resize(materialTextureIndices.GetIndexList().size());
  1170. uint32_t resolvedMaterialTextureIndex = 0;
  1171. for (auto& materialTextureIndex : materialTextureIndices.GetIndexList())
  1172. {
  1173. if (!materialTextureIndices.IsValidIndex(materialTextureIndex))
  1174. {
  1175. resolvedMaterialTextureIndices[resolvedMaterialTextureIndex++] = InvalidIndex;
  1176. }
  1177. else
  1178. {
  1179. resolvedMaterialTextureIndices[resolvedMaterialTextureIndex++] = m_materialTextures.GetIndirectionList()[materialTextureIndex];
  1180. }
  1181. }
  1182. }
  1183. m_materialTextureIndicesGpuBuffer.AdvanceCurrentBufferAndUpdateData(resolvedMaterialTextureIndicesMap);
  1184. #else
  1185. AZStd::unordered_map<int, const void*> rawMaterialData;
  1186. for (auto& [deviceIndex, materialTextureIndices] : m_materialTextureIndices)
  1187. {
  1188. rawMaterialData[deviceIndex] = materialTextureIndices.GetIndexList().data();
  1189. }
  1190. size_t newMaterialTextureIndicesByteCount = m_materialTextureIndices.begin()->second.GetIndexList().size() * sizeof(uint32_t);
  1191. m_materialTextureIndicesGpuBuffer.AdvanceCurrentBufferAndUpdateData(rawMaterialData, newMaterialTextureIndicesByteCount);
  1192. #endif
  1193. m_indexListNeedsUpdate = false;
  1194. }
  1195. }
  1196. void RayTracingFeatureProcessor::UpdateRayTracingSceneSrg()
  1197. {
  1198. const RHI::ShaderResourceGroupLayout* srgLayout = m_rayTracingSceneSrg->GetLayout();
  1199. RHI::ShaderInputImageIndex imageIndex;
  1200. RHI::ShaderInputBufferIndex bufferIndex;
  1201. RHI::ShaderInputConstantIndex constantIndex;
  1202. // TLAS
  1203. uint32_t tlasBufferByteCount = aznumeric_cast<uint32_t>(m_tlas->GetTlasBuffer()->GetDescriptor().m_byteCount);
  1204. RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRayTracingTLAS(tlasBufferByteCount);
  1205. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_scene"));
  1206. m_rayTracingSceneSrg->SetBufferView(bufferIndex, m_tlas->GetTlasBuffer()->GetBufferView(bufferViewDescriptor).get());
  1207. // directional lights
  1208. const auto directionalLightFP = GetParentScene()->GetFeatureProcessor<DirectionalLightFeatureProcessor>();
  1209. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_directionalLights"));
  1210. m_rayTracingSceneSrg->SetBufferView(
  1211. bufferIndex,
  1212. directionalLightFP->GetLightBuffer()->GetBufferView());
  1213. constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_directionalLightCount"));
  1214. m_rayTracingSceneSrg->SetConstant(constantIndex, directionalLightFP->GetLightCount());
  1215. // simple point lights
  1216. const auto simplePointLightFP = GetParentScene()->GetFeatureProcessor<SimplePointLightFeatureProcessor>();
  1217. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_simplePointLights"));
  1218. m_rayTracingSceneSrg->SetBufferView(
  1219. bufferIndex,
  1220. simplePointLightFP->GetLightBuffer()->GetBufferView());
  1221. constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_simplePointLightCount"));
  1222. m_rayTracingSceneSrg->SetConstant(constantIndex, simplePointLightFP->GetLightCount());
  1223. // simple spot lights
  1224. const auto simpleSpotLightFP = GetParentScene()->GetFeatureProcessor<SimpleSpotLightFeatureProcessor>();
  1225. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_simpleSpotLights"));
  1226. m_rayTracingSceneSrg->SetBufferView(
  1227. bufferIndex,
  1228. simpleSpotLightFP->GetLightBuffer()->GetBufferView());
  1229. constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_simpleSpotLightCount"));
  1230. m_rayTracingSceneSrg->SetConstant(constantIndex, simpleSpotLightFP->GetLightCount());
  1231. // point lights (sphere)
  1232. const auto pointLightFP = GetParentScene()->GetFeatureProcessor<PointLightFeatureProcessor>();
  1233. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_pointLights"));
  1234. m_rayTracingSceneSrg->SetBufferView(
  1235. bufferIndex,
  1236. pointLightFP->GetLightBuffer()->GetBufferView());
  1237. constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_pointLightCount"));
  1238. m_rayTracingSceneSrg->SetConstant(constantIndex, pointLightFP->GetLightCount());
  1239. // disk lights
  1240. const auto diskLightFP = GetParentScene()->GetFeatureProcessor<DiskLightFeatureProcessor>();
  1241. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_diskLights"));
  1242. m_rayTracingSceneSrg->SetBufferView(
  1243. bufferIndex,
  1244. diskLightFP->GetLightBuffer()->GetBufferView());
  1245. constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_diskLightCount"));
  1246. m_rayTracingSceneSrg->SetConstant(constantIndex, diskLightFP->GetLightCount());
  1247. // capsule lights
  1248. const auto capsuleLightFP = GetParentScene()->GetFeatureProcessor<CapsuleLightFeatureProcessor>();
  1249. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_capsuleLights"));
  1250. m_rayTracingSceneSrg->SetBufferView(
  1251. bufferIndex,
  1252. capsuleLightFP->GetLightBuffer()->GetBufferView());
  1253. constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_capsuleLightCount"));
  1254. m_rayTracingSceneSrg->SetConstant(constantIndex, capsuleLightFP->GetLightCount());
  1255. // quad lights
  1256. const auto quadLightFP = GetParentScene()->GetFeatureProcessor<QuadLightFeatureProcessor>();
  1257. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_quadLights"));
  1258. m_rayTracingSceneSrg->SetBufferView(
  1259. bufferIndex,
  1260. quadLightFP->GetLightBuffer()->GetBufferView());
  1261. constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_quadLightCount"));
  1262. m_rayTracingSceneSrg->SetConstant(constantIndex, quadLightFP->GetLightCount());
  1263. // diffuse environment map for sky hits
  1264. ImageBasedLightFeatureProcessor* imageBasedLightFeatureProcessor = GetParentScene()->GetFeatureProcessor<ImageBasedLightFeatureProcessor>();
  1265. if (imageBasedLightFeatureProcessor)
  1266. {
  1267. imageIndex = srgLayout->FindShaderInputImageIndex(AZ::Name("m_diffuseEnvMap"));
  1268. m_rayTracingSceneSrg->SetImage(imageIndex, imageBasedLightFeatureProcessor->GetDiffuseImage());
  1269. constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_iblOrientation"));
  1270. m_rayTracingSceneSrg->SetConstant(constantIndex, imageBasedLightFeatureProcessor->GetOrientation());
  1271. constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_iblExposure"));
  1272. m_rayTracingSceneSrg->SetConstant(constantIndex, imageBasedLightFeatureProcessor->GetExposure());
  1273. }
  1274. if (m_meshInfoGpuBuffer.IsCurrentBufferValid())
  1275. {
  1276. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_meshInfo"));
  1277. m_rayTracingSceneSrg->SetBufferView(bufferIndex, m_meshInfoGpuBuffer.GetCurrentBufferView());
  1278. }
  1279. constantIndex = srgLayout->FindShaderInputConstantIndex(AZ::Name("m_meshInfoCount"));
  1280. m_rayTracingSceneSrg->SetConstant(constantIndex, m_subMeshCount);
  1281. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_meshBufferIndices"));
  1282. m_rayTracingSceneSrg->SetBufferView(bufferIndex, m_meshBufferIndicesGpuBuffer.GetCurrentBufferView());
  1283. if (m_proceduralGeometryInfoGpuBuffer.IsCurrentBufferValid())
  1284. {
  1285. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_proceduralGeometryInfo"));
  1286. m_rayTracingSceneSrg->SetBufferView(bufferIndex, m_proceduralGeometryInfoGpuBuffer.GetCurrentBufferView());
  1287. }
  1288. #if !USE_BINDLESS_SRG
  1289. RHI::ShaderInputBufferUnboundedArrayIndex bufferUnboundedArrayIndex = srgLayout->FindShaderInputBufferUnboundedArrayIndex(AZ::Name("m_meshBuffers"));
  1290. m_rayTracingSceneSrg->SetBufferViewUnboundedArray(bufferUnboundedArrayIndex, m_meshBuffers.GetResourceList());
  1291. #endif
  1292. m_rayTracingSceneSrg->Compile();
  1293. }
  1294. void RayTracingFeatureProcessor::UpdateRayTracingMaterialSrg()
  1295. {
  1296. const RHI::ShaderResourceGroupLayout* srgLayout = m_rayTracingMaterialSrg->GetLayout();
  1297. RHI::ShaderInputBufferIndex bufferIndex;
  1298. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_materialInfo"));
  1299. m_rayTracingMaterialSrg->SetBufferView(bufferIndex, m_materialInfoGpuBuffer.GetCurrentBufferView());
  1300. bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_materialTextureIndices"));
  1301. m_rayTracingMaterialSrg->SetBufferView(bufferIndex, m_materialTextureIndicesGpuBuffer.GetCurrentBufferView());
  1302. #if !USE_BINDLESS_SRG
  1303. RHI::ShaderInputImageUnboundedArrayIndex textureUnboundedArrayIndex = srgLayout->FindShaderInputImageUnboundedArrayIndex(AZ::Name("m_materialTextures"));
  1304. m_rayTracingMaterialSrg->SetImageViewUnboundedArray(textureUnboundedArrayIndex, m_materialTextures.GetResourceList());
  1305. #endif
  1306. m_rayTracingMaterialSrg->Compile();
  1307. }
  1308. void RayTracingFeatureProcessor::RemoveBlasInstance(Data::AssetId id)
  1309. {
  1310. m_blasInstanceMap.erase(id);
  1311. m_blasToCreate.erase(id);
  1312. m_skinnedBlasIds.erase(id);
  1313. for (auto& [deviceIndex, entries] : m_blasToBuild)
  1314. {
  1315. entries.erase(id);
  1316. }
  1317. for (auto& [deviceIndex, entries] : m_blasToCompact)
  1318. {
  1319. entries.erase(id);
  1320. }
  1321. for (auto& [deviceIndex, blasEnqueuedForCompact] : m_blasEnqueuedForCompact)
  1322. {
  1323. blasEnqueuedForCompact.erase(id);
  1324. }
  1325. for (auto& [deviceIndex, uncompactedBlasEnqueuedForDeletion] : m_uncompactedBlasEnqueuedForDeletion)
  1326. {
  1327. uncompactedBlasEnqueuedForDeletion.erase(id);
  1328. }
  1329. }
  1330. AZ::RHI::RayTracingAccelerationStructureBuildFlags RayTracingFeatureProcessor::CreateRayTracingAccelerationStructureBuildFlags(bool isSkinnedMesh)
  1331. {
  1332. AZ::RHI::RayTracingAccelerationStructureBuildFlags buildFlags;
  1333. if (isSkinnedMesh)
  1334. {
  1335. buildFlags = AZ::RHI::RayTracingAccelerationStructureBuildFlags::ENABLE_UPDATE | AZ::RHI::RayTracingAccelerationStructureBuildFlags::FAST_BUILD;
  1336. }
  1337. else
  1338. {
  1339. buildFlags = AZ::RHI::RayTracingAccelerationStructureBuildFlags::FAST_TRACE;
  1340. auto rpiDesc = RPI::RPISystemInterface::Get()->GetDescriptor();
  1341. if (rpiDesc.m_rayTracingSystemDescriptor.m_enableBlasCompaction)
  1342. {
  1343. buildFlags = buildFlags | RHI::RayTracingAccelerationStructureBuildFlags::ENABLE_COMPACTION;
  1344. }
  1345. }
  1346. return buildFlags;
  1347. }
  1348. void RayTracingFeatureProcessor::ConvertMaterial(MaterialInfo& materialInfo, const SubMeshMaterial& subMeshMaterial, int deviceIndex)
  1349. {
  1350. subMeshMaterial.m_baseColor.StoreToFloat4(materialInfo.m_baseColor.data());
  1351. subMeshMaterial.m_emissiveColor.StoreToFloat4(materialInfo.m_emissiveColor.data());
  1352. subMeshMaterial.m_irradianceColor.StoreToFloat4(materialInfo.m_irradianceColor.data());
  1353. materialInfo.m_metallicFactor = subMeshMaterial.m_metallicFactor;
  1354. materialInfo.m_roughnessFactor = subMeshMaterial.m_roughnessFactor;
  1355. materialInfo.m_textureFlags = subMeshMaterial.m_textureFlags;
  1356. if (materialInfo.m_textureStartIndex != InvalidIndex)
  1357. {
  1358. m_materialTextureIndices[deviceIndex].RemoveEntry(materialInfo.m_textureStartIndex);
  1359. #if !USE_BINDLESS_SRG
  1360. m_materialTextures.RemoveResource(subMeshMaterial.m_baseColorImageView.get());
  1361. m_materialTextures.RemoveResource(subMeshMaterial.m_normalImageView.get());
  1362. m_materialTextures.RemoveResource(subMeshMaterial.m_metallicImageView.get());
  1363. m_materialTextures.RemoveResource(subMeshMaterial.m_roughnessImageView.get());
  1364. m_materialTextures.RemoveResource(subMeshMaterial.m_emissiveImageView.get());
  1365. #endif
  1366. }
  1367. materialInfo.m_textureStartIndex = m_materialTextureIndices[deviceIndex].AddEntry({
  1368. #if USE_BINDLESS_SRG
  1369. subMeshMaterial.m_baseColorImageView.get() ? subMeshMaterial.m_baseColorImageView->GetDeviceImageView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex,
  1370. subMeshMaterial.m_normalImageView.get() ? subMeshMaterial.m_normalImageView->GetDeviceImageView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex,
  1371. subMeshMaterial.m_metallicImageView.get() ? subMeshMaterial.m_metallicImageView->GetDeviceImageView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex,
  1372. subMeshMaterial.m_roughnessImageView.get() ? subMeshMaterial.m_roughnessImageView->GetDeviceImageView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex,
  1373. subMeshMaterial.m_emissiveImageView.get() ? subMeshMaterial.m_emissiveImageView->GetDeviceImageView(deviceIndex)->GetBindlessReadIndex() : InvalidIndex
  1374. #else
  1375. m_materialTextures.AddResource(subMeshMaterial.m_baseColorImageView.get()),
  1376. m_materialTextures.AddResource(subMeshMaterial.m_normalImageView.get()),
  1377. m_materialTextures.AddResource(subMeshMaterial.m_metallicImageView.get()),
  1378. m_materialTextures.AddResource(subMeshMaterial.m_roughnessImageView.get()),
  1379. m_materialTextures.AddResource(subMeshMaterial.m_emissiveImageView.get())
  1380. #endif
  1381. });
  1382. }
  1383. } // namespace Render
  1384. }