Browse Source

Changed the RayTracingFeatureProcessor and associated shaders to use the bindless Srg
Fixed an issue with the DiffuseProbeGridBorderUpdatePass when submitting on multiple threads
Passed the MaxRecursionDepth to the DiffuseProbeGridRayTracing shaders

Signed-off-by: dmcdiarmid-ly <[email protected]>

dmcdiarmid-ly 2 years ago
parent
commit
8fd4e6d9c7

+ 10 - 0
Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingMaterialSrg.azsli

@@ -8,6 +8,14 @@
 
 #include <Atom/Features/SrgSemantics.azsli>
 
+// this define specifies that the mesh buffers and material textures are stored in the Bindless Srg
+// Note1: The previous implementation using separate unbounded arrays is preserved since it demonstrates a TDR caused by
+//        the RHI unbounded array allocation.  This define and the previous codepath can be removed once the TDR is
+//        investigated and resolved.
+// Note2: There are corresponding USE_BINDLESS_SRG defines in the RayTracingSceneSrg.azsli and RayTracingFeatureProcessor.h files
+//        that must match the setting of this define.
+#define USE_BINDLESS_SRG 1
+
 ShaderResourceGroup RayTracingMaterialSrg : SRG_RayTracingMaterial
 {
     Sampler LinearSampler
@@ -55,6 +63,8 @@ ShaderResourceGroup RayTracingMaterialSrg : SRG_RayTracingMaterial
     #define TEXTURE_FLAG_ROUGHNESS      (1 << 3)
     #define TEXTURE_FLAG_EMISSIVE       (1 << 4)
 
+#if !USE_BINDLESS_SRG
     // unbounded array of Material textures
     Texture2D m_materialTextures[];
+#endif
 }

+ 22 - 0
Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingMaterialUtils.azsli

@@ -6,6 +6,8 @@
  *
  */
 
