소스 검색

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 년 전
부모
커밋
8fd4e6d9c7

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

@@ -8,6 +8,14 @@
 
 
 #include <Atom/Features/SrgSemantics.azsli>
 #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
 ShaderResourceGroup RayTracingMaterialSrg : SRG_RayTracingMaterial
 {
 {
     Sampler LinearSampler
     Sampler LinearSampler
@@ -55,6 +63,8 @@ ShaderResourceGroup RayTracingMaterialSrg : SRG_RayTracingMaterial
     #define TEXTURE_FLAG_ROUGHNESS      (1 << 3)
     #define TEXTURE_FLAG_ROUGHNESS      (1 << 3)
     #define TEXTURE_FLAG_EMISSIVE       (1 << 4)
     #define TEXTURE_FLAG_EMISSIVE       (1 << 4)
 
 
+#if !USE_BINDLESS_SRG
     // unbounded array of Material textures
     // unbounded array of Material textures
     Texture2D m_materialTextures[];
     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
 struct TextureData
 {
 {
     float4 m_baseColor;
     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
         // 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];
         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);
         textureData.m_baseColor = RayTracingMaterialSrg::m_materialTextures[baseColorTextureArrayIndex].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#endif
     }
     }
     else
     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
         // 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];
         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);
         textureData.m_normal = RayTracingMaterialSrg::m_materialTextures[normalTextureArrayIndex].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#endif       
     }
     }
     else
     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
         // 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];
         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);
         textureData.m_metallic = RayTracingMaterialSrg::m_materialTextures[metallicTextureArrayIndex].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#endif
     }
     }
     else
     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
         // 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];
         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);
         textureData.m_roughness = RayTracingMaterialSrg::m_materialTextures[roughnessTextureArrayIndex].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#endif
     }
     }
     else
     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
         // 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];
         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);
         textureData.m_emissiveColor = RayTracingMaterialSrg::m_materialTextures[emissiveTextureArrayIndex].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
+#endif
     }
     }
     else
     else
     {
     {

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

@@ -8,6 +8,14 @@
 
 
 #include <Atom/Features/SrgSemantics.azsli>
 #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
 ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
 {
 {
     RaytracingAccelerationStructure m_scene;
     RaytracingAccelerationStructure m_scene;
@@ -183,8 +191,10 @@ ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
     #define MESH_BUFFER_FLAG_BITANGENT      (1 << 1)
     #define MESH_BUFFER_FLAG_BITANGENT      (1 << 1)
     #define MESH_BUFFER_FLAG_UV             (1 << 2)
     #define MESH_BUFFER_FLAG_UV             (1 << 2)
 
 
+#if !USE_BINDLESS_SRG
     // Unbounded array of mesh stream buffers:
     // Unbounded array of mesh stream buffers:
     // Note 1: Index, Position, and Normal stream buffers are guaranteed to be valid for each mesh
     // 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
     // Note 2: Optional stream buffers such as Tangent, Bitangent, and UV are indicated in the MeshInfo.m_bufferFlags field
     ByteAddressBuffer m_meshBuffers[];
     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
 // returns the normalized camera view ray into the scene for this raytracing dispatch thread
 float3 GetViewRayDirection(float4x4 projectionInverseMatrix, float4x4 viewInverseMatrix)
 float3 GetViewRayDirection(float4x4 projectionInverseMatrix, float4x4 viewInverseMatrix)
 {
 {
@@ -26,7 +28,11 @@ uint3 GetHitIndices(RayTracingSceneSrg::MeshInfo meshInfo)
     uint offsetBytes = meshInfo.m_indexOffset + (PrimitiveIndex() * 12);
     uint offsetBytes = meshInfo.m_indexOffset + (PrimitiveIndex() * 12);
 
 
     // load the indices for this primitive from the index buffer
     // 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);
     return RayTracingSceneSrg::m_meshBuffers[meshIndexBufferArrayIndex].Load3(offsetBytes);
+#endif
 }
 }
 
 
 // returns the interpolated vertex data for the primitive hit by the ray
 // 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);
             uint positionOffset = meshInfo.m_positionOffset + (indices[i] * 12);
 
 
             // load the position data
             // 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];
             vertexData.m_position += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexPositionArrayIndex].Load3(positionOffset)) * barycentrics[i];
+#endif
         }
         }
 
 
         // normal
         // normal
@@ -72,8 +82,12 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f
             // offset into the normal buffer for this vertex
             // offset into the normal buffer for this vertex
             uint normalOffset = meshInfo.m_normalOffset + (indices[i] * 12);
             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];
             vertexData.m_normal += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexNormalArrayIndex].Load3(normalOffset)) * barycentrics[i];
