Added RayTracingMaterialSrg.

Added UV buffer to the RayTracingSceneSrg mesh buffers.
Added RayTracingSceneUtils and RayTracingMaterialUtils shader includes.
main
Doug McDiarmid 5 years ago
parent c29c1825cb
commit 40435fcb2e

@ -0,0 +1,48 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/Features/SrgSemantics.azsli>
ShaderResourceGroup RayTracingMaterialSrg : SRG_RayTracingMaterial
{
Sampler LinearSampler
{
AddressU = Wrap;
AddressV = Wrap;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
MaxAnisotropy = 16;
};
// material info structured buffer
struct MaterialInfo
{
float4 m_baseColor;
float m_metallicFactor;
float m_roughnessFactor;
uint m_textureFlags;
uint m_textureStartIndex;
};
// hit shaders can retrieve the MaterialInfo for a mesh hit using: RayTracingMaterialSrg::m_materialInfo[InstanceIndex()]
StructuredBuffer<MaterialInfo> m_materialInfo;
// texture flag bits indicating if optional textures are present
#define TEXTURE_FLAG_BASECOLOR 1
#define TEXTURE_FLAG_NORMAL 2
#define TEXTURE_FLAG_METALLIC 4
#define TEXTURE_FLAG_ROUGHNESS 8
// unbounded array of Material textures
Texture2D m_materialTextures[];
}

@ -0,0 +1,69 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
struct TextureData
{
float4 m_baseColor;
float3 m_normal;
float m_metallic;
float m_roughness;
};
TextureData GetHitTextureData(RayTracingMaterialSrg::MaterialInfo materialInfo, float2 uv)
{
TextureData textureData = (TextureData)0;
uint textureIndex = materialInfo.m_textureStartIndex;
// base color
if (materialInfo.m_textureFlags & TEXTURE_FLAG_BASECOLOR)
{
textureData.m_baseColor = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
}
else
{
textureData.m_baseColor = materialInfo.m_baseColor;
}
// normal
if (materialInfo.m_textureFlags & TEXTURE_FLAG_NORMAL)
{
textureData.m_normal = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
}
else
{
textureData.m_normal = float3(0.0f, 0.0f, 1.0f);
}
// metallic
if (materialInfo.m_textureFlags & TEXTURE_FLAG_METALLIC)
{
textureData.m_metallic = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
}
else
{
textureData.m_metallic = materialInfo.m_metallicFactor;
}
// roughness
if (materialInfo.m_textureFlags & TEXTURE_FLAG_ROUGHNESS)
{
textureData.m_roughness = RayTracingMaterialSrg::m_materialTextures[textureIndex++].SampleLevel(RayTracingMaterialSrg::LinearSampler, uv, 0);
}
else
{
textureData.m_roughness = materialInfo.m_roughnessFactor;
}
return textureData;
}

@ -136,18 +136,35 @@ ShaderResourceGroup RayTracingSceneSrg : SRG_RayTracingScene
uint m_indexOffset;
uint m_positionOffset;
uint m_normalOffset;
uint m_tangentOffset;
uint m_bitangentOffset;
uint m_uvOffset;
float m_padding0[2];
float4 m_irradianceColor;
float3x3 m_worldInvTranspose;
float m_padding1[1];
uint m_bufferFlags;
uint m_bufferStartIndex;
};
// hit shaders can retrieve the MeshInfo for a mesh hit using: RayTracingSceneSrg::m_meshInfo[InstanceIndex()]
StructuredBuffer<MeshInfo> m_meshInfo;
// unbounded array of Index, VertexPosition, and VertexNormal buffers
// each mesh has three entries in this array starting at its InstanceIndex() * BUFFER_COUNT_PER_MESH
#define BUFFER_COUNT_PER_MESH 3
#define MESH_INDEX_BUFFER_OFFSET 0
#define MESH_POSITION_BUFFER_OFFSET 1
#define MESH_NORMAL_BUFFER_OFFSET 2
// buffer array index offsets for buffers that are always present for each mesh
#define MESH_INDEX_BUFFER_OFFSET 0
#define MESH_POSITION_BUFFER_OFFSET 1
#define MESH_NORMAL_BUFFER_OFFSET 2
#define MESH_TANGENT_BUFFER_OFFSET 3
#define MESH_BITANGENT_BUFFER_OFFSET 4
// buffer flag bits indicating if optional buffers are present
#define MESH_BUFFER_FLAG_UV 1
// Unbounded array of mesh stream buffers:
// - Index, Position, Normal, Tangent, and Bitangent stream buffers are always present
// - Optional stream buffers such as UV are indicated in the MeshInfo.m_bufferFlags field
// - Buffers for a particular mesh start at MeshInfo.m_bufferStartIndex
ByteAddressBuffer m_meshBuffers[];
}