+ #include <Atom/Features/Bindless.azsli>
+
 struct TextureData
 {
     float4 m_baseColor;
@@ -25,7 +27,11 @@ TextureData GetHitTextureData(RayTracingMaterialSrg::MaterialInfo materialInfo,
         // array index of the baseColor texture for this material in the m_materialTextures unbounded array
         uint baseColorTextureArrayIndex = RayTracingMaterialSrg::m_materialTextureIndices[materialInfo.m_textureStartIndex + MATERIAL_BASECOLOR_TEXTURE_OFFSET];
 
+#if USE_BINDLESS_SRG
+        textureData.m_baseColor = Bindless::GetTexture2D(baseColorTextureArrayIndex).SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#else
         textureData.m_baseColor = RayTracingMaterialSrg::m_materialTextures[baseColorTextureArrayIndex].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#endif
     }
     else
     {
@@ -38,7 +44,11 @@ TextureData GetHitTextureData(RayTracingMaterialSrg::MaterialInfo materialInfo,
         // array index of the normal texture for this material in the m_materialTextures unbounded array
         uint normalTextureArrayIndex = RayTracingMaterialSrg::m_materialTextureIndices[materialInfo.m_textureStartIndex + MATERIAL_NORMAL_TEXTURE_OFFSET];
 
+#if USE_BINDLESS_SRG
+        textureData.m_normal = Bindless::GetTexture2D(normalTextureArrayIndex).SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#else
         textureData.m_normal = RayTracingMaterialSrg::m_materialTextures[normalTextureArrayIndex].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#endif       
     }
     else
     {
@@ -51,7 +61,11 @@ TextureData GetHitTextureData(RayTracingMaterialSrg::MaterialInfo materialInfo,
         // array index of the metallic texture for this material in the m_materialTextures unbounded array
         uint metallicTextureArrayIndex = RayTracingMaterialSrg::m_materialTextureIndices[materialInfo.m_textureStartIndex + MATERIAL_METALLIC_TEXTURE_OFFSET];
 
+#if USE_BINDLESS_SRG
+        textureData.m_metallic = Bindless::GetTexture2D(metallicTextureArrayIndex).SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#else
         textureData.m_metallic = RayTracingMaterialSrg::m_materialTextures[metallicTextureArrayIndex].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#endif
     }
     else
     {
@@ -64,7 +78,11 @@ TextureData GetHitTextureData(RayTracingMaterialSrg::MaterialInfo materialInfo,
         // array index of the roughness texture for this material in the m_materialTextures unbounded array
         uint roughnessTextureArrayIndex = RayTracingMaterialSrg::m_materialTextureIndices[materialInfo.m_textureStartIndex + MATERIAL_ROUGHNESS_TEXTURE_OFFSET];
 
+#if USE_BINDLESS_SRG
+        textureData.m_roughness = Bindless::GetTexture2D(roughnessTextureArrayIndex).SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#else
         textureData.m_roughness = RayTracingMaterialSrg::m_materialTextures[roughnessTextureArrayIndex].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#endif
     }
     else
     {
@@ -77,7 +95,11 @@ TextureData GetHitTextureData(RayTracingMaterialSrg::MaterialInfo materialInfo,
         // array index of the emissive texture for this material in the m_materialTextures unbounded array
         uint emissiveTextureArrayIndex = RayTracingMaterialSrg::m_materialTextureIndices[materialInfo.m_textureStartIndex + MATERIAL_EMISSIVE_TEXTURE_OFFSET];
 
+#if USE_BINDLESS_SRG
+        textureData.m_emissiveColor = Bindless::GetTexture2D(emissiveTextureArrayIndex).SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#else
         textureData.m_emissiveColor = RayTracingMaterialSrg::m_materialTextures[emissiveTextureArrayIndex].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#endif
     }
     else
     {

+ 10 - 0
Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli

@@ -8,6 +8,14 @@
 
 #include <Atom/Features/SrgSemantics.azsli>
 
+// this define specifies that the mesh buffers and material textures are stored in the Bindless Srg
+// Note1: The previous implementation using separate unbounded arrays is preserved since it demonstrates a TDR caused by
+//        the RHI unbounded array allocation.  This define and the previous codepath can be removed once the TDR is
+//        investigated and resolved.
+// Note2: There are corresponding USE_BINDLESS_SRG defines in the RayTracingMaterialSrg.azsli and RayTracingFeatureProcessor.h files
+//        that must match the setting of this define.
+#define USE_BINDLESS_SRG 1
+
 ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
 {
     RaytracingAccelerationStructure m_scene;
@@ -183,8 +191,10 @@ ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
     #define MESH_BUFFER_FLAG_BITANGENT      (1 << 1)
     #define MESH_BUFFER_FLAG_UV             (1 << 2)
 
+#if !USE_BINDLESS_SRG
     // Unbounded array of mesh stream buffers:
     // Note 1: Index, Position, and Normal stream buffers are guaranteed to be valid for each mesh
     // Note 2: Optional stream buffers such as Tangent, Bitangent, and UV are indicated in the MeshInfo.m_bufferFlags field
     ByteAddressBuffer m_meshBuffers[];
+#endif
 }

+ 27 - 1
Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli

@@ -6,6 +6,8 @@
  *
  */
 
+#include <Atom/Features/Bindless.azsli>
+
 // returns the normalized camera view ray into the scene for this raytracing dispatch thread
 float3 GetViewRayDirection(float4x4 projectionInverseMatrix, float4x4 viewInverseMatrix)
 {
@@ -26,7 +28,11 @@ uint3 GetHitIndices(RayTracingSceneSrg::MeshInfo meshInfo)
     uint offsetBytes = meshInfo.m_indexOffset + (PrimitiveIndex() * 12);
 
     // load the indices for this primitive from the index buffer
+#if USE_BINDLESS_SRG
+    return Bindless::GetByteAddressBuffer(meshIndexBufferArrayIndex).Load3(offsetBytes);
+#else
     return RayTracingSceneSrg::m_meshBuffers[meshIndexBufferArrayIndex].Load3(offsetBytes);
+#endif
 }
 
 // returns the interpolated vertex data for the primitive hit by the ray
@@ -61,7 +67,11 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f
             uint positionOffset = meshInfo.m_positionOffset + (indices[i] * 12);
 
             // load the position data
+#if USE_BINDLESS_SRG
+            vertexData.m_position += asfloat(Bindless::GetByteAddressBuffer(meshVertexPositionArrayIndex).Load3(positionOffset)) * barycentrics[i];
+#else
             vertexData.m_position += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexPositionArrayIndex].Load3(positionOffset)) * barycentrics[i];
+#endif
         }
 
         // normal
@@ -72,8 +82,12 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f
             // offset into the normal buffer for this vertex
             uint normalOffset = meshInfo.m_normalOffset + (indices[i] * 12);
 
-            // load the normal data
+             // load the normal data
+#if USE_BINDLESS_SRG
+            vertexData.m_normal += asfloat(Bindless::GetByteAddressBuffer(meshVertexNormalArrayIndex).Load3(normalOffset)) * barycentrics[i];
+#else
             vertexData.m_normal += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexNormalArrayIndex].Load3(normalOffset)) * barycentrics[i];
+#endif
         }
 
         // tangent
