ATOM-16656 PassTree tool: ParentPass image attachment preview doesn't work (#5032)
Move imageAttachmentCopy instance from RenderPass to Pass so it can support preview image for all passes but not only for RenderPass. Fixed an issue with image attachment preview when switching render pipeline with attachment preview on. Signed-off-by: Qing Tao <qingtao@amazon.com>
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
#include <Atom/RPI.Public/Pass/PassFilter.h>
|
||||
#include <Atom/RPI.Public/Pass/RenderPass.h>
|
||||
#include <Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h>
|
||||
#include <Atom/RPI.Public/Pass/Specific/SwapChainPass.h>
|
||||
#include <Atom/RPI.Public/ViewportContextManager.h>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <Atom/RPI.Public/GpuQuery/GpuQuerySystemInterface.h>
|
||||
#include <Atom/RPI.Reflect/Image/Image.h>
|
||||
#include <Atom/RPI.Public/Image/AttachmentImage.h>
|
||||
#include <Atom/RPI.Public/Image/AttachmentImage.h>
|
||||
#include <Atom/RPI.Public/Pass/PassAttachment.h>
|
||||
#include <Atom/RPI.Public/Pass/PassDefines.h>
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
@@ -59,6 +60,7 @@ namespace AZ
|
||||
struct PassRequest;
|
||||
struct PassValidationResults;
|
||||
class AttachmentReadback;
|
||||
class ImageAttachmentCopy;
|
||||
|
||||
using SortedPipelineViewTags = AZStd::set<PipelineViewTag, AZNameSortAscending>;
|
||||
using PassesByDrawList = AZStd::map<RHI::DrawListTag, const Pass*>;
|
||||
@@ -94,6 +96,8 @@ namespace AZ
|
||||
{
|
||||
AZ_RPI_PASS(Pass);
|
||||
|
||||
friend class ImageAttachmentPreviewPass;
|
||||
|
||||
public:
|
||||
using ChildPassIndex = RHI::Handle<uint32_t, class ChildPass>;
|
||||
|
||||
@@ -369,6 +373,9 @@ namespace AZ
|
||||
|
||||
void UpdateReadbackAttachment(FramePrepareParams params, bool beforeAddScopes);
|
||||
|
||||
// Setup ImageAttachmentCopy
|
||||
void UpdateAttachmentCopy(FramePrepareParams params);
|
||||
|
||||
// --- Protected Members ---
|
||||
|
||||
const Name PassNameThis{"This"};
|
||||
@@ -466,6 +473,9 @@ namespace AZ
|
||||
AZStd::shared_ptr<AttachmentReadback> m_attachmentReadback;
|
||||
PassAttachmentReadbackOption m_readbackOption;
|
||||
|
||||
// For image attachment preview
|
||||
AZStd::weak_ptr<ImageAttachmentCopy> m_attachmentCopy;
|
||||
|
||||
private:
|
||||
// Return the Timestamp result of this pass
|
||||
virtual TimestampResult GetTimestampResultInternal() const;
|
||||
|
||||
@@ -13,9 +13,7 @@
|
||||
#include <Atom/RHI/DrawList.h>
|
||||
#include <Atom/RHI/ScopeProducer.h>
|
||||
|
||||
#include <Atom/RPI.Public/Pass/AttachmentReadback.h>
|
||||
#include <Atom/RPI.Public/Pass/Pass.h>
|
||||
#include <Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h>
|
||||
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
|
||||
|
||||
namespace AZ
|
||||
@@ -29,7 +27,6 @@ namespace AZ
|
||||
|
||||
namespace RPI
|
||||
{
|
||||
class ImageAttachmentCopy;
|
||||
class RenderPass;
|
||||
class Query;
|
||||
|
||||
@@ -41,8 +38,6 @@ namespace AZ
|
||||
{
|
||||
AZ_RPI_PASS(RenderPass);
|
||||
|
||||
friend class ImageAttachmentPreviewPass;
|
||||
|
||||
using ScopeQuery = AZStd::array<RHI::Ptr<Query>, static_cast<size_t>(ScopeQueryType::Count)>;
|
||||
|
||||
public:
|
||||
@@ -143,8 +138,6 @@ namespace AZ
|
||||
// Readback the results from the ScopeQueries
|
||||
void ReadbackScopeQueryResults();
|
||||
|
||||
AZStd::weak_ptr<ImageAttachmentCopy> m_attachmentCopy;
|
||||
|
||||
// Readback results from the Timestamp queries
|
||||
TimestampResult m_timestampResult;
|
||||
// Readback results from the PipelineStatistics queries
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ namespace AZ
|
||||
~ImageAttachmentPreviewPass();
|
||||
|
||||
//! Preview the PassAttachment of a pass' PassAttachmentBinding
|
||||
void PreviewImageAttachmentForPass(RenderPass* pass, const PassAttachment* passAttachment);
|
||||
void PreviewImageAttachmentForPass(Pass* pass, const PassAttachment* passAttachment);
|
||||
|
||||
//! Set the output color attachment for this pass
|
||||
void SetOutputColorAttachment(RHI::Ptr<PassAttachment> outputImageAttachment);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <Atom/RPI.Public/Pass/PassLibrary.h>
|
||||
#include <Atom/RPI.Public/Pass/PassDefines.h>
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
#include <Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h>
|
||||
#include <Atom/RPI.Public/RenderPipeline.h>
|
||||
|
||||
#include <Atom/RPI.Reflect/Image/AttachmentImageAsset.h>
|
||||
@@ -1215,6 +1216,12 @@ namespace AZ
|
||||
m_queueState = PassQueueState::NoQueue;
|
||||
|
||||
InitializeInternal();
|
||||
|
||||
// Need to recreate the dest attachment because the source attachment might be changed
|
||||
if (!m_attachmentCopy.expired())
|
||||
{
|
||||
m_attachmentCopy.lock()->InvalidateDestImage();
|
||||
}
|
||||
|
||||
m_state = PassState::Initialized;
|
||||
}
|
||||
@@ -1301,6 +1308,9 @@ namespace AZ
|
||||
// readback attachment with output state
|
||||
UpdateReadbackAttachment(params, false);
|
||||
|
||||
// update attachment copy for preview
|
||||
UpdateAttachmentCopy(params);
|
||||
|
||||
UpdateConnectedOutputBindings();
|
||||
}
|
||||
|
||||
@@ -1489,6 +1499,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void Pass::UpdateAttachmentCopy(FramePrepareParams params)
|
||||
{
|
||||
if (!m_attachmentCopy.expired())
|
||||
{
|
||||
m_attachmentCopy.lock()->FrameBegin(params);
|
||||
}
|
||||
}
|
||||
|
||||
bool Pass::IsTimestampQueryEnabled() const
|
||||
{
|
||||
return m_flags.m_timestampQueryEnabled;
|
||||
|
||||
@@ -177,12 +177,6 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Need to recreate the dest attachment because the source attachment might be changed
|
||||
if (!m_attachmentCopy.expired())
|
||||
{
|
||||
m_attachmentCopy.lock()->InvalidateDestImage();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPass::FrameBeginInternal(FramePrepareParams params)
|
||||
@@ -196,11 +190,7 @@ namespace AZ
|
||||
|
||||
// Read back the ScopeQueries submitted from previous frames
|
||||
ReadbackScopeQueryResults();
|
||||
|
||||
if (!m_attachmentCopy.expired())
|
||||
{
|
||||
m_attachmentCopy.lock()->FrameBegin(params);
|
||||
}
|
||||
|
||||
CollectSrgs();
|
||||
|
||||
PassSystemInterface::Get()->IncrementFrameRenderPassCount();
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <Atom/RPI.Public/Buffer/Buffer.h>
|
||||
#include <Atom/RPI.Public/Image/AttachmentImagePool.h>
|
||||
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
|
||||
#include <Atom/RPI.Public/Pass/RenderPass.h>
|
||||
#include <Atom/RPI.Public/Pass/AttachmentReadback.h>
|
||||
#include <Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h>
|
||||
#include <Atom/RPI.Public/Pass/ParentPass.h>
|
||||
#include <Atom/RPI.Public/RenderPipeline.h>
|
||||
@@ -131,7 +131,7 @@ namespace AZ
|
||||
Data::AssetBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void ImageAttachmentPreviewPass::PreviewImageAttachmentForPass(RenderPass* pass, const PassAttachment* passAttachment)
|
||||
void ImageAttachmentPreviewPass::PreviewImageAttachmentForPass(Pass* pass, const PassAttachment* passAttachment)
|
||||
{
|
||||
if (passAttachment->GetAttachmentType() != RHI::AttachmentType::Image)
|
||||
{
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace AZ
|
||||
bool m_showAttachments = false;
|
||||
|
||||
AZ::RPI::Pass* m_selectedPass = nullptr;
|
||||
AZ::RPI::Pass* m_lastSelectedPass = nullptr;
|
||||
AZ::Name m_selectedPassPath;
|
||||
AZ::RHI::AttachmentId m_attachmentId;
|
||||
AZ::Name m_slotName;
|
||||
bool m_selectedChanged = false;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
namespace AZ::Render
|
||||
{
|
||||
inline AZ::RPI::PassAttachment* FindPassAttachment(AZ::RPI::RenderPass* pass, AZ::RHI::AttachmentId attachmentId)
|
||||
inline AZ::RPI::PassAttachment* FindPassAttachment(AZ::RPI::Pass* pass, AZ::RHI::AttachmentId attachmentId)
|
||||
{
|
||||
for (auto& binding : pass->GetAttachmentBindings())
|
||||
{
|
||||
@@ -47,6 +47,10 @@ namespace AZ::Render
|
||||
{
|
||||
using namespace AZ;
|
||||
|
||||
// always set m_selectedPass to empty and use m_selectedPassPath to find it when render the pass tree
|
||||
m_selectedPass = nullptr;
|
||||
bool needSaveAttachment = false;
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(200.f, 200.f), ImGuiCond_FirstUseEver);
|
||||
if (ImGui::Begin("PassTree View", &draw, ImGuiWindowFlags_None))
|
||||
{
|
||||
@@ -83,60 +87,16 @@ namespace AZ::Render
|
||||
|
||||
if (Scriptable_ImGui::Button("Save Attachment"))
|
||||
{
|
||||
m_attachmentReadbackInfo = "";
|
||||
if (!m_readback)
|
||||
{
|
||||
m_readback = AZStd::make_shared<AZ::RPI::AttachmentReadback>(AZ::RHI::ScopeId{ "AttachmentReadback" });
|
||||
m_readback->SetCallback(AZStd::bind(&ImGuiPassTree::ReadbackCallback, this, AZStd::placeholders::_1));
|
||||
}
|
||||
|
||||
if (m_selectedPass && !m_slotName.IsEmpty())
|
||||
{
|
||||
bool readbackResult = m_selectedPass->ReadbackAttachment(m_readback, m_slotName);
|
||||
if (!readbackResult)
|
||||
{
|
||||
AZ_Error("ImGuiPassTree", false, "Failed to readback attachment from pass [%s] slot [%s]", m_selectedPass->GetName().GetCStr(), m_slotName.GetCStr());
|
||||
}
|
||||
}
|
||||
needSaveAttachment = true;
|
||||
}
|
||||
|
||||
ImGui::TextWrapped("%s", m_attachmentReadbackInfo.c_str());
|
||||
}
|
||||
|
||||
if (m_previewAttachment && m_selectedChanged)
|
||||
{
|
||||
m_selectedChanged = false;
|
||||
if (!m_attachmentId.IsEmpty() && m_selectedPass)
|
||||
{
|
||||
AZ::RPI::RenderPass* renderPass = azrtti_cast<AZ::RPI::RenderPass*>(m_selectedPass);
|
||||
if (renderPass)
|
||||
{
|
||||
if (!m_previewPass->GetParent())
|
||||
{
|
||||
RPI::PassSystemInterface::Get()->GetRootPass()->AddChild(m_previewPass);
|
||||
}
|
||||
AZ::RPI::PassAttachment* attachment = FindPassAttachment(renderPass, m_attachmentId);
|
||||
if (attachment)
|
||||
{
|
||||
// Reset output attachment to empty so the preview will use pass's owner render pipeline's output
|
||||
m_previewPass->SetOutputColorAttachment(nullptr);
|
||||
m_previewPass->PreviewImageAttachmentForPass(renderPass, attachment);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_previewPass->ClearPreviewAttachment();
|
||||
if (m_previewPass->GetParent())
|
||||
{
|
||||
m_previewPass->QueueForRemoval();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
// Draw the hierarchical view
|
||||
// It will assign m_seletedPass if there is a pass matches m_seletedPassPath
|
||||
ImGui::SetNextWindowPos(ImVec2(300, 60), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(300, 500), ImGuiCond_FirstUseEver);
|
||||
if (ImGui::Begin("PassTree", nullptr, ImGuiWindowFlags_None))
|
||||
@@ -144,6 +104,63 @@ namespace AZ::Render
|
||||
DrawTreeView(rootPass);
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
// It's possible that the pass pointer changed but selected pass path wasn't changed
|
||||
if (m_selectedPass != m_lastSelectedPass)
|
||||
{
|
||||
m_selectedChanged = true;
|
||||
if (m_selectedPass == nullptr)
|
||||
{
|
||||
m_selectedPassPath = AZ::Name{};
|
||||
}
|
||||
}
|
||||
m_lastSelectedPass = m_selectedPass;
|
||||
|
||||
if (m_previewAttachment && m_selectedChanged)
|
||||
{
|
||||
m_selectedChanged = false;
|
||||
if (!m_attachmentId.IsEmpty() && m_selectedPass)
|
||||
{
|
||||
if (!m_previewPass->GetParent())
|
||||
{
|
||||
RPI::PassSystemInterface::Get()->GetRootPass()->AddChild(m_previewPass);
|
||||
}
|
||||
AZ::RPI::PassAttachment* attachment = FindPassAttachment(m_selectedPass, m_attachmentId);
|
||||
if (attachment)
|
||||
{
|
||||
// Reset output attachment to empty so the preview will use pass's owner render pipeline's output
|
||||
m_previewPass->SetOutputColorAttachment(nullptr);
|
||||
m_previewPass->PreviewImageAttachmentForPass(m_selectedPass, attachment);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_previewPass->ClearPreviewAttachment();
|
||||
if (m_previewPass->GetParent())
|
||||
{
|
||||
m_previewPass->QueueForRemoval();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needSaveAttachment)
|
||||
{
|
||||
m_attachmentReadbackInfo = "";
|
||||
if (!m_readback)
|
||||
{
|
||||
m_readback = AZStd::make_shared<AZ::RPI::AttachmentReadback>(AZ::RHI::ScopeId{ "AttachmentReadback" });
|
||||
m_readback->SetCallback(AZStd::bind(&ImGuiPassTree::ReadbackCallback, this, AZStd::placeholders::_1));
|
||||
}
|
||||
|
||||
if (m_selectedPass && !m_slotName.IsEmpty())
|
||||
{
|
||||
bool readbackResult = m_selectedPass->ReadbackAttachment(m_readback, m_slotName);
|
||||
if (!readbackResult)
|
||||
{
|
||||
AZ_Error("ImGuiPassTree", false, "Failed to readback attachment from pass [%s] slot [%s]", m_selectedPass->GetName().GetCStr(), m_slotName.GetCStr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void ImGuiPassTree::DrawPassAttachments(AZ::RPI::Pass* pass)
|
||||
@@ -202,6 +219,7 @@ namespace AZ::Render
|
||||
|
||||
if (Scriptable_ImGui::Selectable(label.c_str(), m_attachmentId == binding.m_attachment->GetAttachmentId()))
|
||||
{
|
||||
m_selectedPassPath = pass->GetPathName();
|
||||
m_selectedPass = pass;
|
||||
m_attachmentId = binding.m_attachment->GetAttachmentId();
|
||||
m_slotName = binding.m_name;
|
||||
@@ -232,9 +250,9 @@ namespace AZ::Render
|
||||
if (!m_showAttachments)
|
||||
{
|
||||
// Only draw the leaf pass as selectable if we are not showing attachments as its children
|
||||
if (Scriptable_ImGui::Selectable(pass->GetName().GetCStr(), m_selectedPass == pass))
|
||||
if (Scriptable_ImGui::Selectable(pass->GetName().GetCStr(), m_selectedPassPath == pass->GetPathName()))
|
||||
{
|
||||
m_selectedPass = pass;
|
||||
m_selectedPassPath = pass->GetPathName();
|
||||
m_attachmentId = AZ::RHI::AttachmentId{};
|
||||
m_slotName = AZ::Name{};
|
||||
m_selectedChanged = true;
|
||||
@@ -244,13 +262,13 @@ namespace AZ::Render
|
||||
{
|
||||
// Draw the pass as a tree node which has attachments as its children
|
||||
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_DefaultOpen
|
||||
| ((m_selectedPass == pass) ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
| ((m_selectedPassPath == pass->GetPathName()) ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
|
||||
bool nodeOpen = Scriptable_ImGui::TreeNodeEx(pass->GetName().GetCStr(), flags);
|
||||
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
m_selectedPass = pass;
|
||||
m_selectedPassPath = pass->GetPathName();
|
||||
m_attachmentId = AZ::RHI::AttachmentId{};
|
||||
m_slotName = AZ::Name{};
|
||||
m_selectedChanged = true;
|
||||
@@ -259,7 +277,6 @@ namespace AZ::Render
|
||||
if (nodeOpen)
|
||||
{
|
||||
DrawPassAttachments(pass);
|
||||
|
||||
Scriptable_ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
@@ -268,13 +285,13 @@ namespace AZ::Render
|
||||
{
|
||||
// For a ParentPasse, draw it as a tree node
|
||||
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_DefaultOpen
|
||||
| ((m_selectedPass == pass) ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
| ((m_selectedPassPath == pass->GetPathName()) ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
|
||||
bool nodeOpen = ImGui::TreeNodeEx(pass->GetName().GetCStr(), flags);
|
||||
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
m_selectedPass = pass;
|
||||
m_selectedPassPath = pass->GetPathName();
|
||||
m_attachmentId = AZ::RHI::AttachmentId{};
|
||||
m_slotName = AZ::Name{};
|
||||
m_selectedChanged = true;
|
||||
@@ -282,7 +299,10 @@ namespace AZ::Render
|
||||
|
||||
if (nodeOpen)
|
||||
{
|
||||
DrawPassAttachments(pass);
|
||||
if (m_showAttachments)
|
||||
{
|
||||
DrawPassAttachments(pass);
|
||||
}
|
||||
for (const auto& child : asParent->GetChildren())
|
||||
{
|
||||
DrawTreeView(child.get());
|
||||
@@ -296,6 +316,12 @@ namespace AZ::Render
|
||||
{
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
// set m_selectedPass if pass path matches
|
||||
if (pass->GetPathName() == m_selectedPassPath)
|
||||
{
|
||||
m_selectedPass = pass;
|
||||
}
|
||||
}
|
||||
|
||||
inline void ImGuiPassTree::ReadbackCallback(const AZ::RPI::AttachmentReadback::ReadbackResult& readbackResult)
|
||||
@@ -364,7 +390,9 @@ namespace AZ::Render
|
||||
m_previewAttachment = false;
|
||||
m_showAttachments = false;
|
||||
|
||||
m_selectedPassPath = AZ::Name{};
|
||||
m_selectedPass = nullptr;
|
||||
m_lastSelectedPass = nullptr;
|
||||
m_attachmentId = AZ::RHI::AttachmentId{};
|
||||
m_slotName = AZ::Name{};
|
||||
m_selectedChanged = false;
|
||||
|
||||
Reference in New Issue
Block a user