From 01892914ead39f1d968a25c69ae745474f683a57 Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Thu, 3 Feb 2022 14:58:58 -0800 Subject: [PATCH] Atom/qingtao/atom 16135 (#7334) * Changes to AttachmentImage related classes to have better support using render target as texture. - Updated AttachmentImageAsset to support an unique name which can be used as AttachmentId. - Functions in ImageSystemInterface to find an AttachmentImage by its unique name. - Added InsertChild function to ParentPass class so it can insert a child pass at any location. - Change to ImageAttachmentPreviewPass so it can preview cached pass attachment even the source pass was disabled. Signed-off-by: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> --- .../Assets/Textures/BRDFTexture.attimage | 10 +- .../Atom/RPI.Public/Image/AttachmentImage.h | 43 +++++++- .../Atom/RPI.Public/Image/ImageSystem.h | 7 ++ .../RPI.Public/Image/ImageSystemInterface.h | 18 +++- .../Include/Atom/RPI.Public/Pass/ParentPass.h | 4 + .../Specific/ImageAttachmentPreviewPass.h | 2 + .../RPI/Code/Include/Atom/RPI.Public/Scene.h | 8 +- .../RPI.Reflect/Image/AttachmentImageAsset.h | 22 +++- .../Image/AttachmentImageAssetCreator.h | 8 ++ .../RPI.Builders/Common/AnyAssetBuilder.cpp | 2 +- .../RPI.Public/Image/AttachmentImage.cpp | 100 ++++++++++++++---- .../Source/RPI.Public/Image/ImageSystem.cpp | 43 ++++++++ .../Source/RPI.Public/Pass/ParentPass.cpp | 39 ++++++- .../RPI/Code/Source/RPI.Public/Pass/Pass.cpp | 2 + .../Specific/ImageAttachmentPreviewPass.cpp | 23 +++- .../Image/AttachmentImageAsset.cpp | 27 ++++- .../Image/AttachmentImageAssetCreator.cpp | 27 +++-- 17 files changed, 338 insertions(+), 47 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Textures/BRDFTexture.attimage b/Gems/Atom/Feature/Common/Assets/Textures/BRDFTexture.attimage index c31954c5c6..5511b62baa 100644 --- a/Gems/Atom/Feature/Common/Assets/Textures/BRDFTexture.attimage +++ b/Gems/Atom/Feature/Common/Assets/Textures/BRDFTexture.attimage @@ -5,14 +5,16 @@ "ClassData": { "m_imageDescriptor": { "BindFlags": [ - "ShaderRead", - "ShaderWrite" - ], + "ShaderRead", + "ShaderWrite" + ], "Size": { "Width": 256, "Height": 256 }, "Format": 24 - } + }, + "Name": "$BrdfTexture", + "IsUniqueName": true } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/AttachmentImage.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/AttachmentImage.h index 15786a3a44..fc1c326cbf 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/AttachmentImage.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/AttachmentImage.h @@ -21,6 +21,27 @@ namespace AZ class AttachmentImagePool; class ResourcePoolAsset; + struct CreateAttachmentImageRequest + { + //! The name of this image. It will be used as RHI object name (for gpu debug). + Name m_imageName; + //! If true, the AttachmentImage create function may fail if the attachment image with same name already exist. + //! The m_imageName will be used as the attachment id of the created attachment image. + //! The attachment image can be found by its name (same as its attachment id). + //! If false, a random generated uuid will be used for instance id as well as attachment id. + bool m_isUniqueName = false; + //! The ImageDescriptor for this AttachmentImage + RHI::ImageDescriptor m_imageDescriptor; + //! The attachment image pool which the AttachmentImage is created from. + //! A default system attachment image pool will be used if it's set to nullptr + const AttachmentImagePool* m_imagePool = nullptr; + + // (Optional) Set the default clear value for this image + const RHI::ClearValue* m_optimizedClearValue = nullptr; + //! (Optional) The imageViewDescriptor for this image which overides the default ImageViewDescriptor. + const RHI::ImageViewDescriptor* m_imageViewDescriptor = nullptr; + }; + //! AttachmentImage is intended for use, primarily, as an attachment on a pass. Image data can //! be produced by the GPU or uploaded directly from CPU data. Use this class to represent //! color / depth stencil targets, read-write images, etc. @@ -33,20 +54,32 @@ namespace AZ AZ_INSTANCE_DATA(AttachmentImage, "{85691099-5143-4C11-88B0-897DA9064FDF}", Image); AZ_CLASS_ALLOCATOR(AttachmentImage, AZ::SystemAllocator, 0); - ~AttachmentImage() = default; + ~AttachmentImage(); //! Instantiates or returns an existing image instance using its paired asset. static Data::Instance FindOrCreate(const Data::Asset& imageAsset); - //! Instantiates a unique instance with a random id, using data provided at runtime. + //! Creates an AttachmentImage + //! @param imagePool The attachment image pool which the AttachmentImage is created from + //! @param imageDescriptor The ImageDescriptor for this AttachmentImage + //! @param imageName The name of this image. It will be used as RHI object name (for gpu debug). + //! @param optimizedClearValue (Optional) set the default clear value for this image + //! @param imageViewDescriptor (Optional) The imageViewDescriptor for this image which overides the default ImageViewDescriptor. static Data::Instance Create( const AttachmentImagePool& imagePool, const RHI::ImageDescriptor& imageDescriptor, const Name& imageName, const RHI::ClearValue* optimizedClearValue = nullptr, const RHI::ImageViewDescriptor* imageViewDescriptor = nullptr); + + //! Creates an AttachmentImage + static Data::Instance Create(const CreateAttachmentImageRequest& createImageRequest); - const RHI::AttachmentId& GetAttachmentId(); + //! Finds an AttachmentImage by an unique attachment name + static Data::Instance FindByUniqueName(const Name& uniqueAttachmentName); + + //! Return an unique id which can be used as an attachment id in frame graph attachment database + const RHI::AttachmentId& GetAttachmentId() const; private: AttachmentImage() = default; @@ -54,10 +87,14 @@ namespace AZ //! Standard instance creation path. static Data::Instance CreateInternal(AttachmentImageAsset& imageAsset); RHI::ResultCode Init(const AttachmentImageAsset& imageAsset); + void Shutdown(); Data::Instance m_imagePool; RHI::AttachmentId m_attachmentId; + + // Need to keep a reference of the asset so the asset system won't release the asset after AttachmentImage was created + Data::Asset m_imageAsset; }; } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystem.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystem.h index e42cfebc86..4a75f9bd62 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystem.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystem.h @@ -58,6 +58,9 @@ namespace AZ const Data::Instance& GetSystemStreamingPool() const override; const Data::Instance& GetSystemAttachmentPool() const override; const Data::Instance& GetStreamingPool() const override; + bool RegisterAttachmentImage(AttachmentImage* attachmentImage) override; + void UnregisterAttachmentImage(AttachmentImage* attachmentImage) override; + Data::Instance FindRegisteredAttachmentImage(const Name& uniqueName) const override; ////////////////////////////////////////////////////////////////////////// private: @@ -78,6 +81,10 @@ namespace AZ AZStd::fixed_vector, static_cast(SystemImage::Count)> m_systemImages; bool m_initialized = false; + + // a collections of regirested attachment images + // Note: use AttachmentImage* instead of Data::Instance so it can be released properly + AZStd::unordered_map m_registeredAttachmentImages; }; } } diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystemInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystemInterface.h index 920b763bc3..00f628758b 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystemInterface.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Image/ImageSystemInterface.h @@ -14,9 +14,12 @@ namespace AZ { + class Name; + namespace RPI { class Image; + class AttachmentImage; class AttachmentImagePool; class StreamingImagePool; @@ -63,7 +66,20 @@ namespace AZ //! Returns the system attachment image pool. Use this if you do not need a custom pool for your allocation. virtual const Data::Instance& GetSystemAttachmentPool() const = 0; - + + //! Register an attachment image by its unique name (attachment id) + //! Return false if the image was failed to register. + //! It could be the image with same name was already registered. + //! Note: this function is only intended to be used by AttachmentImage class + //! Only attachment images created with an unique name will be registered + virtual bool RegisterAttachmentImage(AttachmentImage* attachmentImage) = 0; + + //! Unregister an attachment image (if it's was registered) + virtual void UnregisterAttachmentImage(AttachmentImage* attachmentImage) = 0; + + //! Find an attachment image by its unique name (same as its attachment id) from registered attachment images. + //! Note: only attachment image created with an uqniue name will be registered. + virtual Data::Instance FindRegisteredAttachmentImage(const Name& uniqueName) const = 0; virtual void Update() = 0; }; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h index c9db343203..e739547255 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/ParentPass.h @@ -63,6 +63,10 @@ namespace AZ //! Adds pass to list of children void AddChild(const Ptr& child); + //! Inserts a pass at specified position + //! If the position is invalid, the child pass won't be added, and the function returns false + bool InsertChild(const Ptr& child, ChildPassIndex position); + //! Searches for a child pass with the given name. Returns the child's index if found, null index otherwise ChildPassIndex FindChildPassIndex(const Name& passName) const; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h index 8ee7a44b6f..4453d62ec0 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -103,6 +104,7 @@ namespace AZ void LoadShader(); // Pass overrides + void BuildInternal() override; void FrameBeginInternal(FramePrepareParams params) override; // RHI::ScopeProducer overrides... diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h index a87184b4b2..0d41e0b5e9 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/Scene.h @@ -165,6 +165,11 @@ namespace AZ //! User should use this event to update the part scene srg they know of void ConnectEvent(PrepareSceneSrgEvent::Handler& handler); + //! Rebuild pipeline states lookup table. + //! This function is called every time scene's render pipelines change. + //! User may call this function explicitly if render pipelines were changed + void RebuildPipelineStatesLookup(); + protected: // SceneFinder overrides... void OnSceneNotifictaionHandlerConnected(SceneNotification* handler); @@ -190,9 +195,6 @@ namespace AZ private: Scene(); - // Rebuild pipeline states lookup table. - // This function is called every time scene's render pipelines change. - void RebuildPipelineStatesLookup(); // Helper function to wait for end of TaskGraph and then delete the TaskGraphEvent void WaitAndCleanTGEvent(AZStd::unique_ptr&& completionTGEvent); diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/AttachmentImageAsset.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/AttachmentImageAsset.h index ceb2dd725d..7f7a6d6e48 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/AttachmentImageAsset.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/AttachmentImageAsset.h @@ -42,12 +42,28 @@ namespace AZ //! Return the clear value of the image. The clear value may only be useful for certain type of images such as render targets (color/depth stencil). const RHI::ClearValue* GetOptimizedClearValue() const; + //! Return the name which can be used as debug name + const AZ::Name& GetName() const; + + //! Return an unique name id which can be used as attachment id + RHI::AttachmentId GetAttachmentId() const; + + //! Return ture if the attachment image has an unique name + //! An attachment image with an unique name will be registered to image system + //! and it can be found by ImageSystemInterface::FindRegisteredAttachmentImage() function + //! The unique name is same as its attachment Id + bool HasUniqueName() const; + private: Data::Asset m_poolAsset; - // Clear value of the image. The value is only valid when m_isClearValueValid is true - RHI::ClearValue m_optimizedClearValue; - bool m_isClearValueValid = false; + // an name id + AZ::Name m_name; + + bool m_isUniqueName = false; + + // Clear value of the image + AZStd::shared_ptr m_optimizedClearValue; }; using AttachmentImageAssetHandler = AssetHandler; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/AttachmentImageAssetCreator.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/AttachmentImageAssetCreator.h index 5d7851b05f..dbeb4b674a 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/AttachmentImageAssetCreator.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/AttachmentImageAssetCreator.h @@ -36,9 +36,17 @@ namespace AZ //! Assigns the attachment image pool, which the runtime attachment image will allocate from. Required. void SetPoolAsset(const Data::Asset& poolAsset); + //! @deprecated. Deprecated, use SetName() instead //! Set a string to asset's hint. This info is only kept for runtime generated asset. //! For asset on disc, the asset system will assign asset path to asset hint void SetAssetHint(AZStd::string_view hint); + + //! Set a name for this attachment image. + //! This name will be used for AttachmentImage's RHI Image's debug name. + //! @param isUniqueName If true the image will be registered to Image System and the unique need to be unique + //! among other attachment image with unique names. And the image can be found by + //! ImageSystemInterface::FindRegisteredAttachmentImage() function + void SetName(const AZ::Name& name, bool isUniqueName); //! Finalizes and assigns ownership of the asset to result, if successful. //! Otherwise false is returned and result is left untouched. diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp index 4d060b97b1..b16c9e6a24 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Common/AnyAssetBuilder.cpp @@ -60,7 +60,7 @@ namespace AZ AZStd::placeholders::_1, AZStd::placeholders::_2); builderDescriptor.m_processJobFunction = AZStd::bind(&AnyAssetBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2); - builderDescriptor.m_version = 9; + builderDescriptor.m_version = 10; BusConnect(builderDescriptor.m_busId); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/AttachmentImage.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/AttachmentImage.cpp index 14eda8af79..64b5b154d3 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/AttachmentImage.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/AttachmentImage.cpp @@ -25,15 +25,9 @@ namespace AZ { Data::Instance AttachmentImage::FindOrCreate(const Data::Asset& imageAsset) { - auto image = Data::InstanceDatabase::Instance().FindOrCreate( + return Data::InstanceDatabase::Instance().FindOrCreate( Data::InstanceId::CreateFromAssetId(imageAsset.GetId()), imageAsset); - if (image && image->m_image) - { - image->m_image->SetName(Name(imageAsset.GetHint())); - image->m_attachmentId = image->m_image->GetName(); - } - return image; } Data::Instance AttachmentImage::Create( @@ -42,24 +36,52 @@ namespace AZ const Name& imageName, const RHI::ClearValue* optimizedClearValue, const RHI::ImageViewDescriptor* imageViewDescriptor) + { + CreateAttachmentImageRequest createImageRequest; + createImageRequest.m_imagePool = &imagePool; + createImageRequest.m_imageDescriptor = imageDescriptor; + createImageRequest.m_imageName = imageName; + createImageRequest.m_isUniqueName = false; + createImageRequest.m_optimizedClearValue = optimizedClearValue; + createImageRequest.m_imageViewDescriptor = imageViewDescriptor; + return Create(createImageRequest); + } + + Data::Instance AttachmentImage::Create(const CreateAttachmentImageRequest& createImageRequest) { Data::Asset imageAsset; - AttachmentImageAssetCreator imageAssetCreator; - auto uuid = Uuid::CreateRandom(); - imageAssetCreator.Begin(uuid); - imageAssetCreator.SetImageDescriptor(imageDescriptor); - imageAssetCreator.SetPoolAsset({imagePool.GetAssetId(), azrtti_typeid()}); - imageAssetCreator.SetAssetHint(imageName.GetCStr()); - - if (imageViewDescriptor) + AZ::Uuid uuid; + if (createImageRequest.m_isUniqueName) { - imageAssetCreator.SetImageViewDescriptor(*imageViewDescriptor); + uuid = Uuid::CreateName(createImageRequest.m_imageName.GetCStr()); + Data::InstanceId instanceId = Data::InstanceId::CreateFromAssetId(uuid); + if (Data::InstanceDatabase::Instance().Find(instanceId)) + { + AZ_Error("AttchmentImage", false, "AttachmentImage with an unique name '%s' was already created", createImageRequest.m_imageName.GetCStr()); + return nullptr; + } + } + else + { + uuid = Uuid::CreateRandom(); } - if (optimizedClearValue) + AttachmentImageAssetCreator imageAssetCreator; + imageAssetCreator.Begin(uuid); + imageAssetCreator.SetImageDescriptor(createImageRequest.m_imageDescriptor); + imageAssetCreator.SetPoolAsset({createImageRequest.m_imagePool->GetAssetId(), azrtti_typeid()}); + + imageAssetCreator.SetName(createImageRequest.m_imageName, createImageRequest.m_isUniqueName); + + if (createImageRequest.m_imageViewDescriptor) { - imageAssetCreator.SetOptimizedClearValue(*optimizedClearValue); + imageAssetCreator.SetImageViewDescriptor(*createImageRequest.m_imageViewDescriptor); + } + + if (createImageRequest.m_optimizedClearValue) + { + imageAssetCreator.SetOptimizedClearValue(*createImageRequest.m_optimizedClearValue); } if (imageAssetCreator.End(imageAsset)) @@ -70,6 +92,11 @@ namespace AZ return nullptr; } + Data::Instance AttachmentImage::FindByUniqueName(const Name& uniqueAttachmentName) + { + return ImageSystemInterface::Get()->FindRegisteredAttachmentImage(uniqueAttachmentName); + } + Data::Instance AttachmentImage::CreateInternal(AttachmentImageAsset& imageAsset) { Data::Instance image = aznew AttachmentImage(); @@ -77,18 +104,33 @@ namespace AZ if (result == RHI::ResultCode::Success) { + image->m_imageAsset = { &imageAsset, AZ::Data::AssetLoadBehavior::PreLoad }; return image; } return nullptr; } + + AttachmentImage::~AttachmentImage() + { + Shutdown(); + } RHI::ResultCode AttachmentImage::Init(const AttachmentImageAsset& imageAsset) { - Data::Instance pool = ImageSystemInterface::Get()->GetSystemAttachmentPool(); + Data::Instance pool; + if (imageAsset.GetPoolAsset().GetId().IsValid()) + { + pool = AttachmentImagePool::FindOrCreate(imageAsset.GetPoolAsset()); + } + else + { + pool = ImageSystemInterface::Get()->GetSystemAttachmentPool(); + } + if (!pool) { - AZ_Error("AttachmentImage", false, "Failed to acquire the image pool instance."); + AZ_Error("AttachmentImage", false, "Failed to acquire the attachment image pool instance."); return RHI::ResultCode::Fail; } @@ -109,6 +151,14 @@ namespace AZ AZ_Error("AttachmentImage", false, "AttachmentImage::Init() failed to initialize RHI image view."); return RHI::ResultCode::Fail; } + + m_image->SetName(imageAsset.GetName()); + m_attachmentId = imageAsset.GetAttachmentId(); + + if (imageAsset.HasUniqueName()) + { + ImageSystemInterface::Get()->RegisterAttachmentImage(this); + } return RHI::ResultCode::Success; } @@ -117,9 +167,17 @@ namespace AZ return resultCode; } - const RHI::AttachmentId& AttachmentImage::GetAttachmentId() + const RHI::AttachmentId& AttachmentImage::GetAttachmentId() const { return m_attachmentId; } + + void AttachmentImage::Shutdown() + { + if (m_imageAsset->HasUniqueName()) + { + ImageSystemInterface::Get()->UnregisterAttachmentImage(this); + } + } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp index 2c85f85424..981af2e2ab 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp @@ -200,6 +200,49 @@ namespace AZ return m_systemImages[static_cast(simpleImage)]; } + bool ImageSystem::RegisterAttachmentImage(AttachmentImage* attachmentImage) + { + if (!attachmentImage) + { + return false; + } + + auto itr = m_registeredAttachmentImages.find(attachmentImage->GetAttachmentId()); + if (itr != m_registeredAttachmentImages.end()) + { + AZ_Assert(false, "AttachmangeImage with name '%s' was already registered", attachmentImage->GetAttachmentId().GetCStr()); + return false; + } + + m_registeredAttachmentImages[attachmentImage->GetAttachmentId()] = attachmentImage; + + return true; + } + + void ImageSystem::UnregisterAttachmentImage(AttachmentImage* attachmentImage) + { + if (!attachmentImage) + { + return; + } + auto itr = m_registeredAttachmentImages.find(attachmentImage->GetAttachmentId()); + if (itr != m_registeredAttachmentImages.end()) + { + m_registeredAttachmentImages.erase(itr); + } + } + + Data::Instance ImageSystem::FindRegisteredAttachmentImage(const Name& uniqueName) const + { + auto itr = m_registeredAttachmentImages.find(uniqueName); + + if (itr != m_registeredAttachmentImages.end()) + { + return itr->second; + } + return nullptr; + } + void ImageSystem::CreateDefaultResources(const ImageSystemDescriptor& desc) { struct SystemImageDescriptor diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp index 77a3e1524a..3933649f13 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/ParentPass.cpp @@ -53,7 +53,11 @@ namespace AZ void ParentPass::AddChild(const Ptr& 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."); + if (child->m_parent != nullptr) + { + AZ_Assert(false, "Can't add Pass that already has a parent. Remove the Pass from it's parent before adding it to another Pass."); + return; + } m_children.push_back(child); child->m_parent = this; @@ -71,6 +75,39 @@ namespace AZ } } + bool ParentPass::InsertChild(const Ptr& child, ChildPassIndex position) + { + if (child->m_parent != nullptr) + { + AZ_Assert(false, "Can't add Pass that already has a parent. Remove the Pass from it's parent before adding it to another Pass."); + return false; + } + + if (!position.IsValid() || position.GetIndex() > m_children.size()) + { + AZ_Assert(false, "Can't insert a child pass with invalid position"); + return false; + } + + auto insertPos = m_children.cbegin() + position.GetIndex(); + m_children.insert(insertPos, 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); + } + return true; + } + void ParentPass::OnHierarchyChange() { Pass::OnHierarchyChange(); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp index 4b68094f9d..3985972223 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Pass.cpp @@ -644,6 +644,7 @@ namespace AZ { attachment->m_path = buffer->GetAttachmentId(); attachment->m_importedResource = buffer; + attachment->m_descriptor = buffer->GetRHIBuffer()->GetDescriptor(); } } } @@ -658,6 +659,7 @@ namespace AZ { attachment->m_path = image->GetAttachmentId(); attachment->m_importedResource = image; + attachment->m_descriptor = image->GetDescriptor(); } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.cpp index f173b2b544..13c3fdb94a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/Specific/ImageAttachmentPreviewPass.cpp @@ -54,13 +54,14 @@ namespace AZ void ImageAttachmentCopy::FrameBegin(Pass::FramePrepareParams params) { + RHI::FrameGraphAttachmentInterface attachmentDatabase = params.m_frameGraphBuilder->GetAttachmentDatabase(); + if (m_srcAttachmentId.IsEmpty()) { return; } // Return if the source attachment is not imported - RHI::FrameGraphAttachmentInterface attachmentDatabase = params.m_frameGraphBuilder->GetAttachmentDatabase(); if (!attachmentDatabase.IsAttachmentValid(m_srcAttachmentId)) { Reset(); @@ -310,13 +311,31 @@ namespace AZ Data::AssetBus::Handler::BusConnect(shaderAsset.GetId()); } + void ImageAttachmentPreviewPass::BuildInternal() + { + m_updateDrawData = true; + } + void ImageAttachmentPreviewPass::FrameBeginInternal(FramePrepareParams params) { bool scopeImported = false; if (!m_imageAttachmentId.IsEmpty() && m_outputColorAttachment) { // Only import the scope if the attachment is valid - if (params.m_frameGraphBuilder->GetAttachmentDatabase().IsAttachmentValid(m_imageAttachmentId)) + auto attachmentDatabase = params.m_frameGraphBuilder->GetAttachmentDatabase(); + bool isAttachmentValid = attachmentDatabase.IsAttachmentValid(m_imageAttachmentId); + if (!isAttachmentValid) + { + // Import the cached copy dest image if it exists (copied) + // So the attachment can be still previewed when the pass is disabled. + if (m_attachmentCopy && m_attachmentCopy->m_destImage) + { + attachmentDatabase.ImportImage(m_attachmentCopy->m_destAttachmentId, m_attachmentCopy->m_destImage->GetRHIImage()); + isAttachmentValid = true; + } + } + + if (isAttachmentValid) { if (m_needsShaderLoad) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/AttachmentImageAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/AttachmentImageAsset.cpp index 57bc548045..b8e8ee9a22 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/AttachmentImageAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/AttachmentImageAsset.cpp @@ -21,7 +21,10 @@ namespace AZ if (auto* serializeContext = azrtti_cast(context)) { serializeContext->Class() - ->Version(1) + ->Version(2) + ->Field("Name", &AttachmentImageAsset::m_name) + ->Field("IsUniqueName", &AttachmentImageAsset::m_isUniqueName) + ->Field("OptimizedClearValue", &AttachmentImageAsset::m_optimizedClearValue) ; } } @@ -33,7 +36,27 @@ namespace AZ const RHI::ClearValue* AttachmentImageAsset::GetOptimizedClearValue() const { - return m_isClearValueValid ? &m_optimizedClearValue : nullptr; + return m_optimizedClearValue.get(); + } + + const AZ::Name& AttachmentImageAsset::GetName() const + { + return m_name; + } + + RHI::AttachmentId AttachmentImageAsset::GetAttachmentId() const + { + if (HasUniqueName()) + { + return m_name; + } + return Name(m_assetId.ToString()); + } + + bool AttachmentImageAsset::HasUniqueName() const + { + // The name can still be empty if the asset was loaded for data file but not from AttachmentImageAssetCreator + return m_isUniqueName && !m_name.IsEmpty(); } } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/AttachmentImageAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/AttachmentImageAssetCreator.cpp index 1cd1cfd7c3..19fa3fb604 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/AttachmentImageAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/AttachmentImageAssetCreator.cpp @@ -7,6 +7,8 @@ */ #include +#include +#include #include @@ -47,8 +49,7 @@ namespace AZ { if (ValidateIsReady()) { - m_asset->m_isClearValueValid = true; - m_asset->m_optimizedClearValue = clearValue; + m_asset->m_optimizedClearValue = AZStd::make_shared(clearValue); } } @@ -59,12 +60,11 @@ namespace AZ return false; } - // Validate assetId instead of validate AssetData* exist. This is mainly because the Asset 's serializer only need serialize asset id instead of asset data - // Instead of create a complete Asset, we could use new Asset(assetId, type, hint) to create a placeholder to save the asset id for serialization. + // If the pool wasn't provided, use the system default attachment pool if (!m_asset->m_poolAsset.GetId().IsValid()) { - ReportError("You must assign a pool asset before calling End()."); - return false; + Data::Instance pool = RPI::ImageSystemInterface::Get()->GetSystemAttachmentPool(); + m_asset->m_poolAsset = {pool->GetAssetId(), azrtti_typeid()}; } m_asset->SetReady(); @@ -75,5 +75,20 @@ namespace AZ { m_asset.SetHint(hint); } + + void AttachmentImageAssetCreator::SetName(const AZ::Name& uniqueName, bool isUniqueName) + { + if (uniqueName.IsEmpty()) + { + m_asset->m_isUniqueName = false; + AZ_Warning("RPI", false, "Can't set empty string as unique name"); + } + else + { + m_asset->m_isUniqueName = isUniqueName; + } + m_asset->m_name = uniqueName; + + } } }