@@ -86,7 +100,11 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f
             uint tangentOffset = meshInfo.m_tangentOffset + (indices[i] * 16);
 
             // load the tangent data
+#if USE_BINDLESS_SRG
+            vertexData.m_tangent += asfloat(Bindless::GetByteAddressBuffer(meshVertexTangentArrayIndex).Load4(tangentOffset)) * barycentrics[i];
+#else
             vertexData.m_tangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexTangentArrayIndex].Load4(tangentOffset)) * barycentrics[i];
+#endif
         }
 
         // bitangent
@@ -99,7 +117,11 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f
             uint bitangentOffset = meshInfo.m_bitangentOffset + (indices[i] * 12);
 
             // load the bitangent data
+#if USE_BINDLESS_SRG
+            vertexData.m_bitangent += asfloat(Bindless::GetByteAddressBuffer(meshVertexBitangentArrayIndex).Load3(bitangentOffset)) * barycentrics[i];
+#else
             vertexData.m_bitangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexBitangentArrayIndex].Load3(bitangentOffset)) * barycentrics[i];
+#endif
         }
 
         // UV
@@ -112,7 +134,11 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f
             uint uvOffset = meshInfo.m_uvOffset + (indices[i] * 8);    
     
             // load the UV data
+#if USE_BINDLESS_SRG
+            vertexData.m_uv += asfloat(Bindless::GetByteAddressBuffer(meshVertexUVArrayIndex).Load2(uvOffset)) * barycentrics[i];
+#else
             vertexData.m_uv += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexUVArrayIndex].Load2(uvOffset)) * barycentrics[i];
+#endif
         }
     }
     

+ 38 - 1
Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp

@@ -208,17 +208,30 @@ namespace AZ
                 worldInvTranspose3x4.StoreToRowMajorFloat12(meshInfo.m_worldInvTranspose.data());
                 meshInfo.m_bufferFlags = subMesh.m_bufferFlags;
 
+                AZ_Assert(subMesh.m_indexShaderBufferView.get(), "RayTracing Mesh IndexBuffer cannot be null");
+                AZ_Assert(subMesh.m_positionShaderBufferView.get(), "RayTracing Mesh PositionBuffer cannot be null");
+                AZ_Assert(subMesh.m_normalShaderBufferView.get(), "RayTracing Mesh NormalBuffer cannot be null");
+
                 // add mesh buffers
                 meshInfo.m_bufferStartIndex = m_meshBufferIndices.AddEntry(
                 {
+#if USE_BINDLESS_SRG
+                    subMesh.m_indexShaderBufferView.get() ? subMesh.m_indexShaderBufferView->GetBindlessReadIndex() : InvalidIndex,
+                    subMesh.m_positionShaderBufferView.get() ? subMesh.m_positionShaderBufferView->GetBindlessReadIndex() : InvalidIndex,
+                    subMesh.m_normalShaderBufferView.get() ? subMesh.m_normalShaderBufferView->GetBindlessReadIndex() : InvalidIndex,
+                    subMesh.m_tangentShaderBufferView.get() ? subMesh.m_tangentShaderBufferView->GetBindlessReadIndex() : InvalidIndex,
+                    subMesh.m_bitangentShaderBufferView.get() ? subMesh.m_bitangentShaderBufferView->GetBindlessReadIndex() : InvalidIndex,
+                    subMesh.m_uvShaderBufferView.get() ? subMesh.m_uvShaderBufferView->GetBindlessReadIndex() : InvalidIndex
+#else
                     m_meshBuffers.AddResource(subMesh.m_indexShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_positionShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_normalShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_tangentShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_bitangentShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_uvShaderBufferView.get())
+#endif
                 });
-                
+
                 meshInfo.m_indexByteOffset = subMesh.m_indexBufferView.GetByteOffset();
                 meshInfo.m_positionByteOffset = subMesh.m_positionVertexBufferView.GetByteOffset();
                 meshInfo.m_normalByteOffset = subMesh.m_normalVertexBufferView.GetByteOffset();