+#endif
         }
         }
 
 
         // tangent
         // tangent
@@ -86,7 +100,11 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f
             uint tangentOffset = meshInfo.m_tangentOffset + (indices[i] * 16);
             uint tangentOffset = meshInfo.m_tangentOffset + (indices[i] * 16);
 
 
             // load the tangent data
             // 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];
             vertexData.m_tangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexTangentArrayIndex].Load4(tangentOffset)) * barycentrics[i];
+#endif
         }
         }
 
 
         // bitangent
         // bitangent
@@ -99,7 +117,11 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f
             uint bitangentOffset = meshInfo.m_bitangentOffset + (indices[i] * 12);
             uint bitangentOffset = meshInfo.m_bitangentOffset + (indices[i] * 12);
 
 
             // load the bitangent data
             // 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];
             vertexData.m_bitangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexBitangentArrayIndex].Load3(bitangentOffset)) * barycentrics[i];
+#endif
         }
         }
 
 
         // UV
         // UV
@@ -112,7 +134,11 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f
             uint uvOffset = meshInfo.m_uvOffset + (indices[i] * 8);    
             uint uvOffset = meshInfo.m_uvOffset + (indices[i] * 8);    
     
     
             // load the UV data
             // 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];
             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());
                 worldInvTranspose3x4.StoreToRowMajorFloat12(meshInfo.m_worldInvTranspose.data());
                 meshInfo.m_bufferFlags = subMesh.m_bufferFlags;
                 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
                 // add mesh buffers
                 meshInfo.m_bufferStartIndex = m_meshBufferIndices.AddEntry(
                 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_indexShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_positionShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_positionShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_normalShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_normalShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_tangentShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_tangentShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_bitangentShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_bitangentShaderBufferView.get()),
                     m_meshBuffers.AddResource(subMesh.m_uvShaderBufferView.get())
                     m_meshBuffers.AddResource(subMesh.m_uvShaderBufferView.get())
+#endif
                 });
                 });
-                
+
                 meshInfo.m_indexByteOffset = subMesh.m_indexBufferView.GetByteOffset();
                 meshInfo.m_indexByteOffset = subMesh.m_indexBufferView.GetByteOffset();
                 meshInfo.m_positionByteOffset = subMesh.m_positionVertexBufferView.GetByteOffset();
                 meshInfo.m_positionByteOffset = subMesh.m_positionVertexBufferView.GetByteOffset();
                 meshInfo.m_normalByteOffset = subMesh.m_normalVertexBufferView.GetByteOffset();
                 meshInfo.m_normalByteOffset = subMesh.m_normalVertexBufferView.GetByteOffset();
@@ -235,11 +248,19 @@ namespace AZ
 
 
                 materialInfo.m_textureStartIndex = m_materialTextureIndices.AddEntry(
                 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_baseColorImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_normalImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_normalImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_metallicImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_metallicImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_roughnessImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_roughnessImageView.get()),
                     m_materialTextures.AddResource(subMesh.m_emissiveImageView.get())
                     m_materialTextures.AddResource(subMesh.m_emissiveImageView.get())
+#endif
                 });
                 });
             }
             }
 
 
@@ -289,6 +310,7 @@ namespace AZ
                     m_meshBufferIndices.RemoveEntry(meshInfo.m_bufferStartIndex);
                     m_meshBufferIndices.RemoveEntry(meshInfo.m_bufferStartIndex);
                     m_materialTextureIndices.RemoveEntry(materialInfo.m_textureStartIndex);
                     m_materialTextureIndices.RemoveEntry(materialInfo.m_textureStartIndex);
 
 
+#if !USE_BINDLESS_SRG
                     m_meshBuffers.RemoveResource(subMesh.m_indexShaderBufferView.get());
                     m_meshBuffers.RemoveResource(subMesh.m_indexShaderBufferView.get());
                     m_meshBuffers.RemoveResource(subMesh.m_positionShaderBufferView.get());
                     m_meshBuffers.RemoveResource(subMesh.m_positionShaderBufferView.get());
                     m_meshBuffers.RemoveResource(subMesh.m_normalShaderBufferView.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_metallicImageView.get());
                     m_materialTextures.RemoveResource(subMesh.m_roughnessImageView.get());
                     m_materialTextures.RemoveResource(subMesh.m_roughnessImageView.get());
                     m_materialTextures.RemoveResource(subMesh.m_emissiveImageView.get());
                     m_materialTextures.RemoveResource(subMesh.m_emissiveImageView.get());
