Przeglądaj źródła

Add support for additional ray tracing vertex formats

Signed-off-by: Markus Prettner <[email protected]>
Markus Prettner 3 tygodni temu
rodzic
commit
e7326645bd
21 zmienionych plików z 415 dodań i 47 usunięć
  1. 19 8
      Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli
  2. 42 18
      Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli
  3. 8 7
      Gems/Atom/Feature/Common/Code/Include/Atom/Feature/RayTracing/RayTracingFeatureProcessorInterface.h
  4. 5 5
      Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp
  5. 6 0
      Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp
  6. 10 0
      Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h
  7. 0 1
      Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake
  8. 72 0
      Gems/Atom/RHI/Assets/ShaderLib/Atom/RHI/VertexFormat.azsli
  9. 10 0
      Gems/Atom/RHI/Assets/atom_rhi_asset_files.cmake
  10. 1 0
      Gems/Atom/RHI/Code/CMakeLists.txt
  11. 34 0
      Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/VertexFormat.h
  12. 2 2
      Gems/Atom/RHI/Code/Include/Atom/RHI/DeviceRayTracingAccelerationStructure.h
  13. 1 1
      Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h
  14. 63 0
      Gems/Atom/RHI/Code/Source/RHI.Reflect/VertexFormat.cpp
  15. 2 0
      Gems/Atom/RHI/Code/atom_rhi_reflect_files.cmake
  16. 1 1
      Gems/Atom/RHI/DX12/Code/Source/RHI/RayTracingBlas.cpp
  17. 1 1
      Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingBlas.cpp
  18. 134 0
      Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/VertexBufferOperations.azsli
  19. 1 0
      Gems/Atom/RPI/Assets/atom_rpi_asset_files.cmake
  20. 1 1
      Gems/DiffuseProbeGrid/Code/Source/Render/DiffuseProbeGridFeatureProcessor.cpp
  21. 2 2
      Gems/Terrain/Code/Source/TerrainRenderer/TerrainMeshManager.cpp

+ 19 - 8
Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneSrg.azsli

@@ -60,15 +60,25 @@ ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
     // mesh info structured buffer containing offsets into the mesh buffers, irradiance color, and transform for each mesh
     // mesh info structured buffer containing offsets into the mesh buffers, irradiance color, and transform for each mesh
     struct MeshInfo
     struct MeshInfo
     {
     {
-        uint     m_indexOffset;
-        uint     m_positionOffset;
-        uint     m_normalOffset;
-        uint     m_tangentOffset;
-        uint     m_bitangentOffset;
-        uint     m_uvOffset;
+        uint m_indexOffset;
+        uint m_positionOffset;
+        uint m_normalOffset;
+        uint m_tangentOffset;
+        uint m_bitangentOffset;
+        uint m_uvOffset;
+
+        uint m_positionFormat;
+        uint m_normalFormat;
+        uint m_uvFormat;
+        uint m_tangentFormat;
+        uint m_bitangentFormat;
         
         
-        uint     m_bufferFlags;
-        uint     m_bufferStartIndex;
+        uint m_bufferFlags;
+        uint m_bufferStartIndex;
+
+        uint _padding1;
+        uint _padding2;
+        uint _padding3;
 
 
         float3x4 m_worldInvTranspose;
         float3x4 m_worldInvTranspose;
     };
     };
@@ -100,6 +110,7 @@ ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
     #define MESH_BUFFER_FLAG_TANGENT        (1 << 0)
     #define MESH_BUFFER_FLAG_TANGENT        (1 << 0)
     #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)
+    #define MESH_BUFFER_UINT16_INDEX        (1 << 3)
 
 
     // Specifies which debug visualization to use (value must be from RayTracingDebugViewMode enum)
     // Specifies which debug visualization to use (value must be from RayTracingDebugViewMode enum)
     uint m_debugViewMode;
     uint m_debugViewMode;

+ 42 - 18
Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/RayTracing/RayTracingSceneUtils.azsli

@@ -7,6 +7,7 @@
  */
  */
 
 
 #include <Atom/Features/Bindless.azsli>
 #include <Atom/Features/Bindless.azsli>
+#include <Atom/RPI/VertexBufferOperations.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)
@@ -24,15 +25,28 @@ uint3 GetHitIndices(RayTracingSceneSrg::MeshInfo meshInfo)
     // get the index buffer resource index from the indirection list
     // get the index buffer resource index from the indirection list
     uint meshIndexBufferArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_INDEX_BUFFER_OFFSET)];
     uint meshIndexBufferArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_INDEX_BUFFER_OFFSET)];
 
 
+    uint indexFormatSize = meshInfo.m_bufferFlags & MESH_BUFFER_UINT16_INDEX ? 2 : 4;
+
     // compute the offset into the index buffer for this primitve of the mesh
     // compute the offset into the index buffer for this primitve of the mesh
-    uint offsetBytes = meshInfo.m_indexOffset + (PrimitiveIndex() * 12);
+    uint offsetBytes = meshInfo.m_indexOffset + (PrimitiveIndex() * 3 * indexFormatSize);
 
 
     // load the indices for this primitive from the index buffer
     // load the indices for this primitive from the index buffer
