Files
o3de/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp
T
Qing Tao fe8dac7989 ATOM-16489 Add find passes functions for Scene or RenderPipeline in PassSystemInterface (#4739)
* ATOM-16489 Add find passes functions for Scene or RenderPipeline in PassSystemInterface
Introduced new PassSystemInterface::ForEachPass() funtion to replace PassSystemInterface::FindPasses(), PassSystemInterface::GetPassesByTemplateName and ParentPass::FindPassByNameRecursive() functions.
Update all the places which were using those three functions.
The new pass finding filter support any combination of pass name, pass template name, pass class type, pass hirechary, owner scene, owner render pipeline.
Update unit tests.

Signed-off-by: Qing Tao <qingtao@amazon.com>
2021-10-25 10:07:55 -07:00

646 lines
28 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Serialization/SerializeContext.h>
#include <Atom/RPI.Public/RPIUtils.h>
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/Shader/Shader.h>
#include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Public/Pass/PassFilter.h>
#include <DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.h>
#include <Atom/Feature/TransformService/TransformServiceFeatureProcessor.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RHI/RHISystemInterface.h>
#include <Atom/RHI/PipelineState.h>
#include <Atom/RHI.Reflect/InputStreamLayoutBuilder.h>
// This component invokes shaders based on Nvidia's RTX-GI SDK.
// Please refer to "Shaders/DiffuseGlobalIllumination/Nvidia RTX-GI License.txt" for license information.
namespace AZ
{
namespace Render
{
void DiffuseProbeGridFeatureProcessor::Reflect(ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext
->Class<DiffuseProbeGridFeatureProcessor, FeatureProcessor>()
->Version(0);
}
}
void DiffuseProbeGridFeatureProcessor::Activate()
{
RHI::RHISystemInterface* rhiSystem = RHI::RHISystemInterface::Get();
m_diffuseProbeGrids.reserve(InitialProbeGridAllocationSize);
m_realTimeDiffuseProbeGrids.reserve(InitialProbeGridAllocationSize);
RHI::BufferPoolDescriptor desc;
desc.m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
desc.m_bindFlags = RHI::BufferBindFlags::InputAssembly;
m_bufferPool = RHI::Factory::Get().CreateBufferPool();
m_bufferPool->SetName(Name("DiffuseProbeGridBoxBufferPool"));
[[maybe_unused]] RHI::ResultCode resultCode = m_bufferPool->Init(*rhiSystem->GetDevice(), desc);
AZ_Error("DiffuseProbeGridFeatureProcessor", resultCode == RHI::ResultCode::Success, "Failed to initialize buffer pool");
// create box mesh vertices and indices
CreateBoxMesh();
// image pool
{
RHI::ImagePoolDescriptor imagePoolDesc;
imagePoolDesc.m_bindFlags = RHI::ImageBindFlags::ShaderReadWrite | RHI::ImageBindFlags::CopyRead;
m_probeGridRenderData.m_imagePool = RHI::Factory::Get().CreateImagePool();
[[maybe_unused]] RHI::ResultCode result = m_probeGridRenderData.m_imagePool->Init(*rhiSystem->GetDevice(), imagePoolDesc);
AZ_Assert(result == RHI::ResultCode::Success, "Failed to initialize output image pool");
}
// create image view descriptors
m_probeGridRenderData.m_probeRayTraceImageViewDescriptor = RHI::ImageViewDescriptor::Create(DiffuseProbeGridRenderData::RayTraceImageFormat, 0, 0);
m_probeGridRenderData.m_probeIrradianceImageViewDescriptor = RHI::ImageViewDescriptor::Create(DiffuseProbeGridRenderData::IrradianceImageFormat, 0, 0);
m_probeGridRenderData.m_probeDistanceImageViewDescriptor = RHI::ImageViewDescriptor::Create(DiffuseProbeGridRenderData::DistanceImageFormat, 0, 0);
m_probeGridRenderData.m_probeRelocationImageViewDescriptor = RHI::ImageViewDescriptor::Create(DiffuseProbeGridRenderData::RelocationImageFormat, 0, 0);
m_probeGridRenderData.m_probeClassificationImageViewDescriptor = RHI::ImageViewDescriptor::Create(DiffuseProbeGridRenderData::ClassificationImageFormat, 0, 0);
// load shader
// Note: the shader may not be available on all platforms
Data::Instance<RPI::Shader> shader = RPI::LoadCriticalShader("Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.azshader");
if (shader)
{
m_probeGridRenderData.m_drawListTag = shader->GetDrawListTag();
m_probeGridRenderData.m_pipelineState = aznew RPI::PipelineStateForDraw;
m_probeGridRenderData.m_pipelineState->Init(shader); // uses default shader variant
m_probeGridRenderData.m_pipelineState->SetInputStreamLayout(m_boxStreamLayout);
m_probeGridRenderData.m_pipelineState->SetOutputFromScene(GetParentScene());
m_probeGridRenderData.m_pipelineState->Finalize();
// load object shader resource group
m_probeGridRenderData.m_shader = shader;
m_probeGridRenderData.m_srgLayout = shader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Object);
AZ_Error("DiffuseProbeGridFeatureProcessor", m_probeGridRenderData.m_srgLayout != nullptr, "Failed to find ObjectSrg layout");
}
EnableSceneNotification();
}
void DiffuseProbeGridFeatureProcessor::Deactivate()
{
AZ_Warning("DiffuseProbeGridFeatureProcessor", m_diffuseProbeGrids.size() == 0,
"Deactivating the DiffuseProbeGridFeatureProcessor, but there are still outstanding probe grids probes. Components\n"
"using DiffuseProbeGridHandles should free them before the DiffuseProbeGridFeatureProcessor is deactivated.\n"
);
DisableSceneNotification();
if (m_bufferPool)
{
m_bufferPool.reset();
}
}
void DiffuseProbeGridFeatureProcessor::Simulate([[maybe_unused]] const FeatureProcessor::SimulatePacket& packet)
{
AZ_PROFILE_SCOPE(AzRender, "DiffuseProbeGridFeatureProcessor: Simulate");
// update pipeline states
if (m_needUpdatePipelineStates)
{
UpdatePipelineStates();
m_needUpdatePipelineStates = false;
}
// check pending textures and connect bus for notifications
for (auto& notificationEntry : m_notifyTextureAssets)
{
if (notificationEntry.m_assetId.IsValid())
{
// asset already has an assetId
continue;
}
// query for the assetId
AZ::Data::AssetId assetId;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
assetId,
&AZ::Data::AssetCatalogRequests::GetAssetIdByPath,
notificationEntry.m_relativePath.c_str(),
azrtti_typeid<AZ::RPI::StreamingImageAsset>(),
false);
if (assetId.IsValid())
{
notificationEntry.m_assetId = assetId;
notificationEntry.m_asset.Create(assetId, true);
Data::AssetBus::MultiHandler::BusConnect(assetId);
}
}
// if the volumes changed we need to re-sort the probe list
if (m_probeGridSortRequired)
{
AZ_PROFILE_SCOPE(AzRender, "Sort diffuse probe grids");
// sort the probes by descending inner volume size, so the smallest volumes are rendered last
auto sortFn = [](AZStd::shared_ptr<DiffuseProbeGrid> const& probe1, AZStd::shared_ptr<DiffuseProbeGrid> const& probe2) -> bool
{
const Obb& obb1 = probe1->GetObbWs();
const Obb& obb2 = probe2->GetObbWs();
float size1 = obb1.GetHalfLengthX() * obb1.GetHalfLengthZ() * obb1.GetHalfLengthY();
float size2 = obb2.GetHalfLengthX() * obb2.GetHalfLengthZ() * obb2.GetHalfLengthY();
return (size1 > size2);
};
AZStd::sort(m_diffuseProbeGrids.begin(), m_diffuseProbeGrids.end(), sortFn);
AZStd::sort(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), sortFn);
m_probeGridSortRequired = false;
}
// call Simulate on all diffuse probe grids
for (uint32_t probeGridIndex = 0; probeGridIndex < m_diffuseProbeGrids.size(); ++probeGridIndex)
{
AZStd::shared_ptr<DiffuseProbeGrid>& diffuseProbeGrid = m_diffuseProbeGrids[probeGridIndex];
AZ_Assert(diffuseProbeGrid.use_count() > 1, "DiffuseProbeGrid found with no corresponding owner, ensure that RemoveProbe() is called before releasing probe handles");
diffuseProbeGrid->Simulate(probeGridIndex);
}
}
void DiffuseProbeGridFeatureProcessor::OnBeginPrepareRender()
{
for (auto& diffuseProbeGrid : m_realTimeDiffuseProbeGrids)
{
diffuseProbeGrid->ResetCullingVisibility();
}
}
void DiffuseProbeGridFeatureProcessor::OnEndPrepareRender()
{
// re-build the list of visible real-time diffuse probe grids
m_visibleRealTimeDiffuseProbeGrids.clear();
for (auto& diffuseProbeGrid : m_realTimeDiffuseProbeGrids)
{
if (diffuseProbeGrid->GetIsVisible())
{
m_visibleRealTimeDiffuseProbeGrids.push_back(diffuseProbeGrid);
}
}
}
DiffuseProbeGridHandle DiffuseProbeGridFeatureProcessor::AddProbeGrid(const AZ::Transform& transform, const AZ::Vector3& extents, const AZ::Vector3& probeSpacing)
{
AZStd::shared_ptr<DiffuseProbeGrid> diffuseProbeGrid = AZStd::make_shared<DiffuseProbeGrid>();
diffuseProbeGrid->Init(GetParentScene(), &m_probeGridRenderData);
diffuseProbeGrid->SetTransform(transform);
diffuseProbeGrid->SetExtents(extents);
diffuseProbeGrid->SetProbeSpacing(probeSpacing);
m_diffuseProbeGrids.push_back(diffuseProbeGrid);
UpdateRealTimeList(diffuseProbeGrid);
m_probeGridSortRequired = true;
return diffuseProbeGrid;
}
void DiffuseProbeGridFeatureProcessor::RemoveProbeGrid(DiffuseProbeGridHandle& probeGrid)
{
AZ_Assert(probeGrid.get(), "RemoveProbeGrid called with an invalid handle");
// remove from main list
auto itEntry = AZStd::find_if(m_diffuseProbeGrids.begin(), m_diffuseProbeGrids.end(), [&](AZStd::shared_ptr<DiffuseProbeGrid> const& entry)
{
return (entry == probeGrid);
});
AZ_Assert(itEntry != m_diffuseProbeGrids.end(), "RemoveProbeGrid called with a probe grid that is not in the probe list");
m_diffuseProbeGrids.erase(itEntry);
// remove from side list of real-time grids
itEntry = AZStd::find_if(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr<DiffuseProbeGrid> const& entry)
{
return (entry == probeGrid);
});
if (itEntry != m_realTimeDiffuseProbeGrids.end())
{
m_realTimeDiffuseProbeGrids.erase(itEntry);
}
// remove from side list of visible real-time grids
itEntry = AZStd::find_if(m_visibleRealTimeDiffuseProbeGrids.begin(), m_visibleRealTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr<DiffuseProbeGrid> const& entry)
{
return (entry == probeGrid);
});
if (itEntry != m_visibleRealTimeDiffuseProbeGrids.end())
{
m_visibleRealTimeDiffuseProbeGrids.erase(itEntry);
}
probeGrid = nullptr;
}
bool DiffuseProbeGridFeatureProcessor::ValidateExtents(const DiffuseProbeGridHandle& probeGrid, const AZ::Vector3& newExtents)
{
AZ_Assert(probeGrid.get(), "SetTransform called with an invalid handle");
return probeGrid->ValidateExtents(newExtents);
}
void DiffuseProbeGridFeatureProcessor::SetExtents(const DiffuseProbeGridHandle& probeGrid, const AZ::Vector3& extents)
{
AZ_Assert(probeGrid.get(), "SetExtents called with an invalid handle");
probeGrid->SetExtents(extents);
m_probeGridSortRequired = true;
}
void DiffuseProbeGridFeatureProcessor::SetTransform(const DiffuseProbeGridHandle& probeGrid, const AZ::Transform& transform)
{
AZ_Assert(probeGrid.get(), "SetTransform called with an invalid handle");
probeGrid->SetTransform(transform);
m_probeGridSortRequired = true;
}
bool DiffuseProbeGridFeatureProcessor::ValidateProbeSpacing(const DiffuseProbeGridHandle& probeGrid, const AZ::Vector3& newSpacing)
{
AZ_Assert(probeGrid.get(), "SetTransform called with an invalid handle");
return probeGrid->ValidateProbeSpacing(newSpacing);
}
void DiffuseProbeGridFeatureProcessor::SetProbeSpacing(const DiffuseProbeGridHandle& probeGrid, const AZ::Vector3& probeSpacing)
{
AZ_Assert(probeGrid.get(), "SetProbeSpacing called with an invalid handle");
probeGrid->SetProbeSpacing(probeSpacing);
}
void DiffuseProbeGridFeatureProcessor::SetViewBias(const DiffuseProbeGridHandle& probeGrid, float viewBias)
{
AZ_Assert(probeGrid.get(), "SetViewBias called with an invalid handle");
probeGrid->SetViewBias(viewBias);
}
void DiffuseProbeGridFeatureProcessor::SetNormalBias(const DiffuseProbeGridHandle& probeGrid, float normalBias)
{
AZ_Assert(probeGrid.get(), "SetNormalBias called with an invalid handle");
probeGrid->SetNormalBias(normalBias);
}
void DiffuseProbeGridFeatureProcessor::SetAmbientMultiplier(const DiffuseProbeGridHandle& probeGrid, float ambientMultiplier)
{
AZ_Assert(probeGrid.get(), "SetAmbientMultiplier called with an invalid handle");
probeGrid->SetAmbientMultiplier(ambientMultiplier);
}
void DiffuseProbeGridFeatureProcessor::Enable(const DiffuseProbeGridHandle& probeGrid, bool enable)
{
AZ_Assert(probeGrid.get(), "Enable called with an invalid handle");
probeGrid->Enable(enable);
}
void DiffuseProbeGridFeatureProcessor::SetGIShadows(const DiffuseProbeGridHandle& probeGrid, bool giShadows)
{
AZ_Assert(probeGrid.get(), "SetGIShadows called with an invalid handle");
probeGrid->SetGIShadows(giShadows);
}
void DiffuseProbeGridFeatureProcessor::SetUseDiffuseIbl(const DiffuseProbeGridHandle& probeGrid, bool useDiffuseIbl)
{
AZ_Assert(probeGrid.get(), "SetUseDiffuseIbl called with an invalid handle");
probeGrid->SetUseDiffuseIbl(useDiffuseIbl);
}
void DiffuseProbeGridFeatureProcessor::BakeTextures(
const DiffuseProbeGridHandle& probeGrid,
DiffuseProbeGridBakeTexturesCallback callback,
const AZStd::string& irradianceTextureRelativePath,
const AZStd::string& distanceTextureRelativePath,
const AZStd::string& relocationTextureRelativePath,
const AZStd::string& classificationTextureRelativePath)
{
AZ_Assert(probeGrid.get(), "BakeTextures called with an invalid handle");
AddNotificationEntry(irradianceTextureRelativePath);
AddNotificationEntry(distanceTextureRelativePath);
AddNotificationEntry(relocationTextureRelativePath);
AddNotificationEntry(classificationTextureRelativePath);
probeGrid->GetTextureReadback().BeginTextureReadback(callback);
}
void DiffuseProbeGridFeatureProcessor::UpdateRealTimeList(const DiffuseProbeGridHandle& diffuseProbeGrid)
{
if (diffuseProbeGrid->GetMode() == DiffuseProbeGridMode::RealTime)
{
// add to side list of real-time grids
auto itEntry = AZStd::find_if(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr<DiffuseProbeGrid> const& entry)
{
return (entry == diffuseProbeGrid);
});
if (itEntry == m_realTimeDiffuseProbeGrids.end())
{
m_realTimeDiffuseProbeGrids.push_back(diffuseProbeGrid);
}
}
else
{
// remove from side list of real-time grids
auto itEntry = AZStd::find_if(m_realTimeDiffuseProbeGrids.begin(), m_realTimeDiffuseProbeGrids.end(), [&](AZStd::shared_ptr<DiffuseProbeGrid> const& entry)
{
return (entry == diffuseProbeGrid);
});
if (itEntry != m_realTimeDiffuseProbeGrids.end())
{
m_realTimeDiffuseProbeGrids.erase(itEntry);
}
}
}
void DiffuseProbeGridFeatureProcessor::AddNotificationEntry(const AZStd::string& relativePath)
{
AZStd::string assetPath = relativePath + ".streamingimage";
// check to see if this is an existing asset
AZ::Data::AssetId assetId;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
assetId,
&AZ::Data::AssetCatalogRequests::GetAssetIdByPath,
assetPath.c_str(),
azrtti_typeid<AZ::RPI::StreamingImageAsset>(),
false);
// We only track notifications for new texture assets, meaning assets that are created the first time a DiffuseProbeGrid is baked.
// On subsequent bakes the existing assets are automatically reloaded by the RPI since they are already known by the asset system.
if (!assetId.IsValid())
{
m_notifyTextureAssets.push_back({ assetPath, assetId });
}
}
bool DiffuseProbeGridFeatureProcessor::CheckTextureAssetNotification(
const AZStd::string& relativePath,
Data::Asset<RPI::StreamingImageAsset>& outTextureAsset,
DiffuseProbeGridTextureNotificationType& outNotificationType)
{
for (NotifyTextureAssetVector::iterator itNotification = m_notifyTextureAssets.begin(); itNotification != m_notifyTextureAssets.end(); ++itNotification)
{
if (itNotification->m_relativePath == relativePath)
{
outNotificationType = itNotification->m_notificationType;
if (outNotificationType != DiffuseProbeGridTextureNotificationType::None)
{
outTextureAsset = itNotification->m_asset;
m_notifyTextureAssets.erase(itNotification);
}
return true;
}
}
return false;
}
bool DiffuseProbeGridFeatureProcessor::AreBakedTexturesReferenced(
const AZStd::string& irradianceTextureRelativePath,
const AZStd::string& distanceTextureRelativePath,
const AZStd::string& relocationTextureRelativePath,
const AZStd::string& classificationTextureRelativePath)
{
for (auto& diffuseProbeGrid : m_diffuseProbeGrids)
{
if ((diffuseProbeGrid->GetBakedIrradianceRelativePath() == irradianceTextureRelativePath) ||
(diffuseProbeGrid->GetBakedDistanceRelativePath() == distanceTextureRelativePath) ||
(diffuseProbeGrid->GetBakedRelocationRelativePath() == relocationTextureRelativePath) ||
(diffuseProbeGrid->GetBakedClassificationRelativePath() == classificationTextureRelativePath))
{
return true;
}
}
return false;
}
void DiffuseProbeGridFeatureProcessor::SetMode(const DiffuseProbeGridHandle& probeGrid, DiffuseProbeGridMode mode)
{
AZ_Assert(probeGrid.get(), "SetMode called with an invalid handle");
probeGrid->SetMode(mode);
UpdateRealTimeList(probeGrid);
m_probeGridSortRequired = true;
}
void DiffuseProbeGridFeatureProcessor::SetBakedTextures(const DiffuseProbeGridHandle& probeGrid, const DiffuseProbeGridBakedTextures& bakedTextures)
{
AZ_Assert(probeGrid.get(), "SetBakedTextures called with an invalid handle");
probeGrid->SetBakedTextures(bakedTextures);
}
void DiffuseProbeGridFeatureProcessor::CreateBoxMesh()
{
// vertex positions
static const Position positions[] =
{
// front
{ -0.5f, -0.5f, 0.5f },
{ 0.5f, -0.5f, 0.5f },
{ 0.5f, 0.5f, 0.5f },
{ -0.5f, 0.5f, 0.5f },
// back
{ -0.5f, -0.5f, -0.5f },
{ 0.5f, -0.5f, -0.5f },
{ 0.5f, 0.5f, -0.5f },
{ -0.5f, 0.5f, -0.5f },
// left
{ -0.5f, -0.5f, 0.5f },
{ -0.5f, 0.5f, 0.5f },
{ -0.5f, 0.5f, -0.5f },
{ -0.5f, -0.5f, -0.5f },
// right
{ 0.5f, -0.5f, 0.5f },
{ 0.5f, 0.5f, 0.5f },
{ 0.5f, 0.5f, -0.5f },
{ 0.5f, -0.5f, -0.5f },
// bottom
{ -0.5f, -0.5f, 0.5f },
{ 0.5f, -0.5f, 0.5f },
{ 0.5f, -0.5f, -0.5f },
{ -0.5f, -0.5f, -0.5f },
// top
{ -0.5f, 0.5f, 0.5f },
{ 0.5f, 0.5f, 0.5f },
{ 0.5f, 0.5f, -0.5f },
{ -0.5f, 0.5f, -0.5f },
};
static const u32 numPositions = sizeof(positions) / sizeof(positions[0]);
for (u32 i = 0; i < numPositions; ++i)
{
m_boxPositions.push_back(positions[i]);
}
// indices
static const uint16_t indices[] =
{
// front
0, 1, 2, 2, 3, 0,
// back
5, 4, 7, 7, 6, 5,
// left
8, 9, 10, 10, 11, 8,
// right
14, 13, 12, 12, 15, 14,
// bottom
18, 17, 16, 16, 19, 18,
// top
23, 20, 21, 21, 22, 23
};
static const u32 numIndices = sizeof(indices) / sizeof(indices[0]);
for (u32 i = 0; i < numIndices; ++i)
{
m_boxIndices.push_back(indices[i]);
}
// create stream layout
RHI::InputStreamLayoutBuilder layoutBuilder;
layoutBuilder.AddBuffer()->Channel("POSITION", RHI::Format::R32G32B32_FLOAT);
layoutBuilder.SetTopology(RHI::PrimitiveTopology::TriangleList);
m_boxStreamLayout = layoutBuilder.End();
// create index buffer
AZ::RHI::BufferInitRequest request;
m_boxIndexBuffer = AZ::RHI::Factory::Get().CreateBuffer();
request.m_buffer = m_boxIndexBuffer.get();
request.m_descriptor = AZ::RHI::BufferDescriptor{ AZ::RHI::BufferBindFlags::InputAssembly, m_boxIndices.size() * sizeof(uint16_t) };
request.m_initialData = m_boxIndices.data();
AZ::RHI::ResultCode result = m_bufferPool->InitBuffer(request);
AZ_Error("DiffuseProbeGridFeatureProcessor", result == RHI::ResultCode::Success, "Failed to initialize box index buffer - error [%d]", result);
// create index buffer view
AZ::RHI::IndexBufferView indexBufferView =
{
*m_boxIndexBuffer,
0,
sizeof(indices),
AZ::RHI::IndexFormat::Uint16,
};
m_probeGridRenderData.m_boxIndexBufferView = indexBufferView;
m_probeGridRenderData.m_boxIndexCount = numIndices;
// create position buffer
m_boxPositionBuffer = AZ::RHI::Factory::Get().CreateBuffer();
request.m_buffer = m_boxPositionBuffer.get();
request.m_descriptor = AZ::RHI::BufferDescriptor{ AZ::RHI::BufferBindFlags::InputAssembly, m_boxPositions.size() * sizeof(Position) };
request.m_initialData = m_boxPositions.data();
result = m_bufferPool->InitBuffer(request);
AZ_Error("DiffuseProbeGridFeatureProcessor", result == RHI::ResultCode::Success, "Failed to initialize box index buffer - error [%d]", result);
// create position buffer view
RHI::StreamBufferView positionBufferView =
{
*m_boxPositionBuffer,
0,
(uint32_t)(m_boxPositions.size() * sizeof(Position)),
sizeof(Position),
};
m_probeGridRenderData.m_boxPositionBufferView = { { positionBufferView } };
AZ::RHI::ValidateStreamBufferViews(m_boxStreamLayout, m_probeGridRenderData.m_boxPositionBufferView);
}
void DiffuseProbeGridFeatureProcessor::OnRenderPipelinePassesChanged([[maybe_unused]] RPI::RenderPipeline* renderPipeline)
{
UpdatePasses();
m_needUpdatePipelineStates = true;
}
void DiffuseProbeGridFeatureProcessor::OnRenderPipelineAdded([[maybe_unused]] RPI::RenderPipelinePtr pipeline)
{
UpdatePasses();
m_needUpdatePipelineStates = true;
}
void DiffuseProbeGridFeatureProcessor::OnRenderPipelineRemoved([[maybe_unused]] RPI::RenderPipeline* pipeline)
{
m_needUpdatePipelineStates = true;
}
void DiffuseProbeGridFeatureProcessor::UpdatePipelineStates()
{
if(m_probeGridRenderData.m_pipelineState)
{
m_probeGridRenderData.m_pipelineState->SetOutputFromScene(GetParentScene());
m_probeGridRenderData.m_pipelineState->Finalize();
}
}
void DiffuseProbeGridFeatureProcessor::UpdatePasses()
{
// disable the DiffuseProbeGridUpdatePass if the platform does not support raytracing
RHI::Ptr<RHI::Device> device = RHI::RHISystemInterface::Get()->GetDevice();
if (device->GetFeatures().m_rayTracing == false)
{
RPI::PassFilter passFilter = RPI::PassFilter::CreateWithPassName(AZ::Name("DiffuseProbeGridUpdatePass"), GetParentScene());
RPI::PassSystemInterface::Get()->ForEachPass(passFilter, [](RPI::Pass* pass) -> RPI::PassFilterExecutionFlow
{
pass->SetEnabled(false);
return RPI::PassFilterExecutionFlow::ContinueVisitingPasses;
});
}
}
void DiffuseProbeGridFeatureProcessor::HandleAssetNotification(Data::Asset<Data::AssetData> asset, DiffuseProbeGridTextureNotificationType notificationType)
{
for (NotifyTextureAssetVector::iterator itNotification = m_notifyTextureAssets.begin(); itNotification != m_notifyTextureAssets.end(); ++itNotification)
{
if (itNotification->m_assetId == asset.GetId())
{
// store the texture asset
itNotification->m_asset = Data::static_pointer_cast<RPI::StreamingImageAsset>(asset);
itNotification->m_notificationType = notificationType;
// stop notifications on this asset
Data::AssetBus::MultiHandler::BusDisconnect(itNotification->m_assetId);
break;
}
}
}
void DiffuseProbeGridFeatureProcessor::OnAssetReady(Data::Asset<Data::AssetData> asset)
{
HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Ready);
}
void DiffuseProbeGridFeatureProcessor::OnAssetError(Data::Asset<Data::AssetData> asset)
{
AZ_Error("ReflectionProbeFeatureProcessor", false, "Failed to load cubemap [%s]", asset.GetHint().c_str());
HandleAssetNotification(asset, DiffuseProbeGridTextureNotificationType::Error);
}
} // namespace Render
} // namespace AZ