You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
238 lines
9.4 KiB
C++
238 lines
9.4 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <Atom/RHI/CommandList.h>
|
|
#include <Atom/RHI/ShaderResourceGroup.h>
|
|
#include <Atom/RHI/DrawListTagRegistry.h>
|
|
#include <Atom/RHI/RHISystemInterface.h>
|
|
|
|
#include <Atom/RPI.Public/RenderPipeline.h>
|
|
#include <Atom/RPI.Public/RPISystemInterface.h>
|
|
#include <Atom/RPI.Public/Scene.h>
|
|
#include <Atom/RPI.Public/View.h>
|
|
#include <Atom/RPI.Public/Pass/CopyPass.h>
|
|
#include <Atom/RPI.Public/Pass/PassUtils.h>
|
|
|
|
namespace AZ
|
|
{
|
|
namespace RPI
|
|
{
|
|
// --- Creation & Initialization ---
|
|
|
|
Ptr<CopyPass> CopyPass::Create(const PassDescriptor& descriptor)
|
|
{
|
|
Ptr<CopyPass> pass = aznew CopyPass(descriptor);
|
|
return pass;
|
|
}
|
|
|
|
CopyPass::CopyPass(const PassDescriptor& descriptor)
|
|
: RenderPass(descriptor)
|
|
{
|
|
const CopyPassData* copyData = PassUtils::GetPassData<CopyPassData>(descriptor);
|
|
|
|
if (copyData)
|
|
{
|
|
m_data = *copyData;
|
|
|
|
if (copyData->m_useCopyQueue)
|
|
{
|
|
m_hardwareQueueClass = RHI::HardwareQueueClass::Copy;
|
|
}
|
|
}
|
|
}
|
|
|
|
RHI::CopyItemType CopyPass::GetCopyItemType()
|
|
{
|
|
RHI::AttachmentType inputType = GetInputBinding(0).m_attachment->GetAttachmentType();
|
|
RHI::AttachmentType outputType = GetOutputBinding(0).m_attachment->GetAttachmentType();
|
|
|
|
RHI::CopyItemType copyType = RHI::CopyItemType::Invalid;
|
|
|
|
if (inputType == RHI::AttachmentType::Buffer && outputType == RHI::AttachmentType::Buffer)
|
|
{
|
|
copyType = RHI::CopyItemType::Buffer;
|
|
}
|
|
else if (inputType == RHI::AttachmentType::Image && outputType == RHI::AttachmentType::Image)
|
|
{
|
|
copyType = RHI::CopyItemType::Image;
|
|
}
|
|
else if (inputType == RHI::AttachmentType::Buffer && outputType == RHI::AttachmentType::Image)
|
|
{
|
|
copyType = RHI::CopyItemType::BufferToImage;
|
|
}
|
|
else if (inputType == RHI::AttachmentType::Image && outputType == RHI::AttachmentType::Buffer)
|
|
{
|
|
copyType = RHI::CopyItemType::ImageToBuffer;
|
|
}
|
|
|
|
return copyType;
|
|
}
|
|
|
|
// --- Pass behavior overrides ---
|
|
|
|
void CopyPass::BuildInternal()
|
|
{
|
|
AZ_Assert(GetInputCount() == 1 && GetOutputCount() == 1,
|
|
"CopyPass has %d inputs and %d outputs. It should have exactly one of each.",
|
|
GetInputCount(), GetOutputCount());
|
|
|
|
AZ_Assert(m_attachmentBindings.size() == 2,
|
|
"CopyPass must have exactly 2 bindings: 1 input and 1 output. %s has %d bindings.",
|
|
GetPathName().GetCStr(), m_attachmentBindings.size());
|
|
|
|
// Create transient attachment based on input if required
|
|
if (m_data.m_cloneInput)
|
|
{
|
|
const Ptr<PassAttachment>& source = GetInputBinding(0).m_attachment;
|
|
Ptr<PassAttachment> dest = source->Clone();
|
|
|
|
// Set bind flags to CopyWrite. Other bind flags will be auto-inferred by pass system
|
|
if (dest->m_descriptor.m_type == RHI::AttachmentType::Image)
|
|
{
|
|
dest->m_descriptor.m_image.m_bindFlags = RHI::ImageBindFlags::CopyWrite;
|
|
}
|
|
else if (dest->m_descriptor.m_type == RHI::AttachmentType::Buffer)
|
|
{
|
|
dest->m_descriptor.m_buffer.m_bindFlags = RHI::BufferBindFlags::CopyWrite;
|
|
}
|
|
|
|
// Set path name for the new attachment and add it to our attachment list
|
|
dest->ComputePathName(GetPathName());
|
|
m_ownedAttachments.push_back(dest);
|
|
|
|
// Set the output binding to the new attachment
|
|
GetOutputBinding(0).SetAttachment(dest);
|
|
}
|
|
}
|
|
|
|
// --- Scope producer functions ---
|
|
|
|
void CopyPass::SetupFrameGraphDependencies(RHI::FrameGraphInterface frameGraph)
|
|
{
|
|
RenderPass::SetupFrameGraphDependencies(frameGraph);
|
|
}
|
|
|
|
void CopyPass::CompileResources(const RHI::FrameGraphCompileContext& context)
|
|
{
|
|
RHI::CopyItemType copyType = GetCopyItemType();
|
|
switch (copyType)
|
|
{
|
|
case AZ::RHI::CopyItemType::Buffer:
|
|
CopyBuffer(context);
|
|
break;
|
|
case AZ::RHI::CopyItemType::Image:
|
|
CopyImage(context);
|
|
break;
|
|
case AZ::RHI::CopyItemType::BufferToImage:
|
|
CopyBufferToImage(context);
|
|
break;
|
|
case AZ::RHI::CopyItemType::ImageToBuffer:
|
|
CopyImageToBuffer(context);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CopyPass::BuildCommandListInternal(const RHI::FrameGraphExecuteContext& context)
|
|
{
|
|
if (m_copyItem.m_type != RHI::CopyItemType::Invalid)
|
|
{
|
|
context.GetCommandList()->Submit(m_copyItem);
|
|
}
|
|
}
|
|
|
|
// --- Copy setup functions ---
|
|
|
|
void CopyPass::CopyBuffer(const RHI::FrameGraphCompileContext& context)
|
|
{
|
|
RHI::CopyBufferDescriptor copyDesc;
|
|
|
|
// Source Buffer
|
|
PassAttachmentBinding& copySource = GetInputBinding(0);
|
|
const AZ::RHI::Buffer* sourceBuffer = context.GetBuffer(copySource.m_attachment->GetAttachmentId());
|
|
copyDesc.m_sourceBuffer = sourceBuffer;
|
|
copyDesc.m_size = static_cast<uint32_t>(sourceBuffer->GetDescriptor().m_byteCount);
|
|
copyDesc.m_sourceOffset = m_data.m_bufferSourceOffset;
|
|
|
|
// Destination Buffer
|
|
PassAttachmentBinding& copyDest = GetOutputBinding(0);
|
|
copyDesc.m_destinationBuffer = context.GetBuffer(copyDest.m_attachment->GetAttachmentId());
|
|
copyDesc.m_destinationOffset = m_data.m_bufferDestinationOffset;
|
|
|
|
m_copyItem = copyDesc;
|
|
}
|
|
|
|
void CopyPass::CopyImage(const RHI::FrameGraphCompileContext& context)
|
|
{
|
|
RHI::CopyImageDescriptor copyDesc;
|
|
|
|
// Source Image
|
|
PassAttachmentBinding& copySource = GetInputBinding(0);
|
|
const AZ::RHI::Image* sourceImage = context.GetImage(copySource.m_attachment->GetAttachmentId());
|
|
copyDesc.m_sourceImage = sourceImage;
|
|
copyDesc.m_sourceSize = sourceImage->GetDescriptor().m_size;
|
|
copyDesc.m_sourceOrigin = m_data.m_imageSourceOrigin;
|
|
copyDesc.m_sourceSubresource = m_data.m_imageSourceSubresource;
|
|
|
|
// Destination Image
|
|
PassAttachmentBinding& copyDest = GetOutputBinding(0);
|
|
copyDesc.m_destinationImage = context.GetImage(copyDest.m_attachment->GetAttachmentId());
|
|
copyDesc.m_destinationOrigin = m_data.m_imageDestinationOrigin;
|
|
copyDesc.m_destinationSubresource = m_data.m_imageDestinationSubresource;
|
|
|
|
m_copyItem = copyDesc;
|
|
}
|
|
|
|
void CopyPass::CopyBufferToImage(const RHI::FrameGraphCompileContext& context)
|
|
{
|
|
RHI::CopyBufferToImageDescriptor copyDesc;
|
|
|
|
// Source Buffer
|
|
PassAttachmentBinding& copySource = GetInputBinding(0);
|
|
const AZ::RHI::Buffer* sourceBuffer = context.GetBuffer(copySource.m_attachment->GetAttachmentId());
|
|
copyDesc.m_sourceBuffer = sourceBuffer;
|
|
copyDesc.m_sourceSize = m_data.m_sourceSize;
|
|
copyDesc.m_sourceOffset = m_data.m_bufferSourceOffset;
|
|
copyDesc.m_sourceBytesPerRow = m_data.m_bufferSourceBytesPerRow;
|
|
copyDesc.m_sourceBytesPerImage = m_data.m_bufferSourceBytesPerImage;
|
|
|
|
// Destination Image
|
|
PassAttachmentBinding& copyDest = GetOutputBinding(0);
|
|
copyDesc.m_destinationImage = context.GetImage(copyDest.m_attachment->GetAttachmentId());
|
|
copyDesc.m_destinationOrigin = m_data.m_imageDestinationOrigin;
|
|
copyDesc.m_destinationSubresource = m_data.m_imageDestinationSubresource;
|
|
|
|
m_copyItem = copyDesc;
|
|
}
|
|
|
|
void CopyPass::CopyImageToBuffer(const RHI::FrameGraphCompileContext& context)
|
|
{
|
|
RHI::CopyImageToBufferDescriptor copyDesc;
|
|
|
|
// Source Image
|
|
PassAttachmentBinding& copySource = GetInputBinding(0);
|
|
const AZ::RHI::Image* sourceImage = context.GetImage(copySource.m_attachment->GetAttachmentId());
|
|
copyDesc.m_sourceImage = sourceImage;
|
|
copyDesc.m_sourceSize = sourceImage->GetDescriptor().m_size;
|
|
copyDesc.m_sourceOrigin = m_data.m_imageSourceOrigin;
|
|
copyDesc.m_sourceSubresource = m_data.m_imageSourceSubresource;
|
|
|
|
// Destination Buffer
|
|
PassAttachmentBinding& copyDest = GetOutputBinding(0);
|
|
copyDesc.m_destinationBuffer = context.GetBuffer(copyDest.m_attachment->GetAttachmentId());
|
|
copyDesc.m_destinationOffset = m_data.m_bufferDestinationOffset;
|
|
copyDesc.m_destinationBytesPerRow = m_data.m_bufferDestinationBytesPerRow;
|
|
copyDesc.m_destinationBytesPerImage = m_data.m_bufferDestinationBytesPerImage;
|
|
|
|
m_copyItem = copyDesc;
|
|
}
|
|
|
|
} // namespace RPI
|
|
} // namespace AZ
|