+    if (meshInfo.m_bufferFlags & MESH_BUFFER_UINT16_INDEX)
+    {
+#if USE_BINDLESS_SRG
+        return LoadUint16x3FromBufferUnaligned(Bindless::GetByteAddressBuffer(meshIndexBufferArrayIndex), offsetBytes);
+#else
+        return LoadUint16x3FromBufferUnaligned(RayTracingSceneSrg::m_meshBuffers[meshIndexBufferArrayIndex], offsetBytes);
+#endif
+    }
+    else
+    {
 #if USE_BINDLESS_SRG
 #if USE_BINDLESS_SRG
-    return Bindless::GetByteAddressBuffer(meshIndexBufferArrayIndex).Load3(offsetBytes);
+        return Bindless::GetByteAddressBuffer(meshIndexBufferArrayIndex).Load3(offsetBytes);
 #else
 #else
-    return RayTracingSceneSrg::m_meshBuffers[meshIndexBufferArrayIndex].Load3(offsetBytes);
+        return RayTracingSceneSrg::m_meshBuffers[meshIndexBufferArrayIndex].Load3(offsetBytes);
 #endif
 #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
@@ -60,84 +74,94 @@ VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, f
     {
     {
         // position
         // position
         {
         {
+            VertexFormat positionFormat = (VertexFormat)meshInfo.m_positionFormat;
+
             // array index of the position buffer for this mesh in the m_meshBuffers unbounded array
             // array index of the position buffer for this mesh in the m_meshBuffers unbounded array
             uint meshVertexPositionArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_POSITION_BUFFER_OFFSET)];
             uint meshVertexPositionArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_POSITION_BUFFER_OFFSET)];
 
 
             // offset into the position buffer for this vertex
             // offset into the position buffer for this vertex
-            uint positionOffset = meshInfo.m_positionOffset + (indices[i] * 12);
+            uint positionOffset = meshInfo.m_positionOffset + (indices[i] * GetVertexFormatSize(positionFormat));
 
 
             // load the position data
             // load the position data
 #if USE_BINDLESS_SRG
 #if USE_BINDLESS_SRG
-            vertexData.m_position += asfloat(Bindless::GetByteAddressBuffer(meshVertexPositionArrayIndex).Load3(positionOffset)) * barycentrics[i];
+            vertexData.m_position += LoadFloat3FromBuffer(Bindless::GetByteAddressBuffer(meshVertexPositionArrayIndex), positionOffset, positionFormat) * barycentrics[i];
 #else
 #else
-            vertexData.m_position += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexPositionArrayIndex].Load3(positionOffset)) * barycentrics[i];
+            vertexData.m_position += LoadFloat3FromBuffer(RayTracingSceneSrg::m_meshBuffers[meshVertexPositionArrayIndex], positionOffset, positionFormat) * barycentrics[i];
 #endif
 #endif
         }
         }
 
 
         // normal
         // normal
         {
         {
+            VertexFormat normalFormat = (VertexFormat)meshInfo.m_normalFormat;
+
             // array index of the normal buffer for this mesh in the m_meshBuffers unbounded array
             // array index of the normal buffer for this mesh in the m_meshBuffers unbounded array
             uint meshVertexNormalArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_NORMAL_BUFFER_OFFSET)];
             uint meshVertexNormalArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_NORMAL_BUFFER_OFFSET)];
 
 
             // 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] * GetVertexFormatSize(normalFormat));
 
 
              // load the normal data
              // load the normal data
 #if USE_BINDLESS_SRG
 #if USE_BINDLESS_SRG
-            vertexData.m_normal += asfloat(Bindless::GetByteAddressBuffer(meshVertexNormalArrayIndex).Load3(normalOffset)) * barycentrics[i];
+            vertexData.m_normal += LoadFloat3FromBuffer(Bindless::GetByteAddressBuffer(meshVertexNormalArrayIndex), normalOffset, normalFormat) * barycentrics[i];
 #else
 #else
-            vertexData.m_normal += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexNormalArrayIndex].Load3(normalOffset)) * barycentrics[i];
+            vertexData.m_normal += LoadFloat3FromBuffer(RayTracingSceneSrg::m_meshBuffers[meshVertexNormalArrayIndex], normalOffset, normalFormat) * barycentrics[i];
 #endif
 #endif
         }
         }
 
 
         // tangent
         // tangent
         if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_TANGENT)
         if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_TANGENT)
         {
         {
+            VertexFormat tangentFormat = (VertexFormat)meshInfo.m_tangentFormat;
+
             // array index of the tangent buffer for this mesh in the m_meshBuffers unbounded array
             // array index of the tangent buffer for this mesh in the m_meshBuffers unbounded array
             uint meshVertexTangentArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_TANGENT_BUFFER_OFFSET)];
             uint meshVertexTangentArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_TANGENT_BUFFER_OFFSET)];
 
 
             // offset into the tangent buffer for this vertex
             // offset into the tangent buffer for this vertex
-            uint tangentOffset = meshInfo.m_tangentOffset + (indices[i] * 16);
+            uint tangentOffset = meshInfo.m_tangentOffset + (indices[i] * GetVertexFormatSize(tangentFormat));
 
 
             // load the tangent data
             // load the tangent data
 #if USE_BINDLESS_SRG
 #if USE_BINDLESS_SRG
-            vertexData.m_tangent += asfloat(Bindless::GetByteAddressBuffer(meshVertexTangentArrayIndex).Load4(tangentOffset)) * barycentrics[i];
+            vertexData.m_tangent += LoadFloat4FromBuffer(Bindless::GetByteAddressBuffer(meshVertexTangentArrayIndex), tangentOffset, tangentFormat) * barycentrics[i];
 #else
 #else
-            vertexData.m_tangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexTangentArrayIndex].Load4(tangentOffset)) * barycentrics[i];
+            vertexData.m_tangent += LoadFloat4FromBuffer(RayTracingSceneSrg::m_meshBuffers[meshVertexTangentArrayIndex], tangentOffset, tangentFormat) * barycentrics[i];
 #endif
 #endif
         }
         }
 
 
         // bitangent
         // bitangent
         if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_BITANGENT)
         if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_BITANGENT)
         {
         {
+            VertexFormat bitangentFormat = (VertexFormat)meshInfo.m_bitangentFormat;
+
             // array index of the bitangent buffer for this mesh in the m_meshBuffers unbounded array
             // array index of the bitangent buffer for this mesh in the m_meshBuffers unbounded array
             uint meshVertexBitangentArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_BITANGENT_BUFFER_OFFSET)];
             uint meshVertexBitangentArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_BITANGENT_BUFFER_OFFSET)];
 
 
             // offset into the bitangent buffer for this vertex
             // offset into the bitangent buffer for this vertex
-            uint bitangentOffset = meshInfo.m_bitangentOffset + (indices[i] * 12);
+            uint bitangentOffset = meshInfo.m_bitangentOffset + (indices[i] * GetVertexFormatSize(bitangentFormat));
 
 
             // load the bitangent data
             // load the bitangent data
 #if USE_BINDLESS_SRG
 #if USE_BINDLESS_SRG
-            vertexData.m_bitangent += asfloat(Bindless::GetByteAddressBuffer(meshVertexBitangentArrayIndex).Load3(bitangentOffset)) * barycentrics[i];
+            vertexData.m_bitangent += LoadFloat3FromBuffer(Bindless::GetByteAddressBuffer(meshVertexBitangentArrayIndex), bitangentOffset, bitangentFormat) * barycentrics[i];
 #else
 #else
