Merge commit '9e0756f3c11ae5218246fec732e1ceb4da14caeb' into barlev/gitflow_211028_O3DE

This commit is contained in:
Adi Bar-Lev
2021-10-28 19:16:57 -04:00
9 changed files with 118 additions and 77 deletions
@@ -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
@@ -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;