@ -0,0 +1,126 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// returns the normalized camera view ray into the scene for this raytracing dispatch thread
float3 GetViewRayDirection(float4x4 viewProjectionInverseMatrix)
{
float2 pixel = ((float2)DispatchRaysIndex().xy + float2(0.5f, 0.5f)) / (float2)DispatchRaysDimensions();
float2 ndc = pixel * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f);
return normalize(mul(viewProjectionInverseMatrix, float4(ndc, 0.0f, 1.0f)).xyz);
}
// returns the vertex indices for the primitive hit by the ray
// Note: usable only in a raytracing Hit shader
uint3 GetHitIndices(RayTracingSceneSrg::MeshInfo meshInfo)
{
// compute the array index of the index buffer for this mesh in the m_meshBuffers unbounded array
uint meshIndexBufferArrayIndex = meshInfo.m_bufferStartIndex + MESH_INDEX_BUFFER_OFFSET;
// compute the offset into the index buffer for this primitve of the mesh
uint offsetBytes = meshInfo.m_indexOffset + (PrimitiveIndex() * 12);
// load the indices for this primitive from the index buffer
return RayTracingSceneSrg::m_meshBuffers[meshIndexBufferArrayIndex].Load3(offsetBytes);
}
// returns the interpolated vertex data for the primitive hit by the ray
// Note: usable only in a raytracing hit shader
struct VertexData
{
float3 m_position;
float3 m_normal;
float3 m_tangent;
float3 m_bitangent;
float2 m_uv;
};
VertexData GetHitInterpolatedVertexData(RayTracingSceneSrg::MeshInfo meshInfo, float2 builtInBarycentrics)
{
// retrieve the poly indices
uint3 indices = GetHitIndices(meshInfo);
// compute barycentrics
float3 barycentrics = float3((1.0f - builtInBarycentrics.x - builtInBarycentrics.y), builtInBarycentrics.x, builtInBarycentrics.y);
// compute the vertex data using barycentric interpolation
VertexData vertexData = (VertexData)0;
for (uint i = 0; i < 3; ++i)
{
// position
{
// array index of the position buffer for this mesh in the m_meshBuffers unbounded array
uint meshVertexPositionArrayIndex = meshInfo.m_bufferStartIndex + MESH_POSITION_BUFFER_OFFSET;
// offset into the position buffer for this vertex
uint positionOffset = meshInfo.m_positionOffset + (indices[i] * 12);
// load the position data
vertexData.m_position += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexPositionArrayIndex].Load3(positionOffset)) * barycentrics[i];
}
// normal
{
// array index of the normal buffer for this mesh in the m_meshBuffers unbounded array
uint meshVertexNormalArrayIndex = meshInfo.m_bufferStartIndex + MESH_NORMAL_BUFFER_OFFSET;
// offset into the normal buffer for this vertex
uint normalOffset = meshInfo.m_normalOffset + (indices[i] * 12);
// load the normal data
vertexData.m_normal += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexNormalArrayIndex].Load3(normalOffset)) * barycentrics[i];
}
// tangent
{
// array index of the tangent buffer for this mesh in the m_meshBuffers unbounded array
uint meshVertexTangentArrayIndex = meshInfo.m_bufferStartIndex + MESH_TANGENT_BUFFER_OFFSET;
// offset into the tangent buffer for this vertex
uint tangentOffset = meshInfo.m_tangentOffset + (indices[i] * 12);
// load the tangent data
vertexData.m_tangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexTangentArrayIndex].Load3(tangentOffset)) * barycentrics[i];
}
// bitangent
{
// array index of the bitangent buffer for this mesh in the m_meshBuffers unbounded array
uint meshVertexBitangentArrayIndex = meshInfo.m_bufferStartIndex + MESH_BITANGENT_BUFFER_OFFSET;
// offset into the bitangent buffer for this vertex
uint bitangentOffset = meshInfo.m_bitangentOffset + (indices[i] * 12);
// load the bitangent data
vertexData.m_bitangent += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexBitangentArrayIndex].Load3(bitangentOffset)) * barycentrics[i];
}
// optional streams begin after MESH_BITANGENT_BUFFER_OFFSET
uint optionalBufferOffset = MESH_BITANGENT_BUFFER_OFFSET + 1;
// UV
if (meshInfo.m_bufferFlags & MESH_BUFFER_FLAG_UV)
{
// array index of the UV buffer for this mesh in the m_meshBuffers unbounded array
uint meshVertexUVArrayIndex = meshInfo.m_bufferStartIndex + optionalBufferOffset++;
// offset into the UV buffer for this vertex
uint uvOffset = meshInfo.m_uvOffset + (indices[i] * 8);
// load the UV data
vertexData.m_uv += asfloat(RayTracingSceneSrg::m_meshBuffers[meshVertexUVArrayIndex].Load2(uvOffset)) * barycentrics[i];
}
}
vertexData.m_normal = normalize(vertexData.m_normal);
return vertexData;
}

@ -64,3 +64,8 @@ ShaderResourceGroupSemantic SRG_RayTracingScene
{
FrequencyId = 1;
};
ShaderResourceGroupSemantic SRG_RayTracingMaterial
{
FrequencyId = 2;
};