-            vertexData.m_bitangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexBitangentArrayIndex].Load3(bitangentOffset)) * barycentrics[i];
+            vertexData.m_bitangent += LoadFloat3FromBuffer(RayTracingSceneSrg::m_meshBuffers[meshVertexBitangentArrayIndex], bitangentOffset, bitangentFormat) * barycentrics[i];
 #endif
 #endif
         }
         }
 
 
         // UV
         // UV
         if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_UV)
         if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_UV)
         {
         {
+            VertexFormat uvFormat = (VertexFormat)meshInfo.m_uvFormat;
+
             // array index of the UV buffer for this mesh in the m_meshBuffers unbounded array
             // array index of the UV buffer for this mesh in the m_meshBuffers unbounded array
             uint meshVertexUVArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_UV_BUFFER_OFFSET)];   
             uint meshVertexUVArrayIndex = RayTracingSceneSrg::m_meshBufferIndices[NonUniformResourceIndex(meshInfo.m_bufferStartIndex + MESH_UV_BUFFER_OFFSET)];   
 
 
             // offset into the UV buffer for this vertex
             // offset into the UV buffer for this vertex
-            uint uvOffset = meshInfo.m_uvOffset + (indices[i] * 8);    
+            uint uvOffset = meshInfo.m_uvOffset + (indices[i] * GetVertexFormatSize(uvFormat));
     
     
             // load the UV data
             // load the UV data
 #if USE_BINDLESS_SRG
 #if USE_BINDLESS_SRG
-            vertexData.m_uv += asfloat(Bindless::GetByteAddressBuffer(meshVertexUVArrayIndex).Load2(uvOffset)) * barycentrics[i];
+            vertexData.m_uv += LoadFloat2FromBuffer(Bindless::GetByteAddressBuffer(meshVertexUVArrayIndex), uvOffset, uvFormat) * barycentrics[i];
 #else
 #else
-            vertexData.m_uv += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexUVArrayIndex].Load2(uvOffset)) * barycentrics[i];
+            vertexData.m_uv += LoadFloat2FromBuffer(RayTracingSceneSrg::m_meshBuffers[meshVertexUVArrayIndex], uvOffset, uvFormat) * barycentrics[i];
 #endif
 #endif
         }
         }
     }
     }

+ 8 - 7
Gems/Atom/Feature/Common/Code/Include/Atom/Feature/RayTracing/RayTracingFeatureProcessorInterface.h

@@ -11,6 +11,7 @@
 #include <Atom/Feature/RayTracing/RayTracingIndexList.h>
 #include <Atom/Feature/RayTracing/RayTracingIndexList.h>
 #include <Atom/RHI/RayTracingAccelerationStructure.h>
 #include <Atom/RHI/RayTracingAccelerationStructure.h>
 #include <Atom/RHI/RayTracingCompactionQueryPool.h>
 #include <Atom/RHI/RayTracingCompactionQueryPool.h>
+#include <Atom/RHI.Reflect/VertexFormat.h>
 #include <Atom/RPI.Public/Buffer/Buffer.h>
 #include <Atom/RPI.Public/Buffer/Buffer.h>
 #include <Atom/RPI.Public/FeatureProcessor.h>
 #include <Atom/RPI.Public/FeatureProcessor.h>
 #include <Atom/RPI.Public/GpuQuery/Query.h>
 #include <Atom/RPI.Public/GpuQuery/Query.h>
@@ -32,7 +33,8 @@ namespace AZ::Render
 
 
         Tangent = AZ_BIT(0),
         Tangent = AZ_BIT(0),
         Bitangent = AZ_BIT(1),
         Bitangent = AZ_BIT(1),
-        UV = AZ_BIT(2)
+        UV = AZ_BIT(2),
+        Uint16Index = AZ_BIT(3),
     };
     };
     AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::Render::RayTracingSubMeshBufferFlags);
     AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::Render::RayTracingSubMeshBufferFlags);
 
 
