Merge pull request #946 from aws-lumberyard-dev/Atom/dmcdiar/ATOM-15555

[ATOM-15555] Data-Driven RayTracingPass
main
dmcdiarmid-ly 5 years ago committed by GitHub
commit b20f3bc72f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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;
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",

@ -89,6 +89,8 @@
#include <ImGui/ImGuiPass.h>
#include <RayTracing/RayTracingAccelerationStructurePass.h>
#include <RayTracing/RayTracingPass.h>
#include <RayTracing/RayTracingPassData.h>
#include <DiffuseProbeGrid/DiffuseProbeGridRayTracingPass.h>
#include <DiffuseProbeGrid/DiffuseProbeGridBlendIrradiancePass.h>
#include <DiffuseProbeGrid/DiffuseProbeGridBlendDistancePass.h>
@ -128,6 +130,7 @@ namespace AZ
SMAAFeatureProcessor::Reflect(context);
PostProcessFeatureProcessor::Reflect(context);
ImGuiPassData::Reflect(context);
RayTracingPassData::Reflect(context);
LightingPreset::Reflect(context);
ModelPreset::Reflect(context);
@ -271,6 +274,9 @@ namespace AZ
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurChildPass"), &Render::ReflectionScreenSpaceBlurChildPass::Create);
passSystem->AddPassCreator(Name("ReflectionCopyFrameBufferPass"), &Render::ReflectionCopyFrameBufferPass::Create);
// Add RayTracing pas
passSystem->AddPassCreator(Name("RayTracingPass"), &Render::RayTracingPass::Create);
// setup handler for load pass template mappings
m_loadTemplatesHandler = RPI::PassSystemInterface::OnReadyLoadTemplatesEvent::Handler([this]() { this->LoadPassTemplateMappings(); });
RPI::PassSystemInterface::Get()->ConnectEvent(m_loadTemplatesHandler);

@ -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,45 @@ 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, nullptr, shaderInputContract, meshIndex);
[[maybe_unused]] bool result = modelLod->GetStreamsForMesh(
inputStreamLayout,
streamBufferViews,
nullptr,
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 +814,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,148 @@ 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)
{
AZStd::string uuidString = AZ::Uuid::CreateRandom().ToString<AZStd::string>();
// allocate the MeshInfo structured buffer
RPI::CommonBufferDescriptor desc;
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
desc.m_bufferName = AZStd::string::format("RayTracingMeshInfo_%s", uuidString.c_str());
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)
{
AZStd::string uuidString = AZ::Uuid::CreateRandom().ToString<AZStd::string>();
// allocate the MaterialInfo structured buffer
RPI::CommonBufferDescriptor desc;
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
desc.m_bufferName = AZStd::string::format("RayTracingMaterialInfo_%s", uuidString.c_str());
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 +422,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 +444,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);
uint32_t newMeshByteCount = m_subMeshCount * sizeof(MeshInfo);
const RHI::ShaderResourceGroupLayout* srgLayout = m_rayTracingMaterialSrg->GetLayout();
RHI::ShaderInputImageIndex imageIndex;
RHI::ShaderInputBufferIndex bufferIndex;
RHI::ShaderInputConstantIndex constantIndex;
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.ExtractUniformScale();
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;
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;
};
}
}