@ -44,8 +44,14 @@
"field": "element",
"typeName": "ShaderResourceGroupLayout",
"typeId": "{1F92C651-9B83-4379-AB5C-5201F1B2C278}",
"version": 6,
"version": 7,
"Objects": [
{
"field": "m_name",
"typeName": "Name",
"typeId": "{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}",
"value": ""
},
{
"field": "m_staticSamplers",
"typeName": "AZStd::vector",
@ -3338,8 +3344,14 @@
"field": "element",
"typeName": "ShaderResourceGroupLayout",
"typeId": "{1F92C651-9B83-4379-AB5C-5201F1B2C278}",
"version": 6,
"version": 7,
"Objects": [
{
"field": "m_name",
"typeName": "Name",
"typeId": "{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}",
"value": ""
},
{
"field": "m_staticSamplers",
"typeName": "AZStd::vector",
@ -6632,8 +6644,14 @@
"field": "element",
"typeName": "ShaderResourceGroupLayout",
"typeId": "{1F92C651-9B83-4379-AB5C-5201F1B2C278}",
"version": 6,
"version": 7,
"Objects": [
{
"field": "m_name",
"typeName": "Name",
"typeId": "{3D2B920C-9EFD-40D5-AAE0-DF131C3D4931}",
"value": ""
},
{
"field": "m_staticSamplers",
"typeName": "AZStd::vector",

@ -710,27 +710,53 @@ namespace AZ
uint32_t rayTracingLod = aznumeric_cast<uint32_t>(modelLods.size() - 1);
const Data::Instance<RPI::ModelLod>& modelLod = modelLods[rayTracingLod];
// setup a stream layout and shader input contract for the position and normal streams
// setup a stream layout and shader input contract for the vertex streams
static const char* PositionSemantic = "POSITION";
static const char* NormalSemantic = "NORMAL";
static const RHI::Format StreamFormat = RHI::Format::R32G32B32_FLOAT;
static const char* TangentSemantic = "TANGENT";
static const char* BitangentSemantic = "BITANGENT";
static const char* UVSemantic = "UV";
static const RHI::Format PositionStreamFormat = RHI::Format::R32G32B32_FLOAT;
static const RHI::Format NormalStreamFormat = RHI::Format::R32G32B32_FLOAT;
static const RHI::Format TangentStreamFormat = RHI::Format::R32G32B32_FLOAT;
static const RHI::Format BitangentStreamFormat = RHI::Format::R32G32B32_FLOAT;
static const RHI::Format UVStreamFormat = RHI::Format::R32G32_FLOAT;
RHI::InputStreamLayoutBuilder layoutBuilder;
layoutBuilder.AddBuffer()->Channel(PositionSemantic, StreamFormat);
layoutBuilder.AddBuffer()->Channel(NormalSemantic, StreamFormat);
layoutBuilder.AddBuffer()->Channel(PositionSemantic, PositionStreamFormat);
layoutBuilder.AddBuffer()->Channel(NormalSemantic, NormalStreamFormat);
layoutBuilder.AddBuffer()->Channel(UVSemantic, UVStreamFormat);
layoutBuilder.AddBuffer()->Channel(TangentSemantic, TangentStreamFormat);
layoutBuilder.AddBuffer()->Channel(BitangentSemantic, BitangentStreamFormat);
RHI::InputStreamLayout inputStreamLayout = layoutBuilder.End();
RPI::ShaderInputContract::StreamChannelInfo positionStreamChannelInfo;
positionStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(PositionSemantic));
positionStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(StreamFormat);
positionStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(PositionStreamFormat);
RPI::ShaderInputContract::StreamChannelInfo normalStreamChannelInfo;
normalStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(NormalSemantic));
normalStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(StreamFormat);
normalStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(NormalStreamFormat);
RPI::ShaderInputContract::StreamChannelInfo tangentStreamChannelInfo;
tangentStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(TangentSemantic));
tangentStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(TangentStreamFormat);
RPI::ShaderInputContract::StreamChannelInfo bitangentStreamChannelInfo;
bitangentStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(BitangentSemantic));
bitangentStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(BitangentStreamFormat);
RPI::ShaderInputContract::StreamChannelInfo uvStreamChannelInfo;
uvStreamChannelInfo.m_semantic = RHI::ShaderSemantic(AZ::Name(UVSemantic));
uvStreamChannelInfo.m_componentCount = RHI::GetFormatComponentCount(UVStreamFormat);
uvStreamChannelInfo.m_isOptional = true;
RPI::ShaderInputContract shaderInputContract;
shaderInputContract.m_streamChannels.emplace_back(positionStreamChannelInfo);
shaderInputContract.m_streamChannels.emplace_back(normalStreamChannelInfo);
shaderInputContract.m_streamChannels.emplace_back(tangentStreamChannelInfo);
shaderInputContract.m_streamChannels.emplace_back(bitangentStreamChannelInfo);
shaderInputContract.m_streamChannels.emplace_back(uvStreamChannelInfo);
// setup the raytracing data for each sub-mesh
const size_t meshCount = modelLod->GetMeshes().size();
@ -739,16 +765,44 @@ namespace AZ
{
const RPI::ModelLod::Mesh& mesh = modelLod->GetMeshes()[meshIndex];
// retrieve the material
Data::Instance<RPI::Material> material = mesh.m_material;
const MaterialAssignmentId materialAssignmentId(rayTracingLod, material ? material->GetAssetId() : AZ::Data::AssetId());
const MaterialAssignment& materialAssignment = GetMaterialAssignmentFromMapWithFallback(m_materialAssignments, materialAssignmentId);
if (materialAssignment.m_materialInstance.get())
{
material = materialAssignment.m_materialInstance;
}
// retrieve vertex/index buffers
RPI::ModelLod::StreamBufferViewList streamBufferViews;
[[maybe_unused]] bool result = modelLod->GetStreamsForMesh(inputStreamLayout, streamBufferViews, shaderInputContract, meshIndex);
[[maybe_unused]] bool result = modelLod->GetStreamsForMesh(
inputStreamLayout,
streamBufferViews,
shaderInputContract,
meshIndex,
materialAssignment.m_matModUvOverrides,
material->GetAsset()->GetMaterialTypeAsset()->GetUvNameMap());
AZ_Assert(result, "Failed to retrieve mesh stream buffer views");
// note that the element count is the size of the entire buffer, even though this mesh may only
// occupy a portion of the vertex buffer. This is necessary since we are accessing it using
// a ByteAddressBuffer in the raytracing shaders and passing the byte offset to the shader in a constant buffer.
uint32_t vertexBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetDescriptor().m_byteCount;
RHI::BufferViewDescriptor vertexBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, vertexBufferByteCount);
uint32_t positionBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetDescriptor().m_byteCount;
RHI::BufferViewDescriptor positionBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, positionBufferByteCount);
uint32_t normalBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[1].GetBuffer())->GetDescriptor().m_byteCount;
RHI::BufferViewDescriptor normalBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, normalBufferByteCount);
uint32_t tangentBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[2].GetBuffer())->GetDescriptor().m_byteCount;
RHI::BufferViewDescriptor tangentBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tangentBufferByteCount);
uint32_t bitangentBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[3].GetBuffer())->GetDescriptor().m_byteCount;
RHI::BufferViewDescriptor bitangentBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, bitangentBufferByteCount);
uint32_t uvBufferByteCount = const_cast<RHI::Buffer*>(streamBufferViews[4].GetBuffer())->GetDescriptor().m_byteCount;
RHI::BufferViewDescriptor uvBufferDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, uvBufferByteCount);
const RHI::IndexBufferView& indexBufferView = mesh.m_indexBufferView;
uint32_t indexElementSize = indexBufferView.GetIndexFormat() == RHI::IndexFormat::Uint16 ? 2 : 4;
@ -759,41 +813,124 @@ namespace AZ
indexBufferDescriptor.m_elementSize = indexElementSize;
indexBufferDescriptor.m_elementFormat = indexBufferView.GetIndexFormat() == RHI::IndexFormat::Uint16 ? RHI::Format::R16_UINT : RHI::Format::R32_UINT;
// retrieve the material
Data::Instance<RPI::Material> material = mesh.m_material;
// set the SubMesh data to pass to the RayTracingFeatureProcessor, starting with vertex/index data
RayTracingFeatureProcessor::SubMesh subMesh;
subMesh.m_positionFormat = PositionStreamFormat;
subMesh.m_positionVertexBufferView = streamBufferViews[0];
subMesh.m_positionShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetBufferView(positionBufferDescriptor);
const MaterialAssignmentId materialAssignmentId(rayTracingLod, material ? material->GetAssetId() : AZ::Data::AssetId());
const MaterialAssignment& materialAssignment = GetMaterialAssignmentFromMapWithFallback(m_materialAssignments, materialAssignmentId);
if (materialAssignment.m_materialInstance.get())
subMesh.m_normalFormat = NormalStreamFormat;
subMesh.m_normalVertexBufferView = streamBufferViews[1];
subMesh.m_normalShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[1].GetBuffer())->GetBufferView(normalBufferDescriptor);
subMesh.m_tangentFormat = TangentStreamFormat;
subMesh.m_tangentVertexBufferView = streamBufferViews[2];
subMesh.m_tangentShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[2].GetBuffer())->GetBufferView(tangentBufferDescriptor);
subMesh.m_bitangentFormat = BitangentStreamFormat;
subMesh.m_bitangentVertexBufferView = streamBufferViews[3];
subMesh.m_bitangentShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[3].GetBuffer())->GetBufferView(bitangentBufferDescriptor);
if (uvBufferByteCount > 0)
{
material = materialAssignment.m_materialInstance;
subMesh.m_bufferFlags |= RayTracingSubMeshBufferFlags::UV;
subMesh.m_uvFormat = UVStreamFormat;
subMesh.m_uvVertexBufferView = streamBufferViews[4];
subMesh.m_uvShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[4].GetBuffer())->GetBufferView(uvBufferDescriptor);
}
AZ::Color irradianceColor(1.0f, 1.0f, 1.0f, 1.0f);
subMesh.m_indexBufferView = mesh.m_indexBufferView;
subMesh.m_indexShaderBufferView = const_cast<RHI::Buffer*>(mesh.m_indexBufferView.GetBuffer())->GetBufferView(indexBufferDescriptor);
// add material data
if (material)
{
// irradiance color
RPI::MaterialPropertyIndex propertyIndex = material->FindPropertyIndex(AZ::Name("irradiance.color"));
if (propertyIndex.IsValid())
{
irradianceColor = material->GetPropertyValue<AZ::Color>(propertyIndex);
subMesh.m_irradianceColor = material->GetPropertyValue<AZ::Color>(propertyIndex);
}
propertyIndex = material->FindPropertyIndex(AZ::Name("irradiance.factor"));
if (propertyIndex.IsValid())
{
irradianceColor *= material->GetPropertyValue<float>(propertyIndex);
subMesh.m_irradianceColor *= material->GetPropertyValue<float>(propertyIndex);
}
// base color
propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.color"));
if (propertyIndex.IsValid())
{
subMesh.m_baseColor = material->GetPropertyValue<AZ::Color>(propertyIndex);
}
propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.factor"));
if (propertyIndex.IsValid())
{
subMesh.m_baseColor *= material->GetPropertyValue<float>(propertyIndex);
}
// metallic
propertyIndex = material->FindPropertyIndex(AZ::Name("metallic.factor"));
if (propertyIndex.IsValid())
{
subMesh.m_metallicFactor = material->GetPropertyValue<float>(propertyIndex);
}
// roughness
propertyIndex = material->FindPropertyIndex(AZ::Name("roughness.factor"));
if (propertyIndex.IsValid())
{
subMesh.m_roughnessFactor = material->GetPropertyValue<float>(propertyIndex);
}
// textures
propertyIndex = material->FindPropertyIndex(AZ::Name("baseColor.textureMap"));
if (propertyIndex.IsValid())
{
Data::Instance<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(propertyIndex);
if (image.get())
{
subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::BaseColor;
subMesh.m_baseColorImageView = image->GetImageView();
}
}
propertyIndex = material->FindPropertyIndex(AZ::Name("normal.textureMap"));
if (propertyIndex.IsValid())
{
Data::Instance<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(propertyIndex);
if (image.get())
{
subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::Normal;
subMesh.m_normalImageView = image->GetImageView();
}
}
propertyIndex = material->FindPropertyIndex(AZ::Name("metallic.textureMap"));
if (propertyIndex.IsValid())
{
Data::Instance<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(propertyIndex);
if (image.get())
{
subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::Metallic;
subMesh.m_metallicImageView = image->GetImageView();
}
}
propertyIndex = material->FindPropertyIndex(AZ::Name("roughness.textureMap"));
if (propertyIndex.IsValid())
{
Data::Instance<RPI::Image> image = material->GetPropertyValue<Data::Instance<RPI::Image>>(propertyIndex);
if (image.get())
{
subMesh.m_textureFlags |= RayTracingSubMeshTextureFlags::Roughness;
subMesh.m_roughnessImageView = image->GetImageView();
}
}
}
RayTracingFeatureProcessor::SubMesh subMesh;
subMesh.m_vertexFormat = StreamFormat;
subMesh.m_positionVertexBufferView = streamBufferViews[0];
subMesh.m_positionShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[0].GetBuffer())->GetBufferView(vertexBufferDescriptor);
subMesh.m_normalVertexBufferView = streamBufferViews[1];
subMesh.m_normalShaderBufferView = const_cast<RHI::Buffer*>(streamBufferViews[1].GetBuffer())->GetBufferView(vertexBufferDescriptor);
subMesh.m_indexBufferView = mesh.m_indexBufferView;
subMesh.m_indexShaderBufferView = const_cast<RHI::Buffer*>(mesh.m_indexBufferView.GetBuffer())->GetBufferView(indexBufferDescriptor);
subMesh.m_irradianceColor = irradianceColor;
subMeshes.push_back(subMesh);
}