+#endif
 
 
                     if (globalIndex < m_subMeshes.size() - 1)
                     if (globalIndex < m_subMeshes.size() - 1)
                     {
                     {
@@ -339,8 +362,10 @@ namespace AZ
                     m_meshBufferIndices.Reset();
                     m_meshBufferIndices.Reset();
                     m_materialTextureIndices.Reset();
                     m_materialTextureIndices.Reset();
 
 
+#if !USE_BINDLESS_SRG
                     m_meshBuffers.Reset();
                     m_meshBuffers.Reset();
                     m_materialTextures.Reset();
                     m_materialTextures.Reset();
+#endif
                 }
                 }
             }
             }
 
 
@@ -505,6 +530,7 @@ namespace AZ
                     currentMeshBufferIndicesGpuBuffer->Resize(newMeshBufferIndicesByteCount);
                     currentMeshBufferIndicesGpuBuffer->Resize(newMeshBufferIndicesByteCount);
                 }
                 }
 
 
+#if !USE_BINDLESS_SRG
                 // resolve to the true indices using the indirection list
                 // resolve to the true indices using the indirection list
                 // Note: this is done on the CPU to avoid double-indirection in the shader
                 // Note: this is done on the CPU to avoid double-indirection in the shader
                 IndexVector resolvedMeshBufferIndices(m_meshBufferIndices.GetIndexList().size());
                 IndexVector resolvedMeshBufferIndices(m_meshBufferIndices.GetIndexList().size());
@@ -522,6 +548,9 @@ namespace AZ
                 }
                 }
 
 
                 currentMeshBufferIndicesGpuBuffer->UpdateData(resolvedMeshBufferIndices.data(), newMeshBufferIndicesByteCount);
                 currentMeshBufferIndicesGpuBuffer->UpdateData(resolvedMeshBufferIndices.data(), newMeshBufferIndicesByteCount);
+#else
+                currentMeshBufferIndicesGpuBuffer->UpdateData(m_meshBufferIndices.GetIndexList().data(), newMeshBufferIndicesByteCount);
+#endif
 
 
                 // update material texture indices buffer
                 // update material texture indices buffer
                 Data::Instance<RPI::Buffer>& currentMaterialTextureIndicesGpuBuffer = m_materialTextureIndicesGpuBuffer[m_currentIndexListFrameIndex];
                 Data::Instance<RPI::Buffer>& currentMaterialTextureIndicesGpuBuffer = m_materialTextureIndicesGpuBuffer[m_currentIndexListFrameIndex];
@@ -544,6 +573,7 @@ namespace AZ
                     currentMaterialTextureIndicesGpuBuffer->Resize(newMaterialTextureIndicesByteCount);
                     currentMaterialTextureIndicesGpuBuffer->Resize(newMaterialTextureIndicesByteCount);
                 }
                 }
 
 
+#if !USE_BINDLESS_SRG
                 // resolve to the true indices using the indirection list
                 // resolve to the true indices using the indirection list
                 // Note: this is done on the CPU to avoid double-indirection in the shader
                 // Note: this is done on the CPU to avoid double-indirection in the shader
                 IndexVector resolvedMaterialTextureIndices(m_materialTextureIndices.GetIndexList().size());
                 IndexVector resolvedMaterialTextureIndices(m_materialTextureIndices.GetIndexList().size());
@@ -561,6 +591,9 @@ namespace AZ
                 }
                 }
 
 
                 currentMaterialTextureIndicesGpuBuffer->UpdateData(resolvedMaterialTextureIndices.data(), newMaterialTextureIndicesByteCount);
                 currentMaterialTextureIndicesGpuBuffer->UpdateData(resolvedMaterialTextureIndices.data(), newMaterialTextureIndicesByteCount);
+#else
+                currentMaterialTextureIndicesGpuBuffer->UpdateData(m_materialTextureIndices.GetIndexList().data(), newMaterialTextureIndicesByteCount);
+#endif
 
 
                 m_indexListNeedsUpdate = false;
                 m_indexListNeedsUpdate = false;
             }
             }
@@ -656,8 +689,10 @@ namespace AZ
             bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_meshBufferIndices"));
             bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_meshBufferIndices"));
             m_rayTracingSceneSrg->SetBufferView(bufferIndex, m_meshBufferIndicesGpuBuffer[m_currentIndexListFrameIndex]->GetBufferView());
             m_rayTracingSceneSrg->SetBufferView(bufferIndex, m_meshBufferIndicesGpuBuffer[m_currentIndexListFrameIndex]->GetBufferView());
 
 