@ -0,0 +1,362 @@
/*
* 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 <AzCore/Asset/AssetCommon.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <Atom/RHI/CommandList.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RHI/FrameScheduler.h>
#include <Atom/RHI/DispatchRaysItem.h>
#include <Atom/RHI/RHISystemInterface.h>
#include <Atom/RHI/PipelineState.h>
#include <Atom/RPI.Reflect/Pass/PassTemplate.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <Atom/RPI.Public/Base.h>
#include <Atom/RPI.Public/Pass/PassUtils.h>
#include <Atom/RPI.Public/RPIUtils.h>
#include <Atom/RPI.Public/RenderPipeline.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/View.h>
#include <RayTracing/RayTracingPass.h>
#include <RayTracing/RayTracingPassData.h>
#include <RayTracing/RayTracingFeatureProcessor.h>
namespace AZ
{
namespace Render
{
RPI::Ptr<RayTracingPass> RayTracingPass::Create(const RPI::PassDescriptor& descriptor)
{
RPI::Ptr<RayTracingPass> pass = aznew RayTracingPass(descriptor);
return pass;
}
RayTracingPass::RayTracingPass(const RPI::PassDescriptor& descriptor)
: RenderPass(descriptor)
, m_passDescriptor(descriptor)
{
RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
if (device->GetFeatures().m_rayTracing == false)
{
// raytracing is not supported on this platform
SetEnabled(false);
return;
}
Init();
}
RayTracingPass::~RayTracingPass()
{
RPI::ShaderReloadNotificationBus::MultiHandler::BusDisconnect();
}
void RayTracingPass::Init()
{
RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
m_passData = RPI::PassUtils::GetPassData<RayTracingPassData>(m_passDescriptor);
if (m_passData == nullptr)
{
AZ_Error("PassSystem", false, "RayTracingPass [%s]: Invalid RayTracingPassData", GetPathName().GetCStr());
return;
}
// ray generation shader
m_rayGenerationShader = LoadShader(m_passData->m_rayGenerationShaderAssetReference);
if (m_rayGenerationShader == nullptr)
{
AZ_Error("PassSystem", false, "RayTracingPass [%s]: Failed to load RayGeneration shader [%s]", GetPathName().GetCStr(), m_passData->m_rayGenerationShaderAssetReference.m_filePath.data());
return;
}
auto shaderVariant = m_rayGenerationShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
RHI::PipelineStateDescriptorForRayTracing rayGenerationShaderDescriptor;
shaderVariant.ConfigurePipelineState(rayGenerationShaderDescriptor);
// closest hit shader
m_closestHitShader = LoadShader(m_passData->m_closestHitShaderAssetReference);
if (m_closestHitShader == nullptr)
{
AZ_Error("PassSystem", false, "RayTracingPass [%s]: Failed to load ClosestHit shader [%s]", GetPathName().GetCStr(), m_passData->m_closestHitShaderAssetReference.m_filePath.data());
return;
}
shaderVariant = m_closestHitShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
RHI::PipelineStateDescriptorForRayTracing closestHitShaderDescriptor;
shaderVariant.ConfigurePipelineState(closestHitShaderDescriptor);
// miss shader
m_missShader = LoadShader(m_passData->m_missShaderAssetReference);
if (m_missShader == nullptr)
{
AZ_Error("PassSystem", false, "RayTracingPass [%s]: Failed to load Miss shader [%s]", GetPathName().GetCStr(), m_passData->m_missShaderAssetReference.m_filePath.data());
return;
}
shaderVariant = m_missShader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId);
RHI::PipelineStateDescriptorForRayTracing missShaderDescriptor;
shaderVariant.ConfigurePipelineState(missShaderDescriptor);
// retrieve global pipeline state
m_globalPipelineState = m_rayGenerationShader->AcquirePipelineState(rayGenerationShaderDescriptor);
AZ_Assert(m_globalPipelineState, "Failed to acquire ray tracing global pipeline state");
// create global srg
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());
m_shaderResourceGroup = RPI::ShaderResourceGroup::Create(globalSrgAsset);
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 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()
->PipelineState(m_globalPipelineState.get())
->MaxPayloadSize(m_passData->m_maxPayloadSize)
->MaxAttributeSize(m_passData->m_maxAttributeSize)
->MaxRecursionDepth(m_passData->m_maxRecursionDepth)
->ShaderLibrary(rayGenerationShaderDescriptor)
->RayGenerationShaderName(AZ::Name(m_passData->m_rayGenerationShaderName.c_str()))
->ShaderLibrary(missShaderDescriptor)
->MissShaderName(AZ::Name(m_passData->m_missShaderName.c_str()))
->ShaderLibrary(closestHitShaderDescriptor)
->ClosestHitShaderName(AZ::Name(m_passData->m_closestHitShaderName.c_str()))
->HitGroup(AZ::Name("HitGroup"))
->ClosestHitShaderName(AZ::Name(m_passData->m_closestHitShaderName.c_str()));
// create the ray tracing pipeline state object
m_rayTracingPipelineState = RHI::Factory::Get().CreateRayTracingPipelineState();
m_rayTracingPipelineState->Init(*device.get(), &descriptor);
// make sure the shader table rebuilds if we're hotreloading
m_rayTracingRevision = 0;
RPI::ShaderReloadNotificationBus::MultiHandler::BusDisconnect();
RPI::ShaderReloadNotificationBus::MultiHandler::BusConnect(m_passData->m_rayGenerationShaderAssetReference.m_assetId);
RPI::ShaderReloadNotificationBus::MultiHandler::BusConnect(m_passData->m_closestHitShaderAssetReference.m_assetId);
RPI::ShaderReloadNotificationBus::MultiHandler::BusConnect(m_passData->m_missShaderAssetReference.m_assetId);
}
Data::Instance<RPI::Shader> RayTracingPass::LoadShader(const RPI::AssetReference& shaderAssetReference)
{
Data::Asset<RPI::ShaderAsset> shaderAsset;
if (shaderAssetReference.m_assetId.IsValid())
{
shaderAsset = RPI::FindShaderAsset(shaderAssetReference.m_assetId, shaderAssetReference.m_filePath);
}
if (!shaderAsset.GetId().IsValid())
{
AZ_Error("PassSystem", false, "RayTracingPass [%s]: Failed to load shader asset [%s]", GetPathName().GetCStr(), shaderAssetReference.m_filePath.data());
return nullptr;
}
return RPI::Shader::FindOrCreate(shaderAsset);
}
void RayTracingPass::FrameBeginInternal(FramePrepareParams params)
{
RPI::Scene* scene = m_pipeline->GetScene();
RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessor>();
if (!rayTracingFeatureProcessor)
{
return;
}
if (!m_rayTracingShaderTable)
{
RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
RHI::RayTracingBufferPools& rayTracingBufferPools = rayTracingFeatureProcessor->GetBufferPools();
m_rayTracingShaderTable = RHI::Factory::Get().CreateRayTracingShaderTable();
m_rayTracingShaderTable->Init(*device.get(), rayTracingBufferPools);
}
RPI::RenderPass::FrameBeginInternal(params);
}
void RayTracingPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
{
RPI::Scene* scene = m_pipeline->GetScene();
RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessor>();
AZ_Assert(rayTracingFeatureProcessor, "RayTracingPass requires the RayTracingFeatureProcessor");
RPI::RenderPass::SetupFrameGraphDependencies(frameGraph);
frameGraph.SetEstimatedItemCount(1);
// TLAS
{
const RHI::Ptr<RHI::Buffer>& rayTracingTlasBuffer = rayTracingFeatureProcessor->GetTlas()->GetTlasBuffer();
if (rayTracingTlasBuffer)
{
AZ::RHI::AttachmentId tlasAttachmentId = rayTracingFeatureProcessor->GetTlasAttachmentId();
if (frameGraph.GetAttachmentDatabase().IsAttachmentValid(tlasAttachmentId) == false)
{
[[maybe_unused]] RHI::ResultCode result = frameGraph.GetAttachmentDatabase().ImportBuffer(tlasAttachmentId, rayTracingTlasBuffer);
AZ_Assert(result == RHI::ResultCode::Success, "Failed to import ray tracing TLAS buffer with error %d", result);
}
uint32_t tlasBufferByteCount = aznumeric_cast<uint32_t>(rayTracingFeatureProcessor->GetTlas()->GetTlasBuffer()->GetDescriptor().m_byteCount);
RHI::BufferViewDescriptor tlasBufferViewDescriptor = RHI::BufferViewDescriptor::CreateRaw(0, tlasBufferByteCount);
RHI::BufferScopeAttachmentDescriptor desc;
desc.m_attachmentId = tlasAttachmentId;
desc.m_bufferViewDescriptor = tlasBufferViewDescriptor;
desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
frameGraph.UseShaderAttachment(desc, RHI::ScopeAttachmentAccess::ReadWrite);
}
}
}
void RayTracingPass::CompileResources(const RHI::FrameGraphCompileContext& context)
{
RPI::Scene* scene = m_pipeline->GetScene();
RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessor>();
AZ_Assert(rayTracingFeatureProcessor, "RayTracingPass requires the RayTracingFeatureProcessor");
if (m_shaderResourceGroup != nullptr)
{
BindPassSrg(context, m_shaderResourceGroup);
m_shaderResourceGroup->Compile();
}
uint32_t rayTracingRevision = rayTracingFeatureProcessor->GetRevision();
if (m_rayTracingRevision != rayTracingRevision)
{
// scene changed, need to rebuild the shader table
m_rayTracingRevision = rayTracingRevision;
AZStd::shared_ptr<RHI::RayTracingShaderTableDescriptor> descriptor = AZStd::make_shared<RHI::RayTracingShaderTableDescriptor>();
if (rayTracingFeatureProcessor->GetSubMeshCount())
{
// build the ray tracing shader table descriptor
RHI::RayTracingShaderTableDescriptor* descriptorBuild = descriptor->Build(AZ::Name("RayTracingShaderTable"), m_rayTracingPipelineState)
->RayGenerationRecord(AZ::Name(m_passData->m_rayGenerationShaderName.c_str()))
->MissRecord(AZ::Name(m_passData->m_missShaderName.c_str()));
// add a hit group for each mesh to the shader table
for (uint32_t i = 0; i < rayTracingFeatureProcessor->GetSubMeshCount(); ++i)
{
descriptorBuild->HitGroupRecord(AZ::Name("HitGroup"));
}
}
m_rayTracingShaderTable->Build(descriptor);
}
}
void RayTracingPass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
{
RPI::Scene* scene = m_pipeline->GetScene();
RayTracingFeatureProcessor* rayTracingFeatureProcessor = scene->GetFeatureProcessor<RayTracingFeatureProcessor>();
AZ_Assert(rayTracingFeatureProcessor, "RayTracingPass requires the RayTracingFeatureProcessor");
if (!rayTracingFeatureProcessor ||
!rayTracingFeatureProcessor->GetTlas()->GetTlasBuffer() ||
!rayTracingFeatureProcessor->GetSubMeshCount() ||
!m_rayTracingShaderTable)
{
return;
}
RHI::DispatchRaysItem dispatchRaysItem;
// calculate thread counts if this is a full screen raytracing pass
if (m_passData->m_makeFullscreenPass)
{
RPI::PassAttachment* outputAttachment = nullptr;
if (GetOutputCount() > 0)
{
outputAttachment = GetOutputBinding(0).m_attachment.get();
}
else if (GetInputOutputCount() > 0)
{
outputAttachment = GetInputOutputBinding(0).m_attachment.get();
}
AZ_Assert(outputAttachment != nullptr, "[RayTracingPass '%s']: A fullscreen RayTracing pass must have a valid output or input/output.", GetPathName().GetCStr());
AZ_Assert(outputAttachment->GetAttachmentType() == RHI::AttachmentType::Image, "[RayTracingPass '%s']: The output of a fullscreen RayTracing pass must be an image.", GetPathName().GetCStr());
RHI::Size imageSize = outputAttachment->m_descriptor.m_image.m_size;
dispatchRaysItem.m_width = imageSize.m_width;
dispatchRaysItem.m_height = imageSize.m_height;
dispatchRaysItem.m_depth = imageSize.m_depth;
}
else
{
dispatchRaysItem.m_width = m_passData->m_threadCountX;
dispatchRaysItem.m_height = m_passData->m_threadCountY;
dispatchRaysItem.m_depth = m_passData->m_threadCountZ;
}
// bind RayTracingGlobal, RayTracingScene, and View Srgs
// [GFX TODO][ATOM-15610] Add RenderPass::SetSrgsForRayTracingDispatch
AZStd::vector<RHI::ShaderResourceGroup*> shaderResourceGroups =
{
m_shaderResourceGroup->GetRHIShaderResourceGroup(),
rayTracingFeatureProcessor->GetRayTracingSceneSrg()->GetRHIShaderResourceGroup()
};
if (m_requiresViewSrg)
{
const AZStd::vector<RPI::ViewPtr>& views = m_pipeline->GetViews(m_passData->m_pipelineViewTag);
if (views.size() > 0)
{
shaderResourceGroups.push_back(views[0]->GetRHIShaderResourceGroup());
}
}
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();
dispatchRaysItem.m_rayTracingShaderTable = m_rayTracingShaderTable.get();
dispatchRaysItem.m_globalPipelineState = m_globalPipelineState.get();
// submit the DispatchRays item
context.GetCommandList()->Submit(dispatchRaysItem);
}
void RayTracingPass::OnShaderReinitialized([[maybe_unused]] const RPI::Shader& shader)
{
Init();
}
void RayTracingPass::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset<RPI::ShaderAsset>& shaderAsset)
{
Init();
}
void RayTracingPass::OnShaderVariantReinitialized([[maybe_unused]] const RPI::Shader& shader, [[maybe_unused]] const RPI::ShaderVariantId& shaderVariantId, [[maybe_unused]] RPI::ShaderVariantStableId shaderVariantStableId)
{
Init();
}
} // namespace RPI
} // namespace AZ

@ -0,0 +1,82 @@
/*
* 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.
*
*/
#pragma once
#include <AzCore/Memory/SystemAllocator.h>
#include <Atom/RHI/RayTracingPipelineState.h>
#include <Atom/RHI/RayTracingShaderTable.h>
#include <Atom/RPI.Public/Pass/RenderPass.h>
#include <Atom/RPI.Public/Shader/Shader.h>
#include <Atom/RPI.Public/Shader/ShaderReloadNotificationBus.h>
namespace AZ
{
namespace Render
{
struct RayTracingPassData;
//! This pass executes a raytracing shader as specified in the PassData.
class RayTracingPass
: public RPI::RenderPass
, private RPI::ShaderReloadNotificationBus::MultiHandler
{
AZ_RPI_PASS(RayTracingPass);
public:
AZ_RTTI(RayTracingPass, "{7A68A36E-956A-4258-93FE-38686042C4D9}", RPI::RenderPass);
AZ_CLASS_ALLOCATOR(RayTracingPass, SystemAllocator, 0);
virtual ~RayTracingPass();
//! Creates a RayTracingPass
static RPI::Ptr<RayTracingPass> Create(const RPI::PassDescriptor& descriptor);
protected:
RayTracingPass(const RPI::PassDescriptor& descriptor);
// Pass overrides
void FrameBeginInternal(FramePrepareParams params) override;
// Scope producer functions
void SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph) override;
void CompileResources(const RHI::FrameGraphCompileContext& context) override;
void BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context) override;
// ShaderReloadNotificationBus::Handler overrides
void OnShaderReinitialized(const RPI::Shader& shader) override;
void OnShaderAssetReinitialized(const Data::Asset<RPI::ShaderAsset>& shaderAsset) override;
void OnShaderVariantReinitialized(const RPI::Shader& shader, const RPI::ShaderVariantId& shaderVariantId, RPI::ShaderVariantStableId shaderVariantStableId) override;
// load the raytracing shaders and setup pipeline states
void Init();
// helper for loading a shader from a shader asset reference
Data::Instance<RPI::Shader> LoadShader(const RPI::AssetReference& shaderAssetReference);
// pass data
RPI::PassDescriptor m_passDescriptor;
const RayTracingPassData* m_passData = nullptr;
// revision number of the ray tracing TLAS when the shader table was built
uint32_t m_rayTracingRevision = 0;
// raytracing shaders, pipeline states, and shader table
Data::Instance<RPI::Shader> m_rayGenerationShader;
Data::Instance<RPI::Shader> m_missShader;
Data::Instance<RPI::Shader> m_closestHitShader;
RHI::Ptr<RHI::RayTracingPipelineState> m_rayTracingPipelineState;
RHI::ConstPtr<RHI::PipelineState> m_globalPipelineState;
RHI::Ptr<RHI::RayTracingShaderTable> m_rayTracingShaderTable;
bool m_requiresViewSrg = false;
bool m_requiresRayTracingMaterialSrg = false;
};
} // namespace RPI
} // namespace AZ