@ -115,11 +115,11 @@ namespace AZ
}
}
// update and compile the RayTracingSceneSrg
// update and compile the RayTracingSceneSrg and RayTracingMaterialSrg
// Note: the timing of this update is very important, it needs to be updated after the TLAS is allocated so it can
// be set on the RayTracingSceneSrg for this frame, and the ray tracing mesh data in the RayTracingSceneSrg must
// exactly match the TLAS. Any mismatch in this data may result in a TDR.
rayTracingFeatureProcessor->UpdateRayTracingSceneSrg();
rayTracingFeatureProcessor->UpdateRayTracingSrgs();
}
}

@ -71,6 +71,13 @@ namespace AZ
AZ_Assert(rayTracingSceneSrgAsset.IsReady(), "Failed to load RayTracingSceneSrg asset");
m_rayTracingSceneSrg = RPI::ShaderResourceGroup::Create(rayTracingSceneSrgAsset);
// load the RayTracingMaterialSrg asset
Data::Asset<RPI::ShaderResourceGroupAsset> rayTracingMaterialSrgAsset =
RPI::AssetUtils::LoadAssetByProductPath<RPI::ShaderResourceGroupAsset>("shaderlib/atom/features/raytracing/raytracingmaterialsrg_raytracingmaterialsrg.azsrg", RPI::AssetUtils::TraceLevel::Error);
AZ_Assert(rayTracingMaterialSrgAsset.IsReady(), "Failed to load RayTracingMaterialSrg asset");
m_rayTracingMaterialSrg = RPI::ShaderResourceGroup::Create(rayTracingMaterialSrgAsset);
}
void RayTracingFeatureProcessor::SetMesh(const ObjectId objectId, const SubMeshVector& subMeshes)
@ -104,7 +111,7 @@ namespace AZ
RHI::RayTracingBlasDescriptor blasDescriptor;
blasDescriptor.Build()
->Geometry()
->VertexFormat(subMesh.m_vertexFormat)
->VertexFormat(subMesh.m_positionFormat)
->VertexBuffer(subMesh.m_positionVertexBufferView)
->IndexBuffer(subMesh.m_indexBufferView)
;
@ -124,6 +131,7 @@ namespace AZ
m_subMeshCount += aznumeric_cast<uint32_t>(subMeshes.size());
m_meshInfoBufferNeedsUpdate = true;
m_materialInfoBufferNeedsUpdate = true;
}
void RayTracingFeatureProcessor::RemoveMesh(const ObjectId objectId)
@ -142,6 +150,7 @@ namespace AZ
}
m_meshInfoBufferNeedsUpdate = true;
m_materialInfoBufferNeedsUpdate = true;
}
void RayTracingFeatureProcessor::SetMeshTransform(const ObjectId objectId, const AZ::Transform transform, const AZ::Vector3 nonUniformScale)
@ -162,14 +171,14 @@ namespace AZ
m_meshInfoBufferNeedsUpdate = true;
}
void RayTracingFeatureProcessor::UpdateRayTracingSceneSrg()
void RayTracingFeatureProcessor::UpdateRayTracingSrgs()
{
if (!m_tlas->GetTlasBuffer())
{
return;
}
if (m_rayTracingSceneSrg->IsQueuedForCompile())
if (m_rayTracingSceneSrg->IsQueuedForCompile() || m_rayTracingMaterialSrg->IsQueuedForCompile())
{
//[GFX TODO][ATOM-14792] AtomSampleViewer: Reset scene and feature processors before switching to sample
return;
@ -178,7 +187,144 @@ namespace AZ
// update the mesh info buffer with the latest ray tracing enabled meshes
UpdateMeshInfoBuffer();
// update the material info buffer with the latest ray tracing enabled meshes
UpdateMaterialInfoBuffer();
// update the RayTracingSceneSrg
UpdateRayTracingSceneSrg();
// update the RayTracingMaterialSrg
UpdateRayTracingMaterialSrg();
}
void RayTracingFeatureProcessor::UpdateMeshInfoBuffer()
{
if (m_meshInfoBufferNeedsUpdate && (m_subMeshCount > 0))
{
TransformServiceFeatureProcessor* transformFeatureProcessor = GetParentScene()->GetFeatureProcessor<TransformServiceFeatureProcessor>();
AZStd::vector<MeshInfo> meshInfos;
meshInfos.reserve(m_subMeshCount);
uint32_t newMeshByteCount = m_subMeshCount * sizeof(MeshInfo);
if (m_meshInfoBuffer == nullptr)
{
// allocate the MeshInfo structured buffer
RPI::CommonBufferDescriptor desc;
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
desc.m_bufferName = "RayTracingMeshInfo";
desc.m_byteCount = newMeshByteCount;
desc.m_elementSize = sizeof(MeshInfo);
m_meshInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
}
else if (m_meshInfoBuffer->GetBufferSize() < newMeshByteCount)
{
// resize for the new sub-mesh count
m_meshInfoBuffer->Resize(newMeshByteCount);
}
// keep track of the start index of the buffers for each mesh, this is put into the MeshInfo
// entry for each mesh so it knows where to find the start of its buffers in the unbounded array
uint32_t bufferStartIndex = 0;
for (const auto& mesh : m_meshes)
{
AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first));
AZ::Transform noScaleTransform = meshTransform;
noScaleTransform.ExtractScale();
AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform);
rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose();
const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes;
for (const auto& subMesh : subMeshes)
{
MeshInfo meshInfo;
meshInfo.m_indexOffset = subMesh.m_indexBufferView.GetByteOffset();
meshInfo.m_positionOffset = subMesh.m_positionVertexBufferView.GetByteOffset();
meshInfo.m_normalOffset = subMesh.m_normalVertexBufferView.GetByteOffset();
meshInfo.m_tangentOffset = subMesh.m_tangentVertexBufferView.GetByteOffset();
meshInfo.m_bitangentOffset = subMesh.m_bitangentVertexBufferView.GetByteOffset();
if (RHI::CheckBitsAll(subMesh.m_bufferFlags, RayTracingSubMeshBufferFlags::UV))
{
meshInfo.m_uvOffset = subMesh.m_uvVertexBufferView.GetByteOffset();
}
subMesh.m_irradianceColor.StoreToFloat4(meshInfo.m_irradianceColor.data());
rotationMatrix.StoreToRowMajorFloat9(meshInfo.m_worldInvTranspose.data());
meshInfo.m_bufferFlags = subMesh.m_bufferFlags;
meshInfo.m_bufferStartIndex = bufferStartIndex;
// add the count of buffers present in this subMesh to the start index for the next subMesh
// note that the Index, Position, Normal, Tangent, and Bitangent buffers are always counted since they are guaranteed
static const uint32_t RayTracingSubMeshFixedStreamCount = 5;
bufferStartIndex += (RayTracingSubMeshFixedStreamCount + RHI::CountBitsSet(aznumeric_cast<uint32_t>(meshInfo.m_bufferFlags)));
meshInfos.emplace_back(meshInfo);
}
}
m_meshInfoBuffer->UpdateData(meshInfos.data(), newMeshByteCount);
m_meshInfoBufferNeedsUpdate = false;
}
}
void RayTracingFeatureProcessor::UpdateMaterialInfoBuffer()
{
if (m_materialInfoBufferNeedsUpdate && (m_subMeshCount > 0))
{
AZStd::vector<MaterialInfo> materialInfos;
materialInfos.reserve(m_subMeshCount);
uint32_t newMaterialByteCount = m_subMeshCount * sizeof(MaterialInfo);
if (m_materialInfoBuffer == nullptr)
{
// allocate the MaterialInfo structured buffer
RPI::CommonBufferDescriptor desc;
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
desc.m_bufferName = "RayTracingMaterialInfo";
desc.m_byteCount = newMaterialByteCount;
desc.m_elementSize = sizeof(MaterialInfo);
m_materialInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
}
else if (m_materialInfoBuffer->GetBufferSize() < newMaterialByteCount)
{
// resize for the new sub-mesh count
m_materialInfoBuffer->Resize(newMaterialByteCount);
}
// keep track of the start index of the textures for each mesh, this is put into the MaterialInfo
// entry for each mesh so it knows where to find the start of its textures in the unbounded array
uint32_t textureStartIndex = 0;
for (const auto& mesh : m_meshes)
{
const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes;
for (const auto& subMesh : subMeshes)
{
MaterialInfo materialInfo;
subMesh.m_baseColor.StoreToFloat4(materialInfo.m_baseColor.data());
materialInfo.m_metallicFactor = subMesh.m_metallicFactor;
materialInfo.m_roughnessFactor = subMesh.m_roughnessFactor;
materialInfo.m_textureFlags = subMesh.m_textureFlags;
materialInfo.m_textureStartIndex = textureStartIndex;
// add the count of textures present in this subMesh to the start index for the next subMesh
textureStartIndex += RHI::CountBitsSet(aznumeric_cast<uint32_t>(materialInfo.m_textureFlags));
materialInfos.emplace_back(materialInfo);
}
}
m_materialInfoBuffer->UpdateData(materialInfos.data(), newMaterialByteCount);
m_materialInfoBufferNeedsUpdate = false;
}
}
void RayTracingFeatureProcessor::UpdateRayTracingSceneSrg()
{
const RHI::ShaderResourceGroupLayout* srgLayout = m_rayTracingSceneSrg->GetLayout();
RHI::ShaderInputImageIndex imageIndex;
RHI::ShaderInputBufferIndex bufferIndex;
@ -272,11 +418,18 @@ namespace AZ
const SubMeshVector& subMeshes = mesh.second.m_subMeshes;
for (const auto& subMesh : subMeshes)
{
// add the index, position, and normal buffers for this sub-mesh to the mesh buffer list, this will
// go into the shader as an unbounded array in the Srg
// add the stream buffers for this sub-mesh to the mesh buffer list,
// this is sent to the shader as an unbounded array in the Srg
meshBuffers.push_back(subMesh.m_indexShaderBufferView.get());
meshBuffers.push_back(subMesh.m_positionShaderBufferView.get());
meshBuffers.push_back(subMesh.m_normalShaderBufferView.get());
meshBuffers.push_back(subMesh.m_tangentShaderBufferView.get());
meshBuffers.push_back(subMesh.m_bitangentShaderBufferView.get());
if (RHI::CheckBitsAll(subMesh.m_bufferFlags, RayTracingSubMeshBufferFlags::UV))
{
meshBuffers.push_back(subMesh.m_uvShaderBufferView.get());
}
}
}
@ -287,58 +440,53 @@ namespace AZ
m_rayTracingSceneSrg->Compile();
}
void RayTracingFeatureProcessor::UpdateMeshInfoBuffer()
void RayTracingFeatureProcessor::UpdateRayTracingMaterialSrg()
{
if (m_meshInfoBufferNeedsUpdate && (m_subMeshCount > 0))
{
TransformServiceFeatureProcessor* transformFeatureProcessor = GetParentScene()->GetFeatureProcessor<TransformServiceFeatureProcessor>();
AZStd::vector<MeshInfo> meshInfos;
meshInfos.reserve(m_subMeshCount);
const RHI::ShaderResourceGroupLayout* srgLayout = m_rayTracingMaterialSrg->GetLayout();
RHI::ShaderInputImageIndex imageIndex;
RHI::ShaderInputBufferIndex bufferIndex;
RHI::ShaderInputConstantIndex constantIndex;
uint32_t newMeshByteCount = m_subMeshCount * sizeof(MeshInfo);
if (m_meshInfoBuffer == nullptr)
{
// allocate the MeshInfo structured buffer
RPI::CommonBufferDescriptor desc;
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
desc.m_bufferName = "RayTracingMeshInfo";
desc.m_byteCount = newMeshByteCount;
desc.m_elementSize = sizeof(MeshInfo);
m_meshInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
}
else if (m_meshInfoBuffer->GetBufferSize() < newMeshByteCount)
{
// resize for the new sub-mesh count
m_meshInfoBuffer->Resize(newMeshByteCount);
}
bufferIndex = srgLayout->FindShaderInputBufferIndex(AZ::Name("m_materialInfo"));
m_rayTracingMaterialSrg->SetBufferView(bufferIndex, m_materialInfoBuffer->GetBufferView());
if (m_subMeshCount)
{
AZStd::vector<const RHI::ImageView*> materialTextures;
for (const auto& mesh : m_meshes)
{
AZ::Transform meshTransform = transformFeatureProcessor->GetTransformForId(TransformServiceFeatureProcessorInterface::ObjectId(mesh.first));
AZ::Transform noScaleTransform = meshTransform;
noScaleTransform.ExtractScale();
AZ::Matrix3x3 rotationMatrix = Matrix3x3::CreateFromTransform(noScaleTransform);
rotationMatrix = rotationMatrix.GetInverseFull().GetTranspose();
const RayTracingFeatureProcessor::SubMeshVector& subMeshes = mesh.second.m_subMeshes;
const SubMeshVector& subMeshes = mesh.second.m_subMeshes;
for (const auto& subMesh : subMeshes)
{
MeshInfo meshInfo;
meshInfo.m_indexOffset = subMesh.m_indexBufferView.GetByteOffset();
meshInfo.m_positionOffset = subMesh.m_positionVertexBufferView.GetByteOffset();
meshInfo.m_normalOffset = subMesh.m_normalVertexBufferView.GetByteOffset();
subMesh.m_irradianceColor.StoreToFloat4(meshInfo.m_irradianceColor.data());
rotationMatrix.StoreToRowMajorFloat9(meshInfo.m_worldInvTranspose.data());
meshInfos.emplace_back(meshInfo);
// add the baseColor, normal, metallic, and roughness images for this sub-mesh to the material texture list,
// this is sent to the shader as an unbounded array in the Srg
if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::BaseColor))
{
materialTextures.push_back(subMesh.m_baseColorImageView.get());
}
if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::Normal))
{
materialTextures.push_back(subMesh.m_normalImageView.get());
}
if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::Metallic))
{
materialTextures.push_back(subMesh.m_metallicImageView.get());
}
if (RHI::CheckBitsAll(subMesh.m_textureFlags, RayTracingSubMeshTextureFlags::Roughness))
{
materialTextures.push_back(subMesh.m_roughnessImageView.get());
}
}
}
m_meshInfoBuffer->UpdateData(meshInfos.data(), newMeshByteCount);
m_meshInfoBufferNeedsUpdate = false;
RHI::ShaderInputImageUnboundedArrayIndex textureUnboundedArrayIndex = srgLayout->FindShaderInputImageUnboundedArrayIndex(AZ::Name("m_materialTextures"));
m_rayTracingMaterialSrg->SetImageViewUnboundedArray(textureUnboundedArrayIndex, materialTextures);
}
m_rayTracingMaterialSrg->Compile();
}
}
}