+#if !USE_BINDLESS_SRG
             RHI::ShaderInputBufferUnboundedArrayIndex bufferUnboundedArrayIndex = srgLayout->FindShaderInputBufferUnboundedArrayIndex(AZ::Name("m_meshBuffers"));
             RHI::ShaderInputBufferUnboundedArrayIndex bufferUnboundedArrayIndex = srgLayout->FindShaderInputBufferUnboundedArrayIndex(AZ::Name("m_meshBuffers"));
             m_rayTracingSceneSrg->SetBufferViewUnboundedArray(bufferUnboundedArrayIndex, m_meshBuffers.GetResourceList());
             m_rayTracingSceneSrg->SetBufferViewUnboundedArray(bufferUnboundedArrayIndex, m_meshBuffers.GetResourceList());
+#endif
             m_rayTracingSceneSrg->Compile();
             m_rayTracingSceneSrg->Compile();
         }
         }
 
 
@@ -672,8 +707,10 @@ namespace AZ
             bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_materialTextureIndices"));
             bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_materialTextureIndices"));
             m_rayTracingMaterialSrg->SetBufferView(bufferIndex, m_materialTextureIndicesGpuBuffer[m_currentIndexListFrameIndex]->GetBufferView());
             m_rayTracingMaterialSrg->SetBufferView(bufferIndex, m_materialTextureIndicesGpuBuffer[m_currentIndexListFrameIndex]->GetBufferView());
 
 
+#if !USE_BINDLESS_SRG
             RHI::ShaderInputImageUnboundedArrayIndex textureUnboundedArrayIndex = srgLayout->FindShaderInputImageUnboundedArrayIndex(AZ::Name("m_materialTextures"));
             RHI::ShaderInputImageUnboundedArrayIndex textureUnboundedArrayIndex = srgLayout->FindShaderInputImageUnboundedArrayIndex(AZ::Name("m_materialTextures"));
             m_rayTracingMaterialSrg->SetImageViewUnboundedArray(textureUnboundedArrayIndex, m_materialTextures.GetResourceList());
             m_rayTracingMaterialSrg->SetImageViewUnboundedArray(textureUnboundedArrayIndex, m_materialTextures.GetResourceList());
+#endif
             m_rayTracingMaterialSrg->Compile();
             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/Color.h>
 #include <AzCore/Math/Transform.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 AZ
 {
 {
     namespace Render
     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
             // 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;
             BlasInstanceMap m_blasInstanceMap;
 
 
+#if !USE_BINDLESS_SRG
             // Mesh buffer and material texture resources are managed with a RayTracingResourceList, which contains an internal
             // 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,
             // 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.
             // 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
             // mesh buffer and material texture resource lists, accessed by the shader through an unbounded array
             RayTracingResourceList<RHI::BufferView> m_meshBuffers;
             RayTracingResourceList<RHI::BufferView> m_meshBuffers;
             RayTracingResourceList<const RHI::ImageView> m_materialTextures;
             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;
             static const uint32_t NumMeshBuffersPerMesh = 6;
             RayTracingIndexList<NumMeshBuffersPerMesh> m_meshBufferIndices;
             RayTracingIndexList<NumMeshBuffersPerMesh> m_meshBufferIndices;
 
 
             static const uint32_t NumMaterialTexturesPerMesh = 5;
             static const uint32_t NumMaterialTexturesPerMesh = 5;
             RayTracingIndexList<NumMaterialTexturesPerMesh> m_materialTextureIndices;
             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_meshBufferIndicesGpuBuffer[BufferFrameCount];
             Data::Instance<RPI::Buffer> m_materialTextureIndicesGpuBuffer[BufferFrameCount];
             Data::Instance<RPI::Buffer> m_materialTextureIndicesGpuBuffer[BufferFrameCount];
             uint32_t m_currentIndexListFrameIndex = 0;
             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());
             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;
             GpuVirtualAddress GetGpuAddress() const;
             ID3D12Resource* GetMemory() const;
             ID3D12Resource* GetMemory() const;
 
 
+            //////////////////////////////////////////////////////////////////////////
+            // RHI::BufferView
+            uint32_t GetBindlessReadIndex() const override;
+            uint32_t GetBindlessReadWriteIndex() const override;
+            //////////////////////////////////////////////////////////////////////////
+
         private:
         private:
             BufferView() = default;
             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 ShaderResourceGroup* srg = static_cast<const ShaderResourceGroup*>(dispatchRaysItem.m_shaderResourceGroups[srgIndex]);
                 const ShaderResourceGroupCompiledData& compiledData = srg->GetCompiledData();
                 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);
                     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
             // set RayTracing pipeline state
             commandList->SetPipelineState1(rayTracingPipelineState->Get());
             commandList->SetPipelineState1(rayTracingPipelineState->Get());
 
 

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

