3
0

DiffuseProbeGridQueryFullscreenPass.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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 <AzCore/Memory/SystemAllocator.h>
  9. #include <Atom/RHI/CommandList.h>
  10. #include <Atom/RHI/FrameGraphBuilder.h>
  11. #include <Atom/RHI/FrameGraphInterface.h>
  12. #include <Atom/RHI/DevicePipelineState.h>
  13. #include <Atom/RPI.Public/RenderPipeline.h>
  14. #include <Atom/RPI.Public/Pass/PassUtils.h>
  15. #include <Atom/RPI.Public/RPIUtils.h>
  16. #include <Atom/RPI.Public/Scene.h>
  17. #include <DiffuseProbeGrid_Traits_Platform.h>
  18. #include <Render/DiffuseProbeGridQueryFullscreenPass.h>
  19. #include <Render/DiffuseProbeGridQueryFullscreenPassData.h>
  20. namespace AZ
  21. {
  22. namespace Render
  23. {
  24. RPI::Ptr<DiffuseProbeGridQueryFullscreenPass> DiffuseProbeGridQueryFullscreenPass::Create(const RPI::PassDescriptor& descriptor)
  25. {
  26. RPI::Ptr<DiffuseProbeGridQueryFullscreenPass> pass = aznew DiffuseProbeGridQueryFullscreenPass(descriptor);
  27. return AZStd::move(pass);
  28. }
  29. DiffuseProbeGridQueryFullscreenPass::DiffuseProbeGridQueryFullscreenPass(const RPI::PassDescriptor& descriptor)
  30. : RPI::RenderPass(descriptor),
  31. m_passDescriptor(descriptor)
  32. {
  33. if (!AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED)
  34. {
  35. // GI is not supported on this platform
  36. SetEnabled(false);
  37. }
  38. else
  39. {
  40. LoadShader();
  41. }
  42. }
  43. void DiffuseProbeGridQueryFullscreenPass::LoadShader()
  44. {
  45. auto passData = RPI::PassUtils::GetPassData<DiffuseProbeGridQueryFullscreenPassData>(m_passDescriptor);
  46. bool useAlbedoTexture = (passData && passData->m_useAlbedoTexture);
  47. // load shader
  48. // Note: the shader may not be available on all platforms
  49. static const char* QueryFullscreenShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridQueryFullscreen.azshader";
  50. static const char* QueryFullscreenWithAlbedoShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridQueryFullscreenWithAlbedo.azshader";
  51. AZStd::string shaderFilePath = useAlbedoTexture ? QueryFullscreenWithAlbedoShaderFilePath : QueryFullscreenShaderFilePath;
  52. m_shader = RPI::LoadCriticalShader(shaderFilePath);
  53. if (m_shader == nullptr)
  54. {
  55. return;
  56. }
  57. // load pipeline state
  58. RHI::PipelineStateDescriptorForDispatch pipelineStateDescriptor;
  59. const auto& shaderVariant = m_shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
  60. shaderVariant.ConfigurePipelineState(pipelineStateDescriptor);
  61. m_pipelineState = m_shader->AcquirePipelineState(pipelineStateDescriptor);
  62. // load the ObjectSrg layout
  63. m_objectSrgLayout = m_shader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Object);
  64. // load the PassSrg
  65. const auto passSrgLayout = m_shader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Pass);
  66. if (passSrgLayout)
  67. {
  68. m_shaderResourceGroup = RPI::ShaderResourceGroup::Create(m_shader->GetAsset(), m_shader->GetSupervariantIndex(), passSrgLayout->GetName());
  69. AZ_Assert(m_shaderResourceGroup, "[DiffuseProbeGridQueryFullscreenPass]: Failed to create PassSrg", GetPathName().GetCStr());
  70. RPI::PassUtils::BindDataMappingsToSrg(m_passDescriptor, m_shaderResourceGroup.get());
  71. }
  72. // retrieve the number of threads per thread group from the shader
  73. const auto outcome = RPI::GetComputeShaderNumThreads(m_shader->GetAsset(), m_dispatchArgs);
  74. if (!outcome.IsSuccess())
  75. {
  76. AZ_Error("PassSystem", false, "[DiffuseProbeGridQueryFullscreenPass '%s']: Shader '%s' contains invalid numthreads arguments:\n%s", GetPathName().GetCStr(), shaderFilePath.c_str(), outcome.GetError().c_str());
  77. }
  78. }
  79. bool DiffuseProbeGridQueryFullscreenPass::IsEnabled() const
  80. {
  81. if (!RenderPass::IsEnabled())
  82. {
  83. return false;
  84. }
  85. RPI::Scene* scene = m_pipeline->GetScene();
  86. if (!scene)
  87. {
  88. return false;
  89. }
  90. // Note: the pass is enabled even if none of the queries are in a DiffuseProbeGrid volume. This is necessary to provide a zero result
  91. // for those queries in the transient output buffer.
  92. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  93. if (!diffuseProbeGridFeatureProcessor)
  94. {
  95. return false;
  96. }
  97. return true;
  98. }
  99. void DiffuseProbeGridQueryFullscreenPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
  100. {
  101. RenderPass::SetupFrameGraphDependencies(frameGraph);
  102. RPI::Scene* scene = m_pipeline->GetScene();
  103. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  104. frameGraph.SetEstimatedItemCount(aznumeric_cast<uint32_t>(diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids().size()));
  105. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids())
  106. {
  107. // grid data buffer
  108. {
  109. RHI::BufferScopeAttachmentDescriptor desc;
  110. desc.m_attachmentId = diffuseProbeGrid->GetGridDataBufferAttachmentId();
  111. desc.m_bufferViewDescriptor = diffuseProbeGrid->GetRenderData()->m_gridDataBufferViewDescriptor;
  112. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  113. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::ComputeShader);
  114. }
  115. // probe irradiance
  116. {
  117. RHI::ImageScopeAttachmentDescriptor desc;
  118. desc.m_attachmentId = diffuseProbeGrid->GetIrradianceImageAttachmentId();
  119. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeIrradianceImageViewDescriptor;
  120. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  121. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::ComputeShader);
  122. }
  123. // probe distance
  124. {
  125. RHI::ImageScopeAttachmentDescriptor desc;
  126. desc.m_attachmentId = diffuseProbeGrid->GetDistanceImageAttachmentId();
  127. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDistanceImageViewDescriptor;
  128. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  129. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::ComputeShader);
  130. }
  131. // probe data
  132. {
  133. RHI::ImageScopeAttachmentDescriptor desc;
  134. desc.m_attachmentId = diffuseProbeGrid->GetProbeDataImageAttachmentId();
  135. desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDataImageViewDescriptor;
  136. desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
  137. frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read, RHI::ScopeAttachmentStage::ComputeShader);
  138. }
  139. }
  140. }
  141. void DiffuseProbeGridQueryFullscreenPass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context)
  142. {
  143. if (m_shaderResourceGroup != nullptr)
  144. {
  145. BindPassSrg(context, m_shaderResourceGroup);
  146. m_shaderResourceGroup->Compile();
  147. }
  148. RPI::Scene* scene = m_pipeline->GetScene();
  149. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  150. for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids())
  151. {
  152. // update DiffuseProbeGrid-specific bindings
  153. diffuseProbeGrid->UpdateQuerySrg(m_shader, m_objectSrgLayout);
  154. diffuseProbeGrid->GetQuerySrg()->Compile();
  155. }
  156. if (auto viewSRG = diffuseProbeGridFeatureProcessor->GetViewSrg(m_pipeline, GetPipelineViewTag()))
  157. {
  158. BindSrg(viewSRG->GetRHIShaderResourceGroup());
  159. }
  160. }
  161. void DiffuseProbeGridQueryFullscreenPass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
  162. {
  163. RHI::CommandList* commandList = context.GetCommandList();
  164. RPI::Scene* scene = m_pipeline->GetScene();
  165. DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
  166. // submit the DispatchItems for each DiffuseProbeGrid in this range
  167. for (uint32_t index = context.GetSubmitRange().m_startIndex; index < context.GetSubmitRange().m_endIndex; ++index)
  168. {
  169. AZStd::shared_ptr<DiffuseProbeGrid> diffuseProbeGrid = diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()[index];
  170. const AZStd::vector<RPI::ViewPtr>& views = m_pipeline->GetViews(RPI::PipelineViewTag{ "MainCamera" });
  171. if (views.empty())
  172. {
  173. return;
  174. }
  175. // retrieve output image for the number of dispatch threads
  176. RPI::PassAttachment* outputAttachment = nullptr;
  177. if (GetOutputCount() > 0)
  178. {
  179. outputAttachment = GetOutputBinding(0).GetAttachment().get();
  180. }
  181. else if (GetInputOutputCount() > 0)
  182. {
  183. outputAttachment = GetInputOutputBinding(0).GetAttachment().get();
  184. }
  185. AZ_Assert(outputAttachment != nullptr, "[DiffuseProbeGridQueryFullscreenPass '%s']: A fullscreen DiffuseProbeGridQuery pass must have a valid output or input/output.", GetPathName().GetCStr());
  186. AZ_Assert(outputAttachment->GetAttachmentType() == RHI::AttachmentType::Image, "[DiffuseProbeGridQueryFullscreenPass '%s']: The output of a fullscreen DiffuseProbeGridQuery pass must be an image.", GetPathName().GetCStr());
  187. RHI::Size imageSize = outputAttachment->m_descriptor.m_image.m_size;
  188. // submit DispatchItem
  189. const uint8_t srgCount = 3;
  190. AZStd::array<const RHI::DeviceShaderResourceGroup*, 8> shaderResourceGroups =
  191. {
  192. diffuseProbeGrid->GetQuerySrg()->GetRHIShaderResourceGroup()->GetDeviceShaderResourceGroup(context.GetDeviceIndex()).get(),
  193. m_shaderResourceGroup->GetRHIShaderResourceGroup()->GetDeviceShaderResourceGroup(context.GetDeviceIndex()).get(),
  194. views[0]->GetRHIShaderResourceGroup()->GetDeviceShaderResourceGroup(context.GetDeviceIndex()).get()
  195. };
  196. RHI::DeviceDispatchItem dispatchItem;
  197. dispatchItem.m_pipelineState = m_pipelineState->GetDevicePipelineState(context.GetDeviceIndex()).get();
  198. dispatchItem.m_arguments = m_dispatchArgs;
  199. dispatchItem.m_shaderResourceGroupCount = srgCount;
  200. dispatchItem.m_shaderResourceGroups = shaderResourceGroups;
  201. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = imageSize.m_width;
  202. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = imageSize.m_height;
  203. dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
  204. commandList->Submit(dispatchItem, index);
  205. }
  206. }
  207. } // namespace Render
  208. } // namespace AZ