@ -16,6 +16,7 @@
#include <Atom/RHI/RayTracingAccelerationStructure.h>
#include <Atom/RHI/RayTracingBufferPools.h>
#include <Atom/RHI/BufferView.h>
#include <Atom/RHI/ImageView.h>
#include <AzCore/Math/Color.h>
#include <AzCore/Math/Transform.h>
@ -23,6 +24,28 @@ namespace AZ
{
namespace Render
{
static const uint32_t RayTracingGlobalSrgBindingSlot = 0;
static const uint32_t RayTracingSceneSrgBindingSlot = 1;
static const uint32_t RayTracingMaterialSrgBindingSlot = 2;
enum class RayTracingSubMeshBufferFlags : uint32_t
{
None = 0,
UV = AZ_BIT(0)
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::Render::RayTracingSubMeshBufferFlags);
enum class RayTracingSubMeshTextureFlags : uint32_t
{
None = 0,
BaseColor = AZ_BIT(0),
Normal = AZ_BIT(1),
Metallic = AZ_BIT(2),
Roughness = AZ_BIT(3)
};
AZ_DEFINE_ENUM_BITWISE_OPERATORS(AZ::Render::RayTracingSubMeshTextureFlags);
//! This feature processor manages ray tracing data for a Scene
class RayTracingFeatureProcessor
: public RPI::FeatureProcessor
@ -42,20 +65,53 @@ namespace AZ
//! Contains data for a single sub-mesh
struct SubMesh
{
// vertex/index buffer data
RHI::Format m_vertexFormat = RHI::Format::Unknown;
// vertex streams
RHI::Format m_positionFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_positionVertexBufferView;
RHI::Ptr<RHI::BufferView> m_positionShaderBufferView;
RHI::Format m_normalFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_normalVertexBufferView;
RHI::Ptr<RHI::BufferView> m_normalShaderBufferView;
RHI::Format m_tangentFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_tangentVertexBufferView;
RHI::Ptr<RHI::BufferView> m_tangentShaderBufferView;
RHI::Format m_bitangentFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_bitangentVertexBufferView;
RHI::Ptr<RHI::BufferView> m_bitangentShaderBufferView;
RHI::Format m_uvFormat = RHI::Format::Unknown;
RHI::StreamBufferView m_uvVertexBufferView;
RHI::Ptr<RHI::BufferView> m_uvShaderBufferView;
// index buffer
RHI::IndexBufferView m_indexBufferView;
RHI::Ptr<RHI::BufferView> m_indexShaderBufferView;
// vertex buffer usage flags
RayTracingSubMeshBufferFlags m_bufferFlags = RayTracingSubMeshBufferFlags::None;
// color of the bounced light from this sub-mesh
AZ::Color m_irradianceColor;
AZ::Color m_irradianceColor = AZ::Color(1.0f);
// ray tracing Blas
RHI::Ptr<RHI::RayTracingBlas> m_blas;
// material data
AZ::Color m_baseColor = AZ::Color(0.0f);
float m_metallicFactor = 0.0f;
float m_roughnessFactor = 0.0f;
// material texture usage flags
RayTracingSubMeshTextureFlags m_textureFlags = RayTracingSubMeshTextureFlags::None;
// material textures
RHI::Ptr<const RHI::ImageView> m_baseColorImageView;
RHI::Ptr<const RHI::ImageView> m_normalImageView;
RHI::Ptr<const RHI::ImageView> m_metallicImageView;
RHI::Ptr<const RHI::ImageView> m_roughnessImageView;
};
using SubMeshVector = AZStd::vector<SubMesh>;
@ -98,6 +154,9 @@ namespace AZ
//! Retrieves the RayTracingSceneSrg
Data::Instance<RPI::ShaderResourceGroup> GetRayTracingSceneSrg() const { return m_rayTracingSceneSrg; }
//! Retrieves the RayTracingMaterialSrg
Data::Instance<RPI::ShaderResourceGroup> GetRayTracingMaterialSrg() const { return m_rayTracingMaterialSrg; }
//! Retrieves the RayTracingTlas
const RHI::Ptr<RHI::RayTracingTlas>& GetTlas() const { return m_tlas; }
RHI::Ptr<RHI::RayTracingTlas>& GetTlas() { return m_tlas; }
@ -118,14 +177,20 @@ namespace AZ
//! Retrieves the GPU buffer containing information for all ray tracing meshes.
const Data::Instance<RPI::Buffer> GetMeshInfoBuffer() const { return m_meshInfoBuffer; }
//! Updates the RayTracingSceneSrg, called after the TLAS is allocated in the RayTracingAccelerationStructurePass
void UpdateRayTracingSceneSrg();
//! Retrieves the GPU buffer containing information for all ray tracing materials.
const Data::Instance<RPI::Buffer> GetMaterialInfoBuffer() const { return m_materialInfoBuffer; }
//! Updates the RayTracingSceneSrg and RayTracingMaterialSrg, called after the TLAS is allocated in the RayTracingAccelerationStructurePass
void UpdateRayTracingSrgs();
private:
AZ_DISABLE_COPY_MOVE(RayTracingFeatureProcessor);
void UpdateMeshInfoBuffer();
void UpdateMaterialInfoBuffer();
void UpdateRayTracingSceneSrg();
void UpdateRayTracingMaterialSrg();
// flag indicating if RayTracing is enabled, currently based on device support
bool m_rayTracingEnabled = false;
@ -143,6 +208,9 @@ namespace AZ
// ray tracing scene Srg
Data::Instance<RPI::ShaderResourceGroup> m_rayTracingSceneSrg;
// ray tracing material Srg
Data::Instance<RPI::ShaderResourceGroup> m_rayTracingMaterialSrg;
// current revision number of ray tracing data
uint32_t m_revision = 0;
@ -158,18 +226,43 @@ namespace AZ
// structure for data in the m_meshInfoBuffer, shaders that use the buffer must match this type
struct MeshInfo
{
uint32_t m_indexOffset;
uint32_t m_positionOffset;
uint32_t m_normalOffset;
uint32_t m_indexOffset;
uint32_t m_positionOffset;
uint32_t m_normalOffset;
uint32_t m_tangentOffset;
uint32_t m_bitangentOffset;
uint32_t m_uvOffset;
float m_padding0[2];
AZStd::array<float, 4> m_irradianceColor; // float4
AZStd::array<float, 9> m_worldInvTranspose; // float3x3
float m_padding1[1];
RayTracingSubMeshBufferFlags m_bufferFlags = RayTracingSubMeshBufferFlags::None;
uint32_t m_bufferStartIndex = 0;
};
// buffer containing a MeshInfo for each sub-mesh
Data::Instance<RPI::Buffer> m_meshInfoBuffer;
// flag indicating we need to update the mesh info GPU buffer
// structure for data in the m_materialInfoBuffer, shaders that use the buffer must match this type
struct MaterialInfo
{
AZStd::array<float, 4> m_baseColor; // float4
float m_metallicFactor = 0.0f;
float m_roughnessFactor = 0.0f;
RayTracingSubMeshTextureFlags m_textureFlags = RayTracingSubMeshTextureFlags::None;
uint32_t m_textureStartIndex = 0;
};
// buffer containing a MaterialInfo for each sub-mesh
Data::Instance<RPI::Buffer> m_materialInfoBuffer;
// flag indicating we need to update the meshInfo buffer
bool m_meshInfoBufferNeedsUpdate = false;
// flag indicating we need to update the materialInfo buffer
bool m_materialInfoBufferNeedsUpdate = false;
};
}
}

