You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp

414 lines
12 KiB
C++

/*
* 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 <AtomCore/Instance/InstanceDatabase.h>
#include <AtomCore/std/containers/vector_set.h>
#include <Atom/RPI.Public/Pass/ParentPass.h>
#include <Atom/RPI.Public/Pass/PassDefines.h>
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
#include <Atom/RPI.Public/RenderPipeline.h>
#include <Atom/RPI.Reflect/Pass/PassRequest.h>
namespace AZ
{
namespace RPI
{
Ptr<ParentPass> ParentPass::Create(const PassDescriptor& descriptor)
{
Ptr<ParentPass> pass = aznew ParentPass(descriptor);
return pass;
}
Ptr<ParentPass> ParentPass::Recreate() const
{
PassDescriptor desc = GetPassDescriptor();
Ptr<ParentPass> pass = aznew ParentPass(desc);
return pass;
}
ParentPass::ParentPass(const PassDescriptor& descriptor)
: Pass(descriptor)
{
m_flags.m_createChildren = true;
}
ParentPass::~ParentPass()
{
// Explicitly remove children so we call their OnOrphan function
RemoveChildren();
}
// --- Child Pass Addition ---
void ParentPass::AddChild(const Ptr<Pass>& child)
{
AZ_Assert(child->m_parent == nullptr, "Can't add Pass that already has a parent. Remove the Pass from it's parent before adding it to another Pass.");
m_children.push_back(child);
child->m_parent = this;
child->OnHierarchyChange();
QueueForBuildAndInitialization();
// Notify pipeline
if (m_pipeline)
{
m_pipeline->SetPassModified();
// Set child's pipeline if the parent has a owning pipeline
child->SetRenderPipeline(m_pipeline);
}
}
void ParentPass::OnHierarchyChange()
{
Pass::OnHierarchyChange();
// Notify children about hierarchy change
for (const Ptr<Pass>& child : m_children)
{
child->OnHierarchyChange();
}
}
// --- Child Pass Removal ---
// The parameter type cannot be a reference as "const Ptr<Pass>&".
// Otherwise, the content of "pass" will be overwritten by AZStd::remove()
// when "pass" is a reference of a member of m_children.
void ParentPass::RemoveChild(Ptr<Pass> pass)
{
AZ_Assert(pass->m_parent == this, "Trying to remove a pass of which we are not the parent.");
// Find child and move it to the end of the list
[[maybe_unused]] auto it = AZStd::remove(m_children.begin(), m_children.end(), pass);
AZ_Assert((it + 1) == m_children.end(), "Pass::RemoveChild found more than one Ptr<Pass> in m_children, which is not allowed.");
// Delete the child that is now at the end of the list
m_children.pop_back();
// Signal child that it was orphaned
pass->OnOrphan();
// Notify pipeline
if (m_pipeline)
{
m_pipeline->SetPassModified();
}
}
void ParentPass::RemoveChildren()
{
for (auto child : m_children)
{
child->OnOrphan();
}
m_children.clear();
// Notify pipeline
if (m_pipeline)
{
m_pipeline->SetPassModified();
}
}
void ParentPass::OnOrphan()
{
Pass::OnOrphan();
for (const Ptr<Pass>& child : m_children)
{
child->OnHierarchyChange();
}
}
// --- Finders ---
Pass::ChildPassIndex ParentPass::FindChildPassIndex(const Name& passName) const
{
for (uint32_t index = 0; index < m_children.size(); ++index)
{
if (passName == m_children[index]->GetName())
{
return ChildPassIndex(index);
}
}
return ChildPassIndex::Null;
}
Ptr<Pass> ParentPass::FindChildPass(const Name& passName) const
{
ChildPassIndex index = FindChildPassIndex(passName);
return index.IsValid() ? m_children[index.GetIndex()] : Ptr<Pass>(nullptr);
}
Ptr<Pass> ParentPass::FindPassByNameRecursive(const Name& passName) const
{
for (const Ptr<Pass>& child : m_children)
{
if (child->GetName() == passName)
{
return child.get();
}
ParentPass* asParent = child->AsParent();
if (asParent)
{
auto pass = asParent->FindPassByNameRecursive(passName);
if (pass)
{
return pass;
}
}
}
return nullptr;
}
const Pass* ParentPass::FindPass(RHI::DrawListTag drawListTag) const
{
if (HasDrawListTag() && GetDrawListTag() == drawListTag)
{
return this;
}
for (const Ptr<Pass>& child : m_children)
{
ParentPass* asParent = child->AsParent();
if (asParent)
{
const Pass* pass = asParent->FindPass(drawListTag);
if (pass)
{
return pass;
}
}
else if (child->HasDrawListTag() && child->GetDrawListTag() == drawListTag)
{
return child.get();
}
}
return nullptr;
}
// --- Timestamp functions ---
void ParentPass::SetTimestampQueryEnabled(bool enable)
{
Pass::SetTimestampQueryEnabled(enable);
for (auto& child : m_children)
{
child->SetTimestampQueryEnabled(enable);
}
}
void ParentPass::SetPipelineStatisticsQueryEnabled(bool enable)
{
Pass::SetPipelineStatisticsQueryEnabled(enable);
for (auto& child : m_children)
{
child->SetPipelineStatisticsQueryEnabled(enable);
}
}
// --- PassTemplate related functions ---
void ParentPass::CreatePassesFromTemplate()
{
PassSystemInterface* passSystem = PassSystemInterface::Get();
if (m_template == nullptr)
{
return;
}
for (const PassRequest& request : m_template->m_passRequests)
{
Ptr<Pass> pass = passSystem->CreatePassFromRequest(&request);
if (pass)
{
AddChild(pass);
}
}
}
// --- Pass behavior functions ---
void ParentPass::CreateChildPasses()
{
// The already created flag prevents this function from executing multiple times a frame
if (!m_flags.m_createChildren || m_flags.m_alreadyCreatedChildren)
{
return;
}
m_flags.m_alreadyCreatedChildren = true;
RemoveChildren();
CreatePassesFromTemplate();
CreateChildPassesInternal();
m_flags.m_createChildren = false;
}
void ParentPass::ResetInternal()
{
for (const Ptr<Pass>& child : m_children)
{
child->Reset();
}
}
void ParentPass::BuildInternal()
{
CreateChildPasses();
for (const Ptr<Pass>& child : m_children)
{
child->Build();
}
}
void ParentPass::OnInitializationFinishedInternal()
{
for (const Ptr<Pass>& child : m_children)
{
child->OnInitializationFinished();
}
}
void ParentPass::InitializeInternal()
{
for (const Ptr<Pass>& child : m_children)
{
child->Initialize();
}
}
void ParentPass::Validate(PassValidationResults& validationResults)
{
if (PassValidation::IsEnabled())
{
Pass::Validate(validationResults);
for (const Ptr<Pass>& child : m_children)
{
child->Validate(validationResults);
}
}
}
void ParentPass::FrameBeginInternal(FramePrepareParams params)
{
for (const Ptr<Pass>& child : m_children)
{
child->FrameBegin(params);
}
}
void ParentPass::FrameEndInternal()
{
for (const Ptr<Pass>& child : m_children)
{
child->FrameEnd();
}
}
// --- Misc ---
void ParentPass::SetRenderPipeline(RenderPipeline* pipeline)
{
// Call base implementation
Pass::SetRenderPipeline(pipeline);
// Set render pipeline on children
for (const auto& child : m_children)
{
child->SetRenderPipeline(pipeline);
}
}
void ParentPass::GetViewDrawListInfo(RHI::DrawListMask& outDrawListMask, PassesByDrawList& outPassesByDrawList, const PipelineViewTag& viewTag) const
{
// Call base implementation
Pass::GetViewDrawListInfo(outDrawListMask, outPassesByDrawList, viewTag);
// Get mask from children
for (const auto& child : m_children)
{
child->GetViewDrawListInfo(outDrawListMask, outPassesByDrawList, viewTag);
}
}
void ParentPass::GetPipelineViewTags(SortedPipelineViewTags& outTags) const
{
// Call base implementation
Pass::GetPipelineViewTags(outTags);
// Get pipeline view tags from children
for (const auto& child : m_children)
{
child->GetPipelineViewTags(outTags);
}
}
Ptr<PassAttachment> ParentPass::GetOwnedAttachment(const Name& attachmentName) const
{
for (Ptr<PassAttachment> attachment : m_ownedAttachments)
{
if (attachment->m_name == attachmentName)
{
return attachment;
}
}
return nullptr;
}
// --- Debug functions ---
AZStd::array_view<Ptr<Pass>> ParentPass::GetChildren() const
{
return m_children;
}
void ParentPass::DebugPrint() const
{
if (PassValidation::IsEnabled())
{
Pass::DebugPrint();
// Print children
for (const Ptr<Pass>& child : m_children)
{
child->DebugPrint();
}
}
}
PipelineStatisticsResult ParentPass::GetPipelineStatisticsResultInternal() const
{
AZStd::vector<PipelineStatisticsResult> pipelineStatisticsResultArray;
pipelineStatisticsResultArray.reserve(m_children.size());
// Calculate the PipelineStatistics result by summing all of its child's PipelineStatistics
for (const Ptr<Pass>& childPass : m_children)
{
pipelineStatisticsResultArray.emplace_back(childPass->GetLatestPipelineStatisticsResult());
}
return PipelineStatisticsResult(pipelineStatisticsResultArray);
}
} // namespace RPI
} // namespace AZ