b9824ed172
* Updated all array_view uses with the C++20 span. The updates were done in the following order 1. `AZStd::array_view<([^>].+)\* ?>` -> `AZStd::span<\1 const>` 2. `AZStd::array_view<(?:const )(.+)>` -> `AZStd::span<const \1>` 3. `AZStd::array_view` -> `AZStd::span` Removed the implementation of array_view. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added missing whitespace between `const` and the typename for spans. Updated the ShaderTest comparison of the ShaderResourceGroupLayout span to compare the sizes as well Updated comments on some of the methods that stated that they return "an array" to mention they return "a span". Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
435 lines
14 KiB
C++
435 lines
14 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 <AtomCore/Instance/InstanceDatabase.h>
|
|
#include <AtomCore/std/containers/vector_set.h>
|
|
|
|
#include <Atom/RPI.Public/Pass/SlowClearPass.h>
|
|
#include <Atom/RPI.Public/Pass/ParentPass.h>
|
|
#include <Atom/RPI.Public/Pass/PassAttachment.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/SlowClearPassData.h>
|
|
#include <Atom/RPI.Reflect/Pass/PassName.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);
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
// --- Child creation ---
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ParentPass::CreateClearPassFromBinding(PassAttachmentBinding& binding, PassRequest& clearRequest)
|
|
{
|
|
if (binding.m_unifiedScopeDesc.m_loadStoreAction.m_loadAction == RHI::AttachmentLoadAction::Clear ||
|
|
binding.m_unifiedScopeDesc.m_loadStoreAction.m_loadActionStencil == RHI::AttachmentLoadAction::Clear)
|
|
{
|
|
// Set the name of the child clear pass as well as the binding it's connected to
|
|
clearRequest.m_passName = ConcatPassName(Name("Clear"), binding.m_name);
|
|
clearRequest.m_connections[0].m_attachmentRef.m_attachment = binding.m_name;
|
|
|
|
// Set the pass clear value to the clear value of the attachment binding
|
|
SlowClearPassData* clearData = static_cast<SlowClearPassData*>(clearRequest.m_passData.get());
|
|
clearData->m_clearValue = binding.m_unifiedScopeDesc.m_loadStoreAction.m_clearValue;
|
|
|
|
// Create and add the pass
|
|
Ptr<Pass> clearPass = PassSystemInterface::Get()->CreatePassFromRequest(&clearRequest);
|
|
if (clearPass)
|
|
{
|
|
AddChild(clearPass);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void ParentPass::CreateClearPassesFromBindings()
|
|
{
|
|
PassRequest clearRequest;
|
|
clearRequest.m_templateName = Name("SlowClearPassTemplate");
|
|
clearRequest.m_passData = AZStd::make_shared<SlowClearPassData>();
|
|
clearRequest.m_connections.push_back();
|
|
clearRequest.m_connections[0].m_localSlot = Name("ClearInputOutput");
|
|
clearRequest.m_connections[0].m_attachmentRef.m_pass = Name("Parent");
|
|
|
|
for (uint32_t idx = 0; idx < GetInputCount(); ++idx)
|
|
{
|
|
CreateClearPassFromBinding(GetInputBinding(idx), clearRequest);
|
|
}
|
|
|
|
for (uint32_t idx = 0; idx < GetInputOutputCount(); ++idx)
|
|
{
|
|
CreateClearPassFromBinding(GetInputOutputBinding(idx), clearRequest);
|
|
}
|
|
}
|
|
|
|
// --- 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();
|
|
CreateClearPassesFromBindings();
|
|
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::span<const 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
|