RayTracingExampleComponent.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  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 <RHI/RayTracingExampleComponent.h>
  9. #include <Utils/Utils.h>
  10. #include <SampleComponentManager.h>
  11. #include <Atom/RHI/CommandList.h>
  12. #include <Atom/RHI/FrameGraphInterface.h>
  13. #include <Atom/RHI/RayTracingPipelineState.h>
  14. #include <Atom/RHI/RayTracingShaderTable.h>
  15. #include <Atom/RHI.Reflect/InputStreamLayoutBuilder.h>
  16. #include <Atom/RHI.Reflect/RenderAttachmentLayoutBuilder.h>
  17. #include <Atom/RPI.Public/Shader/Shader.h>
  18. #include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
  19. #include <AzCore/Serialization/SerializeContext.h>
  20. static const char* RayTracingExampleName = "RayTracingExample";
  21. namespace AtomSampleViewer
  22. {
  23. void RayTracingExampleComponent::Reflect(AZ::ReflectContext* context)
  24. {
  25. if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  26. {
  27. serializeContext->Class<RayTracingExampleComponent, AZ::Component>()
  28. ->Version(0)
  29. ;
  30. }
  31. }
  32. RayTracingExampleComponent::RayTracingExampleComponent()
  33. {
  34. m_supportRHISamplePipeline = true;
  35. }
  36. void RayTracingExampleComponent::Activate()
  37. {
  38. CreateResourcePools();
  39. CreateGeometry();
  40. CreateFullScreenBuffer();
  41. CreateOutputTexture();
  42. CreateRasterShader();
  43. CreateRayTracingAccelerationStructureObjects();
  44. CreateRayTracingPipelineState();
  45. CreateRayTracingShaderTable();
  46. CreateRayTracingAccelerationTableScope();
  47. CreateRayTracingDispatchScope();
  48. CreateRasterScope();
  49. RHI::RHISystemNotificationBus::Handler::BusConnect();
  50. }
  51. void RayTracingExampleComponent::Deactivate()
  52. {
  53. RHI::RHISystemNotificationBus::Handler::BusDisconnect();
  54. m_windowContext = nullptr;
  55. m_scopeProducers.clear();
  56. }
  57. void RayTracingExampleComponent::CreateResourcePools()
  58. {
  59. // create input assembly buffer pool
  60. {
  61. m_inputAssemblyBufferPool = aznew RHI::BufferPool();
  62. RHI::BufferPoolDescriptor bufferPoolDesc;
  63. bufferPoolDesc.m_bindFlags = RHI::BufferBindFlags::InputAssembly;
  64. bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host;
  65. [[maybe_unused]] RHI::ResultCode resultCode = m_inputAssemblyBufferPool->Init(bufferPoolDesc);
  66. AZ_Assert(resultCode == RHI::ResultCode::Success, "Failed to initialize input assembly buffer pool");
  67. }
  68. // create output image pool
  69. {
  70. RHI::ImagePoolDescriptor imagePoolDesc;
  71. imagePoolDesc.m_bindFlags = RHI::ImageBindFlags::ShaderReadWrite;
  72. m_imagePool = aznew RHI::ImagePool();
  73. [[maybe_unused]] RHI::ResultCode result = m_imagePool->Init(imagePoolDesc);
  74. AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize output image pool");
  75. }
  76. // initialize ray tracing buffer pools
  77. m_rayTracingBufferPools = aznew RHI::RayTracingBufferPools;
  78. m_rayTracingBufferPools->Init(RHI::MultiDevice::AllDevices);
  79. }
  80. void RayTracingExampleComponent::CreateGeometry()
  81. {
  82. // triangle
  83. {
  84. // vertex buffer
  85. SetVertexPosition(m_triangleVertices.data(), 0, 0.0f, 0.5f, 1.0);
  86. SetVertexPosition(m_triangleVertices.data(), 1, 0.5f, -0.5f, 1.0);
  87. SetVertexPosition(m_triangleVertices.data(), 2, -0.5f, -0.5f, 1.0);
  88. m_triangleVB = aznew RHI::Buffer();
  89. m_triangleVB->SetName(AZ::Name("Triangle VB"));
  90. RHI::BufferInitRequest request;
  91. request.m_buffer = m_triangleVB.get();
  92. request.m_descriptor = RHI::BufferDescriptor{ RHI::BufferBindFlags::InputAssembly, sizeof(m_triangleVertices) };
  93. request.m_initialData = m_triangleVertices.data();
  94. m_inputAssemblyBufferPool->InitBuffer(request);
  95. // index buffer
  96. SetVertexIndexIncreasing(m_triangleIndices.data(), m_triangleIndices.size());
  97. m_triangleIB = aznew RHI::Buffer();
  98. m_triangleIB->SetName(AZ::Name("Triangle IB"));
  99. request.m_buffer = m_triangleIB.get();
  100. request.m_descriptor = RHI::BufferDescriptor{ RHI::BufferBindFlags::InputAssembly, sizeof(m_triangleIndices) };
  101. request.m_initialData = m_triangleIndices.data();
  102. m_inputAssemblyBufferPool->InitBuffer(request);
  103. }
  104. // rectangle
  105. {
  106. // vertex buffer
  107. SetVertexPosition(m_rectangleVertices.data(), 0, -0.5f, 0.5f, 1.0);
  108. SetVertexPosition(m_rectangleVertices.data(), 1, 0.5f, 0.5f, 1.0);
  109. SetVertexPosition(m_rectangleVertices.data(), 2, 0.5f, -0.5f, 1.0);
  110. SetVertexPosition(m_rectangleVertices.data(), 3, -0.5f, -0.5f, 1.0);
  111. m_rectangleVB = aznew RHI::Buffer();
  112. m_rectangleVB->SetName(AZ::Name("Rectangle VB"));
  113. RHI::BufferInitRequest request;
  114. request.m_buffer = m_rectangleVB.get();
  115. request.m_descriptor = RHI::BufferDescriptor{ RHI::BufferBindFlags::InputAssembly, sizeof(m_rectangleVertices) };
  116. request.m_initialData = m_rectangleVertices.data();
  117. m_inputAssemblyBufferPool->InitBuffer(request);
  118. // index buffer
  119. m_rectangleIndices[0] = 0;
  120. m_rectangleIndices[1] = 1;
  121. m_rectangleIndices[2] = 2;
  122. m_rectangleIndices[3] = 0;
  123. m_rectangleIndices[4] = 2;
  124. m_rectangleIndices[5] = 3;
  125. m_rectangleIB = aznew RHI::Buffer();
  126. m_rectangleIB->SetName(AZ::Name("Rectangle IB"));
  127. request.m_buffer = m_rectangleIB.get();
  128. request.m_descriptor = RHI::BufferDescriptor{ RHI::BufferBindFlags::InputAssembly, sizeof(m_rectangleIndices) };
  129. request.m_initialData = m_rectangleIndices.data();
  130. m_inputAssemblyBufferPool->InitBuffer(request);
  131. }
  132. }
  133. void RayTracingExampleComponent::CreateFullScreenBuffer()
  134. {
  135. FullScreenBufferData bufferData;
  136. SetFullScreenRect(bufferData.m_positions.data(), bufferData.m_uvs.data(), bufferData.m_indices.data());
  137. m_fullScreenInputAssemblyBuffer = aznew RHI::Buffer();
  138. RHI::BufferInitRequest request;
  139. request.m_buffer = m_fullScreenInputAssemblyBuffer.get();
  140. request.m_descriptor = RHI::BufferDescriptor{ RHI::BufferBindFlags::InputAssembly, sizeof(bufferData) };
  141. request.m_initialData = &bufferData;
  142. m_inputAssemblyBufferPool->InitBuffer(request);
  143. m_geometryView.SetDrawArguments(RHI::DrawIndexed(0, 6, 0));
  144. m_geometryView.AddStreamBufferView({
  145. *m_fullScreenInputAssemblyBuffer,
  146. offsetof(FullScreenBufferData, m_positions),
  147. sizeof(FullScreenBufferData::m_positions),
  148. sizeof(VertexPosition)
  149. });
  150. m_geometryView.AddStreamBufferView({
  151. *m_fullScreenInputAssemblyBuffer,
  152. offsetof(FullScreenBufferData, m_uvs),
  153. sizeof(FullScreenBufferData::m_uvs),
  154. sizeof(VertexUV)
  155. });
  156. m_geometryView.SetIndexBufferView({
  157. *m_fullScreenInputAssemblyBuffer,
  158. offsetof(FullScreenBufferData, m_indices),
  159. sizeof(FullScreenBufferData::m_indices),
  160. RHI::IndexFormat::Uint16
  161. });
  162. RHI::InputStreamLayoutBuilder layoutBuilder;
  163. layoutBuilder.AddBuffer()->Channel("POSITION", RHI::Format::R32G32B32_FLOAT);
  164. layoutBuilder.AddBuffer()->Channel("UV", RHI::Format::R32G32_FLOAT);
  165. m_fullScreenInputStreamLayout = layoutBuilder.End();
  166. }
  167. void RayTracingExampleComponent::CreateOutputTexture()
  168. {
  169. // create output image
  170. m_outputImage = aznew RHI::Image();
  171. RHI::ImageInitRequest request;
  172. request.m_image = m_outputImage.get();
  173. request.m_descriptor = RHI::ImageDescriptor::Create2D(RHI::ImageBindFlags::ShaderReadWrite, m_imageWidth, m_imageHeight, RHI::Format::R8G8B8A8_UNORM);
  174. [[maybe_unused]] RHI::ResultCode result = m_imagePool->InitImage(request);
  175. AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize output image");
  176. m_outputImageViewDescriptor = RHI::ImageViewDescriptor::Create(RHI::Format::R8G8B8A8_UNORM, 0, 0);
  177. m_outputImageView = m_outputImage->GetImageView(m_outputImageViewDescriptor);
  178. AZ_Assert(m_outputImageView.get(), "Failed to create output image view");
  179. AZ_Assert(m_outputImageView->GetDeviceImageView(RHI::MultiDevice::DefaultDeviceIndex)->IsFullView(), "Image View initialization IsFullView() failed");
  180. }
  181. void RayTracingExampleComponent::CreateRayTracingAccelerationStructureObjects()
  182. {
  183. m_triangleRayTracingBlas = aznew AZ::RHI::RayTracingBlas;
  184. m_rectangleRayTracingBlas = aznew AZ::RHI::RayTracingBlas;
  185. m_rayTracingTlas = aznew AZ::RHI::RayTracingTlas;
  186. }
  187. void RayTracingExampleComponent::CreateRasterShader()
  188. {
  189. const char* shaderFilePath = "Shaders/RHI/RayTracingDraw.azshader";
  190. auto drawShader = LoadShader(shaderFilePath, RayTracingExampleName);
  191. AZ_Assert(drawShader, "Failed to load Draw shader");
  192. RHI::PipelineStateDescriptorForDraw pipelineDesc;
  193. drawShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId).ConfigurePipelineState(pipelineDesc);
  194. pipelineDesc.m_inputStreamLayout = m_fullScreenInputStreamLayout;
  195. RHI::RenderAttachmentLayoutBuilder attachmentsBuilder;
  196. attachmentsBuilder.AddSubpass()->RenderTargetAttachment(m_outputFormat);
  197. [[maybe_unused]] RHI::ResultCode result = attachmentsBuilder.End(pipelineDesc.m_renderAttachmentConfiguration.m_renderAttachmentLayout);
  198. AZ_Assert(result == RHI::ResultCode::Success, "Failed to create draw render attachment layout");
  199. m_drawPipelineState = drawShader->AcquirePipelineState(pipelineDesc);
  200. AZ_Assert(m_drawPipelineState, "Failed to acquire draw pipeline state");
  201. m_drawSRG = CreateShaderResourceGroup(drawShader, "BufferSrg", RayTracingExampleName);
  202. }
  203. void RayTracingExampleComponent::CreateRayTracingPipelineState()
  204. {
  205. // load ray generation shader
  206. const char* rayGenerationShaderFilePath = "Shaders/RHI/RayTracingDispatch.azshader";
  207. m_rayGenerationShader = LoadShader(rayGenerationShaderFilePath, RayTracingExampleName);
  208. AZ_Assert(m_rayGenerationShader, "Failed to load ray generation shader");
  209. auto rayGenerationShaderVariant = m_rayGenerationShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
  210. RHI::PipelineStateDescriptorForRayTracing rayGenerationShaderDescriptor;
  211. rayGenerationShaderVariant.ConfigurePipelineState(rayGenerationShaderDescriptor);
  212. // load miss shader
  213. const char* missShaderFilePath = "Shaders/RHI/RayTracingMiss.azshader";
  214. m_missShader = LoadShader(missShaderFilePath, RayTracingExampleName);
  215. AZ_Assert(m_missShader, "Failed to load miss shader");
  216. auto missShaderVariant = m_missShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
  217. RHI::PipelineStateDescriptorForRayTracing missShaderDescriptor;
  218. missShaderVariant.ConfigurePipelineState(missShaderDescriptor);
  219. // load closest hit gradient shader
  220. const char* closestHitGradientShaderFilePath = "Shaders/RHI/RayTracingClosestHitGradient.azshader";
  221. m_closestHitGradientShader = LoadShader(closestHitGradientShaderFilePath, RayTracingExampleName);
  222. AZ_Assert(m_closestHitGradientShader, "Failed to load closest hit gradient shader");
  223. auto closestHitGradientShaderVariant = m_closestHitGradientShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
  224. RHI::PipelineStateDescriptorForRayTracing closestHitGradientShaderDescriptor;
  225. closestHitGradientShaderVariant.ConfigurePipelineState(closestHitGradientShaderDescriptor);
  226. // load closest hit solid shader
  227. const char* closestHitSolidShaderFilePath = "Shaders/RHI/RayTracingClosestHitSolid.azshader";
  228. m_closestHitSolidShader = LoadShader(closestHitSolidShaderFilePath, RayTracingExampleName);
  229. AZ_Assert(m_closestHitSolidShader, "Failed to load closest hit solid shader");
  230. auto closestHitSolidShaderVariant = m_closestHitSolidShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
  231. RHI::PipelineStateDescriptorForRayTracing closestHitSolidShaderDescriptor;
  232. closestHitSolidShaderVariant.ConfigurePipelineState(closestHitSolidShaderDescriptor);
  233. // global pipeline state and srg
  234. m_globalPipelineState = m_rayGenerationShader->AcquirePipelineState(rayGenerationShaderDescriptor);
  235. AZ_Assert(m_globalPipelineState, "Failed to acquire ray tracing global pipeline state");
  236. m_globalSrg = CreateShaderResourceGroup(m_rayGenerationShader, "RayTracingGlobalSrg", RayTracingExampleName);
  237. // build the ray tracing pipeline state descriptor
  238. RHI::RayTracingPipelineStateDescriptor descriptor;
  239. descriptor.m_pipelineState = m_globalPipelineState.get();
  240. descriptor.AddRayGenerationShaderLibrary(rayGenerationShaderDescriptor, Name("RayGenerationShader"));
  241. descriptor.AddMissShaderLibrary(missShaderDescriptor, Name("MissShader"));
  242. descriptor.AddClosestHitShaderLibrary(closestHitGradientShaderDescriptor, Name("ClosestHitGradientShader"));
  243. descriptor.AddClosestHitShaderLibrary(closestHitSolidShaderDescriptor, Name("ClosestHitSolidShader"));
  244. descriptor.AddHitGroup(Name("HitGroupGradient"), Name("ClosestHitGradientShader"));
  245. descriptor.AddHitGroup(Name("HitGroupSolid"), Name("ClosestHitSolidShader"));
  246. // create the ray tracing pipeline state object
  247. m_rayTracingPipelineState = aznew RHI::RayTracingPipelineState;
  248. m_rayTracingPipelineState->Init(RHI::MultiDevice::AllDevices, descriptor);
  249. }
  250. void RayTracingExampleComponent::CreateRayTracingShaderTable()
  251. {
  252. m_rayTracingShaderTable = aznew RHI::RayTracingShaderTable;
  253. m_rayTracingShaderTable->Init(RHI::MultiDevice::AllDevices, *m_rayTracingBufferPools);
  254. }
  255. void RayTracingExampleComponent::CreateRayTracingAccelerationTableScope()
  256. {
  257. struct ScopeData
  258. {
  259. };
  260. const auto prepareFunction = [this]([[maybe_unused]] RHI::FrameGraphInterface frameGraph, [[maybe_unused]] ScopeData& scopeData)
  261. {
  262. // create triangle BLAS buffer if necessary
  263. if (!m_triangleRayTracingBlas->IsValid())
  264. {
  265. RHI::StreamBufferView triangleVertexBufferView =
  266. {
  267. *m_triangleVB,
  268. 0,
  269. sizeof(m_triangleVertices),
  270. sizeof(VertexPosition)
  271. };
  272. RHI::IndexBufferView triangleIndexBufferView =
  273. {
  274. *m_triangleIB,
  275. 0,
  276. sizeof(m_triangleIndices),
  277. RHI::IndexFormat::Uint16
  278. };
  279. RHI::RayTracingBlasDescriptor triangleBlasDescriptor;
  280. RHI::RayTracingGeometry& triangleBlasGeometry = triangleBlasDescriptor.m_geometries.emplace_back();
  281. triangleBlasGeometry.m_vertexFormat = RHI::Format::R32G32B32_FLOAT;
  282. triangleBlasGeometry.m_vertexBuffer = triangleVertexBufferView;
  283. triangleBlasGeometry.m_indexBuffer = triangleIndexBufferView;
  284. m_triangleRayTracingBlas->CreateBuffers(RHI::MultiDevice::AllDevices, &triangleBlasDescriptor, *m_rayTracingBufferPools);
  285. }
  286. // create rectangle BLAS if necessary
  287. if (!m_rectangleRayTracingBlas->IsValid())
  288. {
  289. RHI::StreamBufferView rectangleVertexBufferView =
  290. {
  291. *m_rectangleVB,
  292. 0,
  293. sizeof(m_rectangleVertices),
  294. sizeof(VertexPosition)
  295. };
  296. RHI::IndexBufferView rectangleIndexBufferView =
  297. {
  298. *m_rectangleIB,
  299. 0,
  300. sizeof(m_rectangleIndices),
  301. RHI::IndexFormat::Uint16
  302. };
  303. RHI::RayTracingBlasDescriptor rectangleBlasDescriptor;
  304. RHI::RayTracingGeometry& rectangleBlasGeometry = rectangleBlasDescriptor.m_geometries.emplace_back();
  305. rectangleBlasGeometry.m_vertexFormat = RHI::Format::R32G32B32_FLOAT;
  306. rectangleBlasGeometry.m_vertexBuffer = rectangleVertexBufferView;
  307. rectangleBlasGeometry.m_indexBuffer = rectangleIndexBufferView;
  308. m_rectangleRayTracingBlas->CreateBuffers(RHI::MultiDevice::AllDevices, &rectangleBlasDescriptor, *m_rayTracingBufferPools);
  309. }
  310. m_time += 0.005f;
  311. // transforms
  312. AZ::Transform triangleTransform1 = AZ::Transform::CreateIdentity();
  313. triangleTransform1.SetTranslation(sinf(m_time) * -100.0f, cosf(m_time) * -100.0f, 1.0f);
  314. triangleTransform1.MultiplyByUniformScale(100.0f);
  315. AZ::Transform triangleTransform2 = AZ::Transform::CreateIdentity();
  316. triangleTransform2.SetTranslation(sinf(m_time) * -100.0f, cosf(m_time) * 100.0f, 2.0f);
  317. triangleTransform2.MultiplyByUniformScale(100.0f);
  318. AZ::Transform triangleTransform3 = AZ::Transform::CreateIdentity();
  319. triangleTransform3.SetTranslation(sinf(m_time) * 100.0f, cosf(m_time) * 100.0f, 3.0f);
  320. triangleTransform3.MultiplyByUniformScale(100.0f);
  321. AZ::Transform rectangleTransform = AZ::Transform::CreateIdentity();
  322. rectangleTransform.SetTranslation(sinf(m_time) * 100.0f, cosf(m_time) * -100.0f, 4.0f);
  323. rectangleTransform.MultiplyByUniformScale(100.0f);
  324. // create the TLAS
  325. RHI::RayTracingTlasDescriptor tlasDescriptor;
  326. {
  327. RHI::RayTracingTlasInstance& tlasInstance = tlasDescriptor.m_instances.emplace_back();
  328. tlasInstance.m_instanceID = 0;
  329. tlasInstance.m_hitGroupIndex = 0;
  330. tlasInstance.m_blas = m_triangleRayTracingBlas;
  331. tlasInstance.m_transform = triangleTransform1;
  332. }
  333. {
  334. RHI::RayTracingTlasInstance& tlasInstance = tlasDescriptor.m_instances.emplace_back();
  335. tlasInstance.m_instanceID = 1;
  336. tlasInstance.m_hitGroupIndex = 1;
  337. tlasInstance.m_blas = m_triangleRayTracingBlas;
  338. tlasInstance.m_transform = triangleTransform2;
  339. }
  340. {
  341. RHI::RayTracingTlasInstance& tlasInstance = tlasDescriptor.m_instances.emplace_back();
  342. tlasInstance.m_instanceID = 2;
  343. tlasInstance.m_hitGroupIndex = 2;
  344. tlasInstance.m_blas = m_triangleRayTracingBlas;
  345. tlasInstance.m_transform = triangleTransform3;
  346. }
  347. {
  348. RHI::RayTracingTlasInstance& tlasInstance = tlasDescriptor.m_instances.emplace_back();
  349. tlasInstance.m_instanceID = 3;
  350. tlasInstance.m_hitGroupIndex = 3;
  351. tlasInstance.m_blas = m_rectangleRayTracingBlas;
  352. tlasInstance.m_transform = rectangleTransform;
  353. }
  354. m_rayTracingTlas->CreateBuffers(RHI::MultiDevice::AllDevices, &tlasDescriptor, *m_rayTracingBufferPools);
  355. m_tlasBufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, (uint32_t)m_rayTracingTlas->GetTlasBuffer()->GetDescriptor().m_byteCount);
  356. [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(m_tlasBufferAttachmentId, m_rayTracingTlas->GetTlasBuffer());
  357. AZ_Error(RayTracingExampleName, result == RHI::ResultCode::Success, "Failed to import TLAS buffer with error %d", result);
  358. RHI::BufferScopeAttachmentDescriptor desc;
  359. desc.m_attachmentId = m_tlasBufferAttachmentId;
  360. desc.m_bufferViewDescriptor = m_tlasBufferViewDescriptor;
  361. desc.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Load;
  362. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::AnyGraphics);
  363. };
  364. RHI::EmptyCompileFunction<ScopeData> compileFunction;
  365. const auto executeFunction = [this]([[maybe_unused]] const RHI::FrameGraphExecuteContext& context, [[maybe_unused]] const ScopeData& scopeData)
  366. {
  367. RHI::CommandList* commandList = context.GetCommandList();
  368. commandList->BuildBottomLevelAccelerationStructure(*m_triangleRayTracingBlas->GetDeviceRayTracingBlas(context.GetDeviceIndex()));
  369. commandList->BuildBottomLevelAccelerationStructure(*m_rectangleRayTracingBlas->GetDeviceRayTracingBlas(context.GetDeviceIndex()));
  370. commandList->BuildTopLevelAccelerationStructure(
  371. *m_rayTracingTlas->GetDeviceRayTracingTlas(context.GetDeviceIndex()), { m_triangleRayTracingBlas->GetDeviceRayTracingBlas(context.GetDeviceIndex()).get(), m_rectangleRayTracingBlas->GetDeviceRayTracingBlas(context.GetDeviceIndex()).get() });
  372. };
  373. m_scopeProducers.emplace_back(
  374. aznew RHI::ScopeProducerFunction<
  375. ScopeData,
  376. decltype(prepareFunction),
  377. decltype(compileFunction),
  378. decltype(executeFunction)>(
  379. RHI::ScopeId{ "RayTracingBuildAccelerationStructure" },
  380. ScopeData{},
  381. prepareFunction,
  382. compileFunction,
  383. executeFunction));
  384. }
  385. void RayTracingExampleComponent::CreateRayTracingDispatchScope()
  386. {
  387. struct ScopeData
  388. {
  389. };
  390. const auto prepareFunction = [this]([[maybe_unused]] RHI::FrameGraphInterface frameGraph, [[maybe_unused]] ScopeData& scopeData)
  391. {
  392. // attach output image
  393. {
  394. [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(m_outputImageAttachmentId, m_outputImage);
  395. AZ_Error(RayTracingExampleName, result == RHI::ResultCode::Success, "Failed to import output image with error %d", result);
  396. RHI::ImageScopeAttachmentDescriptor desc;
  397. desc.m_attachmentId = m_outputImageAttachmentId;
  398. desc.m_imageViewDescriptor = m_outputImageViewDescriptor;
  399. desc.m_loadStoreAction.m_clearValue = RHI::ClearValue::CreateVector4Float(0.0f, 0.0f, 0.0f, 0.0f);
  400. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::RayTracingShader);
  401. }
  402. // attach TLAS buffer
  403. if (m_rayTracingTlas->GetTlasBuffer())
  404. {
  405. RHI::BufferScopeAttachmentDescriptor desc;
  406. desc.m_attachmentId = m_tlasBufferAttachmentId;
  407. desc.m_bufferViewDescriptor = m_tlasBufferViewDescriptor;
  408. desc.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::Load;
  409. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::RayTracingShader);
  410. }
  411. frameGraph.SetEstimatedItemCount(1);
  412. };
  413. const auto compileFunction = [this]([[maybe_unused]] const RHI::FrameGraphCompileContext& context, [[maybe_unused]] const ScopeData& scopeData)
  414. {
  415. if (m_rayTracingTlas->GetTlasBuffer())
  416. {
  417. // set the TLAS and output image in the ray tracing global Srg
  418. RHI::ShaderInputBufferIndex tlasConstantIndex;
  419. FindShaderInputIndex(&tlasConstantIndex, m_globalSrg, AZ::Name{ "m_scene" }, RayTracingExampleName);
  420. uint32_t tlasBufferByteCount = aznumeric_cast<uint32_t>(m_rayTracingTlas->GetTlasBuffer()->GetDescriptor().m_byteCount);
  421. RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRayTracingTLAS(tlasBufferByteCount);
  422. m_globalSrg->SetBufferView(tlasConstantIndex, m_rayTracingTlas->GetTlasBuffer()->GetBufferView(bufferViewDescriptor).get());
  423. RHI::ShaderInputImageIndex outputConstantIndex;
  424. FindShaderInputIndex(&outputConstantIndex, m_globalSrg, AZ::Name{ "m_output" }, RayTracingExampleName);
  425. m_globalSrg->SetImageView(outputConstantIndex, m_outputImageView.get());
  426. // set hit shader data, each array element corresponds to the InstanceIndex() of the geometry in the TLAS
  427. // Note: this method is used instead of LocalRootSignatures for compatibility with non-DX12 platforms
  428. // set HitGradient values
  429. RHI::ShaderInputConstantIndex hitGradientDataConstantIndex;
  430. FindShaderInputIndex(&hitGradientDataConstantIndex, m_globalSrg, AZ::Name{"m_hitGradientData"}, RayTracingExampleName);
  431. struct HitGradientData
  432. {
  433. AZ::Vector4 m_color;
  434. };
  435. AZStd::array<HitGradientData, 4> hitGradientData = {{
  436. {AZ::Vector4(1.0f, 0.0f, 0.0f, 1.0f)}, // triangle1
  437. {AZ::Vector4(0.0f, 1.0f, 0.0f, 1.0f)}, // triangle2
  438. {AZ::Vector4(0.0f, 0.0f, 0.0f, 0.0f)}, // unused
  439. {AZ::Vector4(0.0f, 0.0f, 0.0f, 0.0f)}, // unused
  440. }};
  441. m_globalSrg->SetConstantArray(hitGradientDataConstantIndex, hitGradientData);
  442. // set HitSolid values
  443. RHI::ShaderInputConstantIndex hitSolidDataConstantIndex;
  444. FindShaderInputIndex(&hitSolidDataConstantIndex, m_globalSrg, AZ::Name{"m_hitSolidData"}, RayTracingExampleName);
  445. struct HitSolidData
  446. {
  447. AZ::Vector4 m_color1;
  448. float m_lerp;
  449. float m_pad[3];
  450. AZ::Vector4 m_color2;
  451. };
  452. AZStd::array<HitSolidData, 4> hitSolidData = {{
  453. {AZ::Vector4(0.0f, 0.0f, 0.0f, 0.0f), 0.0f, {0.0f, 0.0f, 0.0f}, AZ::Vector4(0.0f, 0.0f, 0.0f, 0.0f)}, // unused
  454. {AZ::Vector4(0.0f, 0.0f, 0.0f, 0.0f), 0.0f, {0.0f, 0.0f, 0.0f}, AZ::Vector4(0.0f, 0.0f, 0.0f, 0.0f)}, // unused
  455. {AZ::Vector4(1.0f, 0.0f, 0.0f, 1.0f), 0.5f, {0.0f, 0.0f, 0.0f}, AZ::Vector4(0.0f, 1.0f, 0.0f, 1.0f)}, // triangle3
  456. {AZ::Vector4(1.0f, 0.0f, 0.0f, 1.0f), 0.5f, {0.0f, 0.0f, 0.0f}, AZ::Vector4(0.0f, 0.0f, 1.0f, 1.0f)}, // rectangle
  457. }};
  458. m_globalSrg->SetConstantArray(hitSolidDataConstantIndex, hitSolidData);
  459. m_globalSrg->Compile();
  460. // update the ray tracing shader table
  461. AZStd::shared_ptr<RHI::RayTracingShaderTableDescriptor> descriptor = AZStd::make_shared<RHI::RayTracingShaderTableDescriptor>();
  462. descriptor->m_name = AZ::Name("RayTracingExampleShaderTable");
  463. descriptor->m_rayTracingPipelineState = m_rayTracingPipelineState;
  464. descriptor->m_rayGenerationRecord.emplace_back(AZ::Name("RayGenerationShader"));
  465. descriptor->m_missRecords.emplace_back(AZ::Name("MissShader"));
  466. descriptor->m_hitGroupRecords.emplace_back(AZ::Name("HitGroupGradient")); // triangle1
  467. descriptor->m_hitGroupRecords.emplace_back(AZ::Name("HitGroupGradient")); // triangle2
  468. descriptor->m_hitGroupRecords.emplace_back(AZ::Name("HitGroupSolid")); // triangle3
  469. descriptor->m_hitGroupRecords.emplace_back(AZ::Name("HitGroupSolid")); // rectangle
  470. m_rayTracingShaderTable->Build(descriptor);
  471. }
  472. };
  473. const auto executeFunction = [this](const RHI::FrameGraphExecuteContext& context, [[maybe_unused]] const ScopeData& scopeData)
  474. {
  475. if (!m_rayTracingTlas->GetTlasBuffer())
  476. {
  477. return;
  478. }
  479. RHI::CommandList* commandList = context.GetCommandList();
  480. const RHI::DeviceShaderResourceGroup* shaderResourceGroups[] = {
  481. m_globalSrg->GetRHIShaderResourceGroup()->GetDeviceShaderResourceGroup(context.GetDeviceIndex()).get()
  482. };
  483. RHI::DeviceDispatchRaysItem dispatchRaysItem;
  484. dispatchRaysItem.m_arguments.m_direct.m_width = m_imageWidth;
  485. dispatchRaysItem.m_arguments.m_direct.m_height = m_imageHeight;
  486. dispatchRaysItem.m_arguments.m_direct.m_depth = 1;
  487. dispatchRaysItem.m_rayTracingPipelineState = m_rayTracingPipelineState->GetDeviceRayTracingPipelineState(context.GetDeviceIndex()).get();
  488. dispatchRaysItem.m_rayTracingShaderTable = m_rayTracingShaderTable->GetDeviceRayTracingShaderTable(context.GetDeviceIndex()).get();
  489. dispatchRaysItem.m_shaderResourceGroupCount = RHI::ArraySize(shaderResourceGroups);
  490. dispatchRaysItem.m_shaderResourceGroups = shaderResourceGroups;
  491. dispatchRaysItem.m_globalPipelineState = m_globalPipelineState->GetDevicePipelineState(context.GetDeviceIndex()).get();
  492. // submit the DispatchRays item
  493. commandList->Submit(dispatchRaysItem);
  494. };
  495. m_scopeProducers.emplace_back(
  496. aznew RHI::ScopeProducerFunction<
  497. ScopeData,
  498. decltype(prepareFunction),
  499. decltype(compileFunction),
  500. decltype(executeFunction)>(
  501. RHI::ScopeId{ "RayTracingDispatch" },
  502. ScopeData{},
  503. prepareFunction,
  504. compileFunction,
  505. executeFunction));
  506. }
  507. void RayTracingExampleComponent::CreateRasterScope()
  508. {
  509. struct ScopeData
  510. {
  511. };
  512. const auto prepareFunction = [this](RHI::FrameGraphInterface frameGraph, [[maybe_unused]] ScopeData& scopeData)
  513. {
  514. // attach swapchain
  515. {
  516. RHI::ImageScopeAttachmentDescriptor descriptor;
  517. descriptor.m_attachmentId = m_outputAttachmentId;
  518. descriptor.m_loadStoreAction.m_loadAction = RHI::AttachmentLoadAction::DontCare;
  519. frameGraph.UseColorAttachment(descriptor);
  520. }
  521. // attach output buffer
  522. {
  523. RHI::ImageScopeAttachmentDescriptor desc;
  524. desc.m_attachmentId = m_outputImageAttachmentId;
  525. desc.m_imageViewDescriptor = m_outputImageViewDescriptor;
  526. desc.m_loadStoreAction.m_clearValue = RHI::ClearValue::CreateVector4Float(0.0f, 0.0f, 0.0f, 0.0f);
  527. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite, RHI::ScopeAttachmentStage::FragmentShader);
  528. const Name outputImageId{ "m_output" };
  529. RHI::ShaderInputImageIndex outputImageIndex = m_drawSRG->FindShaderInputImageIndex(outputImageId);
  530. AZ_Error(RayTracingExampleName, outputImageIndex.IsValid(), "Failed to find shader input image %s.", outputImageId.GetCStr());
  531. m_drawSRG->SetImageView(outputImageIndex, m_outputImageView.get());
  532. m_drawSRG->Compile();
  533. }
  534. frameGraph.SetEstimatedItemCount(1);
  535. };
  536. RHI::EmptyCompileFunction<ScopeData> compileFunction;
  537. const auto executeFunction = [this](const RHI::FrameGraphExecuteContext& context, [[maybe_unused]] const ScopeData& scopeData)
  538. {
  539. RHI::CommandList* commandList = context.GetCommandList();
  540. commandList->SetViewports(&m_viewport, 1);
  541. commandList->SetScissors(&m_scissor, 1);
  542. const RHI::DeviceShaderResourceGroup* shaderResourceGroups[] = {
  543. m_drawSRG->GetRHIShaderResourceGroup()->GetDeviceShaderResourceGroup(context.GetDeviceIndex()).get()
  544. };
  545. RHI::DeviceDrawItem drawItem;
  546. drawItem.m_geometryView = m_geometryView.GetDeviceGeometryView(context.GetDeviceIndex());
  547. drawItem.m_streamIndices = m_geometryView.GetFullStreamBufferIndices();
  548. drawItem.m_pipelineState = m_drawPipelineState->GetDevicePipelineState(context.GetDeviceIndex()).get();
  549. drawItem.m_shaderResourceGroupCount = static_cast<uint8_t>(RHI::ArraySize(shaderResourceGroups));
  550. drawItem.m_shaderResourceGroups = shaderResourceGroups;
  551. // submit the triangle draw item.
  552. commandList->Submit(drawItem);
  553. };
  554. m_scopeProducers.emplace_back(
  555. aznew RHI::ScopeProducerFunction<
  556. ScopeData,
  557. decltype(prepareFunction),
  558. decltype(compileFunction),
  559. decltype(executeFunction)>(
  560. RHI::ScopeId{ "Raster" },
  561. ScopeData{},
  562. prepareFunction,
  563. compileFunction,
  564. executeFunction));
  565. }
  566. } // namespace AtomSampleViewer