@@ -235,11 +248,19 @@ namespace AZ
 
                 materialInfo.m_textureStartIndex = m_materialTextureIndices.AddEntry(
                 {
+#if USE_BINDLESS_SRG
+                    subMesh.m_baseColorImageView.get() ? subMesh.m_baseColorImageView->GetBindlessReadIndex() : InvalidIndex,
+                    subMesh.m_normalImageView.get() ? subMesh.m_normalImageView->GetBindlessReadIndex() : InvalidIndex,
+                    subMesh.m_metallicImageView.get() ? subMesh.m_metallicImageView->GetBindlessReadIndex() : InvalidIndex,
+                    subMesh.m_roughnessImageView.get() ? subMesh.m_roughnessImageView->GetBindlessReadIndex() : InvalidIndex,
+                    subMesh.m_emissiveImageView.get() ? subMesh.m_emissiveImageView->GetBindlessReadIndex() : InvalidIndex
+#else
                     m_materialTextures.AddResource(subMesh.m_baseColorImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_normalImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_metallicImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_roughnessImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_emissiveImageView.get())
+#endif
                 });
             }
 
@@ -289,6 +310,7 @@ namespace AZ
                     m_meshBufferIndices.RemoveEntry(meshInfo.m_bufferStartIndex);
                     m_materialTextureIndices.RemoveEntry(materialInfo.m_textureStartIndex);
 
+#if !USE_BINDLESS_SRG
                     m_meshBuffers.RemoveResource(subMesh.m_indexShaderBufferView.get());
                     m_meshBuffers.RemoveResource(subMesh.m_positionShaderBufferView.get());
                     m_meshBuffers.RemoveResource(subMesh.m_normalShaderBufferView.get());
@@ -301,6 +323,7 @@ namespace AZ
                     m_materialTextures.RemoveResource(subMesh.m_metallicImageView.get());
                     m_materialTextures.RemoveResource(subMesh.m_roughnessImageView.get());
                     m_materialTextures.RemoveResource(subMesh.m_emissiveImageView.get());
+#endif
 
                     if (globalIndex < m_subMeshes.size() - 1)
                     {
@@ -339,8 +362,10 @@ namespace AZ
                     m_meshBufferIndices.Reset();
                     m_materialTextureIndices.Reset();
 
+#if !USE_BINDLESS_SRG
                     m_meshBuffers.Reset();
                     m_materialTextures.Reset();
+#endif
                 }
             }
 
@@ -505,6 +530,7 @@ namespace AZ
                     currentMeshBufferIndicesGpuBuffer->Resize(newMeshBufferIndicesByteCount);
                 }
 
+#if !USE_BINDLESS_SRG
                 // resolve to the true indices using the indirection list
                 // Note: this is done on the CPU to avoid double-indirection in the shader
                 IndexVector resolvedMeshBufferIndices(m_meshBufferIndices.GetIndexList().size());
@@ -522,6 +548,9 @@ namespace AZ
                 }
 
                 currentMeshBufferIndicesGpuBuffer->UpdateData(resolvedMeshBufferIndices.data(), newMeshBufferIndicesByteCount);
+#else
+                currentMeshBufferIndicesGpuBuffer->UpdateData(m_meshBufferIndices.GetIndexList().data(), newMeshBufferIndicesByteCount);
+#endif
 
                 // update material texture indices buffer
                 Data::Instance<RPI::Buffer>& currentMaterialTextureIndicesGpuBuffer = m_materialTextureIndicesGpuBuffer[m_currentIndexListFrameIndex];
@@ -544,6 +573,7 @@ namespace AZ
                     currentMaterialTextureIndicesGpuBuffer->Resize(newMaterialTextureIndicesByteCount);
                 }
 
+#if !USE_BINDLESS_SRG
                 // resolve to the true indices using the indirection list
                 // Note: this is done on the CPU to avoid double-indirection in the shader
                 IndexVector resolvedMaterialTextureIndices(m_materialTextureIndices.GetIndexList().size());
@@ -561,6 +591,9 @@ namespace AZ
                 }
 
                 currentMaterialTextureIndicesGpuBuffer->UpdateData(resolvedMaterialTextureIndices.data(), newMaterialTextureIndicesByteCount);