@@ -82,24 +84,23 @@ namespace AZ::Render
         struct SubMesh
         struct SubMesh
         {
         {
             // vertex streams
             // vertex streams
-            RHI::Format m_positionFormat = RHI::Format::Unknown;
-
+            RHI::VertexFormat m_positionFormat = RHI::VertexFormat::Unknown;
             RHI::StreamBufferView m_positionVertexBufferView;
             RHI::StreamBufferView m_positionVertexBufferView;
             RHI::Ptr<RHI::BufferView> m_positionShaderBufferView;
             RHI::Ptr<RHI::BufferView> m_positionShaderBufferView;
 
 
-            RHI::Format m_normalFormat = RHI::Format::Unknown;
+            RHI::VertexFormat m_normalFormat = RHI::VertexFormat::Unknown;
             RHI::StreamBufferView m_normalVertexBufferView;
             RHI::StreamBufferView m_normalVertexBufferView;
             RHI::Ptr<RHI::BufferView> m_normalShaderBufferView;
             RHI::Ptr<RHI::BufferView> m_normalShaderBufferView;
 
 
-            RHI::Format m_tangentFormat = RHI::Format::Unknown;
+            RHI::VertexFormat m_tangentFormat = RHI::VertexFormat::Unknown;
             RHI::StreamBufferView m_tangentVertexBufferView;
             RHI::StreamBufferView m_tangentVertexBufferView;
             RHI::Ptr<RHI::BufferView> m_tangentShaderBufferView;
             RHI::Ptr<RHI::BufferView> m_tangentShaderBufferView;
 
 
-            RHI::Format m_bitangentFormat = RHI::Format::Unknown;
+            RHI::VertexFormat m_bitangentFormat = RHI::VertexFormat::Unknown;
             RHI::StreamBufferView m_bitangentVertexBufferView;
             RHI::StreamBufferView m_bitangentVertexBufferView;
             RHI::Ptr<RHI::BufferView> m_bitangentShaderBufferView;
             RHI::Ptr<RHI::BufferView> m_bitangentShaderBufferView;
 
 
-            RHI::Format m_uvFormat = RHI::Format::Unknown;
+            RHI::VertexFormat m_uvFormat = RHI::VertexFormat::Unknown;
             RHI::StreamBufferView m_uvVertexBufferView;
             RHI::StreamBufferView m_uvVertexBufferView;
             RHI::Ptr<RHI::BufferView> m_uvShaderBufferView;
             RHI::Ptr<RHI::BufferView> m_uvShaderBufferView;
 
 

+ 5 - 5
Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp

@@ -2421,12 +2421,12 @@ namespace AZ
                 // set the SubMesh data to pass to the RayTracingFeatureProcessor, starting with vertex/index data
                 // set the SubMesh data to pass to the RayTracingFeatureProcessor, starting with vertex/index data
                 RayTracingFeatureProcessor::SubMesh subMesh;
                 RayTracingFeatureProcessor::SubMesh subMesh;
                 RayTracingFeatureProcessor::SubMeshMaterial& subMeshMaterial = subMesh.m_material;
                 RayTracingFeatureProcessor::SubMeshMaterial& subMeshMaterial = subMesh.m_material;
-                subMesh.m_positionFormat = PositionStreamFormat;
+                subMesh.m_positionFormat = RHI::ConvertToVertexFormat(PositionStreamFormat);
                 subMesh.m_positionVertexBufferView = streamIter[0];
                 subMesh.m_positionVertexBufferView = streamIter[0];
                 subMesh.m_positionShaderBufferView =
                 subMesh.m_positionShaderBufferView =
                     const_cast<RHI::Buffer*>(streamIter[0].GetBuffer())->GetBufferView(positionBufferDescriptor);
                     const_cast<RHI::Buffer*>(streamIter[0].GetBuffer())->GetBufferView(positionBufferDescriptor);
 
 
-                subMesh.m_normalFormat = NormalStreamFormat;
+                subMesh.m_normalFormat = RHI::ConvertToVertexFormat(NormalStreamFormat);
                 subMesh.m_normalVertexBufferView = streamIter[1];
                 subMesh.m_normalVertexBufferView = streamIter[1];
                 subMesh.m_normalShaderBufferView =
                 subMesh.m_normalShaderBufferView =
                     const_cast<RHI::Buffer*>(streamIter[1].GetBuffer())->GetBufferView(normalBufferDescriptor);
                     const_cast<RHI::Buffer*>(streamIter[1].GetBuffer())->GetBufferView(normalBufferDescriptor);
@@ -2434,7 +2434,7 @@ namespace AZ
                 if (tangentBufferByteCount > 0)
                 if (tangentBufferByteCount > 0)
                 {
                 {
                     subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::Tangent;
                     subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::Tangent;
-                    subMesh.m_tangentFormat = TangentStreamFormat;
+                    subMesh.m_tangentFormat = RHI::ConvertToVertexFormat(TangentStreamFormat);
                     subMesh.m_tangentVertexBufferView = streamIter[2];
                     subMesh.m_tangentVertexBufferView = streamIter[2];
                     subMesh.m_tangentShaderBufferView =
                     subMesh.m_tangentShaderBufferView =
                         const_cast<RHI::Buffer*>(streamIter[2].GetBuffer())->GetBufferView(tangentBufferDescriptor);
                         const_cast<RHI::Buffer*>(streamIter[2].GetBuffer())->GetBufferView(tangentBufferDescriptor);
@@ -2443,7 +2443,7 @@ namespace AZ
                 if (bitangentBufferByteCount > 0)
                 if (bitangentBufferByteCount > 0)
                 {
                 {
                     subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::Bitangent;
                     subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::Bitangent;
-                    subMesh.m_bitangentFormat = BitangentStreamFormat;
+                    subMesh.m_bitangentFormat = RHI::ConvertToVertexFormat(BitangentStreamFormat);
                     subMesh.m_bitangentVertexBufferView = streamIter[3];
                     subMesh.m_bitangentVertexBufferView = streamIter[3];
                     subMesh.m_bitangentShaderBufferView =
                     subMesh.m_bitangentShaderBufferView =
                         const_cast<RHI::Buffer*>(streamIter[3].GetBuffer())->GetBufferView(bitangentBufferDescriptor);
                         const_cast<RHI::Buffer*>(streamIter[3].GetBuffer())->GetBufferView(bitangentBufferDescriptor);
@@ -2452,7 +2452,7 @@ namespace AZ
                 if (uvBufferByteCount > 0)
                 if (uvBufferByteCount > 0)
                 {
                 {
                     subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::UV;
                     subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::UV;
-                    subMesh.m_uvFormat = UVStreamFormat;
+                    subMesh.m_uvFormat = RHI::ConvertToVertexFormat(UVStreamFormat);
                     subMesh.m_uvVertexBufferView = streamIter[4];
                     subMesh.m_uvVertexBufferView = streamIter[4];
                     subMesh.m_uvShaderBufferView = const_cast<RHI::Buffer*>(streamIter[4].GetBuffer())->GetBufferView(uvBufferDescriptor);
                     subMesh.m_uvShaderBufferView = const_cast<RHI::Buffer*>(streamIter[4].GetBuffer())->GetBufferView(uvBufferDescriptor);
                 }
                 }

+ 6 - 0
Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp

@@ -462,6 +462,12 @@ namespace AZ
                         subMesh.m_bitangentShaderBufferView ? subMesh.m_bitangentVertexBufferView.GetByteOffset() : 0;
                         subMesh.m_bitangentShaderBufferView ? subMesh.m_bitangentVertexBufferView.GetByteOffset() : 0;
                     meshInfo.m_uvByteOffset = subMesh.m_uvShaderBufferView ? subMesh.m_uvVertexBufferView.GetByteOffset() : 0;
                     meshInfo.m_uvByteOffset = subMesh.m_uvShaderBufferView ? subMesh.m_uvVertexBufferView.GetByteOffset() : 0;
 
 
+                    meshInfo.m_positionFormat = subMesh.m_positionFormat;
+                    meshInfo.m_normalFormat = subMesh.m_normalFormat;
+                    meshInfo.m_uvFormat = subMesh.m_uvFormat;
+                    meshInfo.m_tangentFormat = subMesh.m_tangentFormat;
+                    meshInfo.m_bitangentFormat = subMesh.m_bitangentFormat;
+
                     auto& materialInfos{ m_materialInfos[deviceIndex] };
                     auto& materialInfos{ m_materialInfos[deviceIndex] };
                     MaterialInfo& materialInfo = materialInfos[subMesh.m_globalIndex];
                     MaterialInfo& materialInfo = materialInfos[subMesh.m_globalIndex];
                     ConvertMaterial(materialInfo, subMesh.m_material, deviceIndex);
                     ConvertMaterial(materialInfo, subMesh.m_material, deviceIndex);

+ 10 - 0
Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h

@@ -192,9 +192,19 @@ namespace AZ
                 uint32_t m_bitangentByteOffset = 0;
                 uint32_t m_bitangentByteOffset = 0;
                 uint32_t m_uvByteOffset = 0;
                 uint32_t m_uvByteOffset = 0;
 
 
+                RHI::VertexFormat m_positionFormat;
+                RHI::VertexFormat m_normalFormat;
+                RHI::VertexFormat m_uvFormat;
+                RHI::VertexFormat m_tangentFormat;
+                RHI::VertexFormat m_bitangentFormat;
+
                 RayTracingSubMeshBufferFlags m_bufferFlags = RayTracingSubMeshBufferFlags::None;
                 RayTracingSubMeshBufferFlags m_bufferFlags = RayTracingSubMeshBufferFlags::None;
                 uint32_t m_bufferStartIndex = 0;
                 uint32_t m_bufferStartIndex = 0;
 
 
+                uint32_t _padding1;
+                uint32_t _padding2;
+                uint32_t _padding3;
+
                 AZStd::array<float, 12> m_worldInvTranspose; // float3x4
                 AZStd::array<float, 12> m_worldInvTranspose; // float3x4
             };
             };
 
 

+ 0 - 1
Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake

@@ -113,7 +113,6 @@ set(FILES
     Include/Atom/Feature/RayTracing/RayTracingPass.h
     Include/Atom/Feature/RayTracing/RayTracingPass.h
     Include/Atom/Feature/RayTracing/RayTracingPassData.h
     Include/Atom/Feature/RayTracing/RayTracingPassData.h
     Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h
     Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h
-    Include/Atom/Feature/ReflectionProbe/ReflectionProbeFeatureProcessorInterface.h
     Include/Atom/Feature/RenderCommon.h
     Include/Atom/Feature/RenderCommon.h
     Include/Atom/Feature/ScreenSpace/DeferredFogParams.inl
     Include/Atom/Feature/ScreenSpace/DeferredFogParams.inl
     Include/Atom/Feature/ScreenSpace/DeferredFogSettingsInterface.h
     Include/Atom/Feature/ScreenSpace/DeferredFogSettingsInterface.h

+ 72 - 0
Gems/Atom/RHI/Assets/ShaderLib/Atom/RHI/VertexFormat.azsli

@@ -0,0 +1,72 @@
+/*
+ * 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
+
+#if !defined(VertexFormatEnumType)
+#define VertexFormatEnumType
+#endif
+
+enum class VertexFormat VertexFormatEnumType
+{
+    Unknown = 0,
+
+    R32G32B32A32_FLOAT,
+    R16G16B16A16_FLOAT,
+
+    R32G32B32_FLOAT,
+    R16G16B16_FLOAT,
+
+    R32G32_FLOAT,
+    R16G16_FLOAT,
+    R8G8_UNORM,
+
+    N32_OCT, // 32 bit octahedron-encoded normal (15-15-1)
+    N16_OCT, // 16 bit octahedron-encoded normal (7-7-1)
+    N8_OCT, // 8 bit octahedron-encoded normal (3-3-1)
+
+    T32_OCT, // 32 bit octahedron-encoded tangent (15-15-1-1)
+    T16_OCT, // 16 bit octahedron-encoded tangent (7-7-1-1)
+    T8_OCT, // 8 bit octahedron-encoded tangent (3-3-1-1)
+};
+
+inline uint GetVertexFormatSize(VertexFormat format)
+{
+    switch (format)
+    {
+    case VertexFormat::R32G32B32A32_FLOAT:
+        return 16;
+
+    case VertexFormat::R32G32B32_FLOAT:
+        return 12;
+
+    case VertexFormat::R32G32_FLOAT:
+    case VertexFormat::R16G16B16A16_FLOAT:
+        return 8;
+
+    case VertexFormat::R16G16B16_FLOAT:
+        return 6;
+
+    case VertexFormat::R16G16_FLOAT:
+    case VertexFormat::N32_OCT:
+    case VertexFormat::T32_OCT:
+        return 4;
+
+    case VertexFormat::R8G8_UNORM:
+    case VertexFormat::N16_OCT:
+    case VertexFormat::T16_OCT:
+        return 2;
+
+    case VertexFormat::N8_OCT:
+    case VertexFormat::T8_OCT:
+        return 1;
+
+    default:
+        return 0;
+    }
+}

+ 10 - 0
Gems/Atom/RHI/Assets/atom_rhi_asset_files.cmake

@@ -0,0 +1,10 @@
+# 
+# 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 
+# 
+
+set(FILES
+    ShaderLib/Atom/RHI/VertexFormat.azsli
+)

+ 1 - 0
Gems/Atom/RHI/Code/CMakeLists.txt

@@ -103,6 +103,7 @@ ly_add_target(
     NAMESPACE Gem
     NAMESPACE Gem
     FILES_CMAKE
     FILES_CMAKE
         atom_rhi_public_files.cmake
         atom_rhi_public_files.cmake
+        ../Assets/atom_rhi_asset_files.cmake
         ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
         ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
     INCLUDE_DIRECTORIES
     INCLUDE_DIRECTORIES
         PRIVATE
         PRIVATE

+ 34 - 0
Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/VertexFormat.h

@@ -0,0 +1,34 @@
+/*
+ * 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 <Atom/RHI.Reflect/Format.h>
+
+namespace AZ::RHI
+{
+    // Use "Internal" namespace to avoid exposing "using uint..." to the AZ::RHI namespace
+    namespace Internal
+    {
+        using uint = uint32_t;
+#define VertexFormatEnumType : uint32_t
+#include "../../../RHI/Assets/ShaderLib/Atom/RHI/VertexFormat.azsli"
+#undef VertexFormatEnumType
+    } // namespace Internal
+
+    using VertexFormat = Internal::VertexFormat;
+
+    //! @brief Returns the size of the given vertex format in bytes.
+    uint32_t GetVertexFormatSize(VertexFormat vertexFormat);
+
+    //! @brief Converts the given image format to a VertexFormat or asserts if no such conversion is possible
+    VertexFormat ConvertToVertexFormat(RHI::Format format);
+
+    //! @brief Converts the given VertexFormat to an image format or asserts if no such conversion is possible
+    RHI::Format ConvertToImageFormat(VertexFormat vertexFormat);
+} // namespace AZ::RHI

+ 2 - 2
Gems/Atom/RHI/Code/Include/Atom/RHI/DeviceRayTracingAccelerationStructure.h

@@ -12,7 +12,7 @@
 #include <AzCore/Math/Transform.h>
 #include <AzCore/Math/Transform.h>
 #include <Atom/RHI/DeviceIndexBufferView.h>
 #include <Atom/RHI/DeviceIndexBufferView.h>
 #include <Atom/RHI/DeviceStreamBufferView.h>
 #include <Atom/RHI/DeviceStreamBufferView.h>
-#include <Atom/RHI.Reflect/Format.h>
+#include <Atom/RHI.Reflect/VertexFormat.h>
 #include <Atom/RHI/DeviceObject.h>
 #include <Atom/RHI/DeviceObject.h>
 
 
 namespace AZ::RHI
 namespace AZ::RHI
@@ -62,7 +62,7 @@ namespace AZ::RHI
     //! scene.  Each DeviceRayTracingBlas contains a list of these entries.
     //! scene.  Each DeviceRayTracingBlas contains a list of these entries.
     struct DeviceRayTracingGeometry
     struct DeviceRayTracingGeometry
     {
     {
-        RHI::Format m_vertexFormat = RHI::Format::Unknown;
+        RHI::VertexFormat m_vertexFormat = RHI::VertexFormat::Unknown;
         RHI::DeviceStreamBufferView m_vertexBuffer;
         RHI::DeviceStreamBufferView m_vertexBuffer;
         RHI::DeviceIndexBufferView m_indexBuffer;
         RHI::DeviceIndexBufferView m_indexBuffer;
         // [GFX TODO][ATOM-4989] Add DXR BLAS Transform Buffer
         // [GFX TODO][ATOM-4989] Add DXR BLAS Transform Buffer

+ 1 - 1
Gems/Atom/RHI/Code/Include/Atom/RHI/RayTracingAccelerationStructure.h

@@ -28,7 +28,7 @@ namespace AZ::RHI
     //! scene.  Each RayTracingBlas contains a list of these entries.
     //! scene.  Each RayTracingBlas contains a list of these entries.
     struct RayTracingGeometry
     struct RayTracingGeometry
     {
     {
-        RHI::Format m_vertexFormat = RHI::Format::Unknown;
+        RHI::VertexFormat m_vertexFormat = RHI::VertexFormat::Unknown;
         RHI::StreamBufferView m_vertexBuffer;
         RHI::StreamBufferView m_vertexBuffer;
         RHI::IndexBufferView m_indexBuffer;
         RHI::IndexBufferView m_indexBuffer;
     };
     };

+ 63 - 0
Gems/Atom/RHI/Code/Source/RHI.Reflect/VertexFormat.cpp

@@ -0,0 +1,63 @@
+/*
+ * 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 <Atom/RHI.Reflect/VertexFormat.h>
+
+namespace AZ::RHI
+{
+    uint32_t GetVertexFormatSize(VertexFormat vertexFormat)
+    {
+        uint32_t vertexFormatSize{ Internal::GetVertexFormatSize(vertexFormat) };
+        AZ_Assert(vertexFormatSize != 0, "Failed to get size of vertex format %d", vertexFormat);
+        return vertexFormatSize;
+    }
+
+    VertexFormat ConvertToVertexFormat(RHI::Format format)
+    {
+        switch (format)
+        {
+        case RHI::Format::R32G32B32A32_FLOAT:
+            return VertexFormat::R32G32B32A32_FLOAT;
+        case RHI::Format::R32G32B32_FLOAT:
+            return VertexFormat::R32G32B32_FLOAT;
+        case RHI::Format::R32G32_FLOAT:
+            return VertexFormat::R32G32_FLOAT;
+        case RHI::Format::R16G16B16A16_FLOAT:
+            return VertexFormat::R16G16B16A16_FLOAT;
+        case RHI::Format::R16G16_FLOAT:
+            return VertexFormat::R16G16_FLOAT;
+        case RHI::Format::R8G8_UNORM:
+            return VertexFormat::R8G8_UNORM;
+        default:
+            AZ_Assert(false, "Failed to convert format %s to vertex format", RHI::ToString(format));
+            return VertexFormat::Unknown;
+        }
+    }
+
+    RHI::Format ConvertToImageFormat(VertexFormat vertexFormat)
+    {
+        switch (vertexFormat)
+        {
+        case VertexFormat::R32G32B32A32_FLOAT:
+            return Format::R32G32B32A32_FLOAT;
+        case VertexFormat::R32G32B32_FLOAT:
+            return Format::R32G32B32_FLOAT;
+        case VertexFormat::R32G32_FLOAT:
+            return Format::R32G32_FLOAT;
+        case VertexFormat::R16G16B16A16_FLOAT:
+            return Format::R16G16B16A16_FLOAT;
+        case VertexFormat::R16G16_FLOAT:
+            return Format::R16G16_FLOAT;
+        case VertexFormat::R8G8_UNORM:
+            return Format::R8G8_UNORM;
+        default:
+            AZ_Assert(false, "Failed to convert vertex format %d to image format", vertexFormat);
+            return Format::Unknown;
+        }
+    }
+} // namespace AZ::RHI

+ 2 - 0
Gems/Atom/RHI/Code/atom_rhi_reflect_files.cmake

@@ -132,4 +132,6 @@ set(FILES
     Source/RHI.Reflect/ShaderInputNameIndex.cpp
     Source/RHI.Reflect/ShaderInputNameIndex.cpp
     Include/Atom/RHI.Reflect/VariableRateShadingEnums.h
     Include/Atom/RHI.Reflect/VariableRateShadingEnums.h
     Include/Atom/RHI.Reflect/Allocators.h
     Include/Atom/RHI.Reflect/Allocators.h
+    Include/Atom/RHI.Reflect/VertexFormat.h
+    Source/RHI.Reflect/VertexFormat.cpp
 )
 )

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

@@ -91,7 +91,7 @@ namespace AZ
                     geometryDesc.Triangles.VertexBuffer.StartAddress = static_cast<const DX12::Buffer*>(geometry.m_vertexBuffer.GetBuffer())->GetMemoryView().GetGpuAddress() + geometry.m_vertexBuffer.GetByteOffset();
                     geometryDesc.Triangles.VertexBuffer.StartAddress = static_cast<const DX12::Buffer*>(geometry.m_vertexBuffer.GetBuffer())->GetMemoryView().GetGpuAddress() + geometry.m_vertexBuffer.GetByteOffset();
                     geometryDesc.Triangles.VertexBuffer.StrideInBytes = geometry.m_vertexBuffer.GetByteStride();
                     geometryDesc.Triangles.VertexBuffer.StrideInBytes = geometry.m_vertexBuffer.GetByteStride();
                     geometryDesc.Triangles.VertexCount = geometry.m_vertexBuffer.GetByteCount() / aznumeric_cast<UINT>(geometryDesc.Triangles.VertexBuffer.StrideInBytes);
                     geometryDesc.Triangles.VertexCount = geometry.m_vertexBuffer.GetByteCount() / aznumeric_cast<UINT>(geometryDesc.Triangles.VertexBuffer.StrideInBytes);
-                    geometryDesc.Triangles.VertexFormat = ConvertFormat(geometry.m_vertexFormat);
+                    geometryDesc.Triangles.VertexFormat = ConvertFormat(RHI::ConvertToImageFormat(geometry.m_vertexFormat));
                     geometryDesc.Triangles.IndexBuffer = static_cast<const DX12::Buffer*>(geometry.m_indexBuffer.GetBuffer())->GetMemoryView().GetGpuAddress() + geometry.m_indexBuffer.GetByteOffset();
                     geometryDesc.Triangles.IndexBuffer = static_cast<const DX12::Buffer*>(geometry.m_indexBuffer.GetBuffer())->GetMemoryView().GetGpuAddress() + geometry.m_indexBuffer.GetByteOffset();
                     geometryDesc.Triangles.IndexFormat = (geometry.m_indexBuffer.GetIndexFormat() == RHI::IndexFormat::Uint16) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
                     geometryDesc.Triangles.IndexFormat = (geometry.m_indexBuffer.GetIndexFormat() == RHI::IndexFormat::Uint16) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
                     geometryDesc.Triangles.IndexCount = aznumeric_cast<UINT>(geometry.m_indexBuffer.GetByteCount()) / ((geometry.m_indexBuffer.GetIndexFormat() == RHI::IndexFormat::Uint16) ? 2 : 4);
                     geometryDesc.Triangles.IndexCount = aznumeric_cast<UINT>(geometry.m_indexBuffer.GetByteCount()) / ((geometry.m_indexBuffer.GetIndexFormat() == RHI::IndexFormat::Uint16) ? 2 : 4);

+ 1 - 1
Gems/Atom/RHI/Vulkan/Code/Source/RHI/RayTracingBlas.cpp

@@ -128,7 +128,7 @@ namespace AZ
                         geometry.m_vertexBuffer.GetByteOffset();
                         geometry.m_vertexBuffer.GetByteOffset();
                     geometryDesc.geometry.triangles.vertexStride = geometry.m_vertexBuffer.GetByteStride();
                     geometryDesc.geometry.triangles.vertexStride = geometry.m_vertexBuffer.GetByteStride();
                     geometryDesc.geometry.triangles.maxVertex = geometry.m_vertexBuffer.GetByteCount() / aznumeric_cast<uint32_t>(geometryDesc.geometry.triangles.vertexStride);
                     geometryDesc.geometry.triangles.maxVertex = geometry.m_vertexBuffer.GetByteCount() / aznumeric_cast<uint32_t>(geometryDesc.geometry.triangles.vertexStride);
-                    geometryDesc.geometry.triangles.vertexFormat = ConvertFormat(geometry.m_vertexFormat);
+                    geometryDesc.geometry.triangles.vertexFormat = ConvertFormat(RHI::ConvertToImageFormat(geometry.m_vertexFormat));
 
 
                     addressInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
                     addressInfo.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
                     addressInfo.pNext = nullptr;
                     addressInfo.pNext = nullptr;

+ 134 - 0
Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/VertexBufferOperations.azsli

@@ -0,0 +1,134 @@
+/*
+ * 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 <Atom/RPI/Math.azsli>
+#include <Atom/RHI/VertexFormat.azsli>
+
+uint LoadUint8FromBufferUnaligned(ByteAddressBuffer buffer, uint byteOffset)
+{
+    uint value = buffer.Load(byteOffset & ~0x3);
+    value >>= (byteOffset & 0x3) * 8;
+    value &= 0xFF;
+    return value;
+}
+
+uint LoadUint16FromBufferUnaligned(ByteAddressBuffer buffer, uint byteOffset)
+{
+    uint value = buffer.Load(byteOffset & ~0x3);
+    value >>= (byteOffset & 0x3) * 8;
+    value &= 0xFFFF;
+    return value;
+}
+
+uint3 LoadUint16x3FromBufferUnaligned(ByteAddressBuffer buffer, uint byteOffset)
+{
+    uint2 value = buffer.Load2(byteOffset & ~0x3);
+    if (byteOffset % 4 != 0)
+    {
+        value.x >>= 16;
+        value.x |= (value.y & 0xFFFF) << 16;
+        value.y >>= 16;
+    }
+    return uint3(value.x & 0xFFFF, value.x >> 16, value.y & 0xFFFF);
+}
+
+float2 LoadFloat16x2FromBuffer(ByteAddressBuffer buffer, uint byteOffset)
+{
+    uint valuePacked = buffer.Load(byteOffset);
+    return float2(
+        f16tof32(valuePacked.x & 0xFFFF),
+        f16tof32(valuePacked.x >> 16));
+}
+
+float2 LoadUnorm8x2FromBufferUnaligned(ByteAddressBuffer buffer, uint byteOffset)
+{
+    uint valuePacked = LoadUint16FromBufferUnaligned(buffer, byteOffset);
+    return float2(
+        (float)(valuePacked & 0xFF) / 0xFF,
+        (float)((valuePacked >> 8) & 0xFF) / 0xFF);
+}
+
+float3 LoadFloat16x3FromBufferUnaligned(ByteAddressBuffer buffer, uint byteOffset)
+{
+    uint3 valuePacked = LoadUint16x3FromBufferUnaligned(buffer, byteOffset);
+    return float3(
+        f16tof32(valuePacked.x),
+        f16tof32(valuePacked.y),
+        f16tof32(valuePacked.z));
+}
+
+float4 LoadFloat16x4FromBuffer(ByteAddressBuffer buffer, uint byteOffset)
+{
+    uint2 valuePacked = buffer.Load2(byteOffset);
+    return float4(
+        f16tof32(valuePacked.x & 0xFFFF),
+        f16tof32(valuePacked.x >> 16),
+        f16tof32(valuePacked.y & 0xFFFF),
+        f16tof32(valuePacked.y >> 16));
+}
+
+float3 DecodeNormalPackedOctahedron(uint encodedPackedValue, uint xyBits)
+{
+    uint mask = (1u << xyBits) - 1;
+    float3 encodedNormal = float3(
+        (float)(encodedPackedValue & mask) / mask,
+        (float)((encodedPackedValue >> xyBits) & mask) / mask,
+        (float)((encodedPackedValue >> (xyBits * 2)) & 1));
+    return DecodeNormalSignedOctahedron(encodedNormal);
+}
+
+float2 LoadFloat2FromBuffer(ByteAddressBuffer buffer, uint byteOffset, VertexFormat format)
+{
+    switch (format)
+    {
+    case VertexFormat::R32G32_FLOAT:
+        return asfloat(buffer.Load2(byteOffset));
+    case VertexFormat::R16G16_FLOAT:
+        return LoadFloat16x2FromBuffer(buffer, byteOffset);
+    case VertexFormat::R8G8_UNORM:
+        return LoadUnorm8x2FromBufferUnaligned(buffer, byteOffset);
+    default:
+        return float2(0.f, 0.f);
+    }
+}
+
+float3 LoadFloat3FromBuffer(ByteAddressBuffer buffer, uint byteOffset, VertexFormat format)
+{
+    switch (format)
+    {
+    case VertexFormat::R32G32B32_FLOAT:
+        return asfloat(buffer.Load3(byteOffset));
+    case VertexFormat::R16G16B16_FLOAT:
+        return LoadFloat16x3FromBufferUnaligned(buffer, byteOffset);
+    case VertexFormat::R16G16B16A16_FLOAT:
+        return LoadFloat16x4FromBuffer(buffer, byteOffset).xyz;
+    case VertexFormat::N32_OCT:
+        return DecodeNormalPackedOctahedron(buffer.Load(byteOffset), 15);
+    case VertexFormat::N16_OCT:
+        return DecodeNormalPackedOctahedron(LoadUint16FromBufferUnaligned(buffer, byteOffset), 7);
+    case VertexFormat::N8_OCT:
+        return DecodeNormalPackedOctahedron(LoadUint8FromBufferUnaligned(buffer, byteOffset), 3);
+    default:
+        return float3(0.f, 0.f, 0.f);
+    }
+}
+
+float4 LoadFloat4FromBuffer(ByteAddressBuffer buffer, uint byteOffset, VertexFormat format)
+{
+    switch (format)
+    {
+    case VertexFormat::R32G32B32A32_FLOAT:
+        return asfloat(buffer.Load4(byteOffset));
+    case VertexFormat::R16G16B16A16_FLOAT:
+        return LoadFloat16x4FromBuffer(buffer, byteOffset);
+    default:
+        return float4(0.f, 0.f, 0.f, 0.f);
+    }
+}

+ 1 - 0
Gems/Atom/RPI/Assets/atom_rpi_asset_files.cmake

@@ -10,6 +10,7 @@ set(FILES
     ShaderLib/Atom/RPI/DummyEntryFunctions.azsli
     ShaderLib/Atom/RPI/DummyEntryFunctions.azsli
     ShaderLib/Atom/RPI/Math.azsli
     ShaderLib/Atom/RPI/Math.azsli
     ShaderLib/Atom/RPI/TangentSpace.azsli
     ShaderLib/Atom/RPI/TangentSpace.azsli
+    ShaderLib/Atom/RPI/VertexBufferOperations.azsli
     ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli
     ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli
     ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultSceneSrg.azsli
     ShaderLib/Atom/RPI/ShaderResourceGroups/DefaultSceneSrg.azsli
     ShaderLib/Atom/RPI/ShaderResourceGroups/UnusedFallbackDrawSrg.azsli
     ShaderLib/Atom/RPI/ShaderResourceGroups/UnusedFallbackDrawSrg.azsli

+ 1 - 1
Gems/DiffuseProbeGrid/Code/Source/Render/DiffuseProbeGridFeatureProcessor.cpp

@@ -1046,7 +1046,7 @@ namespace AZ
             // create the BLAS object
             // create the BLAS object
             RHI::RayTracingBlasDescriptor blasDescriptor;
             RHI::RayTracingBlasDescriptor blasDescriptor;
             RHI::RayTracingGeometry& blasGeometry = blasDescriptor.m_geometries.emplace_back();
             RHI::RayTracingGeometry& blasGeometry = blasDescriptor.m_geometries.emplace_back();
-            blasGeometry.m_vertexFormat = PositionStreamFormat;
+            blasGeometry.m_vertexFormat = RHI::ConvertToVertexFormat(PositionStreamFormat);
             blasGeometry.m_vertexBuffer = m_visualizationVB;
             blasGeometry.m_vertexBuffer = m_visualizationVB;
             blasGeometry.m_indexBuffer = m_visualizationIB;
             blasGeometry.m_indexBuffer = m_visualizationIB;
 
 

+ 2 - 2
Gems/Terrain/Code/Source/TerrainRenderer/TerrainMeshManager.cpp

@@ -406,10 +406,10 @@ namespace Terrain
             meshGroup.m_submeshVector.clear();
             meshGroup.m_submeshVector.clear();
             AZ::Render::RayTracingFeatureProcessorInterface::SubMesh& subMesh = meshGroup.m_submeshVector.emplace_back();
             AZ::Render::RayTracingFeatureProcessorInterface::SubMesh& subMesh = meshGroup.m_submeshVector.emplace_back();
 
 
-            subMesh.m_positionFormat = positionsBufferFormat;
+            subMesh.m_positionFormat = AZ::RHI::ConvertToVertexFormat(positionsBufferFormat);
             subMesh.m_positionVertexBufferView = positionsVertexBufferView;
             subMesh.m_positionVertexBufferView = positionsVertexBufferView;
             subMesh.m_positionShaderBufferView = rhiPositionsBuffer.GetBufferView(positionsBufferDescriptor);
             subMesh.m_positionShaderBufferView = rhiPositionsBuffer.GetBufferView(positionsBufferDescriptor);
-            subMesh.m_normalFormat = normalsBufferFormat;
+            subMesh.m_normalFormat = AZ::RHI::ConvertToVertexFormat(normalsBufferFormat);
             subMesh.m_normalVertexBufferView = normalsVertexBufferView;
             subMesh.m_normalVertexBufferView = normalsVertexBufferView;
             subMesh.m_normalShaderBufferView = rhiNormalsBuffer.GetBufferView(normalsBufferDescriptor);
             subMesh.m_normalShaderBufferView = rhiNormalsBuffer.GetBufferView(normalsBufferDescriptor);
             subMesh.m_indexBufferView = AZ::RHI::IndexBufferView(rhiIndexBuffer, indexBufferByteOffset, indexBufferByteCount, indexBufferFormat);
             subMesh.m_indexBufferView = AZ::RHI::IndexBufferView(rhiIndexBuffer, indexBufferByteOffset, indexBufferByteCount, indexBufferFormat);