@ -111,7 +111,6 @@ namespace AZ
AZ_Assert(m_globalPipelineState, "Failed to acquire ray tracing global pipeline state");
// create global srg
static const uint32_t RayTracingGlobalSrgBindingSlot = 0;
Data::Asset<RPI::ShaderResourceGroupAsset> globalSrgAsset = m_rayGenerationShader->FindShaderResourceGroupAsset(RayTracingGlobalSrgBindingSlot);
AZ_Error("PassSystem", globalSrgAsset.GetId().IsValid(), "RayTracingPass [%s] Failed to find RayTracingGlobalSrg asset", GetPathName().GetCStr());
AZ_Error("PassSystem", globalSrgAsset.IsReady(), "RayTracingPass [%s] asset is not loaded for shader", GetPathName().GetCStr());
@ -120,10 +119,13 @@ namespace AZ
AZ_Assert(m_shaderResourceGroup, "RayTracingPass [%s]: Failed to create RayTracingGlobalSrg", GetPathName().GetCStr());
RPI::PassUtils::BindDataMappingsToSrg(m_passDescriptor, m_shaderResourceGroup.get());
// check to see if the shader requires a ViewSrg
// check to see if the shader requires the View and RayTracingMaterial Srgs
Data::Asset<RPI::ShaderResourceGroupAsset> viewSrgAsset = m_rayGenerationShader->FindShaderResourceGroupAsset(RPI::SrgBindingSlot::View);
m_requiresViewSrg = viewSrgAsset.GetId().IsValid();
Data::Asset<RPI::ShaderResourceGroupAsset> rayTracingMaterialSrgAsset = m_rayGenerationShader->FindShaderResourceGroupAsset(RayTracingMaterialSrgBindingSlot);
m_requiresRayTracingMaterialSrg = rayTracingMaterialSrgAsset.GetId().IsValid();
// build the ray tracing pipeline state descriptor
RHI::RayTracingPipelineStateDescriptor descriptor;
descriptor.Build()
@ -298,6 +300,11 @@ namespace AZ
}
}
if (m_requiresRayTracingMaterialSrg)
{
shaderResourceGroups.push_back(rayTracingFeatureProcessor->GetRayTracingMaterialSrg()->GetRHIShaderResourceGroup());
}
dispatchRaysItem.m_shaderResourceGroupCount = aznumeric_cast<uint32_t>(shaderResourceGroups.size());
dispatchRaysItem.m_shaderResourceGroups = shaderResourceGroups.data();
dispatchRaysItem.m_rayTracingPipelineState = m_rayTracingPipelineState.get();

@ -76,6 +76,7 @@ namespace AZ
RHI::ConstPtr<RHI::PipelineState> m_globalPipelineState;
RHI::Ptr<RHI::RayTracingShaderTable> m_rayTracingShaderTable;
bool m_requiresViewSrg = false;
bool m_requiresRayTracingMaterialSrg = false;
};
} // namespace RPI
} // namespace AZ

Loading…
Cancel
Save