+#else
+                currentMaterialTextureIndicesGpuBuffer->UpdateData(m_materialTextureIndices.GetIndexList().data(), newMaterialTextureIndicesByteCount);
+#endif
 
                 m_indexListNeedsUpdate = false;
             }
@@ -656,8 +689,10 @@ namespace AZ
             bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_meshBufferIndices"));
             m_rayTracingSceneSrg->SetBufferView(bufferIndex, m_meshBufferIndicesGpuBuffer[m_currentIndexListFrameIndex]->GetBufferView());
 
+#if !USE_BINDLESS_SRG
             RHI::ShaderInputBufferUnboundedArrayIndex bufferUnboundedArrayIndex = srgLayout->FindShaderInputBufferUnboundedArrayIndex(AZ::Name("m_meshBuffers"));
             m_rayTracingSceneSrg->SetBufferViewUnboundedArray(bufferUnboundedArrayIndex, m_meshBuffers.GetResourceList());
+#endif
             m_rayTracingSceneSrg->Compile();
         }
 
@@ -672,8 +707,10 @@ namespace AZ
             bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_materialTextureIndices"));
             m_rayTracingMaterialSrg->SetBufferView(bufferIndex, m_materialTextureIndicesGpuBuffer[m_currentIndexListFrameIndex]->GetBufferView());
 
+#if !USE_BINDLESS_SRG
             RHI::ShaderInputImageUnboundedArrayIndex textureUnboundedArrayIndex = srgLayout->FindShaderInputImageUnboundedArrayIndex(AZ::Name("m_materialTextures"));
             m_rayTracingMaterialSrg->SetImageViewUnboundedArray(textureUnboundedArrayIndex, m_materialTextures.GetResourceList());
+#endif
             m_rayTracingMaterialSrg->Compile();
         }
 

+ 15 - 5
Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h

@@ -18,6 +18,14 @@
 #include <AzCore/Math/Color.h>
 #include <AzCore/Math/Transform.h>
 
+// this define specifies that the mesh buffers and material textures are stored in the Bindless Srg
+// Note1: The previous implementation using separate unbounded arrays is preserved since it demonstrates a TDR caused by
+//        the RHI unbounded array allocation.  This define and the previous codepath can be removed once the TDR is
+//        investigated and resolved.
+// Note2: There are corresponding USE_BINDLESS_SRG defines in the RayTracingSceneSrg.azsli and RayTracingMaterialSrg.azsli
+//        shader files that must match the setting of this define.
+#define USE_BINDLESS_SRG 1
+
 namespace AZ
 {
     namespace Render
@@ -313,25 +321,27 @@ namespace AZ
             // side list for looking up existing BLAS objects so they can be re-used when the same mesh is added multiple times
             BlasInstanceMap m_blasInstanceMap;
 
+#if !USE_BINDLESS_SRG
             // Mesh buffer and material texture resources are managed with a RayTracingResourceList, which contains an internal
             // indirection list.  This allows resource entries to be swapped inside the RayTracingResourceList when removing entries,
             // without invalidating the indices held here in the m_meshBufferIndices and m_materialTextureIndices lists.
-            //
-            // RayTracingIndexList implements an internal freelist chain stored inside the list itself, allowing entries to be
-            // reused after elements are removed.
             
             // mesh buffer and material texture resource lists, accessed by the shader through an unbounded array
             RayTracingResourceList<RHI::BufferView> m_meshBuffers;
             RayTracingResourceList<const RHI::ImageView> m_materialTextures;
+#endif
+
+            // RayTracingIndexList implements an internal freelist chain stored inside the list itself, allowing entries to be
+            // reused after elements are removed.
 
-            // mesh buffer and material texture index lists, these are the indices into the resource lists
+            // mesh buffer and material texture index lists, which contain the array indices of the mesh resources
             static const uint32_t NumMeshBuffersPerMesh = 6;
             RayTracingIndexList<NumMeshBuffersPerMesh> m_meshBufferIndices;
 
             static const uint32_t NumMaterialTexturesPerMesh = 5;
             RayTracingIndexList<NumMaterialTexturesPerMesh> m_materialTextureIndices;
 
-            // Gpu buffers for the mesh and material resources
+            // Gpu buffers for the mesh and material index lists
             Data::Instance<RPI::Buffer> m_meshBufferIndicesGpuBuffer[BufferFrameCount];
             Data::Instance<RPI::Buffer> m_materialTextureIndicesGpuBuffer[BufferFrameCount];
             uint32_t m_currentIndexListFrameIndex = 0;

+ 10 - 0
Gems/Atom/RHI/DX12/Code/Source/RHI/BufferView.cpp

@@ -110,5 +110,15 @@ namespace AZ
         {
             return static_cast<const Buffer&>(Base::GetBuffer());
         }
+
+        uint32_t BufferView::GetBindlessReadIndex() const
+        {
+            return m_staticReadDescriptor.m_index;
+        }
+
+        uint32_t BufferView::GetBindlessReadWriteIndex() const
+        {
+            return m_staticReadWriteDescriptor.m_index;
+        }
     }
 }

