diff --git a/Gems/Atom/Feature/Common/Assets/Models/DiffuseProbeSphere.fbx b/Gems/Atom/Feature/Common/Assets/Models/DiffuseProbeSphere.fbx new file mode 100644 index 0000000000..0fdf350c1f --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Models/DiffuseProbeSphere.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18a2bfdeeabfbbf6397daab7c89f9f7321e4863b54a4669fa87e457cb113322c +size 78256 diff --git a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseGlobalIllumination.pass b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseGlobalIllumination.pass index 45278cd511..a70f4446a4 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseGlobalIllumination.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseGlobalIllumination.pass @@ -42,6 +42,22 @@ }, "LoadAction": "Clear" } + }, + { + "Name": "VisualizationOutput", + "SlotType": "Output", + "ScopeAttachmentUsage": "RenderTarget", + "LoadStoreAction": { + "ClearValue": { + "Value": [ + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "LoadAction": "Clear" + } } ], "ImageAttachments": [ @@ -73,7 +89,14 @@ "AttachmentRef": { "Pass": "This", "Attachment": "IrradianceImage" - } + } + }, + { + "LocalSlot": "VisualizationOutput", + "AttachmentRef": { + "Pass": "DiffuseProbeGridVisualizationRayTracingPass", + "Attachment": "Output" + } } ], "PassRequests": [ @@ -193,6 +216,18 @@ } } ] + }, + { + "Name": "DiffuseProbeGridVisualizationPreparePass", + "TemplateName": "DiffuseProbeGridVisualizationPreparePassTemplate" + }, + { + "Name": "DiffuseProbeGridVisualizationAccelerationStructurePass", + "TemplateName": "DiffuseProbeGridVisualizationAccelerationStructurePassTemplate" + }, + { + "Name": "DiffuseProbeGridVisualizationRayTracingPass", + "TemplateName": "DiffuseProbeGridVisualizationRayTracingPassTemplate" } ] } diff --git a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationAccelerationStructure.pass b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationAccelerationStructure.pass new file mode 100644 index 0000000000..78d4c82dcf --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationAccelerationStructure.pass @@ -0,0 +1,13 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": + { + "PassTemplate": + { + "Name": "DiffuseProbeGridVisualizationAccelerationStructurePassTemplate", + "PassClass": "DiffuseProbeGridVisualizationAccelerationStructurePass" + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationComposite.pass b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationComposite.pass new file mode 100644 index 0000000000..9f19fde4af --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationComposite.pass @@ -0,0 +1,40 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "DiffuseProbeGridVisualizationCompositePassTemplate", + "PassClass": "DiffuseProbeGridVisualizationCompositePass", + "Slots": [ + { + "Name": "VisualizationInput", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader" + }, + { + "Name": "Depth", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader", + "ImageViewDesc": { + "AspectFlags": [ + "Depth" + ] + } + }, + { + "Name": "ColorInputOutput", + "SlotType": "InputOutput", + "ScopeAttachmentUsage": "RenderTarget" + } + ], + "PassData": { + "$type": "FullscreenTrianglePassData", + "ShaderAsset": { + "FilePath": "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.shader" + }, + "PipelineViewTag": "MainCamera" + } + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationPrepare.pass b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationPrepare.pass new file mode 100644 index 0000000000..aa95128a2e --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationPrepare.pass @@ -0,0 +1,13 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": + { + "PassTemplate": + { + "Name": "DiffuseProbeGridVisualizationPreparePassTemplate", + "PassClass": "DiffuseProbeGridVisualizationPreparePass" + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationRayTracing.pass b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationRayTracing.pass new file mode 100644 index 0000000000..bdfba0d478 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Passes/DiffuseProbeGridVisualizationRayTracing.pass @@ -0,0 +1,54 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PassAsset", + "ClassData": { + "PassTemplate": { + "Name": "DiffuseProbeGridVisualizationRayTracingPassTemplate", + "PassClass": "DiffuseProbeGridVisualizationRayTracingPass", + "Slots": [ + { + "Name": "Output", + "SlotType": "Output", + "ShaderInputName": "m_output", + "ScopeAttachmentUsage": "Shader", + "LoadStoreAction": { + "ClearValue": { + "Value": [ + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "LoadAction": "Clear" + } + } + ], + "ImageAttachments": [ + { + "Name": "VisualizationImage", + "SizeSource": { + "Source": { + "Pass": "Parent", + "Attachment": "NormalInput" + } + }, + "ImageDescriptor": { + "Format": "R32G32B32A32_FLOAT", + "SharedQueueMask": "Graphics" + } + } + ], + "Connections": [ + { + "LocalSlot": "Output", + "AttachmentRef": { + "Pass": "This", + "Attachment": "VisualizationImage" + } + } + ] + } + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass index 314d999e4d..f0c1c212c0 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/MainPipeline.pass @@ -357,6 +357,33 @@ } ] }, + { + "Name": "DiffuseProbeGridVisualizationCompositePass", + "TemplateName": "DiffuseProbeGridVisualizationCompositePassTemplate", + "Connections": [ + { + "LocalSlot": "VisualizationInput", + "AttachmentRef": { + "Pass": "OpaquePass", + "Attachment": "DiffuseProbeGridVisualization" + } + }, + { + "LocalSlot": "Depth", + "AttachmentRef": { + "Pass": "DepthPrePass", + "Attachment": "Depth" + } + }, + { + "LocalSlot": "ColorInputOutput", + "AttachmentRef": { + "Pass": "PostProcessPass", + "Attachment": "Output" + } + } + ] + }, { "Name": "AuxGeomPass", "TemplateName": "AuxGeomPassTemplate", @@ -365,8 +392,8 @@ { "LocalSlot": "ColorInputOutput", "AttachmentRef": { - "Pass": "PostProcessPass", - "Attachment": "Output" + "Pass": "DiffuseProbeGridVisualizationCompositePass", + "Attachment": "ColorInputOutput" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass index 752d565234..dcf5ef3550 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass @@ -46,6 +46,10 @@ "Name": "Output", "SlotType": "Output" }, + { + "Name": "DiffuseProbeGridVisualization", + "SlotType": "Output" + }, // SwapChain here is only used to reference the frame height and format { "Name": "SwapChainOutput", @@ -59,6 +63,13 @@ "Pass": "DiffuseSpecularMergePass", "Attachment": "Output" } + }, + { + "LocalSlot": "DiffuseProbeGridVisualization", + "AttachmentRef": { + "Pass": "DiffuseGlobalIlluminationPass", + "Attachment": "VisualizationOutput" + } } ], "PassRequests": [ diff --git a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset index 96cf769690..16e6a7ee72 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset +++ b/Gems/Atom/Feature/Common/Assets/Passes/PassTemplates.azasset @@ -476,6 +476,22 @@ "Name": "DiffuseCompositePassTemplate", "Path": "Passes/DiffuseComposite.pass" }, + { + "Name": "DiffuseProbeGridVisualizationPreparePassTemplate", + "Path": "Passes/DiffuseProbeGridVisualizationPrepare.pass" + }, + { + "Name": "DiffuseProbeGridVisualizationAccelerationStructurePassTemplate", + "Path": "Passes/DiffuseProbeGridVisualizationAccelerationStructure.pass" + }, + { + "Name": "DiffuseProbeGridVisualizationRayTracingPassTemplate", + "Path": "Passes/DiffuseProbeGridVisualizationRayTracing.pass" + }, + { + "Name": "DiffuseProbeGridVisualizationCompositePassTemplate", + "Path": "Passes/DiffuseProbeGridVisualizationComposite.pass" + }, { "Name": "DiffuseGlobalFullscreenPassTemplate", "Path": "Passes/DiffuseGlobalFullscreen.pass" diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.azsl new file mode 100644 index 0000000000..e6b28da8c8 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.azsl @@ -0,0 +1,65 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +ShaderResourceGroup PassSrg : SRG_PerPass +{ + Texture2D m_visualization; + Texture2D m_depth; + + Sampler LinearSampler + { + MinFilter = Linear; + MagFilter = Linear; + MipFilter = Linear; + AddressU = Clamp; + AddressV = Clamp; + AddressW = Clamp; + }; +} + +// Vertex Shader +VSOutput MainVS(VSInput input) +{ + VSOutput OUT; + + float4 posTex = GetVertexPositionAndTexCoords(input.m_vertexID); + OUT.m_position = float4(posTex.x, posTex.y, 0.0, 1.0); + + return OUT; +} + +// Pixel Shader +PSOutput MainPS(VSOutput IN) +{ + uint2 screenCoords = IN.m_position.xy; + float depth = PassSrg::m_depth.Load(uint3(screenCoords, 0)).r; + float4 visualization = PassSrg::m_visualization.Load(uint3(screenCoords, 0)); + + if (!any(visualization)) + { + discard; + } + + if (depth > visualization.a) + { + discard; + } + + PSOutput OUT; + OUT.m_color = float4(visualization.rgb, 1.0f); + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.shader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.shader new file mode 100644 index 0000000000..8d758b9b6d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationComposite.shader @@ -0,0 +1,42 @@ +{ + "Source" : "DiffuseProbeGridVisualizationComposite.azsl", + + "RasterState" : + { + "CullMode" : "Back" + }, + + "DepthStencilState" : + { + "Depth" : + { + "Enable" : false + } + }, + + "DrawList" : "forward", + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + }, + + "Supervariants": + [ + { + "Name": "NoMSAA", + "PlusArguments": "--no-ms", + "MinusArguments": "" + } + ] +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPrepare.precompiledshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPrepare.precompiledshader new file mode 100644 index 0000000000..d77b7fcb0e --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPrepare.precompiledshader @@ -0,0 +1,34 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PrecompiledShaderAssetSourceData", + "ClassData": + { + "ShaderAssetFileName": "diffuseprobegridvisualizationprepare.azshader", + "PlatformIdentifiers": [ + "pc", + "linux" + ], + "Supervariants": + [ + { + "Name": "", + "RootShaderVariantAssets": + [ + { + "APIName": "dx12", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationprepare_dx12_0.azshadervariant" + }, + { + "APIName": "vulkan", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationprepare_vulkan_0.azshadervariant" + }, + { + "APIName": "null", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationprepare_null_0.azshadervariant" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracing.precompiledshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracing.precompiledshader new file mode 100644 index 0000000000..ff38bfd843 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracing.precompiledshader @@ -0,0 +1,34 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PrecompiledShaderAssetSourceData", + "ClassData": + { + "ShaderAssetFileName": "diffuseprobegridvisualizationraytracing.azshader", + "PlatformIdentifiers": [ + "pc", + "linux" + ], + "Supervariants": + [ + { + "Name": "", + "RootShaderVariantAssets": + [ + { + "APIName": "dx12", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracing_dx12_0.azshadervariant" + }, + { + "APIName": "vulkan", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracing_vulkan_0.azshadervariant" + }, + { + "APIName": "null", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracing_null_0.azshadervariant" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingClosestHit.precompiledshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingClosestHit.precompiledshader new file mode 100644 index 0000000000..1f0d0f7e11 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingClosestHit.precompiledshader @@ -0,0 +1,35 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PrecompiledShaderAssetSourceData", + "ClassData": + { + "ShaderAssetFileName": "diffuseprobegridvisualizationraytracingclosesthit.azshader", + "PlatformIdentifiers": + [ + "pc", + "linux" + ], + "Supervariants": + [ + { + "Name": "", + "RootShaderVariantAssets": + [ + { + "APIName": "dx12", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingclosesthit_dx12_0.azshadervariant" + }, + { + "APIName": "vulkan", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingclosesthit_vulkan_0.azshadervariant" + }, + { + "APIName": "null", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingclosesthit_null_0.azshadervariant" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingMiss.precompiledshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingMiss.precompiledshader new file mode 100644 index 0000000000..905006d92a --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingMiss.precompiledshader @@ -0,0 +1,35 @@ +{ + "Type": "JsonSerialization", + "Version": 1, + "ClassName": "PrecompiledShaderAssetSourceData", + "ClassData": + { + "ShaderAssetFileName": "diffuseprobegridvisualizationraytracingmiss.azshader", + "PlatformIdentifiers": + [ + "pc", + "linux" + ], + "Supervariants": + [ + { + "Name": "", + "RootShaderVariantAssets": + [ + { + "APIName": "dx12", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingmiss_dx12_0.azshadervariant" + }, + { + "APIName": "vulkan", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingmiss_vulkan_0.azshadervariant" + }, + { + "APIName": "null", + "RootShaderVariantAssetFileName": "diffuseprobegridvisualizationraytracingmiss_null_0.azshadervariant" + } + ] + } + ] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader index 4186489303..69507ebd96 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant index 7cfce8e245..e2e46af613 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant index 3fa87b4e79..b7a82735bc 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant index 9b831386eb..570f94dc34 100644 Binary files a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrelocation_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare.azshader new file mode 100644 index 0000000000..3d9904c607 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_dx12_0.azshadervariant new file mode 100644 index 0000000000..507fd5e5a9 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_null_0.azshadervariant new file mode 100644 index 0000000000..84b6226022 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_vulkan_0.azshadervariant new file mode 100644 index 0000000000..9ad3c0deb1 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationprepare_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing.azshader new file mode 100644 index 0000000000..0b8181e53f Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_dx12_0.azshadervariant new file mode 100644 index 0000000000..99c5a3791b Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_null_0.azshadervariant new file mode 100644 index 0000000000..6c9bcb846b Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_vulkan_0.azshadervariant new file mode 100644 index 0000000000..8d0eb8a2a8 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracing_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit.azshader new file mode 100644 index 0000000000..045817ff6a Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_dx12_0.azshadervariant new file mode 100644 index 0000000000..e20b15d485 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_null_0.azshadervariant new file mode 100644 index 0000000000..4f3437ccda Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_vulkan_0.azshadervariant new file mode 100644 index 0000000000..918e729d99 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingclosesthit_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss.azshader new file mode 100644 index 0000000000..bf5102b8fa Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss.azshader differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_dx12_0.azshadervariant new file mode 100644 index 0000000000..db77503c25 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_dx12_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_null_0.azshadervariant new file mode 100644 index 0000000000..b44637279f Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_null_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_vulkan_0.azshadervariant new file mode 100644 index 0000000000..095e78c700 Binary files /dev/null and b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridvisualizationraytracingmiss_vulkan_0.azshadervariant differ diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessorInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessorInterface.h index 066efabb96..5aedc2f6c6 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessorInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessorInterface.h @@ -125,6 +125,9 @@ namespace AZ virtual void SetUseDiffuseIbl(const DiffuseProbeGridHandle& probeGrid, bool useDiffuseIbl) = 0; virtual void SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode) = 0; virtual void SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures) = 0; + virtual void SetVisualizationEnabled(const DiffuseProbeGridHandle& probeGrid, bool visualizationEnabled) = 0; + virtual void SetVisualizationShowInactiveProbes(const DiffuseProbeGridHandle& probeGrid, bool visualizationShowInactiveProbes) = 0; + virtual void SetVisualizationSphereRadius(const DiffuseProbeGridHandle& probeGrid, float visualizationSphereRadius) = 0; virtual void BakeTextures( const DiffuseProbeGridHandle& probeGrid, diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp index fa473cb8c6..2294c00d71 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp @@ -94,6 +94,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -278,6 +282,10 @@ namespace AZ passSystem->AddPassCreator(Name("DiffuseProbeGridClassificationPass"), &Render::DiffuseProbeGridClassificationPass::Create); passSystem->AddPassCreator(Name("DiffuseProbeGridDownsamplePass"), &Render::DiffuseProbeGridDownsamplePass::Create); passSystem->AddPassCreator(Name("DiffuseProbeGridRenderPass"), &Render::DiffuseProbeGridRenderPass::Create); + passSystem->AddPassCreator(Name("DiffuseProbeGridVisualizationPreparePass"), &Render::DiffuseProbeGridVisualizationPreparePass::Create); + passSystem->AddPassCreator(Name("DiffuseProbeGridVisualizationAccelerationStructurePass"), &Render::DiffuseProbeGridVisualizationAccelerationStructurePass::Create); + passSystem->AddPassCreator(Name("DiffuseProbeGridVisualizationRayTracingPass"), &Render::DiffuseProbeGridVisualizationRayTracingPass::Create); + passSystem->AddPassCreator(Name("DiffuseProbeGridVisualizationCompositePass"), &Render::DiffuseProbeGridVisualizationCompositePass::Create); passSystem->AddPassCreator(Name("LuminanceHistogramGeneratorPass"), &LuminanceHistogramGeneratorPass::Create); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp index 798ebc502b..ac7d4bbb4d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.cpp @@ -43,10 +43,15 @@ namespace AZ m_irradianceImageAttachmentId = AZStd::string::format("ProbeIrradianceImageAttachmentId_%s", uuidString.c_str()); m_distanceImageAttachmentId = AZStd::string::format("ProbeDistanceImageAttachmentId_%s", uuidString.c_str()); m_probeDataImageAttachmentId = AZStd::string::format("ProbeDataImageAttachmentId_%s", uuidString.c_str()); + m_visualizationTlasAttachmentId = AZStd::string::format("ProbeVisualizationTlasAttachmentId_%s", uuidString.c_str()); + m_visualizationTlasInstancesAttachmentId = AZStd::string::format("ProbeVisualizationTlasInstancesAttachmentId_%s", uuidString.c_str()); // setup culling m_cullable.m_cullData.m_scene = m_scene; m_cullable.SetDebugName(AZ::Name("DiffuseProbeGrid Volume")); + + // create the visualization TLAS + m_visualizationTlas = AZ::RHI::RayTracingTlas::CreateRHIRayTracingTlas(); } void DiffuseProbeGrid::Simulate(uint32_t probeIndex) @@ -116,9 +121,6 @@ namespace AZ // recompute the number of probes since the spacing changed UpdateProbeCount(); - // probes need to be relocated since the grid density changed - m_remainingRelocationIterations = DefaultNumRelocationIterations; - m_updateTextures = true; } @@ -169,9 +171,6 @@ namespace AZ m_obbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_renderExtents / 2.0f); - // probes need to be relocated since the grid extents changed - m_remainingRelocationIterations = DefaultNumRelocationIterations; - m_updateTextures = true; } @@ -201,9 +200,6 @@ namespace AZ } m_updateTextures = true; - - // probes need to be relocated since the mode has changed - m_remainingRelocationIterations = DefaultNumRelocationIterations; } void DiffuseProbeGrid::SetBakedTextures(const DiffuseProbeGridBakedTextures& bakedTextures) @@ -253,6 +249,23 @@ namespace AZ return m_cullable.m_isVisible; } + void DiffuseProbeGrid::SetVisualizationEnabled(bool visualizationEnabled) + { + m_visualizationEnabled = visualizationEnabled; + m_visualizationTlasUpdateRequired = true; + } + + void DiffuseProbeGrid::SetVisualizationSphereRadius(float visualizationSphereRadius) + { + m_visualizationSphereRadius = visualizationSphereRadius; + m_visualizationTlasUpdateRequired = true; + } + + bool DiffuseProbeGrid::GetVisualizationTlasUpdateRequired() const + { + return m_visualizationTlasUpdateRequired || m_remainingRelocationIterations > 0; + } + uint32_t DiffuseProbeGrid::GetTotalProbeCount() const { return m_probeCountX * m_probeCountY * m_probeCountZ; @@ -341,6 +354,9 @@ namespace AZ [[maybe_unused]] RHI::ResultCode result = m_renderData->m_imagePool->InitImage(request); AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize m_probeDataImage image"); } + + // probes need to be relocated since the textures changed + m_remainingRelocationIterations = DefaultNumRelocationIterations; } m_updateTextures = false; @@ -348,8 +364,8 @@ namespace AZ // textures have changed so we need to update the render Srg to bind the new ones m_updateRenderObjectSrg = true; - // we need to clear the irradiance texture - m_irradianceClearRequired = true; + // we need to clear the Irradiance, Distance, and ProbeData textures + m_textureClearRequired = true; } void DiffuseProbeGrid::ComputeProbeCount(const AZ::Vector3& extents, const AZ::Vector3& probeSpacing, uint32_t& probeCountX, uint32_t& probeCountY, uint32_t& probeCountZ) @@ -753,6 +769,77 @@ namespace AZ UpdateCulling(); } + void DiffuseProbeGrid::UpdateVisualizationPrepareSrg(const Data::Instance& shader, const RHI::Ptr& layout) + { + if (!m_visualizationPrepareSrg) + { + m_visualizationPrepareSrg = RPI::ShaderResourceGroup::Create(shader->GetAsset(), shader->GetSupervariantIndex(), layout->GetName()); + AZ_Error("DiffuseProbeGrid", m_visualizationPrepareSrg.get(), "Failed to create VisualizationPrepare shader resource group"); + } + + RHI::ShaderInputConstantIndex constantIndex; + RHI::ShaderInputImageIndex imageIndex; + RHI::ShaderInputBufferIndex bufferIndex; + + // TLAS instances + bufferIndex = layout->FindShaderInputBufferIndex(AZ::Name("m_tlasInstances")); + uint32_t tlasInstancesBufferByteCount = aznumeric_cast(m_visualizationTlas->GetTlasInstancesBuffer()->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateStructured(0, tlasInstancesBufferByteCount / RayTracingTlasInstanceElementSize, RayTracingTlasInstanceElementSize); + m_visualizationPrepareSrg->SetBufferView(bufferIndex, m_visualizationTlas->GetTlasInstancesBuffer()->GetBufferView(bufferViewDescriptor).get()); + + // probe data + imageIndex = layout->FindShaderInputImageIndex(AZ::Name("m_probeData")); + m_visualizationPrepareSrg->SetImageView(imageIndex, GetProbeDataImage()->GetImageView(m_renderData->m_probeDataImageViewDescriptor).get()); + + // probe sphere radius + constantIndex = layout->FindShaderInputConstantIndex(Name("m_probeSphereRadius")); + m_visualizationPrepareSrg->SetConstant(constantIndex, m_visualizationSphereRadius); + + SetGridConstants(m_visualizationPrepareSrg); + } + + void DiffuseProbeGrid::UpdateVisualizationRayTraceSrg(const Data::Instance& shader, const RHI::Ptr& layout, const RHI::ImageView* outputImageView) + { + if (!m_visualizationRayTraceSrg) + { + m_visualizationRayTraceSrg = RPI::ShaderResourceGroup::Create(shader->GetAsset(), shader->GetSupervariantIndex(), layout->GetName()); + AZ_Error("DiffuseProbeGrid", m_visualizationRayTraceSrg.get(), "Failed to create VisualizationRayTrace shader resource group"); + } + + RHI::ShaderInputConstantIndex constantIndex; + RHI::ShaderInputImageIndex imageIndex; + RHI::ShaderInputBufferIndex bufferIndex; + + // TLAS + uint32_t tlasBufferByteCount = aznumeric_cast(m_visualizationTlas->GetTlasBuffer()->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRayTracingTLAS(tlasBufferByteCount); + + bufferIndex = layout->FindShaderInputBufferIndex(AZ::Name("m_tlas")); + m_visualizationRayTraceSrg->SetBufferView(bufferIndex, m_visualizationTlas->GetTlasBuffer()->GetBufferView(bufferViewDescriptor).get()); + + // probe irradiance + imageIndex = layout->FindShaderInputImageIndex(AZ::Name("m_probeIrradiance")); + m_visualizationRayTraceSrg->SetImageView(imageIndex, GetIrradianceImage()->GetImageView(m_renderData->m_probeIrradianceImageViewDescriptor).get()); + + // probe distance + imageIndex = layout->FindShaderInputImageIndex(AZ::Name("m_probeDistance")); + m_visualizationRayTraceSrg->SetImageView(imageIndex, GetDistanceImage()->GetImageView(m_renderData->m_probeDistanceImageViewDescriptor).get()); + + // probe data + imageIndex = layout->FindShaderInputImageIndex(AZ::Name("m_probeData")); + m_visualizationRayTraceSrg->SetImageView(imageIndex, GetProbeDataImage()->GetImageView(m_renderData->m_probeDataImageViewDescriptor).get()); + + // show inactive probes + constantIndex = layout->FindShaderInputConstantIndex(Name("m_showInactiveProbes")); + m_visualizationRayTraceSrg->SetConstant(constantIndex, m_visualizationShowInactiveProbes); + + // output + imageIndex = layout->FindShaderInputImageIndex(AZ::Name("m_output")); + m_visualizationRayTraceSrg->SetImageView(imageIndex, outputImageView); + + SetGridConstants(m_visualizationRayTraceSrg); + } + void DiffuseProbeGrid::UpdateCulling() { if (!m_drawPacket) diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h index 8c8470cdad..3f65d6083a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGrid.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include #include @@ -98,6 +99,15 @@ namespace AZ DiffuseProbeGridMode GetMode() const { return m_mode; } void SetMode(DiffuseProbeGridMode mode); + bool GetVisualizationEnabled() const { return m_visualizationEnabled; } + void SetVisualizationEnabled(bool visualizationEnabled); + + bool GetVisualizationShowInactiveProbes() const { return m_visualizationShowInactiveProbes; } + void SetVisualizationShowInactiveProbes(bool visualizationShowInactiveProbes) { m_visualizationShowInactiveProbes = visualizationShowInactiveProbes; } + + float GetVisualizationSphereRadius() const { return m_visualizationSphereRadius; } + void SetVisualizationSphereRadius(float visualizationSphereRadius); + uint32_t GetRemainingRelocationIterations() const { return aznumeric_cast(m_remainingRelocationIterations); } void DecrementRemainingRelocationIterations() { m_remainingRelocationIterations = AZStd::max(0, m_remainingRelocationIterations - 1); } void ResetRemainingRelocationIterations() { m_remainingRelocationIterations = DefaultNumRelocationIterations; } @@ -125,6 +135,8 @@ namespace AZ const Data::Instance& GetRelocationSrg() const { return m_relocationSrg; } const Data::Instance& GetClassificationSrg() const { return m_classificationSrg; } const Data::Instance& GetRenderObjectSrg() const { return m_renderObjectSrg; } + const Data::Instance& GetVisualizationPrepareSrg() const { return m_visualizationPrepareSrg; } + const Data::Instance& GetVisualizationRayTraceSrg() const { return m_visualizationRayTraceSrg; } // Srg updates void UpdateRayTraceSrg(const Data::Instance& shader, const RHI::Ptr& srgLayout); @@ -135,6 +147,8 @@ namespace AZ void UpdateRelocationSrg(const Data::Instance& shader, const RHI::Ptr& srgLayout); void UpdateClassificationSrg(const Data::Instance& shader, const RHI::Ptr& srgLayout); void UpdateRenderObjectSrg(); + void UpdateVisualizationPrepareSrg(const Data::Instance& shader, const RHI::Ptr& srgLayout); + void UpdateVisualizationRayTraceSrg(const Data::Instance& shader, const RHI::Ptr& srgLayout, const RHI::ImageView* outputImageView); // textures const RHI::Ptr GetRayTraceImage() { return m_rayTraceImage[m_currentImageIndex]; } @@ -151,12 +165,14 @@ namespace AZ const RHI::AttachmentId GetIrradianceImageAttachmentId() const { return m_irradianceImageAttachmentId; } const RHI::AttachmentId GetDistanceImageAttachmentId() const { return m_distanceImageAttachmentId; } const RHI::AttachmentId GetProbeDataImageAttachmentId() const { return m_probeDataImageAttachmentId; } + const RHI::AttachmentId GetProbeVisualizationTlasAttachmentId() const { return m_visualizationTlasAttachmentId; } + const RHI::AttachmentId GetProbeVisualizationTlasInstancesAttachmentId() const { return m_visualizationTlasInstancesAttachmentId; } const DiffuseProbeGridRenderData* GetRenderData() const { return m_renderData; } - // the irradiance image needs to be manually cleared after it is resized in the editor - bool GetIrradianceClearRequired() const { return m_irradianceClearRequired; } - void ResetIrradianceClearRequired() { m_irradianceClearRequired = false; } + // the Irradiance, Distance, and ProbeData images need to be manually cleared after certain operations, e.g., changing the grid size + bool GetTextureClearRequired() const { return m_textureClearRequired; } + void ResetTextureClearRequired() { m_textureClearRequired = false; } // texture readback DiffuseProbeGridTextureReadback& GetTextureReadback() { return m_textureReadback; } @@ -168,7 +184,16 @@ namespace AZ static constexpr uint32_t DefaultNumDistanceTexels = 14; static constexpr int32_t DefaultNumRelocationIterations = 100; + // visualization TLAS + const RHI::Ptr& GetVisualizationTlas() const { return m_visualizationTlas; } + RHI::Ptr& GetVisualizationTlas() { return m_visualizationTlas; } + + bool GetVisualizationTlasUpdateRequired() const; + void ResetVisualizationTlasUpdateRequired() { m_visualizationTlasUpdateRequired = false; } + private: + + // helper functions void UpdateTextures(); void ComputeProbeCount(const AZ::Vector3& extents, const AZ::Vector3& probeSpacing, uint32_t& probeCountX, uint32_t& probeCountY, uint32_t& probeCountZ); bool ValidateProbeCount(const AZ::Vector3& extents, const AZ::Vector3& probeSpacing); @@ -248,7 +273,7 @@ namespace AZ RHI::Ptr m_probeDataImage[ImageFrameCount]; uint32_t m_currentImageIndex = 0; bool m_updateTextures = false; - bool m_irradianceClearRequired = true; + bool m_textureClearRequired = true; // baked textures Data::Instance m_bakedIrradianceImage; @@ -281,6 +306,17 @@ namespace AZ RHI::AttachmentId m_irradianceImageAttachmentId; RHI::AttachmentId m_distanceImageAttachmentId; RHI::AttachmentId m_probeDataImageAttachmentId; + + // probe visualization + bool m_visualizationEnabled = false; + bool m_visualizationShowInactiveProbes = false; + float m_visualizationSphereRadius = 0.5f; + RHI::Ptr m_visualizationTlas; + bool m_visualizationTlasUpdateRequired = false; + RHI::AttachmentId m_visualizationTlasAttachmentId; + RHI::AttachmentId m_visualizationTlasInstancesAttachmentId; + Data::Instance m_visualizationPrepareSrg; + Data::Instance m_visualizationRayTraceSrg; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp index a5da79a482..0b2f74191f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.cpp @@ -75,27 +75,34 @@ namespace AZ } } - void DiffuseProbeGridBlendDistancePass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridBlendDistancePass::IsEnabled() const { - RPI::Scene* scene = m_pipeline->GetScene(); - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!RenderPass::IsEnabled()) + { + return false; + } - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) { - // no diffuse probe grids - return; + return false; } RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridBlendDistancePass requires the RayTracingFeatureProcessor"); - - if (!rayTracingFeatureProcessor->GetSubMeshCount()) + if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount()) { // empty scene - return; + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; } - RenderPass::FrameBeginInternal(params); + return true; } void DiffuseProbeGridBlendDistancePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.h index 942f90eb10..6d9d26f9b3 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendDistancePass.h @@ -42,8 +42,7 @@ namespace AZ void LoadShader(); // Pass overrides - void FrameBeginInternal(FramePrepareParams params) override; - + bool IsEnabled() const override; void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; void CompileResources(const RHI::FrameGraphCompileContext& context) override; void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp index 7a12fc5415..4e29339a38 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.cpp @@ -75,27 +75,34 @@ namespace AZ } } - void DiffuseProbeGridBlendIrradiancePass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridBlendIrradiancePass::IsEnabled() const { - RPI::Scene* scene = m_pipeline->GetScene(); - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!RenderPass::IsEnabled()) + { + return false; + } - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) { - // no diffuse probe grids - return; + return false; } RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridBlendIrradiancePass requires the RayTracingFeatureProcessor"); - - if (!rayTracingFeatureProcessor->GetSubMeshCount()) + if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount()) { // empty scene - return; + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; } - RenderPass::FrameBeginInternal(params); + return true; } void DiffuseProbeGridBlendIrradiancePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.h index 77dba9745c..a9bf9bfc31 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBlendIrradiancePass.h @@ -42,8 +42,7 @@ namespace AZ void LoadShader(); // Pass overrides - void FrameBeginInternal(FramePrepareParams params) override; - + bool IsEnabled() const override; void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; void CompileResources(const RHI::FrameGraphCompileContext& context) override; void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp index c4fcb49c17..ee2b638cb7 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.cpp @@ -83,27 +83,34 @@ namespace AZ } } - void DiffuseProbeGridBorderUpdatePass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridBorderUpdatePass::IsEnabled() const { - RPI::Scene* scene = m_pipeline->GetScene(); - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!RenderPass::IsEnabled()) + { + return false; + } - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) { - // no diffuse probe grids - return; + return false; } RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridBorderUpdatePass requires the RayTracingFeatureProcessor"); - - if (!rayTracingFeatureProcessor->GetSubMeshCount()) + if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount()) { // empty scene - return; + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; } - RenderPass::FrameBeginInternal(params); + return true; } void DiffuseProbeGridBorderUpdatePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.h index ee49c66f78..415231c281 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridBorderUpdatePass.h @@ -40,8 +40,7 @@ namespace AZ RHI::DispatchDirect& dispatchArgs); // Pass overrides - void FrameBeginInternal(FramePrepareParams params) override; - + bool IsEnabled() const override; void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; void CompileResources(const RHI::FrameGraphCompileContext& context) override; void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp index 1d1e6f745f..acb5b73c1a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.cpp @@ -79,27 +79,34 @@ namespace AZ } } - void DiffuseProbeGridClassificationPass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridClassificationPass::IsEnabled() const { - RPI::Scene* scene = m_pipeline->GetScene(); - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!RenderPass::IsEnabled()) + { + return false; + } - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) { - // no diffuse probe grids - return; + return false; } RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridClassificationPass requires the RayTracingFeatureProcessor"); - - if (!rayTracingFeatureProcessor->GetSubMeshCount()) + if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount()) { // empty scene - return; + return false; } - RenderPass::FrameBeginInternal(params); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; + } + + return true; } void DiffuseProbeGridClassificationPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) @@ -160,15 +167,11 @@ namespace AZ const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetClassificationSrg()->GetRHIShaderResourceGroup(); commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup); - uint32_t probeCountX; - uint32_t probeCountY; - diffuseProbeGrid->GetTexture2DProbeCount(probeCountX, probeCountY); - RHI::DispatchItem dispatchItem; dispatchItem.m_arguments = shader.m_dispatchArgs; dispatchItem.m_pipelineState = shader.m_pipelineState; - dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX; - dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY; + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = diffuseProbeGrid->GetTotalProbeCount(); + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = 1; dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1; commandList->Submit(dispatchItem); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.h index 3ec76fd0f0..894e9df098 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridClassificationPass.h @@ -43,8 +43,7 @@ namespace AZ void LoadShader(); // Pass overrides - void FrameBeginInternal(FramePrepareParams params) override; - + bool IsEnabled() const override; void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; void CompileResources(const RHI::FrameGraphCompileContext& context) override; void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp index d690c57dea..84c066604a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -39,6 +40,7 @@ namespace AZ void DiffuseProbeGridFeatureProcessor::Activate() { RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get(); + RHI::Ptr device = rhiSystem->GetDevice(); m_diffuseProbeGrids.reserve(InitialProbeGridAllocationSize); m_realTimeDiffuseProbeGrids.reserve(InitialProbeGridAllocationSize); @@ -49,7 +51,7 @@ namespace AZ m_bufferPool = RHI::Factory::Get().CreateBufferPool(); m_bufferPool->SetName(Name("DiffuseProbeGridBoxBufferPool")); - [[maybe_unused]] RHI::ResultCode resultCode = m_bufferPool->Init(*rhiSystem->GetDevice(), desc); + [[maybe_unused]] RHI::ResultCode resultCode = m_bufferPool->Init(*device, desc); AZ_Error("DiffuseProbeGridFeatureProcessor", resultCode == RHI::ResultCode::Success, "Failed to initialize buffer pool"); // create box mesh vertices and indices @@ -61,7 +63,7 @@ namespace AZ imagePoolDesc.m_bindFlags = RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead; m_probeGridRenderData.m_imagePool = RHI::Factory::Get().CreateImagePool(); - [[maybe_unused]] RHI::ResultCode result = m_probeGridRenderData.m_imagePool->Init(*rhiSystem->GetDevice(), imagePoolDesc); + [[maybe_unused]] RHI::ResultCode result = m_probeGridRenderData.m_imagePool->Init(*device, imagePoolDesc); AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize output image pool"); } @@ -90,6 +92,22 @@ namespace AZ AZ_Error("DiffuseProbeGridFeatureProcessor", m_probeGridRenderData.m_srgLayout != nullptr, "Failed to find ObjectSrg layout"); } + // initialize the buffer pools for the DiffuseProbeGrid visualization + m_visualizationBufferPools = RHI::RayTracingBufferPools::CreateRHIRayTracingBufferPools(); + m_visualizationBufferPools->Init(device); + + // load probe visualization model, the BLAS will be created in OnAssetReady() + m_visualizationModelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath( + "Models/DiffuseProbeSphere.azmodel", + AZ::RPI::AssetUtils::TraceLevel::Assert); + + if (!m_visualizationModelAsset.IsReady()) + { + m_visualizationModelAsset.QueueLoad(); + } + + Data::AssetBus::MultiHandler::BusConnect(m_visualizationModelAsset.GetId()); + EnableSceneNotification(); } @@ -106,6 +124,8 @@ namespace AZ { m_bufferPool.reset(); } + + Data::AssetBus::MultiHandler::BusDisconnect(); } void DiffuseProbeGridFeatureProcessor::Simulate([[maybe_unused]] const FeatureProcessor::SimulatePacket& packet) @@ -186,13 +206,19 @@ namespace AZ void DiffuseProbeGridFeatureProcessor::OnEndPrepareRender() { - // re-build the list of visible real-time diffuse probe grids + // re-build the list of visible diffuse probe grids + m_visibleDiffuseProbeGrids.clear(); m_visibleRealTimeDiffuseProbeGrids.clear(); - for (auto& diffuseProbeGrid : m_realTimeDiffuseProbeGrids) + for (auto& diffuseProbeGrid : m_diffuseProbeGrids) { if (diffuseProbeGrid->GetIsVisible()) { - m_visibleRealTimeDiffuseProbeGrids.push_back(diffuseProbeGrid); + if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::RealTime) + { + m_visibleRealTimeDiffuseProbeGrids.push_back(diffuseProbeGrid); + } + + m_visibleDiffuseProbeGrids.push_back(diffuseProbeGrid); } } } @@ -237,6 +263,17 @@ namespace AZ m_realTimeDiffuseProbeGrids.erase(itEntry); } + // remove from side list of visible grids + itEntry = AZStd::find_if(m_visibleDiffuseProbeGrids.begin(), m_visibleDiffuseProbeGrids.end(), [&](AZStd::shared_ptr const& entry) + { + return (entry == probeGrid); + }); + + if (itEntry != m_visibleDiffuseProbeGrids.end()) + { + m_visibleDiffuseProbeGrids.erase(itEntry); + } + // remove from side list of visible real-time grids itEntry = AZStd::find_if(m_visibleRealTimeDiffuseProbeGrids.begin(), m_visibleRealTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr const& entry) { @@ -449,6 +486,24 @@ namespace AZ probeGrid->SetBakedTextures(bakedTextures); } + void DiffuseProbeGridFeatureProcessor::SetVisualizationEnabled(const DiffuseProbeGridHandle& probeGrid, bool visualizationEnabled) + { + AZ_Assert(probeGrid.get(), "SetVisualizationEnabled called with an invalid handle"); + probeGrid->SetVisualizationEnabled(visualizationEnabled); + } + + void DiffuseProbeGridFeatureProcessor::SetVisualizationShowInactiveProbes(const DiffuseProbeGridHandle& probeGrid, bool visualizationShowInactiveProbes) + { + AZ_Assert(probeGrid.get(), "SetVisualizationShowInactiveProbes called with an invalid handle"); + probeGrid->SetVisualizationShowInactiveProbes(visualizationShowInactiveProbes); + } + + void DiffuseProbeGridFeatureProcessor::SetVisualizationSphereRadius(const DiffuseProbeGridHandle& probeGrid, float visualizationSphereRadius) + { + AZ_Assert(probeGrid.get(), "SetVisualizationSphereRadius called with an invalid handle"); + probeGrid->SetVisualizationSphereRadius(visualizationSphereRadius); + } + void DiffuseProbeGridFeatureProcessor::CreateBoxMesh() { // vertex positions @@ -613,6 +668,71 @@ namespace AZ } } + void DiffuseProbeGridFeatureProcessor::OnVisualizationModelAssetReady(Data::Asset asset) + { + Data::Asset modelAsset = asset; + + m_visualizationModel = RPI::Model::FindOrCreate(modelAsset); + AZ_Assert(m_visualizationModel.get(), "Failed to load DiffuseProbeGrid visualization model"); + + const AZStd::span>& modelLods = m_visualizationModel->GetLods(); + AZ_Assert(!modelLods.empty(), "Invalid DiffuseProbeGrid visualization model"); + if (modelLods.empty()) + { + return; + } + + const Data::Instance& modelLod = modelLods[0]; + AZ_Assert(!modelLod->GetMeshes().empty(), "Invalid DiffuseProbeGrid visualization model asset"); + if (modelLod->GetMeshes().empty()) + { + return; + } + + const RPI::ModelLod::Mesh& mesh = modelLod->GetMeshes()[0]; + + // setup a stream layout and shader input contract for the position vertex stream + static const char* PositionSemantic = "POSITION"; + static const RHI::Format PositionStreamFormat = RHI::Format::R32G32B32_FLOAT; + + RHI::InputStreamLayoutBuilder layoutBuilder; + layoutBuilder.AddBuffer()->Channel(PositionSemantic, PositionStreamFormat); + RHI::InputStreamLayout inputStreamLayout = layoutBuilder.End(); + + RPI::ShaderInputContract::StreamChannelInfo positionStreamChannelInfo; + positionStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(PositionSemantic)); + positionStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(PositionStreamFormat); + + RPI::ShaderInputContract shaderInputContract; + shaderInputContract.m_streamChannels.emplace_back(positionStreamChannelInfo); + + // retrieve vertex/index buffers + RPI::ModelLod::StreamBufferViewList streamBufferViews; + [[maybe_unused]] bool result = modelLod->GetStreamsForMesh( + inputStreamLayout, + streamBufferViews, + nullptr, + shaderInputContract, + 0); + AZ_Assert(result, "Failed to retrieve DiffuseProbeGrid visualization mesh stream buffer views"); + + m_visualizationVB = streamBufferViews[0]; + m_visualizationIB = mesh.m_indexBufferView; + + // create the BLAS object + RHI::RayTracingBlasDescriptor blasDescriptor; + blasDescriptor.Build() + ->Geometry() + ->VertexFormat(PositionStreamFormat) + ->VertexBuffer(m_visualizationVB) + ->IndexBuffer(m_visualizationIB) + ; + + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + m_visualizationBlas = AZ::RHI::RayTracingBlas::CreateRHIRayTracingBlas(); + m_visualizationBlas->CreateBuffers(*device, &blasDescriptor, *m_visualizationBufferPools); + } + void DiffuseProbeGridFeatureProcessor::HandleAssetNotification(Data::Asset asset, DiffuseProbeGridTextureNotificationType notificationType) { for (NotifyTextureAssetVector::iterator itNotification = m_notifyTextureAssets.begin(); itNotification != m_notifyTextureAssets.end(); ++itNotification) @@ -633,14 +753,28 @@ namespace AZ void DiffuseProbeGridFeatureProcessor::OnAssetReady(Data::Asset asset) { - HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Ready); + if (asset.GetId() == m_visualizationModelAsset.GetId()) + { + OnVisualizationModelAssetReady(asset); + } + else + { + HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Ready); + } } void DiffuseProbeGridFeatureProcessor::OnAssetError(Data::Asset asset) { - AZ_Error("ReflectionProbeFeatureProcessor", false, "Failed to load cubemap [%s]", asset.GetHint().c_str()); + if (asset.GetId() == m_visualizationModelAsset.GetId()) + { + AZ_Error("DiffuseProbeGridFeatureProcessor", false, "Failed to load probe visualization model asset [%s]", asset.GetHint().c_str()); + } + else + { + AZ_Error("DiffuseProbeGridFeatureProcessor", false, "Failed to load cubemap [%s]", asset.GetHint().c_str()); - HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Error); + HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Error); + } } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h index d0df7dfbfe..239de5ea27 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h @@ -9,6 +9,9 @@ #pragma once #include +#include +#include +#include #include namespace AZ @@ -46,6 +49,9 @@ namespace AZ void SetUseDiffuseIbl(const DiffuseProbeGridHandle& probeGrid, bool useDiffuseIbl) override; void SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode) override; void SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures) override; + void SetVisualizationEnabled(const DiffuseProbeGridHandle& probeGrid, bool visualizationEnabled) override; + void SetVisualizationShowInactiveProbes(const DiffuseProbeGridHandle& probeGrid, bool visualizationShowInactiveProbes) override; + void SetVisualizationSphereRadius(const DiffuseProbeGridHandle& probeGrid, float visualizationSphereRadius) override; void BakeTextures( const DiffuseProbeGridHandle& probeGrid, @@ -76,9 +82,19 @@ namespace AZ // retrieve the side list of probe grids that are using real-time (raytraced) mode DiffuseProbeGridVector& GetRealTimeProbeGrids() { return m_realTimeDiffuseProbeGrids; } - // retrieve the side list of probe grids that are using real-time (raytraced) mode and visible (on screen) + // retrieve the side list of probe grids that are visible (on screen), both real-time (raytraced) and baked + DiffuseProbeGridVector& GetVisibleProbeGrids() { return m_visibleDiffuseProbeGrids; } + + // retrieve the side list of probe grids that are real-time (raytraced) and visible (on screen) DiffuseProbeGridVector& GetVisibleRealTimeProbeGrids() { return m_visibleRealTimeDiffuseProbeGrids; } + // returns the RayTracingBufferPool used for the DiffuseProbeGrid visualization + RHI::RayTracingBufferPools& GetVisualizationBufferPools() { return *m_visualizationBufferPools; } + + // returns the RayTracingBlas for the visualization model + const RHI::Ptr& GetVisualizationBlas() const { return m_visualizationBlas; } + RHI::Ptr& GetVisualizationBlas() { return m_visualizationBlas; } + private: AZ_DISABLE_COPY_MOVE(DiffuseProbeGridFeatureProcessor); @@ -108,6 +124,9 @@ namespace AZ void UpdatePipelineStates(); void UpdatePasses(); + // loads the probe visualization model and creates the BLAS + void OnVisualizationModelAssetReady(Data::Asset asset); + // list of all diffuse probe grids const size_t InitialProbeGridAllocationSize = 64; DiffuseProbeGridVector m_diffuseProbeGrids; @@ -115,6 +134,9 @@ namespace AZ // side list of diffuse probe grids that are in real-time mode (subset of m_diffuseProbeGrids) DiffuseProbeGridVector m_realTimeDiffuseProbeGrids; + // side list of diffuse probe grids that are visible, both real-time and baked modes (subset of m_diffuseProbeGrids) + DiffuseProbeGridVector m_visibleDiffuseProbeGrids; + // side list of diffuse probe grids that are in real-time mode and visible (subset of m_realTimeDiffuseProbeGrids) DiffuseProbeGridVector m_visibleRealTimeDiffuseProbeGrids; @@ -157,6 +179,14 @@ namespace AZ }; typedef AZStd::vector NotifyTextureAssetVector; NotifyTextureAssetVector m_notifyTextureAssets; + + // visualization + RHI::Ptr m_visualizationBufferPools; + Data::Asset m_visualizationModelAsset; + RHI::Ptr m_visualizationBlas; + Data::Instance m_visualizationModel; + RHI::StreamBufferView m_visualizationVB; + RHI::IndexBufferView m_visualizationIB; }; } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp index 7af6f4c8ec..3fa4837a23 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.cpp @@ -107,15 +107,40 @@ namespace AZ m_rayTracingPipelineState->Init(*device.get(), &descriptor); } - void DiffuseProbeGridRayTracingPass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridRayTracingPass::IsEnabled() const { + if (!RenderPass::IsEnabled()) + { + return false; + } + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); if (!rayTracingFeatureProcessor) { - return; + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) + { + // no diffuse probe grids + return false; } + return true; + } + + void DiffuseProbeGridRayTracingPass::FrameBeginInternal(FramePrepareParams params) + { + RPI::Scene* scene = m_pipeline->GetScene(); + RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); + if (!m_initialized) { CreateRayTracingPipelineState(); @@ -131,13 +156,6 @@ namespace AZ m_rayTracingShaderTable->Init(*device.get(), rayTracingBufferPools); } - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); - if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) - { - // no diffuse probe grids - return; - } - RenderPass::FrameBeginInternal(params); } @@ -156,9 +174,16 @@ namespace AZ // TLAS { AZ::RHI::AttachmentId tlasAttachmentId = rayTracingFeatureProcessor->GetTlasAttachmentId(); - if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(tlasAttachmentId)) + const RHI::Ptr& rayTracingTlasBuffer = rayTracingFeatureProcessor->GetTlas()->GetTlasBuffer(); + if (rayTracingTlasBuffer) { - uint32_t tlasBufferByteCount = aznumeric_cast(rayTracingFeatureProcessor->GetTlas()->GetTlasBuffer()->GetDescriptor().m_byteCount); + if (!frameGraph.GetAttachmentDatabase().IsAttachmentValid(tlasAttachmentId)) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(tlasAttachmentId, rayTracingTlasBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import ray tracing TLAS buffer with error %d", result); + } + + uint32_t tlasBufferByteCount = aznumeric_cast(rayTracingTlasBuffer->GetDescriptor().m_byteCount); RHI::BufferViewDescriptor tlasBufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tlasBufferByteCount); RHI::BufferScopeAttachmentDescriptor desc; @@ -191,10 +216,10 @@ namespace AZ RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = diffuseProbeGrid->GetIrradianceImageAttachmentId(); desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeIrradianceImageViewDescriptor; - if (diffuseProbeGrid->GetIrradianceClearRequired()) + + if (diffuseProbeGrid->GetTextureClearRequired()) { desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Clear; - diffuseProbeGrid->ResetIrradianceClearRequired(); } else { @@ -212,7 +237,15 @@ namespace AZ RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = diffuseProbeGrid->GetDistanceImageAttachmentId(); desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDistanceImageViewDescriptor; - desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::DontCare; + + if (diffuseProbeGrid->GetTextureClearRequired()) + { + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Clear; + } + else + { + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + } frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite); } @@ -225,10 +258,20 @@ namespace AZ RHI::ImageScopeAttachmentDescriptor desc; desc.m_attachmentId = diffuseProbeGrid->GetProbeDataImageAttachmentId(); desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDataImageViewDescriptor; - desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + if (diffuseProbeGrid->GetTextureClearRequired()) + { + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Clear; + } + else + { + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + } frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite); } + + diffuseProbeGrid->ResetTextureClearRequired(); } } diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.h index f5775f7624..13063b57a7 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRayTracingPass.h @@ -45,6 +45,7 @@ namespace AZ void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; // Pass overrides + bool IsEnabled() const override; void FrameBeginInternal(FramePrepareParams params) override; // revision number of the ray tracing TLAS when the shader table was built diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp index fd23dadf6f..3922be0481 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.cpp @@ -74,50 +74,71 @@ namespace AZ } } - void DiffuseProbeGridRelocationPass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridRelocationPass::IsEnabled() const { + if (!RenderPass::IsEnabled()) + { + return false; + } + RPI::Scene* scene = m_pipeline->GetScene(); - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!scene) + { + return false; + } + RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); + if (!rayTracingFeatureProcessor || !rayTracingFeatureProcessor->GetSubMeshCount()) + { + // empty scene + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().empty()) { // no diffuse probe grids - return; + return false; } - RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); - AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridRelocationPass requires the RayTracingFeatureProcessor"); - - if (!rayTracingFeatureProcessor->GetSubMeshCount()) + // check TLAS version + uint32_t rayTracingDataRevision = rayTracingFeatureProcessor->GetRevision(); + if (rayTracingDataRevision != m_rayTracingDataRevision) { - // empty scene - return; + return true; } - // create the Relocation Srgs for each DiffuseProbeGrid, and check to see if any grids need relocation - bool needRelocation = false; + // check to see if any grids need relocation for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids()) { - uint32_t rayTracingDataRevision = rayTracingFeatureProcessor->GetRevision(); - if (rayTracingDataRevision != m_rayTracingDataRevision) - { - // the TLAS changed, relocate probes - m_rayTracingDataRevision = rayTracingDataRevision; - diffuseProbeGrid->ResetRemainingRelocationIterations(); - } - if (diffuseProbeGrid->GetRemainingRelocationIterations() > 0) { - needRelocation = true; + return true; } } + + return false; + } + + void DiffuseProbeGridRelocationPass::FrameBeginInternal(FramePrepareParams params) + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor(); + AZ_Assert(rayTracingFeatureProcessor, "DiffuseProbeGridRelocationPass requires the RayTracingFeatureProcessor"); - if (!needRelocation) + // reset the relocation iterations on the grids if the TLAS was updated + uint32_t rayTracingDataRevision = rayTracingFeatureProcessor->GetRevision(); + if (rayTracingDataRevision != m_rayTracingDataRevision) { - // no diffuseProbeGrids require relocation, this pass can be skipped entirely - return; + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids()) + { + diffuseProbeGrid->ResetRemainingRelocationIterations(); + } } + m_rayTracingDataRevision = rayTracingDataRevision; + RenderPass::FrameBeginInternal(params); } @@ -160,11 +181,7 @@ namespace AZ // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs // (see ValidateSetImageView() in ShaderResourceGroupData.cpp) diffuseProbeGrid->UpdateRelocationSrg(m_shader, m_srgLayout); - diffuseProbeGrid->GetRelocationSrg()->Compile(); - - // relocation stops after a limited number of iterations - diffuseProbeGrid->DecrementRemainingRelocationIterations(); } } @@ -180,19 +197,30 @@ namespace AZ const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetRelocationSrg()->GetRHIShaderResourceGroup(); commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup); - uint32_t probeCountX; - uint32_t probeCountY; - diffuseProbeGrid->GetTexture2DProbeCount(probeCountX, probeCountY); - RHI::DispatchItem dispatchItem; dispatchItem.m_arguments = m_dispatchArgs; dispatchItem.m_pipelineState = m_pipelineState; - dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX; - dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY; + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = diffuseProbeGrid->GetTotalProbeCount(); + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = 1; dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1; commandList->Submit(dispatchItem); } } + + void DiffuseProbeGridRelocationPass::FrameEndInternal() + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + // submit the DispatchItems for each DiffuseProbeGrid + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids()) + { + // relocation stops after a limited number of iterations + diffuseProbeGrid->DecrementRemainingRelocationIterations(); + } + + RenderPass::FrameEndInternal(); + } } // namespace Render } // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.h index a6ede22ee6..121c51050d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRelocationPass.h @@ -42,11 +42,12 @@ namespace AZ void LoadShader(); // Pass overrides + bool IsEnabled() const override; void FrameBeginInternal(FramePrepareParams params) override; - void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; void CompileResources(const RHI::FrameGraphCompileContext& context) override; void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; + void FrameEndInternal() override; // shader Data::Instance m_shader; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp index f444c0c6ba..db95e17a9e 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.cpp @@ -51,18 +51,35 @@ namespace AZ AZ_Assert(m_shaderResourceGroup, "[DiffuseProbeGridRenderPass '%s']: Failed to create SRG", GetPathName().GetCStr()); } - void DiffuseProbeGridRenderPass::FrameBeginInternal(FramePrepareParams params) + bool DiffuseProbeGridRenderPass::IsEnabled() const { - RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + if (!RenderPass::IsEnabled()) + { + return false; + } + RPI::Scene* scene = m_pipeline->GetScene(); - DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (!scene) + { + return false; + } + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); if (!diffuseProbeGridFeatureProcessor || diffuseProbeGridFeatureProcessor->GetProbeGrids().empty()) { // no diffuse probe grids - return; + return false; } + return true; + } + + void DiffuseProbeGridRenderPass::FrameBeginInternal(FramePrepareParams params) + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + // get output attachment size AZ_Assert(GetInputOutputCount() > 0, "DiffuseProbeGridRenderPass: Could not find output bindings"); RPI::PassAttachment* m_outputAttachment = GetInputOutputBinding(0).m_attachment.get(); diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.h index 6f4a91d9c6..c3612649fa 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.h +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridRenderPass.h @@ -36,7 +36,8 @@ namespace AZ explicit DiffuseProbeGridRenderPass(const RPI::PassDescriptor& descriptor); // Pass behavior overrides... - virtual void FrameBeginInternal(FramePrepareParams params) override; + bool IsEnabled() const override; + void FrameBeginInternal(FramePrepareParams params) override; // Scope producer functions... void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.cpp new file mode 100644 index 0000000000..29e50fb158 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + RPI::Ptr DiffuseProbeGridVisualizationAccelerationStructurePass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr diffuseProbeGridVisualizationAccelerationStructurePass = aznew DiffuseProbeGridVisualizationAccelerationStructurePass(descriptor); + return AZStd::move(diffuseProbeGridVisualizationAccelerationStructurePass); + } + + DiffuseProbeGridVisualizationAccelerationStructurePass::DiffuseProbeGridVisualizationAccelerationStructurePass(const RPI::PassDescriptor& descriptor) + : Pass(descriptor) + { + // disable this pass if we're on a platform that doesn't support raytracing + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + if (device->GetFeatures().m_rayTracing == false || !AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED) + { + SetEnabled(false); + } + } + + bool DiffuseProbeGridVisualizationAccelerationStructurePass::ShouldUpdate(const AZStd::shared_ptr& diffuseProbeGrid) const + { + return (diffuseProbeGrid->GetVisualizationEnabled() && diffuseProbeGrid->GetVisualizationTlasUpdateRequired()); + } + + bool DiffuseProbeGridVisualizationAccelerationStructurePass::IsEnabled() const + { + if (!Pass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (diffuseProbeGridFeatureProcessor) + { + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (ShouldUpdate(diffuseProbeGrid)) + { + return true; + } + } + } + + return false; + } + + void DiffuseProbeGridVisualizationAccelerationStructurePass::BuildInternal() + { + SetScopeId(RHI::ScopeId(GetPathName())); + } + + void DiffuseProbeGridVisualizationAccelerationStructurePass::FrameBeginInternal(FramePrepareParams params) + { + params.m_frameGraphBuilder->ImportScopeProducer(*this); + } + + void DiffuseProbeGridVisualizationAccelerationStructurePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + // import and attach the visualization TLAS buffers + RHI::Ptr& visualizationTlas = diffuseProbeGrid->GetVisualizationTlas(); + const RHI::Ptr& tlasBuffer = visualizationTlas->GetTlasBuffer(); + const RHI::Ptr& tlasInstancesBuffer = visualizationTlas->GetTlasInstancesBuffer(); + if (tlasBuffer && tlasInstancesBuffer) + { + // TLAS buffer + { + AZ::RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeVisualizationTlasAttachmentId(); + if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId) == false) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(attachmentId, tlasBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import DiffuseProbeGrid visualization TLAS buffer with error %d", result); + } + + uint32_t byteCount = aznumeric_cast(tlasBuffer->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRayTracingTLAS(byteCount); + + RHI::BufferScopeAttachmentDescriptor desc; + desc.m_attachmentId = attachmentId; + desc.m_bufferViewDescriptor = bufferViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::DontCare; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Write); + } + + // TLAS Instances buffer + { + AZ::RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeVisualizationTlasInstancesAttachmentId(); + if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId) == false) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(attachmentId, tlasInstancesBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import DiffuseProbeGrid visualization TLAS Instances buffer with error %d", result); + } + + uint32_t byteCount = aznumeric_cast(tlasInstancesBuffer->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateStructured(0, byteCount / RayTracingTlasInstanceElementSize, RayTracingTlasInstanceElementSize); + + RHI::BufferScopeAttachmentDescriptor desc; + desc.m_attachmentId = attachmentId; + desc.m_bufferViewDescriptor = bufferViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read); + } + } + } + } + + void DiffuseProbeGridVisualizationAccelerationStructurePass::BuildCommandList(const RHI::FrameGraphExecuteContext& context) + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + // build the visualization BLAS from the DiffuseProbeGridFeatureProcessor + // Note: the BLAS is used by all DiffuseProbeGrid visualization TLAS objects + if (m_visualizationBlasBuilt == false) + { + context.GetCommandList()->BuildBottomLevelAccelerationStructure(*diffuseProbeGridFeatureProcessor->GetVisualizationBlas()); + m_visualizationBlasBuilt = true; + } + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + if (!diffuseProbeGrid->GetVisualizationTlas()->GetTlasBuffer()) + { + continue; + } + + // build the TLAS object + context.GetCommandList()->BuildTopLevelAccelerationStructure(*diffuseProbeGrid->GetVisualizationTlas()); + } + } + + void DiffuseProbeGridVisualizationAccelerationStructurePass::FrameEndInternal() + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + // TLAS is now updated + diffuseProbeGrid->ResetVisualizationTlasUpdateRequired(); + } + } + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.h new file mode 100644 index 0000000000..b353b9a41a --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + //! This pass builds the DiffuseProbeGrid visualization acceleration structure + class DiffuseProbeGridVisualizationAccelerationStructurePass final + : public RPI::Pass + , public RHI::ScopeProducer + { + public: + AZ_RPI_PASS(DiffuseProbeGridVisualizationAccelerationStructurePass); + + AZ_RTTI(DiffuseProbeGridVisualizationAccelerationStructurePass, "{103D8917-D4DC-4CA3-BFB4-CD62846D282A}", Pass); + AZ_CLASS_ALLOCATOR(DiffuseProbeGridVisualizationAccelerationStructurePass, SystemAllocator, 0); + + //! Creates a DiffuseProbeGridVisualizationAccelerationStructurePass + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + ~DiffuseProbeGridVisualizationAccelerationStructurePass() = default; + + private: + explicit DiffuseProbeGridVisualizationAccelerationStructurePass(const RPI::PassDescriptor& descriptor); + + bool ShouldUpdate(const AZStd::shared_ptr& diffuseProbeGrid) const; + + // Scope producer functions + void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; + void BuildCommandList(const RHI::FrameGraphExecuteContext& context) override; + + // Pass overrides + bool IsEnabled() const override; + void BuildInternal() override; + void FrameBeginInternal(FramePrepareParams params) override; + void FrameEndInternal() override; + + bool m_visualizationBlasBuilt = false; + }; + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.cpp new file mode 100644 index 0000000000..722b42daf7 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + RPI::Ptr DiffuseProbeGridVisualizationCompositePass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew DiffuseProbeGridVisualizationCompositePass(descriptor); + return AZStd::move(pass); + } + + DiffuseProbeGridVisualizationCompositePass::DiffuseProbeGridVisualizationCompositePass(const RPI::PassDescriptor& descriptor) + : RPI::FullscreenTrianglePass(descriptor) + { + if (!AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED) + { + SetEnabled(false); + } + } + + bool DiffuseProbeGridVisualizationCompositePass::IsEnabled() const + { + if (!FullscreenTrianglePass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (diffuseProbeGridFeatureProcessor) + { + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (diffuseProbeGrid->GetVisualizationEnabled()) + { + return true; + } + } + } + + return false; + } + + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.h new file mode 100644 index 0000000000..af0109039b --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include + +namespace AZ +{ + namespace Render + { + //! This pass composites the DiffuseProbeGrid visualization image onto the main scene + class DiffuseProbeGridVisualizationCompositePass + : public RPI::FullscreenTrianglePass + { + public: + AZ_RPI_PASS(DiffuseProbeGridVisualizationCompositePass); + + AZ_RTTI(Render::DiffuseProbeGridVisualizationCompositePass, "{64BD5779-AB30-41C1-81B7-B93D864355E5}", RPI::FullscreenTrianglePass); + AZ_CLASS_ALLOCATOR(Render::DiffuseProbeGridVisualizationCompositePass, SystemAllocator, 0); + + //! Creates a new pass without a PassTemplate + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + ~DiffuseProbeGridVisualizationCompositePass() = default; + + private: + explicit DiffuseProbeGridVisualizationCompositePass(const RPI::PassDescriptor& descriptor); + + // Pass behavior overrides... + bool IsEnabled() const override; + }; + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.cpp new file mode 100644 index 0000000000..29d7ff4aaa --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.cpp @@ -0,0 +1,270 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + RPI::Ptr DiffuseProbeGridVisualizationPreparePass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr diffuseProbeGridVisualizationPreparePass = aznew DiffuseProbeGridVisualizationPreparePass(descriptor); + return AZStd::move(diffuseProbeGridVisualizationPreparePass); + } + + DiffuseProbeGridVisualizationPreparePass::DiffuseProbeGridVisualizationPreparePass(const RPI::PassDescriptor& descriptor) + : RenderPass(descriptor) + { + // disable this pass if we're on a platform that doesn't support raytracing + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + if (device->GetFeatures().m_rayTracing == false || !AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED) + { + SetEnabled(false); + } + else + { + LoadShader(); + } + } + + void DiffuseProbeGridVisualizationPreparePass::LoadShader() + { + // load shaders + // Note: the shader may not be available on all platforms + AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPrepare.azshader"; + m_shader = RPI::LoadCriticalShader(shaderFilePath); + if (m_shader == nullptr) + { + return; + } + + RHI::PipelineStateDescriptorForDispatch pipelineStateDescriptor; + const auto& shaderVariant = m_shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); + shaderVariant.ConfigurePipelineState(pipelineStateDescriptor); + m_pipelineState = m_shader->AcquirePipelineState(pipelineStateDescriptor); + AZ_Assert(m_pipelineState, "Failed to acquire pipeline state"); + + m_srgLayout = m_shader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Pass); + AZ_Assert(m_srgLayout.get(), "Failed to find Srg layout"); + + const auto outcome = RPI::GetComputeShaderNumThreads(m_shader->GetAsset(), m_dispatchArgs); + if (!outcome.IsSuccess()) + { + AZ_Error("PassSystem", false, "[DiffuseProbeGridVisualizationPreparePass '%s']: Shader '%s' contains invalid numthreads arguments:\n%s", GetPathName().GetCStr(), shaderFilePath.c_str(), outcome.GetError().c_str()); + } + } + + bool DiffuseProbeGridVisualizationPreparePass::ShouldUpdate(const AZStd::shared_ptr& diffuseProbeGrid) const + { + return (diffuseProbeGrid->GetVisualizationEnabled() && diffuseProbeGrid->GetVisualizationTlasUpdateRequired()); + } + + bool DiffuseProbeGridVisualizationPreparePass::IsEnabled() const + { + if (!RenderPass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (diffuseProbeGridFeatureProcessor) + { + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (ShouldUpdate(diffuseProbeGrid)) + { + return true; + } + } + } + + return false; + } + + void DiffuseProbeGridVisualizationPreparePass::FrameBeginInternal(FramePrepareParams params) + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + // create the TLAS descriptor by adding an instance entry for each probe in the grid + RHI::RayTracingTlasDescriptor tlasDescriptor; + RHI::RayTracingTlasDescriptor* tlasDescriptorBuild = tlasDescriptor.Build(); + + // initialize the transform for each probe to Identity(), they will be updated by the compute shader + AZ::Transform transform = AZ::Transform::Identity(); + + uint32_t probeCount = diffuseProbeGrid->GetTotalProbeCount(); + for (uint32_t index = 0; index < probeCount; ++index) + { + tlasDescriptorBuild->Instance() + ->InstanceID(index) + ->HitGroupIndex(0) + ->Blas(diffuseProbeGridFeatureProcessor->GetVisualizationBlas()) + ->Transform(transform) + ; + } + + // create the TLAS buffers from on the descriptor + RHI::Ptr& visualizationTlas = diffuseProbeGrid->GetVisualizationTlas(); + visualizationTlas->CreateBuffers(*device, &tlasDescriptor, diffuseProbeGridFeatureProcessor->GetVisualizationBufferPools()); + } + + RenderPass::FrameBeginInternal(params); + } + + void DiffuseProbeGridVisualizationPreparePass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) + { + RenderPass::SetupFrameGraphDependencies(frameGraph); + + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + // import and attach the visualization TLAS and probe data + RHI::Ptr& visualizationTlas = diffuseProbeGrid->GetVisualizationTlas(); + const RHI::Ptr& tlasBuffer = visualizationTlas->GetTlasBuffer(); + const RHI::Ptr& tlasInstancesBuffer = visualizationTlas->GetTlasInstancesBuffer(); + if (tlasBuffer && tlasInstancesBuffer) + { + // TLAS buffer + { + AZ::RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeVisualizationTlasAttachmentId(); + if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId) == false) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(attachmentId, tlasBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import DiffuseProbeGrid visualization TLAS buffer with error %d", result); + } + + uint32_t byteCount = aznumeric_cast(tlasBuffer->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateRayTracingTLAS(byteCount); + + RHI::BufferScopeAttachmentDescriptor desc; + desc.m_attachmentId = attachmentId; + desc.m_bufferViewDescriptor = bufferViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::DontCare; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Write); + } + + // TLAS Instances buffer + { + AZ::RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeVisualizationTlasInstancesAttachmentId(); + if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId) == false) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(attachmentId, tlasInstancesBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import DiffuseProbeGrid visualization TLAS Instances buffer with error %d", result); + } + + uint32_t byteCount = aznumeric_cast(tlasInstancesBuffer->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor bufferViewDescriptor = RHI::BufferViewDescriptor::CreateStructured(0, byteCount / RayTracingTlasInstanceElementSize, RayTracingTlasInstanceElementSize); + + RHI::BufferScopeAttachmentDescriptor desc; + desc.m_attachmentId = attachmentId; + desc.m_bufferViewDescriptor = bufferViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::DontCare; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Write); + } + + // probe data + { + AZ::RHI::AttachmentId attachmentId = diffuseProbeGrid->GetProbeDataImageAttachmentId(); + if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentId) == false) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportImage(attachmentId, diffuseProbeGrid->GetProbeDataImage()); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import DiffuseProbeGrid probe data buffer with error %d", result); + } + + RHI::ImageScopeAttachmentDescriptor desc; + desc.m_attachmentId = attachmentId; + desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDataImageViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read); + } + } + } + } + + void DiffuseProbeGridVisualizationPreparePass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context) + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + // the DiffuseProbeGrid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader inputs + // (see ValidateSetImageView() in ShaderResourceGroupData.cpp) + diffuseProbeGrid->UpdateVisualizationPrepareSrg(m_shader, m_srgLayout); + diffuseProbeGrid->GetVisualizationPrepareSrg()->Compile(); + } + } + + void DiffuseProbeGridVisualizationPreparePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) + { + RHI::CommandList* commandList = context.GetCommandList(); + + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!ShouldUpdate(diffuseProbeGrid)) + { + continue; + } + + const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetVisualizationPrepareSrg()->GetRHIShaderResourceGroup(); + commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup); + + RHI::DispatchItem dispatchItem; + dispatchItem.m_arguments = m_dispatchArgs; + dispatchItem.m_pipelineState = m_pipelineState; + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = diffuseProbeGrid->GetTotalProbeCount(); + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = 1; + dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1; + + commandList->Submit(dispatchItem); + } + } + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.h new file mode 100644 index 0000000000..5e86a606aa --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include + +namespace AZ +{ + namespace Render + { + //! This pass updates the DiffuseProbeGrid visualization TLAS instances buffer + class DiffuseProbeGridVisualizationPreparePass final + : public RPI::RenderPass + { + public: + AZ_RPI_PASS(DiffuseProbeGridVisualizationPreparePass); + + AZ_RTTI(DiffuseProbeGridVisualizationPreparePass, "{33BD769D-378B-4142-8C11-6A2ADA2BB095}", Pass); + AZ_CLASS_ALLOCATOR(DiffuseProbeGridVisualizationPreparePass, SystemAllocator, 0); + + //! Creates a DiffuseProbeGridVisualizationPreparePass + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + ~DiffuseProbeGridVisualizationPreparePass() = default; + + private: + explicit DiffuseProbeGridVisualizationPreparePass(const RPI::PassDescriptor& descriptor); + + void LoadShader(); + bool ShouldUpdate(const AZStd::shared_ptr& diffuseProbeGrid) const; + + // Pass overrides + bool IsEnabled() const override; + void FrameBeginInternal(FramePrepareParams params) override; + void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; + void CompileResources(const RHI::FrameGraphCompileContext& context) override; + void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; + + // shader + Data::Instance m_shader; + const RHI::PipelineState* m_pipelineState = nullptr; + RHI::Ptr m_srgLayout; + RHI::DispatchDirect m_dispatchArgs; + }; + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.cpp new file mode 100644 index 0000000000..69c033f76c --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.cpp @@ -0,0 +1,300 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + RPI::Ptr DiffuseProbeGridVisualizationRayTracingPass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew DiffuseProbeGridVisualizationRayTracingPass(descriptor); + return AZStd::move(pass); + } + + DiffuseProbeGridVisualizationRayTracingPass::DiffuseProbeGridVisualizationRayTracingPass(const RPI::PassDescriptor& descriptor) + : RPI::RenderPass(descriptor) + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + if (device->GetFeatures().m_rayTracing == false || !AZ_TRAIT_DIFFUSE_GI_PASSES_SUPPORTED) + { + // raytracing or GI is not supported on this platform + SetEnabled(false); + } + } + + void DiffuseProbeGridVisualizationRayTracingPass::CreateRayTracingPipelineState() + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + + // load the ray tracing shader + // Note: the shader may not be available on all platforms + AZStd::string shaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracing.azshader"; + m_rayTracingShader = RPI::LoadCriticalShader(shaderFilePath); + if (m_rayTracingShader == nullptr) + { + return; + } + + auto shaderVariant = m_rayTracingShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); + RHI::PipelineStateDescriptorForRayTracing rayGenerationShaderDescriptor; + shaderVariant.ConfigurePipelineState(rayGenerationShaderDescriptor); + + // closest hit shader + AZStd::string closestHitShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingClosestHit.azshader"; + m_closestHitShader = RPI::LoadCriticalShader(closestHitShaderFilePath); + + auto closestHitShaderVariant = m_closestHitShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); + RHI::PipelineStateDescriptorForRayTracing closestHitShaderDescriptor; + closestHitShaderVariant.ConfigurePipelineState(closestHitShaderDescriptor); + + // miss shader + AZStd::string missShaderFilePath = "Shaders/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingMiss.azshader"; + m_missShader = RPI::LoadCriticalShader(missShaderFilePath); + + auto missShaderVariant = m_missShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); + RHI::PipelineStateDescriptorForRayTracing missShaderDescriptor; + missShaderVariant.ConfigurePipelineState(missShaderDescriptor); + + // global pipeline state and Srg + m_globalPipelineState = m_rayTracingShader->AcquirePipelineState(rayGenerationShaderDescriptor); + AZ_Assert(m_globalPipelineState, "Failed to acquire ray tracing global pipeline state"); + + m_globalSrgLayout = m_rayTracingShader->FindShaderResourceGroupLayout(Name{ "RayTracingGlobalSrg" }); + AZ_Assert(m_globalSrgLayout != nullptr, "Failed to find RayTracingGlobalSrg layout for shader [%s]", shaderFilePath.c_str()); + + // build the ray tracing pipeline state descriptor + RHI::RayTracingPipelineStateDescriptor descriptor; + descriptor.Build() + ->PipelineState(m_globalPipelineState.get()) + ->MaxPayloadSize(64) + ->MaxAttributeSize(32) + ->MaxRecursionDepth(2) + ->ShaderLibrary(rayGenerationShaderDescriptor) + ->RayGenerationShaderName(AZ::Name("RayGen")) + ->ShaderLibrary(missShaderDescriptor) + ->MissShaderName(AZ::Name("Miss")) + ->ShaderLibrary(closestHitShaderDescriptor) + ->ClosestHitShaderName(AZ::Name("ClosestHit")) + ->HitGroup(AZ::Name("HitGroup")) + ->ClosestHitShaderName(AZ::Name("ClosestHit")); + + // create the ray tracing pipeline state object + m_rayTracingPipelineState = RHI::Factory::Get().CreateRayTracingPipelineState(); + m_rayTracingPipelineState->Init(*device.get(), &descriptor); + } + + bool DiffuseProbeGridVisualizationRayTracingPass::IsEnabled() const + { + if (!RenderPass::IsEnabled()) + { + return false; + } + + RPI::Scene* scene = m_pipeline->GetScene(); + if (!scene) + { + return false; + } + + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + if (diffuseProbeGridFeatureProcessor) + { + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (diffuseProbeGrid->GetVisualizationEnabled()) + { + return true; + } + } + } + + return false; + } + + void DiffuseProbeGridVisualizationRayTracingPass::FrameBeginInternal(FramePrepareParams params) + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + if (!m_initialized) + { + CreateRayTracingPipelineState(); + m_initialized = true; + } + + if (!m_rayTracingShaderTable) + { + RHI::Ptr device = RHI::RHISystemInterface::Get()->GetDevice(); + RHI::RayTracingBufferPools& rayTracingBufferPools = diffuseProbeGridFeatureProcessor->GetVisualizationBufferPools(); + + m_rayTracingShaderTable = RHI::Factory::Get().CreateRayTracingShaderTable(); + m_rayTracingShaderTable->Init(*device.get(), rayTracingBufferPools); + + AZStd::shared_ptr descriptor = AZStd::make_shared(); + + // build the ray tracing shader table descriptor + descriptor->Build(AZ::Name("RayTracingShaderTable"), m_rayTracingPipelineState) + ->RayGenerationRecord(AZ::Name("RayGen")) + ->MissRecord(AZ::Name("Miss")) + ->HitGroupRecord(AZ::Name("HitGroup")) + ; + + m_rayTracingShaderTable->Build(descriptor); + } + + RenderPass::FrameBeginInternal(params); + } + + void DiffuseProbeGridVisualizationRayTracingPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) + { + RenderPass::SetupFrameGraphDependencies(frameGraph); + + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!diffuseProbeGrid->GetVisualizationEnabled()) + { + continue; + } + + // TLAS + { + AZ::RHI::AttachmentId tlasAttachmentId = diffuseProbeGrid->GetProbeVisualizationTlasAttachmentId(); + const RHI::Ptr& visualizationTlasBuffer = diffuseProbeGrid->GetVisualizationTlas()->GetTlasBuffer(); + if (visualizationTlasBuffer) + { + if (!frameGraph.GetAttachmentDatabase().IsAttachmentValid(tlasAttachmentId)) + { + [[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(tlasAttachmentId, visualizationTlasBuffer); + AZ_Assert(result == RHI::ResultCode::Success, "Failed to import ray tracing TLAS buffer with error %d", result); + } + + uint32_t tlasBufferByteCount = aznumeric_cast(visualizationTlasBuffer->GetDescriptor().m_byteCount); + RHI::BufferViewDescriptor tlasBufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tlasBufferByteCount); + + RHI::BufferScopeAttachmentDescriptor desc; + desc.m_attachmentId = tlasAttachmentId; + desc.m_bufferViewDescriptor = tlasBufferViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite); + } + } + + // probe irradiance + { + RHI::ImageScopeAttachmentDescriptor desc; + desc.m_attachmentId = diffuseProbeGrid->GetIrradianceImageAttachmentId(); + desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeIrradianceImageViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read); + } + + // probe distance + { + RHI::ImageScopeAttachmentDescriptor desc; + desc.m_attachmentId = diffuseProbeGrid->GetDistanceImageAttachmentId(); + desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDistanceImageViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read); + } + + // probe data + { + RHI::ImageScopeAttachmentDescriptor desc; + desc.m_attachmentId = diffuseProbeGrid->GetProbeDataImageAttachmentId(); + desc.m_imageViewDescriptor = diffuseProbeGrid->GetRenderData()->m_probeDataImageViewDescriptor; + desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load; + + frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::Read); + } + } + + // retrieve the visualization image size, this will determine the number of rays to cast + RPI::Ptr visualizationImageAttachment = m_ownedAttachments[0]; + AZ_Assert(visualizationImageAttachment.get(), "Invalid DiffuseProbeGrid Visualization image"); + + m_outputAttachmentSize = visualizationImageAttachment->GetTransientImageDescriptor().m_imageDescriptor.m_size; + } + + void DiffuseProbeGridVisualizationRayTracingPass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context) + { + const RHI::ImageView* outputImageView = context.GetImageView(GetOutputBinding(0).m_attachment->GetAttachmentId()); + AZ_Assert(outputImageView, "Failed to retrieve output ImageView"); + + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!diffuseProbeGrid->GetVisualizationEnabled()) + { + continue; + } + + // the DiffuseProbeGridVisualization Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader + // inputs (see line ValidateSetImageView() in ShaderResourceGroupData.cpp) + diffuseProbeGrid->UpdateVisualizationRayTraceSrg(m_rayTracingShader, m_globalSrgLayout, outputImageView); + diffuseProbeGrid->GetVisualizationRayTraceSrg()->Compile(); + } + } + + void DiffuseProbeGridVisualizationRayTracingPass::BuildCommandListInternal([[maybe_unused]] const RHI::FrameGraphExecuteContext& context) + { + RPI::Scene* scene = m_pipeline->GetScene(); + DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor(); + + const AZStd::vector& views = m_pipeline->GetViews(RPI::PipelineViewTag{ "MainCamera" }); + if (views.empty()) + { + return; + } + + for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleProbeGrids()) + { + if (!diffuseProbeGrid->GetVisualizationEnabled()) + { + continue; + } + + const RHI::ShaderResourceGroup* shaderResourceGroups[] = { + diffuseProbeGrid->GetVisualizationRayTraceSrg()->GetRHIShaderResourceGroup(), + views[0]->GetRHIShaderResourceGroup() + }; + + RHI::DispatchRaysItem dispatchRaysItem; + dispatchRaysItem.m_width = m_outputAttachmentSize.m_width; + dispatchRaysItem.m_height = m_outputAttachmentSize.m_height; + dispatchRaysItem.m_depth = 1; + dispatchRaysItem.m_rayTracingPipelineState = m_rayTracingPipelineState.get(); + dispatchRaysItem.m_rayTracingShaderTable = m_rayTracingShaderTable.get(); + dispatchRaysItem.m_shaderResourceGroupCount = RHI::ArraySize(shaderResourceGroups); + dispatchRaysItem.m_shaderResourceGroups = shaderResourceGroups; + dispatchRaysItem.m_globalPipelineState = m_globalPipelineState.get(); + + // submit the DispatchRays item + context.GetCommandList()->Submit(dispatchRaysItem); + } + } + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.h b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.h new file mode 100644 index 0000000000..c2e5ecf3de --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + //! Ray tracing shader that generates the probe visualization image for a DiffuseProbeGrid + class DiffuseProbeGridVisualizationRayTracingPass final + : public RPI::RenderPass + { + public: + AZ_RPI_PASS(DiffuseProbeGridVisualizationRayTracingPass); + + AZ_RTTI(DiffuseProbeGridVisualizationRayTracingPass, "{CDFB5C03-08D1-4FCA-8B63-2F8326E0DF1D}", RPI::RenderPass); + AZ_CLASS_ALLOCATOR(DiffuseProbeGridVisualizationRayTracingPass, SystemAllocator, 0); + + //! Creates a DiffuseProbeGridVisualizationRayTracingPass + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + ~DiffuseProbeGridVisualizationRayTracingPass() = default; + + private: + explicit DiffuseProbeGridVisualizationRayTracingPass(const RPI::PassDescriptor& descriptor); + + void CreateRayTracingPipelineState(); + + // Scope producer functions + void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override; + void CompileResources(const RHI::FrameGraphCompileContext& context) override; + void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override; + + // Pass overrides + bool IsEnabled() const override; + void FrameBeginInternal(FramePrepareParams params) override; + + // ray tracing shader and pipeline state + Data::Instance m_rayTracingShader; + Data::Instance m_missShader; + Data::Instance m_closestHitShader; + RHI::Ptr m_rayTracingPipelineState; + + // ray tracing shader table + RHI::Ptr m_rayTracingShaderTable; + + // current size of output attachment, updated every frame + RHI::Size m_outputAttachmentSize; + + // ray tracing global shader resource group layout and pipeline state + RHI::Ptr m_globalSrgLayout; + RHI::ConstPtr m_globalPipelineState; + + bool m_initialized = false; + }; + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h index d098fca35a..dce340807d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h @@ -24,6 +24,8 @@ namespace AZ static const uint32_t RayTracingSceneSrgBindingSlot = 1; static const uint32_t RayTracingMaterialSrgBindingSlot = 2; + static const uint32_t RayTracingTlasInstanceElementSize = 64; + enum class RayTracingSubMeshBufferFlags : uint32_t { None = 0, diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index 1ec6402b3e..6ba0ed1165 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -140,6 +140,14 @@ set(FILES Source/DiffuseGlobalIllumination/DiffuseProbeGridTextureReadback.h Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.h + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationPreparePass.cpp + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.h + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationAccelerationStructurePass.cpp + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.h + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationRayTracingPass.cpp + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.h + Source/DiffuseGlobalIllumination/DiffuseProbeGridVisualizationCompositePass.cpp Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.h Source/DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.cpp Source/DisplayMapper/AcesOutputTransformPass.cpp diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h index cd58ee359f..ce12d12162 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h @@ -182,6 +182,7 @@ namespace AZ //! Returns the TLAS RHI buffer virtual const RHI::Ptr GetTlasBuffer() const = 0; + virtual const RHI::Ptr GetTlasInstancesBuffer() const = 0; private: // Platform API diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingBufferPools.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingBufferPools.h index 288a83b4da..6b3e2a4abd 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingBufferPools.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingBufferPools.h @@ -46,7 +46,7 @@ namespace AZ virtual RHI::BufferBindFlags GetShaderTableBufferBindFlags() const { return RHI::BufferBindFlags::ShaderRead | RHI::BufferBindFlags::CopyRead | RHI::BufferBindFlags::RayTracingShaderTable; } virtual RHI::BufferBindFlags GetScratchBufferBindFlags() const { return RHI::BufferBindFlags::ShaderReadWrite | RHI::BufferBindFlags::RayTracingScratchBuffer; } virtual RHI::BufferBindFlags GetBlasBufferBindFlags() const { return RHI::BufferBindFlags::ShaderReadWrite | RHI::BufferBindFlags::RayTracingAccelerationStructure; } - virtual RHI::BufferBindFlags GetTlasInstancesBufferBindFlags() const { return RHI::BufferBindFlags::ShaderRead; } + virtual RHI::BufferBindFlags GetTlasInstancesBufferBindFlags() const { return RHI::BufferBindFlags::ShaderReadWrite; } virtual RHI::BufferBindFlags GetTlasBufferBindFlags() const { return RHI::BufferBindFlags::RayTracingAccelerationStructure; } private: diff --git a/Gems/Atom/RHI/Code/Source/RHI/RayTracingBufferPools.cpp b/Gems/Atom/RHI/Code/Source/RHI/RayTracingBufferPools.cpp index 3ef2ba05ac..7899d9b5d0 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RayTracingBufferPools.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RayTracingBufferPools.cpp @@ -97,7 +97,7 @@ namespace AZ // create TLAS Instances buffer pool { RHI::BufferPoolDescriptor bufferPoolDesc; - bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Host; + bufferPoolDesc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device; bufferPoolDesc.m_bindFlags = GetTlasInstancesBufferBindFlags(); m_tlasInstancesBufferPool = RHI::Factory::Get().CreateBufferPool(); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp index c28c5e4db5..a91f995671 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.cpp @@ -54,7 +54,7 @@ namespace AZ // create instances buffer buffers.m_tlasInstancesBuffer = RHI::Factory::Get().CreateBuffer(); AZ::RHI::BufferDescriptor tlasInstancesBufferDescriptor; - tlasInstancesBufferDescriptor.m_bindFlags = RHI::BufferBindFlags::ShaderRead; + tlasInstancesBufferDescriptor.m_bindFlags = RHI::BufferBindFlags::ShaderReadWrite; tlasInstancesBufferDescriptor.m_byteCount = instanceDescsSizeInBytes; tlasInstancesBufferDescriptor.m_alignment = D3D12_RAYTRACING_INSTANCE_DESCS_BYTE_ALIGNMENT; diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.h index accc43ec92..41aad8cf87 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingTlas.h @@ -40,7 +40,8 @@ namespace AZ const TlasBuffers& GetBuffers() const { return m_buffers[m_currentBufferIndex]; } // RHI::RayTracingTlas overrides... - virtual const RHI::Ptr GetTlasBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasBuffer; } + const RHI::Ptr GetTlasBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasBuffer; } + const RHI::Ptr GetTlasInstancesBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasInstancesBuffer; } private: RayTracingTlas() = default; diff --git a/Gems/Atom/RHI/Null/Code/Source/RHI/RayTracingTlas.h b/Gems/Atom/RHI/Null/Code/Source/RHI/RayTracingTlas.h index 7bb0316230..a3e5d8c558 100644 --- a/Gems/Atom/RHI/Null/Code/Source/RHI/RayTracingTlas.h +++ b/Gems/Atom/RHI/Null/Code/Source/RHI/RayTracingTlas.h @@ -26,7 +26,8 @@ namespace AZ static RHI::Ptr Create(); // RHI::RayTracingTlas overrides... - virtual const RHI::Ptr GetTlasBuffer() const override { return nullptr; } + const RHI::Ptr GetTlasBuffer() const override { return nullptr; } + const RHI::Ptr GetTlasInstancesBuffer() const override { return nullptr; } private: RayTracingTlas() = default; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandList.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandList.cpp index c1d87b0211..6211adf35c 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandList.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandList.cpp @@ -970,6 +970,26 @@ namespace AZ const VkAccelerationStructureBuildRangeInfoKHR& offsetInfo = tlasBuffers.m_offsetInfo; const VkAccelerationStructureBuildRangeInfoKHR* pOffsetInfo = &offsetInfo; vkCmdBuildAccelerationStructuresKHR(GetNativeCommandBuffer(), 1, &tlasBuffers.m_buildInfo, &pOffsetInfo); + + // we need a pipeline barrier on VK_ACCESS_ACCELERATION_STRUCTURE (both read and write) in case we are building + // multiple TLAS objects in a command list + VkMemoryBarrier memoryBarrier = {}; + memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER; + memoryBarrier.pNext = nullptr; + memoryBarrier.srcAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + memoryBarrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; + + vkCmdPipelineBarrier( + GetNativeCommandBuffer(), + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, + 0, + 1, + &memoryBarrier, + 0, + nullptr, + 0, + nullptr); } void CommandList::ClearImage(const ResourceClearRequest& request) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingBufferPools.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingBufferPools.h index a7547c7106..0ae3b37c50 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingBufferPools.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingBufferPools.h @@ -24,8 +24,8 @@ namespace AZ static RHI::Ptr Create() { return aznew RayTracingBufferPools; } protected: - virtual RHI::BufferBindFlags GetShaderTableBufferBindFlags() const override { return RHI::BufferBindFlags::CopyRead | RHI::BufferBindFlags::RayTracingShaderTable; } - virtual RHI::BufferBindFlags GetTlasInstancesBufferBindFlags() const override { return RHI::BufferBindFlags::ShaderRead | RHI::BufferBindFlags::RayTracingAccelerationStructure; } + RHI::BufferBindFlags GetShaderTableBufferBindFlags() const override { return RHI::BufferBindFlags::CopyRead | RHI::BufferBindFlags::RayTracingShaderTable; } + RHI::BufferBindFlags GetTlasInstancesBufferBindFlags() const override { return RHI::BufferBindFlags::ShaderReadWrite | RHI::BufferBindFlags::RayTracingAccelerationStructure; } private: RayTracingBufferPools() = default; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp index 08b933c96b..b081e3f82d 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.cpp @@ -60,7 +60,7 @@ namespace AZ // create instances buffer buffers.m_tlasInstancesBuffer = RHI::Factory::Get().CreateBuffer(); AZ::RHI::BufferDescriptor tlasInstancesBufferDescriptor; - tlasInstancesBufferDescriptor.m_bindFlags = RHI::BufferBindFlags::ShaderRead | RHI::BufferBindFlags::RayTracingAccelerationStructure; + tlasInstancesBufferDescriptor.m_bindFlags = RHI::BufferBindFlags::ShaderReadWrite | RHI::BufferBindFlags::RayTracingAccelerationStructure; tlasInstancesBufferDescriptor.m_byteCount = instanceDescsSizeInBytes; AZ::RHI::BufferInitRequest tlasInstancesBufferRequest; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.h index 96d5f8f5f6..55fcf481af 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingTlas.h @@ -43,7 +43,8 @@ namespace AZ const TlasBuffers& GetBuffers() const { return m_buffers[m_currentBufferIndex]; } // RHI::RayTracingTlas overrides... - virtual const RHI::Ptr GetTlasBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasBuffer; } + const RHI::Ptr GetTlasBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasBuffer; } + const RHI::Ptr GetTlasInstancesBuffer() const override { return m_buffers[m_currentBufferIndex].m_tlasInstancesBuffer; } private: RayTracingTlas() = default; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentConstants.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentConstants.h index 91c4e2bcf4..32d77c1c3a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentConstants.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentConstants.h @@ -20,5 +20,6 @@ namespace AZ static constexpr float DefaultDiffuseProbeGridViewBias = 0.2f; static constexpr float DefaultDiffuseProbeGridNormalBias = 0.1f; static constexpr DiffuseProbeGridNumRaysPerProbe DefaultDiffuseProbeGridNumRaysPerProbe = DiffuseProbeGridNumRaysPerProbe::NumRaysPerProbe_288; + static constexpr float DefaultVisualizationSphereRadius = 0.5f; } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.cpp index 8c8b29a053..9aa58c1082 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.cpp @@ -34,7 +34,7 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(2) // Added NumRaysPerProbe setting + ->Version(3) // Added probe visualization ->Field("ProbeSpacing", &DiffuseProbeGridComponentConfig::m_probeSpacing) ->Field("Extents", &DiffuseProbeGridComponentConfig::m_extents) ->Field("AmbientMultiplier", &DiffuseProbeGridComponentConfig::m_ambientMultiplier) @@ -49,6 +49,9 @@ namespace AZ ->Field("BakedIrradianceTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedIrradianceTextureAsset) ->Field("BakedDistanceTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedDistanceTextureAsset) ->Field("BakedProbeDataTextureAsset", &DiffuseProbeGridComponentConfig::m_bakedProbeDataTextureAsset) + ->Field("VisualizationEnabled", &DiffuseProbeGridComponentConfig::m_visualizationEnabled) + ->Field("VisualizationShowInactiveProbes", &DiffuseProbeGridComponentConfig::m_visualizationShowInactiveProbes) + ->Field("VisualizationSphereRadius", &DiffuseProbeGridComponentConfig::m_visualizationSphereRadius) ; } } @@ -140,6 +143,9 @@ namespace AZ m_featureProcessor->SetViewBias(m_handle, m_configuration.m_viewBias); m_featureProcessor->SetNormalBias(m_handle, m_configuration.m_normalBias); m_featureProcessor->SetNumRaysPerProbe(m_handle, m_configuration.m_numRaysPerProbe); + m_featureProcessor->SetVisualizationEnabled(m_handle, m_configuration.m_visualizationEnabled); + m_featureProcessor->SetVisualizationShowInactiveProbes(m_handle, m_configuration.m_visualizationShowInactiveProbes); + m_featureProcessor->SetVisualizationSphereRadius(m_handle, m_configuration.m_visualizationSphereRadius); // load the baked texture assets, but only if they are all valid if (m_configuration.m_bakedIrradianceTextureAsset.GetId().IsValid() && @@ -356,6 +362,39 @@ namespace AZ m_configuration.m_runtimeMode = runtimeMode; } + void DiffuseProbeGridComponentController::SetVisualizationEnabled(bool visualizationEnabled) + { + if (!m_featureProcessor) + { + return; + } + + m_configuration.m_visualizationEnabled = visualizationEnabled; + m_featureProcessor->SetVisualizationEnabled(m_handle, m_configuration.m_visualizationEnabled); + } + + void DiffuseProbeGridComponentController::SetVisualizationShowInactiveProbes(bool visualizationShowInactiveProbes) + { + if (!m_featureProcessor) + { + return; + } + + m_configuration.m_visualizationShowInactiveProbes = visualizationShowInactiveProbes; + m_featureProcessor->SetVisualizationShowInactiveProbes(m_handle, m_configuration.m_visualizationShowInactiveProbes); + } + + void DiffuseProbeGridComponentController::SetVisualizationSphereRadius(float visualizationSphereRadius) + { + if (!m_featureProcessor) + { + return; + } + + m_configuration.m_visualizationSphereRadius = visualizationSphereRadius; + m_featureProcessor->SetVisualizationSphereRadius(m_handle, m_configuration.m_visualizationSphereRadius); + } + void DiffuseProbeGridComponentController::BakeTextures(DiffuseProbeGridBakeTexturesCallback callback) { if (!m_featureProcessor) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.h index 8f84954b2c..44cab5fc32 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridComponentController.h @@ -48,6 +48,10 @@ namespace AZ Data::Asset m_bakedDistanceTextureAsset; Data::Asset m_bakedProbeDataTextureAsset; + bool m_visualizationEnabled = false; + bool m_visualizationShowInactiveProbes = false; + float m_visualizationSphereRadius = DefaultVisualizationSphereRadius; + AZ::u64 m_entityId{ EntityId::InvalidEntityId }; }; @@ -102,6 +106,9 @@ namespace AZ void SetNumRaysPerProbe(const DiffuseProbeGridNumRaysPerProbe& numRaysPerProbe); void SetEditorMode(DiffuseProbeGridMode editorMode); void SetRuntimeMode(DiffuseProbeGridMode runtimeMode); + void SetVisualizationEnabled(bool visualizationEnabled); + void SetVisualizationShowInactiveProbes(bool visualizationShowInactiveProbes); + void SetVisualizationSphereRadius(float visualizationSphereRadius); // Bake the diffuse probe grid textures to assets void BakeTextures(DiffuseProbeGridBakeTexturesCallback callback); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp index 6588b18636..dd4ffd25e6 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp @@ -43,6 +43,9 @@ namespace AZ ->Field("numRaysPerProbe", &EditorDiffuseProbeGridComponent::m_numRaysPerProbe) ->Field("editorMode", &EditorDiffuseProbeGridComponent::m_editorMode) ->Field("runtimeMode", &EditorDiffuseProbeGridComponent::m_runtimeMode) + ->Field("showVisualization", &EditorDiffuseProbeGridComponent::m_showVisualization) + ->Field("showInactiveProbes", &EditorDiffuseProbeGridComponent::m_showInactiveProbes) + ->Field("visualizationSphereRadius", &EditorDiffuseProbeGridComponent::m_visualizationSphereRadius) ; if (AZ::EditContext* editContext = serializeContext->GetEditContext()) @@ -94,10 +97,22 @@ namespace AZ ->Attribute(Edit::Attributes::Step, 0.1f) ->Attribute(Edit::Attributes::Min, 0.0f) ->Attribute(Edit::Attributes::Max, 1.0f) - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorDiffuseProbeGridComponent::m_numRaysPerProbe, "Number of Rays Per Probe", "Number of rays cast by each probe to detect lighting in its surroundings") + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorDiffuseProbeGridComponent::m_numRaysPerProbe, "Number of Rays Per Probe", "Number of rays cast by each probe to detect lighting in its surroundings") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnNumRaysPerProbeChanged) ->Attribute(AZ::Edit::Attributes::EnumValues, &EditorDiffuseProbeGridComponent::GetNumRaysPerProbeEnumList) - ->ClassElement(AZ::Edit::ClassElements::EditorData, "Grid mode") + ->ClassElement(AZ::Edit::ClassElements::Group, "Visualization") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &EditorDiffuseProbeGridComponent::m_showVisualization, "Show Visualization", "Show the probe grid visualization") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnShowVisualizationChanged) + ->DataElement(AZ::Edit::UIHandlers::CheckBox, &EditorDiffuseProbeGridComponent::m_showInactiveProbes, "Show Inactive Probes", "Show inactive probes in the probe grid visualization") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnShowInactiveProbesChanged) + ->DataElement(AZ::Edit::UIHandlers::Slider, &EditorDiffuseProbeGridComponent::m_visualizationSphereRadius, "Visualization Sphere Radius", "Radius of the spheres in the probe grid visualization") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorDiffuseProbeGridComponent::OnVisualizationSphereRadiusChanged) + ->Attribute(Edit::Attributes::Decimals, 2) + ->Attribute(Edit::Attributes::Step, 0.25f) + ->Attribute(Edit::Attributes::Min, 0.25f) + ->Attribute(Edit::Attributes::Max, 2.0f) + ->ClassElement(AZ::Edit::ClassElements::Group, "Grid mode") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(Edit::UIHandlers::ComboBox, &EditorDiffuseProbeGridComponent::m_editorMode, "Editor Mode", "Controls whether the editor uses RealTime or Baked diffuse GI. RealTime requires a ray-tracing capable GPU. Auto-Select will fallback to Baked if ray-tracing is not available") ->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorDiffuseProbeGridComponent::OnModeChangeValidate) @@ -350,6 +365,24 @@ namespace AZ return AZ::Edit::PropertyRefreshLevels::None; } + AZ::u32 EditorDiffuseProbeGridComponent::OnShowVisualizationChanged() + { + m_controller.SetVisualizationEnabled(m_showVisualization); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::u32 EditorDiffuseProbeGridComponent::OnShowInactiveProbesChanged() + { + m_controller.SetVisualizationShowInactiveProbes(m_showInactiveProbes); + return AZ::Edit::PropertyRefreshLevels::None; + } + + AZ::u32 EditorDiffuseProbeGridComponent::OnVisualizationSphereRadiusChanged() + { + m_controller.SetVisualizationSphereRadius(m_visualizationSphereRadius); + return AZ::Edit::PropertyRefreshLevels::None; + } + AZ::Outcome EditorDiffuseProbeGridComponent::OnModeChangeValidate([[maybe_unused]] void* newValue, [[maybe_unused]] const AZ::Uuid& valueType) { DiffuseProbeGridMode newMode = (*(reinterpret_cast(newValue))); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.h index c7832902a8..2b3d4dfe0e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.h @@ -69,6 +69,9 @@ namespace AZ AZ::u32 OnNumRaysPerProbeChanged(); AZ::u32 OnEditorModeChanged(); AZ::u32 OnRuntimeModeChanged(); + AZ::u32 OnShowVisualizationChanged(); + AZ::u32 OnShowInactiveProbesChanged(); + AZ::u32 OnVisualizationSphereRadiusChanged(); AZ::Outcome OnModeChangeValidate(void* newValue, const AZ::Uuid& valueType); // Button handler @@ -85,6 +88,9 @@ namespace AZ DiffuseProbeGridNumRaysPerProbe m_numRaysPerProbe = DefaultDiffuseProbeGridNumRaysPerProbe; DiffuseProbeGridMode m_editorMode = DiffuseProbeGridMode::RealTime; DiffuseProbeGridMode m_runtimeMode = DiffuseProbeGridMode::RealTime; + bool m_showVisualization = false; + bool m_showInactiveProbes = false; + float m_visualizationSphereRadius = DefaultVisualizationSphereRadius; // flags bool m_editorModeSet = false;