@@ -121,7 +121,9 @@ namespace AZ
             DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
             DiffuseProbeGridFeatureProcessor* diffuseProbeGridFeatureProcessor = scene->GetFeatureProcessor<DiffuseProbeGridFeatureProcessor>();
 
 
             // there are 4 submits per grid
             // 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())
             for (auto& diffuseProbeGrid : diffuseProbeGridFeatureProcessor->GetVisibleRealTimeProbeGrids())
             {
             {
@@ -162,88 +164,78 @@ namespace AZ
                 diffuseProbeGrid->GetBorderUpdateColumnIrradianceSrg()->Compile();
                 diffuseProbeGrid->GetBorderUpdateColumnIrradianceSrg()->Compile();
                 diffuseProbeGrid->GetBorderUpdateRowDistanceSrg()->Compile();
                 diffuseProbeGrid->GetBorderUpdateRowDistanceSrg()->Compile();
                 diffuseProbeGrid->GetBorderUpdateColumnDistanceSrg()->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 probeCountX;
                 uint32_t probeCountY;
                 uint32_t probeCountY;
                 diffuseProbeGrid->GetTexture2DProbeCount(probeCountX, probeCountY);
                 diffuseProbeGrid->GetTexture2DProbeCount(probeCountX, probeCountY);
 
 
                 // row irradiance
                 // 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
                 // 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
                 // 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
                 // 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 Render
 }   // namespace AZ
 }   // namespace AZ

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

@@ -44,6 +44,16 @@ namespace AZ
             void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
             void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
             void CompileResources(const RHI::FrameGraphCompileContext& context) override;
             void CompileResources(const RHI::FrameGraphCompileContext& context) override;
             void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& 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
             // shader
             Data::Instance<RPI::Shader> m_rowShader;
             Data::Instance<RPI::Shader> m_rowShader;

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

@@ -98,9 +98,9 @@ namespace AZ
             RHI::RayTracingPipelineStateDescriptor descriptor;
             RHI::RayTracingPipelineStateDescriptor descriptor;
             descriptor.Build()
             descriptor.Build()
                 ->PipelineState(m_globalPipelineState.get())
                 ->PipelineState(m_globalPipelineState.get())
-                ->MaxPayloadSize(108)
+                ->MaxPayloadSize(112)
                 ->MaxAttributeSize(32)
                 ->MaxAttributeSize(32)
-                ->MaxRecursionDepth(16)
+                ->MaxRecursionDepth(MaxRecursionDepth)
                 ->ShaderLibrary(rayGenerationShaderDescriptor)
                 ->ShaderLibrary(rayGenerationShaderDescriptor)
                     ->RayGenerationShaderName(AZ::Name("RayGen"))
                     ->RayGenerationShaderName(AZ::Name("RayGen"))
                 ->ShaderLibrary(missShaderDescriptor)
                 ->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
                     // 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)
                     // inputs (see line ValidateSetImageView() in ShaderResourceGroupData.cpp)
                     diffuseProbeGrid->UpdateRayTraceSrg(m_rayTracingShader, m_globalSrgLayout);
                     diffuseProbeGrid->UpdateRayTraceSrg(m_rayTracingShader, m_globalSrgLayout);
+
+                    diffuseProbeGrid->GetRayTraceSrg()->SetConstant(m_maxRecursionDepthNameIndex, MaxRecursionDepth);
                     diffuseProbeGrid->GetRayTraceSrg()->Compile();
                     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
             // ray tracing global shader resource group layout and pipeline state
             RHI::Ptr<RHI::ShaderResourceGroupLayout> m_globalSrgLayout;
             RHI::Ptr<RHI::ShaderResourceGroupLayout> m_globalSrgLayout;
-
             RHI::ConstPtr<RHI::PipelineState> m_globalPipelineState;
             RHI::ConstPtr<RHI::PipelineState> m_globalPipelineState;
 
 
+            RHI::ShaderInputNameIndex m_maxRecursionDepthNameIndex = "m_maxRecursionDepth";
+            static const uint32_t MaxRecursionDepth = 16;
+
             bool m_initialized = false;
             bool m_initialized = false;
         };
         };
     }   // namespace RPI
     }   // namespace RPI