+ 6 - 0
Gems/Atom/RHI/DX12/Code/Source/RHI/BufferView.h

@@ -37,6 +37,12 @@ namespace AZ
             GpuVirtualAddress GetGpuAddress() const;
             ID3D12Resource* GetMemory() const;
 
+            //////////////////////////////////////////////////////////////////////////
+            // RHI::BufferView
+            uint32_t GetBindlessReadIndex() const override;
+            uint32_t GetBindlessReadWriteIndex() const override;
+            //////////////////////////////////////////////////////////////////////////
+
         private:
             BufferView() = default;
 

+ 14 - 1
Gems/Atom/RHI/DX12/Code/Source/RHI/CommandList.cpp

@@ -360,7 +360,8 @@ namespace AZ
                 const ShaderResourceGroup* srg = static_cast<const ShaderResourceGroup*>(dispatchRaysItem.m_shaderResourceGroups[srgIndex]);
                 const ShaderResourceGroupCompiledData& compiledData = srg->GetCompiledData();
 
-                if (binding.m_resourceTable.IsValid())
+                if (binding.m_resourceTable.IsValid()
+                    && compiledData.m_gpuViewsDescriptorHandle.ptr)
                 {
                     GetCommandList()->SetComputeRootDescriptorTable(binding.m_resourceTable.GetIndex(), compiledData.m_gpuViewsDescriptorHandle);
                 }
@@ -382,6 +383,18 @@ namespace AZ
                 }
             }
 
+            // set the bindless descriptor table if required by the shader
+            for (uint32_t bindingIndex = 0; bindingIndex < globalPipelineLayout.GetRootParameterBindingCount(); ++bindingIndex)
+            {
+                RootParameterBinding binding = globalPipelineLayout.GetRootParameterBindingByIndex(bindingIndex);
+                if (binding.m_bindlessTable.IsValid())
+                {
+                    GetCommandList()->SetComputeRootDescriptorTable(
+                        binding.m_bindlessTable.GetIndex(), m_descriptorContext->GetBindlessGpuPlatformHandle());
+                    break;
+                }
+            }
+
             // set RayTracing pipeline state
             commandList->SetPipelineState1(rayTracingPipelineState->Get());
 

+ 53 - 61
Gems/DiffuseProbeGrid/Code/Source/Render/DiffuseProbeGridBorderUpdatePass.cpp

@@ -121,7 +121,9 @@ namespace AZ
             DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
 
             // there are 4 submits per grid
