Reenable support for UI Elements that use Render Targets (#2352)
* Re-add support for UI Elements that use Render Targets * Move LyShine pass request from Atom's MainPipeline.pass to project's * Make all dynamic draw contexts in LyShine draw to pass directly without the need of draw list tags * Remove local RPI changes that are no longer needed * Prevent crash if LyShine gem is enabled but its custom pass hasn't been added to the main render pipeline * Revert to default UI pass if the LyShine pass has not been added to project's main render pipeline Signed-off-by: abrmich <abrmich@amazon.com>monroegm-disable-blank-issue-2
parent
03722789cf
commit
3a689aa319
@ -0,0 +1,483 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "PassAsset",
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "MainPipeline",
|
||||
"PassClass": "ParentPass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "SwapChainOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "RenderTarget"
|
||||
}
|
||||
],
|
||||
"PassRequests": [
|
||||
{
|
||||
"Name": "MorphTargetPass",
|
||||
"TemplateName": "MorphTargetPassTemplate"
|
||||
},
|
||||
{
|
||||
"Name": "SkinningPass",
|
||||
"TemplateName": "SkinningPassTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshOutputStream",
|
||||
"AttachmentRef": {
|
||||
"Pass": "MorphTargetPass",
|
||||
"Attachment": "MorphTargetDeltaOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "RayTracingAccelerationStructurePass",
|
||||
"TemplateName": "RayTracingAccelerationStructurePassTemplate"
|
||||
},
|
||||
{
|
||||
"Name": "DiffuseProbeGridUpdatePass",
|
||||
"TemplateName": "DiffuseProbeGridUpdatePassTemplate",
|
||||
"ExecuteAfter": [
|
||||
"RayTracingAccelerationStructurePass"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "DepthPrePass",
|
||||
"TemplateName": "DepthMSAAParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
"AttachmentRef": {
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "MotionVectorPass",
|
||||
"TemplateName": "MotionVectorParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
"AttachmentRef": {
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "Depth",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "Depth"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LightCullingPass",
|
||||
"TemplateName": "LightCullingParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
"AttachmentRef": {
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthMSAA",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "DepthMSAA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ShadowPass",
|
||||
"TemplateName": "ShadowParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "SkinnedMeshes",
|
||||
"AttachmentRef": {
|
||||
"Pass": "SkinningPass",
|
||||
"Attachment": "SkinnedMeshOutputStream"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "OpaquePass",
|
||||
"TemplateName": "OpaqueParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "DirectionalShadowmap",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "DirectionalShadowmap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DirectionalESM",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "DirectionalESM"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ProjectedShadowmap",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "ProjectedShadowmap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ProjectedESM",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "ProjectedESM"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "TileLightData",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "TileLightData"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "LightListRemapped",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "LightListRemapped"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthLinear",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "DepthLinear"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthStencil",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "DepthMSAA"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "TransparentPass",
|
||||
"TemplateName": "TransparentParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "DirectionalShadowmap",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "DirectionalShadowmap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DirectionalESM",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "DirectionalESM"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ProjectedShadowmap",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "ProjectedShadowmap"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "ProjectedESM",
|
||||
"AttachmentRef": {
|
||||
"Pass": "ShadowPass",
|
||||
"Attachment": "ProjectedESM"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "TileLightData",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "TileLightData"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "LightListRemapped",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "LightListRemapped"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "InputLinearDepth",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "DepthLinear"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthStencil",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "Depth"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "InputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "OpaquePass",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "DeferredFogPass",
|
||||
"TemplateName": "DeferredFogPassTemplate",
|
||||
"Enabled": false,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "InputLinearDepth",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "DepthLinear"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "InputDepthStencil",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "Depth"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "RenderTargetInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "TransparentPass",
|
||||
"Attachment": "InputOutput"
|
||||
}
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "FullscreenTrianglePassData",
|
||||
"ShaderAsset": {
|
||||
"FilePath": "Shaders/ScreenSpace/DeferredFog.shader"
|
||||
},
|
||||
"PipelineViewTag": "MainCamera"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "ReflectionCopyFrameBufferPass",
|
||||
"TemplateName": "ReflectionCopyFrameBufferPassTemplate",
|
||||
"Enabled": false,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Input",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DeferredFogPass",
|
||||
"Attachment": "RenderTargetInputOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "PostProcessPass",
|
||||
"TemplateName": "PostProcessParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "LightingInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DeferredFogPass",
|
||||
"Attachment": "RenderTargetInputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "Depth",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "Depth"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "MotionVectors",
|
||||
"AttachmentRef": {
|
||||
"Pass": "MotionVectorPass",
|
||||
"Attachment": "MotionVectorOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "SwapChainOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "AuxGeomPass",
|
||||
"TemplateName": "AuxGeomPassTemplate",
|
||||
"Enabled": true,
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "ColorInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "PostProcessPass",
|
||||
"Attachment": "Output"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "Depth"
|
||||
}
|
||||
}
|
||||
],
|
||||
"PassData": {
|
||||
"$type": "RasterPassData",
|
||||
"DrawListTag": "auxgeom",
|
||||
"PipelineViewTag": "MainCamera"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "DebugOverlayPass",
|
||||
"TemplateName": "DebugOverlayParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "TileLightData",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LightCullingPass",
|
||||
"Attachment": "TileLightData"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "RawLightingInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "PostProcessPass",
|
||||
"Attachment": "RawLightingOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "LuminanceMipChainInput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "PostProcessPass",
|
||||
"Attachment": "LuminanceMipChainOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "InputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "AuxGeomPass",
|
||||
"Attachment": "ColorInputOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "LyShinePass",
|
||||
"TemplateName": "LyShineParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "ColorInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DebugOverlayPass",
|
||||
"Attachment": "InputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "Depth"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "UIPass",
|
||||
"TemplateName": "UIParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "InputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "LyShinePass",
|
||||
"Attachment": "ColorInputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "Depth"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "CopyToSwapChain",
|
||||
"TemplateName": "FullscreenCopyTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "Input",
|
||||
"AttachmentRef": {
|
||||
"Pass": "UIPass",
|
||||
"Attachment": "InputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "Output",
|
||||
"AttachmentRef": {
|
||||
"Pass": "Parent",
|
||||
"Attachment": "SwapChainOutput"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "PassAsset",
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "LyShineParentTemplate",
|
||||
"PassClass": "LyShinePass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "ColorInputOutput",
|
||||
"SlotType": "InputOutput"
|
||||
},
|
||||
{
|
||||
"Name": "DepthInputOutput",
|
||||
"SlotType": "InputOutput",
|
||||
"ScopeAttachmentUsage": "DepthStencil"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "AssetAliasesSourceData",
|
||||
"ClassData": {
|
||||
"AssetPaths": [
|
||||
{
|
||||
"Name": "LyShineParentTemplate",
|
||||
"Path": "Passes/LyShineParent.pass"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* 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 <AzCore/Debug/Trace.h>
|
||||
#include <Atom/RHI/DrawListTagRegistry.h>
|
||||
#include <Atom/RHI/RHISystemInterface.h>
|
||||
#include <Atom/RPI.Public/Pass/PassAttachment.h>
|
||||
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
|
||||
#include <Atom/RPI.Public/Image/AttachmentImagePool.h>
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
#include <Atom/RPI.Reflect/Pass/RasterPassData.h>
|
||||
#include <AzCore/std/iterator.h>
|
||||
|
||||
#include "LyShinePass.h"
|
||||
|
||||
namespace LyShine
|
||||
{
|
||||
AZ::RPI::Ptr<LyShinePass> LyShinePass::Create(const AZ::RPI::PassDescriptor& descriptor)
|
||||
{
|
||||
return aznew LyShinePass(descriptor);
|
||||
}
|
||||
|
||||
LyShinePass::LyShinePass(const AZ::RPI::PassDescriptor& descriptor)
|
||||
: Base(descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
LyShinePass::~LyShinePass()
|
||||
{
|
||||
LyShinePassRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void LyShinePass::ResetInternal()
|
||||
{
|
||||
LyShinePassRequestBus::Handler::BusDisconnect();
|
||||
|
||||
Base::ResetInternal();
|
||||
}
|
||||
|
||||
void LyShinePass::BuildInternal()
|
||||
{
|
||||
AZ::RPI::Scene* scene = GetScene();
|
||||
if (scene)
|
||||
{
|
||||
// Listen for rebuild requests
|
||||
LyShinePassRequestBus::Handler::BusConnect(scene->GetId());
|
||||
|
||||
RemoveChildren();
|
||||
|
||||
// Get the current list of render targets being used across all loaded UI Canvases
|
||||
LyShine::AttachmentImagesAndDependencies attachmentImagesAndDependencies;
|
||||
LyShinePassDataRequestBus::EventResult(
|
||||
attachmentImagesAndDependencies,
|
||||
scene->GetId(),
|
||||
&LyShinePassDataRequestBus::Events::GetRenderTargets
|
||||
);
|
||||
|
||||
AddRttChildPasses(attachmentImagesAndDependencies);
|
||||
AddUiCanvasChildPass(attachmentImagesAndDependencies);
|
||||
}
|
||||
|
||||
Base::BuildInternal();
|
||||
}
|
||||
|
||||
void LyShinePass::RebuildRttChildren()
|
||||
{
|
||||
QueueForBuildAndInitialization();
|
||||
}
|
||||
|
||||
AZ::RPI::RasterPass* LyShinePass::GetRttPass(const AZStd::string& name)
|
||||
{
|
||||
for (auto child:m_children)
|
||||
{
|
||||
if (child->GetName() == AZ::Name(name))
|
||||
{
|
||||
return azrtti_cast<AZ::RPI::RasterPass*>(child.get());
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AZ::RPI::RasterPass* LyShinePass::GetUiCanvasPass()
|
||||
{
|
||||
return m_uiCanvasChildPass.get();
|
||||
}
|
||||
|
||||
void LyShinePass::AddRttChildPasses(LyShine::AttachmentImagesAndDependencies attachmentImagesAndDependencies)
|
||||
{
|
||||
for (const auto& attachmentImageAndDependencies : attachmentImagesAndDependencies)
|
||||
{
|
||||
AddRttChildPass(attachmentImageAndDependencies.first, attachmentImageAndDependencies.second);
|
||||
}
|
||||
}
|
||||
|
||||
void LyShinePass::AddRttChildPass(AZ::Data::Instance<AZ::RPI::AttachmentImage> attachmentImage, AttachmentImages attachmentImageDependencies)
|
||||
{
|
||||
// Add a pass that renders to the specified texture
|
||||
|
||||
// Create a pass template
|
||||
auto passTemplate = AZStd::make_shared<AZ::RPI::PassTemplate>();
|
||||
passTemplate->m_name = "RttChildPass";
|
||||
passTemplate->m_passClass = AZ::Name("RttChildPass");
|
||||
|
||||
// Slots
|
||||
passTemplate->m_slots.resize(2);
|
||||
|
||||
AZ::RPI::PassSlot& depthInOutSlot = passTemplate->m_slots[0];
|
||||
depthInOutSlot.m_name = "DepthInputOutput";
|
||||
depthInOutSlot.m_slotType = AZ::RPI::PassSlotType::InputOutput;
|
||||
depthInOutSlot.m_scopeAttachmentUsage = AZ::RHI::ScopeAttachmentUsage::DepthStencil;
|
||||
depthInOutSlot.m_loadStoreAction.m_clearValue = AZ::RHI::ClearValue::CreateDepthStencil(0.0f, 0);
|
||||
depthInOutSlot.m_loadStoreAction.m_loadActionStencil = AZ::RHI::AttachmentLoadAction::Clear;
|
||||
|
||||
AZ::RPI::PassSlot& outSlot = passTemplate->m_slots[1];
|
||||
outSlot.m_name = AZ::Name("RenderTargetOutput");
|
||||
outSlot.m_slotType = AZ::RPI::PassSlotType::Output;
|
||||
outSlot.m_scopeAttachmentUsage = AZ::RHI::ScopeAttachmentUsage::RenderTarget;
|
||||
outSlot.m_loadStoreAction.m_clearValue = AZ::RHI::ClearValue::CreateVector4Float(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
outSlot.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Clear;
|
||||
|
||||
// Connections
|
||||
passTemplate->m_connections.resize(1);
|
||||
|
||||
AZ::RPI::PassConnection& depthInOutConnection = passTemplate->m_connections[0];
|
||||
depthInOutConnection.m_localSlot = "DepthInputOutput";
|
||||
depthInOutConnection.m_attachmentRef.m_pass = "Parent";
|
||||
depthInOutConnection.m_attachmentRef.m_attachment = "DepthInputOutput";
|
||||
|
||||
// Pass data
|
||||
AZStd::shared_ptr<AZ::RPI::RasterPassData> passData = AZStd::make_shared<AZ::RPI::RasterPassData>();
|
||||
passData->m_drawListTag = AZ::Name("uicanvas");
|
||||
passData->m_pipelineViewTag = AZ::Name("MainCamera");
|
||||
auto size = attachmentImage->GetRHIImage()->GetDescriptor().m_size;
|
||||
passData->m_overrideScissor = AZ::RHI::Scissor(0, 0, size.m_width, size.m_height);
|
||||
passData->m_overrideViewport = AZ::RHI::Viewport(0, size.m_width, 0, size.m_height);
|
||||
passTemplate->m_passData = AZStd::move(passData);
|
||||
// Create a pass descriptor for the new child pass
|
||||
AZ::RPI::PassDescriptor childDesc;
|
||||
childDesc.m_passTemplate = passTemplate;
|
||||
childDesc.m_passName = attachmentImage->GetAttachmentId();
|
||||
|
||||
AZ::RPI::PassSystemInterface* passSystem = AZ::RPI::PassSystemInterface::Get();
|
||||
AZ::RPI::Ptr<RttChildPass> rttChildPass = passSystem->CreatePass<RttChildPass>(childDesc);
|
||||
AZ_Assert(rttChildPass, "[LyShinePass] Unable to create %s.", passTemplate->m_name.GetCStr());
|
||||
|
||||
// Store the info needed to attach to slots and set up frame graph dependencies
|
||||
rttChildPass->m_attachmentImage = attachmentImage;
|
||||
rttChildPass->m_attachmentImageDependencies = attachmentImageDependencies;
|
||||
|
||||
AddChild(rttChildPass);
|
||||
}
|
||||
|
||||
void LyShinePass::AddUiCanvasChildPass(LyShine::AttachmentImagesAndDependencies AttachmentImagesAndDependencies)
|
||||
{
|
||||
if (!m_uiCanvasChildPass)
|
||||
{
|
||||
// Create a pass template
|
||||
auto passTemplate = AZStd::make_shared<AZ::RPI::PassTemplate>();
|
||||
passTemplate->m_name = AZ::Name("LyShineChildPass");
|
||||
passTemplate->m_passClass = AZ::Name("LyShineChildPass");
|
||||
|
||||
// Slots
|
||||
passTemplate->m_slots.resize(2);
|
||||
|
||||
AZ::RPI::PassSlot& depthInOutSlot = passTemplate->m_slots[0];
|
||||
depthInOutSlot.m_name = "DepthInputOutput";
|
||||
depthInOutSlot.m_slotType = AZ::RPI::PassSlotType::InputOutput;
|
||||
depthInOutSlot.m_scopeAttachmentUsage = AZ::RHI::ScopeAttachmentUsage::DepthStencil;
|
||||
depthInOutSlot.m_loadStoreAction.m_clearValue = AZ::RHI::ClearValue::CreateDepthStencil(0.0f, 0);
|
||||
depthInOutSlot.m_loadStoreAction.m_loadActionStencil = AZ::RHI::AttachmentLoadAction::Clear;
|
||||
|
||||
AZ::RPI::PassSlot& inOutSlot = passTemplate->m_slots[1];
|
||||
inOutSlot.m_name = "ColorInputOutput";
|
||||
inOutSlot.m_slotType = AZ::RPI::PassSlotType::InputOutput;
|
||||
inOutSlot.m_scopeAttachmentUsage = AZ::RHI::ScopeAttachmentUsage::RenderTarget;
|
||||
|
||||
// Connections
|
||||
passTemplate->m_connections.resize(2);
|
||||
|
||||
AZ::RPI::PassConnection& depthInOutConnection = passTemplate->m_connections[0];
|
||||
depthInOutConnection.m_localSlot = "DepthInputOutput";
|
||||
depthInOutConnection.m_attachmentRef.m_pass = "Parent";
|
||||
depthInOutConnection.m_attachmentRef.m_attachment = "DepthInputOutput";
|
||||
|
||||
AZ::RPI::PassConnection& inOutConnection = passTemplate->m_connections[1];
|
||||
inOutConnection.m_localSlot = "ColorInputOutput";
|
||||
inOutConnection.m_attachmentRef.m_pass = "Parent";
|
||||
inOutConnection.m_attachmentRef.m_attachment = "ColorInputOutput";
|
||||
|
||||
// Pass data
|
||||
AZStd::shared_ptr<AZ::RPI::RasterPassData> passData = AZStd::make_shared<AZ::RPI::RasterPassData>();
|
||||
passData->m_drawListTag = AZ::Name("uicanvas");
|
||||
passData->m_pipelineViewTag = AZ::Name("MainCamera");
|
||||
passTemplate->m_passData = AZStd::move(passData);
|
||||
|
||||
// Create a pass descriptor for the new child pass
|
||||
AZ::RPI::PassDescriptor childDesc;
|
||||
childDesc.m_passTemplate = passTemplate;
|
||||
childDesc.m_passName = AZ::Name("LyShineChildPass");
|
||||
|
||||
AZ::RPI::PassSystemInterface* passSystem = AZ::RPI::PassSystemInterface::Get();
|
||||
m_uiCanvasChildPass = passSystem->CreatePass<LyShineChildPass>(childDesc);
|
||||
AZ_Assert(m_uiCanvasChildPass, "[LyShinePass] Unable to create %s.", passTemplate->m_name.GetCStr());
|
||||
}
|
||||
|
||||
// Store the info needed to set up frame graph dependencies
|
||||
m_uiCanvasChildPass->m_attachmentImageDependencies.clear();
|
||||
for (const auto& attachmentImageAndDescendents : AttachmentImagesAndDependencies)
|
||||
{
|
||||
m_uiCanvasChildPass->m_attachmentImageDependencies.emplace_back(attachmentImageAndDescendents.first);
|
||||
}
|
||||
|
||||
AddChild(m_uiCanvasChildPass);
|
||||
}
|
||||
|
||||
AZ::RPI::Ptr<LyShineChildPass> LyShineChildPass::Create(const AZ::RPI::PassDescriptor& descriptor)
|
||||
{
|
||||
return aznew LyShineChildPass(descriptor);
|
||||
}
|
||||
|
||||
LyShineChildPass::LyShineChildPass(const AZ::RPI::PassDescriptor& descriptor)
|
||||
: RasterPass(descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
LyShineChildPass::~LyShineChildPass()
|
||||
{
|
||||
}
|
||||
|
||||
void LyShineChildPass::SetupFrameGraphDependencies(AZ::RHI::FrameGraphInterface frameGraph)
|
||||
{
|
||||
AZ::RPI::RasterPass::SetupFrameGraphDependencies(frameGraph);
|
||||
|
||||
for (auto attachmentImage : m_attachmentImageDependencies)
|
||||
{
|
||||
// Ensure that the image is imported into the attachment database.
|
||||
// The image may not be imported if the owning pass has been disabled.
|
||||
auto attachmentImageId = attachmentImage->GetAttachmentId();
|
||||
if (!frameGraph.GetAttachmentDatabase().IsAttachmentValid(attachmentImageId))
|
||||
{
|
||||
frameGraph.GetAttachmentDatabase().ImportImage(attachmentImageId, attachmentImage->GetRHIImage());
|
||||
}
|
||||
|
||||
AZ::RHI::ImageScopeAttachmentDescriptor desc;
|
||||
desc.m_attachmentId = attachmentImageId;
|
||||
desc.m_imageViewDescriptor = attachmentImage->GetImageView()->GetDescriptor();
|
||||
desc.m_loadStoreAction.m_loadAction = AZ::RHI::AttachmentLoadAction::Load;
|
||||
|
||||
frameGraph.UseShaderAttachment(desc, AZ::RHI::ScopeAttachmentAccess::Read);
|
||||
}
|
||||
}
|
||||
|
||||
AZ::RPI::Ptr<RttChildPass> RttChildPass::Create(const AZ::RPI::PassDescriptor& descriptor)
|
||||
{
|
||||
return aznew RttChildPass(descriptor);
|
||||
}
|
||||
|
||||
RttChildPass::RttChildPass(const AZ::RPI::PassDescriptor& descriptor)
|
||||
: LyShineChildPass(descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
RttChildPass::~RttChildPass()
|
||||
{
|
||||
}
|
||||
|
||||
void RttChildPass::BuildInternal()
|
||||
{
|
||||
AttachImageToSlot(AZ::Name("RenderTargetOutput"), m_attachmentImage);
|
||||
}
|
||||
} // namespace LyShine
|
||||
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RPI.Public/Pass/ParentPass.h>
|
||||
#include <Atom/RPI.Public/Pass/RasterPass.h>
|
||||
#include <AtomCore/std/containers/array_view.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include "LyShinePassDataBus.h"
|
||||
|
||||
namespace LyShine
|
||||
{
|
||||
class LyShineChildPass;
|
||||
|
||||
//! Manages child passes at runtime that render to render targets
|
||||
class LyShinePass final
|
||||
: public AZ::RPI::ParentPass
|
||||
, protected LyShinePassRequestBus::Handler
|
||||
{
|
||||
AZ_RPI_PASS(LyShinePass);
|
||||
using Base = AZ::RPI::ParentPass;
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(LyShinePass, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(LyShinePass, "C3B812ED-3771-42F4-A96F-EBD94B4D54CA", Base);
|
||||
|
||||
virtual ~LyShinePass();
|
||||
static AZ::RPI::Ptr<LyShinePass> Create(const AZ::RPI::PassDescriptor& descriptor);
|
||||
|
||||
protected:
|
||||
// Pass behavior overrides
|
||||
void ResetInternal() override;
|
||||
void BuildInternal() override;
|
||||
|
||||
// LyShinePassRequestBus overrides
|
||||
void RebuildRttChildren() override;
|
||||
AZ::RPI::RasterPass* GetRttPass(const AZStd::string& name) override;
|
||||
AZ::RPI::RasterPass* GetUiCanvasPass() override;
|
||||
|
||||
private:
|
||||
LyShinePass() = delete;
|
||||
explicit LyShinePass(const AZ::RPI::PassDescriptor& descriptor);
|
||||
|
||||
// Build the render to texture child passes
|
||||
void AddRttChildPasses(LyShine::AttachmentImagesAndDependencies AttachmentImagesAndDependencies);
|
||||
|
||||
// Add a render to texture child pass
|
||||
void AddRttChildPass(AZ::Data::Instance<AZ::RPI::AttachmentImage> attachmentImage, AttachmentImages dependentAttachmentImages);
|
||||
|
||||
// Append the final pass to render UI Canvas elements to the screen
|
||||
void AddUiCanvasChildPass(LyShine::AttachmentImagesAndDependencies AttachmentImagesAndDependencies);
|
||||
|
||||
// Pass that renders the UI Canvas elements to the screen
|
||||
AZ::RPI::Ptr<LyShineChildPass> m_uiCanvasChildPass;
|
||||
};
|
||||
|
||||
// Child pass with potential attachment dependencies
|
||||
class LyShineChildPass
|
||||
: public AZ::RPI::RasterPass
|
||||
{
|
||||
AZ_RPI_PASS(LyShineChildPass);
|
||||
|
||||
friend class LyShinePass;
|
||||
public:
|
||||
AZ_RTTI(LyShineChildPass, "{41D525F9-09EB-4004-97DC-082078FF8DD2}", RasterPass);
|
||||
AZ_CLASS_ALLOCATOR(LyShineChildPass, AZ::SystemAllocator, 0);
|
||||
virtual ~LyShineChildPass();
|
||||
|
||||
//! Creates a LyShineChildPass
|
||||
static AZ::RPI::Ptr<LyShineChildPass> Create(const AZ::RPI::PassDescriptor& descriptor);
|
||||
|
||||
protected:
|
||||
LyShineChildPass(const AZ::RPI::PassDescriptor& descriptor);
|
||||
|
||||
// Scope producer Overrides...
|
||||
void SetupFrameGraphDependencies(AZ::RHI::FrameGraphInterface frameGraph) override;
|
||||
|
||||
AttachmentImages m_attachmentImageDependencies;
|
||||
};
|
||||
|
||||
// Child pass that renders UI elements to a render target
|
||||
class RttChildPass
|
||||
: public LyShineChildPass
|
||||
{
|
||||
AZ_RPI_PASS(RttChildPass);
|
||||
|
||||
friend class LyShinePass;
|
||||
|
||||
public:
|
||||
AZ_RTTI(RttChildPass, "{54B0574D-2EB3-4054-9E1D-0E0D9C8CB09A}", LyShineChildPass);
|
||||
AZ_CLASS_ALLOCATOR(RttChildPass, AZ::SystemAllocator, 0);
|
||||
virtual ~RttChildPass();
|
||||
|
||||
//! Creates a RttChildPass
|
||||
static AZ::RPI::Ptr<RttChildPass> Create(const AZ::RPI::PassDescriptor& descriptor);
|
||||
|
||||
protected:
|
||||
RttChildPass(const AZ::RPI::PassDescriptor& descriptor);
|
||||
|
||||
// Pass behavior overrides
|
||||
void BuildInternal() override;
|
||||
|
||||
AZ::Data::Instance<AZ::RPI::AttachmentImage> m_attachmentImage;
|
||||
};
|
||||
} // namespace LyShine
|
||||
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AtomCore/Instance/Instance.h>
|
||||
#include <Atom/RPI.Public/Base.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RPI
|
||||
{
|
||||
class AttachmentImage;
|
||||
class RasterPass;
|
||||
}
|
||||
}
|
||||
|
||||
namespace LyShine
|
||||
{
|
||||
using AttachmentImages = AZStd::vector<AZ::Data::Instance<AZ::RPI::AttachmentImage>>;
|
||||
using AttachmentImageAndDependentsPair = AZStd::pair<AZ::Data::Instance<AZ::RPI::AttachmentImage>, AttachmentImages>;
|
||||
using AttachmentImagesAndDependencies = AZStd::vector<AttachmentImageAndDependentsPair>;
|
||||
}
|
||||
|
||||
class LyShinePassRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
|
||||
using BusIdType = AZ::RPI::SceneId;
|
||||
|
||||
//! Called when the number of render targets has changed and the LyShine pass needs to rebuild
|
||||
virtual void RebuildRttChildren() = 0;
|
||||
|
||||
//! Returns a render to texture pass based on render target name
|
||||
virtual AZ::RPI::RasterPass* GetRttPass(const AZStd::string& name) = 0;
|
||||
|
||||
//! Returns the final pass that renders the UI canvas contents
|
||||
virtual AZ::RPI::RasterPass* GetUiCanvasPass() = 0;
|
||||
};
|
||||
using LyShinePassRequestBus = AZ::EBus<LyShinePassRequests>;
|
||||
|
||||
class LyShinePassDataRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
|
||||
using BusIdType = AZ::RPI::SceneId;
|
||||
|
||||
//! Get a list of render targets that require a render to texture pass, and any
|
||||
//! other render targets that are drawn on them
|
||||
virtual LyShine::AttachmentImagesAndDependencies GetRenderTargets() = 0;
|
||||
};
|
||||
using LyShinePassDataRequestBus = AZ::EBus<LyShinePassDataRequests>;
|
||||
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace LyShine
|
||||
{
|
||||
//! Ebus to handle render target requests
|
||||
class RenderToTextureRequests
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
virtual AZ::RHI::AttachmentId UseRenderTarget(const AZ::Name& renderTargetName, AZ::RHI::Size size) = 0;
|
||||
virtual void ReleaseRenderTarget(const AZ::RHI::AttachmentId& attachmentId) = 0;
|
||||
virtual AZ::Data::Instance<AZ::RPI::AttachmentImage> GetRenderTarget(const AZ::RHI::AttachmentId& attachmentId) = 0;
|
||||
};
|
||||
|
||||
using RenderToTextureRequestBus = AZ::EBus<RenderToTextureRequests>;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"Name": "LyShinePass",
|
||||
"TemplateName": "LyShineParentTemplate",
|
||||
"Connections": [
|
||||
{
|
||||
"LocalSlot": "ColorInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DebugOverlayPass",
|
||||
"Attachment": "InputOutput"
|
||||
}
|
||||
},
|
||||
{
|
||||
"LocalSlot": "DepthInputOutput",
|
||||
"AttachmentRef": {
|
||||
"Pass": "DepthPrePass",
|
||||
"Attachment": "Depth"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
"""
|
||||
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
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Parse arguments
|
||||
if len(sys.argv) != 3:
|
||||
print('Incorrect number of args')
|
||||
exit()
|
||||
|
||||
engine_path = sys.argv[1]
|
||||
if not os.path.exists(engine_path):
|
||||
print(f'Given path {engine_path} does not exist')
|
||||
exit()
|
||||
|
||||
project_path = sys.argv[2]
|
||||
if not os.path.exists(project_path):
|
||||
print(f'Given path {project_path} does not exist')
|
||||
exit()
|
||||
|
||||
sys.path.insert(0, os.path.join(engine_path, 'Gems/Atom/RPI/Tools/'))
|
||||
|
||||
from atom_rpi_tools.pass_data import PassTemplate
|
||||
import atom_rpi_tools.utils as utils
|
||||
|
||||
# Folder of this py file
|
||||
dir_name = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
# Patch render pipeline to insert a custom LyShine parent pass
|
||||
|
||||
# Gem::Atom_Feature_Common gem's path since default render pipeline is comming from this gem
|
||||
gem_assets_path = os.path.join(engine_path,'Gems/Atom/feature/Common/Assets/')
|
||||
|
||||
pipeline_relatvie_path = 'Passes/MainPipeline.pass'
|
||||
srcRenderPipeline = os.path.join(gem_assets_path, pipeline_relatvie_path)
|
||||
destRenderPipeline = os.path.join(project_path, pipeline_relatvie_path)
|
||||
# If the project doesn't have a customized main pipeline
|
||||
# copy the default render pipeline from Atom_Common_Feature gem to same path in project folder
|
||||
utils.find_or_copy_file(destRenderPipeline, srcRenderPipeline)
|
||||
|
||||
# Load project render pipeline
|
||||
renderPipeline = PassTemplate(destRenderPipeline)
|
||||
|
||||
# Skip if LyShinePass already exist
|
||||
newPassName = 'LyShinePass'
|
||||
if renderPipeline.find_pass(newPassName)>-1:
|
||||
print('Skip merging. LyShinePass already exists')
|
||||
exit()
|
||||
|
||||
# Insert LyShinePass between DebugOverlayPass and UIPass
|
||||
refPass = 'DebugOverlayPass'
|
||||
# The data file for new pass request is in the same folder of the py file
|
||||
newPassRequestFilePath = os.path.join(dir_name, 'LyShinePass.data')
|
||||
newPassRequestData = utils.load_json_file(newPassRequestFilePath)
|
||||
insertIndex = renderPipeline.find_pass(refPass) + 1
|
||||
if insertIndex>-1:
|
||||
renderPipeline.insert_pass_request(insertIndex, newPassRequestData)
|
||||
else:
|
||||
print('Failed to find ', refPass)
|
||||
exit()
|
||||
|
||||
# Update attachment references for the passes following LyShinePass
|
||||
renderPipeline.replace_references_after(newPassName, 'DebugOverlayPass', 'InputOutput', 'LyShinePass', 'ColorInputOutput')
|
||||
|
||||
# Save the updated render pipeline
|
||||
renderPipeline.save()
|
||||
Loading…
Reference in New Issue