@ -0,0 +1,73 @@
/*
* 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.
*
*/
#pragma once
#include <Atom/RPI.Reflect/Asset/AssetReference.h>
#include <Atom/RPI.Reflect/Pass/RenderPassData.h>
namespace AZ
{
namespace Render
{
//! Custom data for the RayTracingPass, specified in the PassRequest.
struct RayTracingPassData
: public RPI::RenderPassData
{
AZ_RTTI(RayTracingPassData, "{26C2E2FD-D30A-4142-82A3-0167BC94B3EE}", RPI::RenderPassData);
AZ_CLASS_ALLOCATOR(RayTracingPassData, SystemAllocator, 0);
RayTracingPassData() = default;
virtual ~RayTracingPassData() = default;
static void Reflect(ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext->Class<RayTracingPassData, RenderPassData>()
->Version(1)
->Field("RayGenerationShaderAsset", &RayTracingPassData::m_rayGenerationShaderAssetReference)
->Field("RayGenerationShaderName", &RayTracingPassData::m_rayGenerationShaderName)
->Field("ClosestHitShaderAsset", &RayTracingPassData::m_closestHitShaderAssetReference)
->Field("ClosestHitShaderName", &RayTracingPassData::m_closestHitShaderName)
->Field("MissShaderAsset", &RayTracingPassData::m_missShaderAssetReference)
->Field("MissShaderName", &RayTracingPassData::m_missShaderName)
->Field("MaxPayloadSize", &RayTracingPassData::m_maxPayloadSize)
->Field("MaxAttributeSize", &RayTracingPassData::m_maxAttributeSize)
->Field("MaxRecursionDepth", &RayTracingPassData::m_maxRecursionDepth)
->Field("Thread Count X", &RayTracingPassData::m_threadCountX)
->Field("Thread Count Y", &RayTracingPassData::m_threadCountY)
->Field("Thread Count Z", &RayTracingPassData::m_threadCountZ)
->Field("Make Fullscreen Pass", &RayTracingPassData::m_makeFullscreenPass)
;
}
}
RPI::AssetReference m_rayGenerationShaderAssetReference;
AZStd::string m_rayGenerationShaderName;
RPI::AssetReference m_closestHitShaderAssetReference;
AZStd::string m_closestHitShaderName;
RPI::AssetReference m_missShaderAssetReference;
AZStd::string m_missShaderName;
uint32_t m_maxPayloadSize = 64;
uint32_t m_maxAttributeSize = 32;
uint32_t m_maxRecursionDepth = 1;
uint32_t m_threadCountX = 1;
uint32_t m_threadCountY = 1;
uint32_t m_threadCountZ = 1;
bool m_makeFullscreenPass = false;
};
} // namespace RPI
} // namespace AZ

@ -250,6 +250,9 @@ set(FILES
Source/RayTracing/RayTracingFeatureProcessor.cpp
Source/RayTracing/RayTracingAccelerationStructurePass.cpp
Source/RayTracing/RayTracingAccelerationStructurePass.h
Source/RayTracing/RayTracingPass.cpp
Source/RayTracing/RayTracingPass.h
Source/RayTracing/RayTracingPassData.h
Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp
Source/ReflectionProbe/ReflectionProbe.cpp
Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.cpp

@ -59,7 +59,10 @@ namespace AZ
static constexpr uint32_t Draw = 0;
static constexpr uint32_t Object = 1;
static constexpr uint32_t Material = 2;
static constexpr uint32_t SubPass = 3;
static constexpr uint32_t Pass = 4;
static constexpr uint32_t View = 5;
static constexpr uint32_t Scene = 6;
};
}
}

Loading…
Cancel
Save