-            frameGraph.SetEstimatedItemCount(aznumeric_cast<uint32_t>(diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().size() * 4));
+            uint32_t totalSubmits = aznumeric_cast<uint32_t>(diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids().size() * 4);
+            frameGraph.SetEstimatedItemCount(totalSubmits);
+            m_submitItems.reserve(totalSubmits);
 
             for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids())
             {
@@ -162,88 +164,78 @@ namespace AZ
                 diffuseProbeGrid->GetBorderUpdateColumnIrradianceSrg()->Compile();
                 diffuseProbeGrid->GetBorderUpdateRowDistanceSrg()->Compile();
                 diffuseProbeGrid->GetBorderUpdateColumnDistanceSrg()->Compile();
-            }
-        }
-
-        void DiffuseProbeGridBorderUpdatePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
-        {
-            RHI::CommandList* commandList = context.GetCommandList();
-            RPI::Scene* scene = m_pipeline->GetScene();
-            DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
-
-            // submit the DispatchItems for each DiffuseProbeGrid in this range
-            uint32_t index = context.GetSubmitRange().m_startIndex;
-            while (index < context.GetSubmitRange().m_endIndex)
-            {
-                // Note: there are 4 submits per grid, so we need to calculate the diffuseProbeGridIndex in the list as (submit index / 4)
-                AZ_Assert(index % 4 == 0, "Incorrect number of submits in DiffuseProbeGridBorderUpdatePass::BuildCommandListInternal");
-                uint32_t diffuseProbeGridIndex = index / 4;
-                AZStd::shared_ptr<DiffuseProbeGrid> diffuseProbeGrid = diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids()[diffuseProbeGridIndex];
 
+                // setup the submit items now to properly handle submitting on multiple threads
                 uint32_t probeCountX;
                 uint32_t probeCountY;
                 diffuseProbeGrid->GetTexture2DProbeCount(probeCountX, probeCountY);
 
                 // row irradiance
                 {
-                    const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateRowIrradianceSrg()->GetRHIShaderResourceGroup();
-                    commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup);
-
-                    RHI::DispatchItem dispatchItem;
-                    dispatchItem.m_arguments = m_rowDispatchArgs;
-                    dispatchItem.m_pipelineState = m_rowPipelineState;
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX * (DiffuseProbeGrid::DefaultNumIrradianceTexels + 2);
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY;
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
-
-                    commandList->Submit(dispatchItem, index++);
+                    SubmitItem& submitItem = m_submitItems.emplace_back();
+                    submitItem.m_shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateRowIrradianceSrg()->GetRHIShaderResourceGroup();
+                    submitItem.m_dispatchItem.m_arguments = m_rowDispatchArgs;
+                    submitItem.m_dispatchItem.m_pipelineState = m_rowPipelineState;
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX * (DiffuseProbeGrid::DefaultNumIrradianceTexels + 2);
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY;
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
                 }
 
                 // column irradiance
                 {
-                    const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateColumnIrradianceSrg()->GetRHIShaderResourceGroup();
-                    commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup);
-
-                    RHI::DispatchItem dispatchItem;
-                    dispatchItem.m_arguments = m_columnDispatchArgs;
-                    dispatchItem.m_pipelineState = m_columnPipelineState;
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX;
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY * (DiffuseProbeGrid::DefaultNumIrradianceTexels + 2);
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
-
-                    commandList->Submit(dispatchItem, index++);
+                    SubmitItem& submitItem = m_submitItems.emplace_back();
+                    submitItem.m_shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateColumnIrradianceSrg()->GetRHIShaderResourceGroup();
+                    submitItem.m_dispatchItem.m_arguments = m_columnDispatchArgs;
+                    submitItem.m_dispatchItem.m_pipelineState = m_columnPipelineState;
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX;
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY * (DiffuseProbeGrid::DefaultNumIrradianceTexels + 2);
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
                 }
 
                 // row distance
                 {
-                    const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateRowDistanceSrg()->GetRHIShaderResourceGroup();
-                    commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup);
-
-                    RHI::DispatchItem dispatchItem;
-                    dispatchItem.m_arguments = m_rowDispatchArgs;
-                    dispatchItem.m_pipelineState = m_rowPipelineState;
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX * (DiffuseProbeGrid::DefaultNumDistanceTexels + 2);
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY;
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
-
-                    commandList->Submit(dispatchItem, index++);
+                    SubmitItem& submitItem = m_submitItems.emplace_back();
+                    submitItem.m_shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateRowDistanceSrg()->GetRHIShaderResourceGroup();
+                    submitItem.m_dispatchItem.m_arguments = m_rowDispatchArgs;
+                    submitItem.m_dispatchItem.m_pipelineState = m_rowPipelineState;
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX * (DiffuseProbeGrid::DefaultNumDistanceTexels + 2);
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY;
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
                 }
 
                 // column distance
                 {
-                    const RHI::ShaderResourceGroup* shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateColumnDistanceSrg()->GetRHIShaderResourceGroup();
-                    commandList->SetShaderResourceGroupForDispatch(*shaderResourceGroup);
+                    SubmitItem& submitItem = m_submitItems.emplace_back();
+                    submitItem.m_shaderResourceGroup = diffuseProbeGrid->GetBorderUpdateColumnDistanceSrg()->GetRHIShaderResourceGroup();
+                    submitItem.m_dispatchItem.m_arguments = m_columnDispatchArgs;
+                    submitItem.m_dispatchItem.m_pipelineState = m_columnPipelineState;
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX;
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY * (DiffuseProbeGrid::DefaultNumDistanceTexels + 2);
+                    submitItem.m_dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
+                }
+            }     
+        }
 
-                    RHI::DispatchItem dispatchItem;
-                    dispatchItem.m_arguments = m_columnDispatchArgs;
-                    dispatchItem.m_pipelineState = m_columnPipelineState;
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsX = probeCountX;
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsY = probeCountY * (DiffuseProbeGrid::DefaultNumDistanceTexels + 2);
-                    dispatchItem.m_arguments.m_direct.m_totalNumberOfThreadsZ = 1;
+        void DiffuseProbeGridBorderUpdatePass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
+        {
+            RHI::CommandList* commandList = context.GetCommandList();
 
-                    commandList->Submit(dispatchItem, index++);
-                }
+            // submit the DispatchItems for each DiffuseProbeGrid in this range
+            uint32_t index = context.GetSubmitRange().m_startIndex;
+            while (index < context.GetSubmitRange().m_endIndex)
+            {
+                SubmitItem& submitItem = m_submitItems[index];
+
+                commandList->SetShaderResourceGroupForDispatch(*submitItem.m_shaderResourceGroup);
+                commandList->Submit(submitItem.m_dispatchItem, index++);
             }
         }
+
+        void DiffuseProbeGridBorderUpdatePass::FrameEndInternal()
+        {
+            m_submitItems.clear();
+
+            RenderPass::FrameEndInternal();
+        }
     }   // namespace Render
 }   // namespace AZ

+ 10 - 0
Gems/DiffuseProbeGrid/Code/Source/Render/DiffuseProbeGridBorderUpdatePass.h

@@ -44,6 +44,16 @@ namespace AZ
             void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
             void CompileResources(const RHI::FrameGraphCompileContext& context) override;
             void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
+            void FrameEndInternal() override;
+
+            // the data for submits in this pass are pre-built to properly handle submitting on multiple threads
+            struct SubmitItem
+            {
+                RHI::ShaderResourceGroup* m_shaderResourceGroup = nullptr;
+                RHI::DispatchItem m_dispatchItem;
+            };
+
+            AZStd::vector<SubmitItem> m_submitItems;
 
             // shader
             Data::Instance<RPI::Shader> m_rowShader;

+ 4 - 2
Gems/DiffuseProbeGrid/Code/Source/Render/DiffuseProbeGridRayTracingPass.cpp

@@ -98,9 +98,9 @@ namespace AZ
             RHI::RayTracingPipelineStateDescriptor descriptor;
             descriptor.Build()
                 ->PipelineState(m_globalPipelineState.get())
-                ->MaxPayloadSize(108)
+                ->MaxPayloadSize(112)
                 ->MaxAttributeSize(32)
-                ->MaxRecursionDepth(16)
+                ->MaxRecursionDepth(MaxRecursionDepth)
                 ->ShaderLibrary(rayGenerationShaderDescriptor)
                     ->RayGenerationShaderName(AZ::Name("RayGen"))
                 ->ShaderLibrary(missShaderDescriptor)
@@ -310,6 +310,8 @@ namespace AZ
                     // the diffuse probe grid Srg must be updated in the Compile phase in order to successfully bind the ReadWrite shader
                     // inputs (see line ValidateSetImageView() in ShaderResourceGroupData.cpp)
                     diffuseProbeGrid->UpdateRayTraceSrg(m_rayTracingShader, m_globalSrgLayout);
+
+                    diffuseProbeGrid->GetRayTraceSrg()->SetConstant(m_maxRecursionDepthNameIndex, MaxRecursionDepth);
                     diffuseProbeGrid->GetRayTraceSrg()->Compile();
                 }
             }

+ 3 - 1
Gems/DiffuseProbeGrid/Code/Source/Render/DiffuseProbeGridRayTracingPass.h

@@ -63,9 +63,11 @@ namespace AZ
 
             // ray tracing global shader resource group layout and pipeline state
             RHI::Ptr<RHI::ShaderResourceGroupLayout> m_globalSrgLayout;
-
             RHI::ConstPtr<RHI::PipelineState> m_globalPipelineState;
 
+            RHI::ShaderInputNameIndex m_maxRecursionDepthNameIndex = "m_maxRecursionDepth";
+            static const uint32_t MaxRecursionDepth = 16;
+
             bool m_initialized = false;
         };
     }   // namespace RPI