Multiple bug fixes (#6221)

* Multiple bug fixes
 - Handle Dx12 validation error related to multiple resource transitions happening on the same resource.
 - Added API to better query for image/buffer views associated with an attachment.
 - Address possible serialization issues by usage of size_t
 - Reduced number of Descriptor sets allowed per SRG Pool in order to reduce descriptor waste.

Signed-off-by: moudgils <47460854+moudgils@users.noreply.github.com>

* Addressed minor feedback

Signed-off-by: moudgils <47460854+moudgils@users.noreply.github.com>

* Fix compile issues

Signed-off-by: moudgils <47460854+moudgils@users.noreply.github.com>

* Missed a few other fixes

Signed-off-by: moudgils <47460854+moudgils@users.noreply.github.com>
This commit is contained in:
moudgils
2021-12-09 09:45:45 -08:00
committed by GitHub
parent 4b3d1452fd
commit 3540974b08
15 changed files with 206 additions and 81 deletions
@@ -10,12 +10,7 @@
{
"Name": "DepthStencilTextureInput",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ImageViewDesc": {
"AspectFlags": [
"Depth"
]
}
"ScopeAttachmentUsage": "Shader"
},
{
"Name": "NormalInput",
@@ -127,9 +127,9 @@ namespace AZ
static void Reflect(AZ::ReflectContext* context);
ImageSubresourceLayoutPlaced() = default;
ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, size_t offset);
ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, uint32_t offset);
size_t m_offset = 0;
uint32_t m_offset = 0;
};
/**
@@ -40,78 +40,94 @@ namespace AZ
public:
FrameGraphAttachmentDatabase() = default;
/// Clears the database back to an empty state.
//! Clears the database back to an empty state.
void Clear();
/// Imports an image into the database.
//! Imports an image into the database.
ResultCode ImportImage(const AttachmentId& attachmentId, Ptr<Image> image);
/// Imports a swapchain into the database.
//! Imports a swapchain into the database.
ResultCode ImportSwapChain(const AttachmentId& attachmentId, Ptr<SwapChain> swapChain);
/// Imports a buffer into the database.
//! Imports a buffer into the database.
ResultCode ImportBuffer(const AttachmentId& attachmentId, Ptr<Buffer> buffer);
/// Creates a transient image and inserts it into the database.
//! Creates a transient image and inserts it into the database.
ResultCode CreateTransientImage(const TransientImageDescriptor& descriptor);
/// Creates a transient buffer and inserts it into the database.
//! Creates a transient buffer and inserts it into the database.
ResultCode CreateTransientBuffer(const TransientBufferDescriptor& descriptor);
/// Finds the attachment associated with \param attachmentId and returns its image descriptor.
//! Finds the attachment associated with \param attachmentId and returns its image descriptor.
ImageDescriptor GetImageDescriptor(const AttachmentId& attachmentId) const;
/// Finds the attachment associated with \param attachmentId and returns its buffer descriptor.
//! Finds the attachment associated with \param attachmentId and returns its buffer descriptor.
BufferDescriptor GetBufferDescriptor(const AttachmentId& attachmentId) const;
/// Returns whether the attachment exists in the database.
//! Returns whether the attachment exists in the database.
bool IsAttachmentValid(const AttachmentId& attachmentId) const;
/// Finds an attachment associated with \param attachmentId.
//! Finds an attachment associated with \param attachmentId.
const FrameAttachment* FindAttachment(const AttachmentId& attachmentId) const;
FrameAttachment* FindAttachment(const AttachmentId& attachmentId);
/// Finds an attachment associated with \param attachmentId and attempts to cast
/// to the requested type. Will return null if the type is not compatible, or the
/// attachment was not found.
//! Finds an attachment associated with \param attachmentId and attempts to cast
//! to the requested type. Will return null if the type is not compatible, or the
//! attachment was not found.
template <typename AttachmentType>
const AttachmentType* FindAttachment(const AttachmentId& attachmentId) const;
template <typename AttachmentType>
AttachmentType* FindAttachment(const AttachmentId& attachmentId);
/// Returns the full list of attachments.
//! Returns the full list of attachments.
const AZStd::vector<FrameAttachment*>& GetAttachments() const;
/// Returns the full list of image attachments.
//! Returns the full list of image attachments.
const AZStd::vector<ImageFrameAttachment*>& GetImageAttachments() const;
/// Returns the full list of buffer attachments.
//! Returns the full list of buffer attachments.
const AZStd::vector<BufferFrameAttachment*>& GetBufferAttachments() const;
/// Returns the transient swap chain attachments registered in the graph.
//! Returns the transient swap chain attachments registered in the graph.
const AZStd::vector<SwapChainFrameAttachment*>& GetSwapChainAttachments() const;
/// Returns the imported image attachments registered in the graph.
//! Returns the imported image attachments registered in the graph.
const AZStd::vector<ImageFrameAttachment*>& GetImportedImageAttachments() const;
/// Returns the imported buffer attachments registered in the graph.
//! Returns the imported buffer attachments registered in the graph.
const AZStd::vector<BufferFrameAttachment*>& GetImportedBufferAttachments() const;
/// Returns the transient image attachments registered in the graph.
//! Returns the transient image attachments registered in the graph.
const AZStd::vector<ImageFrameAttachment*>& GetTransientImageAttachments() const;
/// Returns the transient buffer attachments registered in the graph.
//! Returns the transient buffer attachments registered in the graph.
const AZStd::vector<BufferFrameAttachment*>& GetTransientBufferAttachments() const;
/// Finds the list of scope attachments used by a scope for the given attachment.
//! Finds the list of scope attachments used by a scope for the given attachment.
const ScopeAttachmentPtrList* FindScopeAttachmentList(const ScopeId& scopeId, const AttachmentId& attachmentId) const;
/// Finds the scope attachment used by a scope for the given attachment. If multiple scope attachments are used for the
/// same attachment (like binding multiple mips of a texture), the index parameter will specify which one to select.
const ScopeAttachment* FindScopeAttachment(const ScopeId& scopeId, const AttachmentId& attachmentId, size_t index = 0) const;
//! Finds the scope attachment used by a scope for the given attachment
const ScopeAttachment* FindScopeAttachment(const ScopeId& scopeId, const AttachmentId& attachmentId) const;
/// Returns the full list of scope attachments.
//! Finds the scope attachment used by a scope for the given attachment. If multiple scope image attachments are used for the
//! same attachment, provide ScopeAttachmentUsage (in case attachments are merged) and
//! ImageViewDescriptor (in case the attachments are different based on view, i.e different mips or aspect of a texture) to ensure
//! that the correct scope attachment is returned.
const ScopeAttachment* FindScopeAttachment(
const ScopeId& scopeId,
const AttachmentId& attachmentId,
const ImageViewDescriptor& imageViewDescriptor,
const RHI::ScopeAttachmentUsage attachmentUsage) const;
//! Finds the scope attachment used by a scope for the given attachment. If multiple scope attachments are used for the same attachment
//! provide attachmentUsage to ensure that the correct scope attachment is returned
const ScopeAttachment* FindScopeAttachment(
const ScopeId& scopeId,
const AttachmentId& attachmentId,
const RHI::ScopeAttachmentUsage attachmentUsage) const;
//! Returns the full list of scope attachments.
const ScopeAttachmentPtrList& GetScopeAttachments() const;
template <typename ScopeAttachmentType, typename... Args>
@@ -120,8 +136,8 @@ namespace AZ
FrameAttachment& attachment,
Args&&... arguments);
/// Emplaces a use of a resource pool by a specific scope. Returns the ScopeId of the most recent use of the pool or en empty
/// ScopeId if this is the first use.
//! Emplaces a use of a resource pool by a specific scope. Returns the ScopeId of the most recent use of the pool or en empty
//! ScopeId if this is the first use.
ScopeId EmplaceResourcePoolUse(ResourcePool& pool, ScopeId scopeId);
private:
@@ -8,6 +8,7 @@
#pragma once
#include <Atom/RHI.Reflect/AttachmentId.h>
#include <Atom/RHI.Reflect/AttachmentEnums.h>
#include <Atom/RHI.Reflect/ScopeId.h>
namespace AZ
@@ -19,15 +20,15 @@ namespace AZ
class BufferView;
class Image;
class ImageView;
class ScopeAttachment;
struct BufferDescriptor;
struct ImageDescriptor;
struct ImageViewDescriptor;
/**
* FrameGraphCompileContext provides access to compiled image and buffer views
* associated with the provided scope id, along with other query methods for
* accessing attachment resource data. This information can be used to
* compile ShaderResourceGroups.
*/
//! FrameGraphCompileContext provides access to compiled image and buffer views
//! associated with the provided scope id, along with other query methods for
//! accessing attachment resource data. This information can be used to
//! compile ShaderResourceGroups.
class FrameGraphCompileContext
{
public:
@@ -37,31 +38,46 @@ namespace AZ
const ScopeId& scopeId,
const FrameGraphAttachmentDatabase& attachmentDatabase);
/// Returns the scope id associated with this context.
//! Returns the scope id associated with this context.
const ScopeId& GetScopeId() const;
/// Returns whether the given attachment id is valid within the current frame.
//! Returns whether the given attachment id is valid within the current frame.
bool IsAttachmentValid(const AttachmentId& attachmentId) const;
/// Returns the number of scope attachments used by the current scope for the given attachment
//! Returns the number of scope attachments used by the current scope for the given attachment
const size_t GetScopeAttachmentCount(const AttachmentId& attachmentId) const;
/// Returns the buffer view associated with usage on the current scope.
const BufferView* GetBufferView(const AttachmentId& attachmentId, size_t index = 0) const;
//! Returns the buffer view associated with the scope attachment.
const BufferView* GetBufferView(const ScopeAttachment* scopeAttachment) const;
/// Returns the buffer associated with usage on the current scope.
//! Returns the buffer view associated with the attachmentId.
const BufferView* GetBufferView(const AttachmentId& attachmentId) const;
//! Returns the buffer view associated with attachmentId and the attachmentUsage on the current scope.
const BufferView* GetBufferView(const AttachmentId& attachmentId, RHI::ScopeAttachmentUsage attachmentUsage) const;
//! Returns the buffer associated with attachmentId.
const Buffer* GetBuffer(const AttachmentId& attachmentId) const;
/// Returns the image view associated with usage on the current scope.
const ImageView* GetImageView(const AttachmentId& attachmentId, size_t index = 0) const;
//! Returns the image view associated with the scope attachment
const ImageView* GetImageView(const ScopeAttachment* scopeAttacment) const;
/// Returns the image associated with usage on the current scope.
//! Returns the image view associated with attachmentId, attachmentUsage and imageViewDescriptor on the current scope.
const ImageView* GetImageView(
const AttachmentId& attachmentId,
const ImageViewDescriptor& imageViewDescriptor,
const RHI::ScopeAttachmentUsage attachmentUsage) const;
//! Returns the image view associated with the attachmentId.
const ImageView* GetImageView(const AttachmentId& attachmentId) const;
//! Returns the image associated with the attachmentId.
const Image* GetImage(const AttachmentId& attachmentId) const;
/// Returns the buffer descriptor for the given attachment id.
//! Returns the buffer descriptor for the given attachment id.
BufferDescriptor GetBufferDescriptor(const AttachmentId& attachmentId) const;
/// Returns the image descriptor for the given attachment id.
//! Returns the image descriptor for the given attachment id.
ImageDescriptor GetImageDescriptor(const AttachmentId& attachmentId) const;
private:
@@ -142,9 +142,6 @@ namespace AZ
}
}
// [GFX TODO][ATOM-1669]: Review if it's needed to validate
// overlapping of ranges.
return true;
}
@@ -124,7 +124,7 @@ namespace AZ
, m_blockElementHeight{blockElementHeight}
{}
ImageSubresourceLayoutPlaced::ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, size_t offset)
ImageSubresourceLayoutPlaced::ImageSubresourceLayoutPlaced(const ImageSubresourceLayout& subresourceLayout, uint32_t offset)
: ImageSubresourceLayout(subresourceLayout)
, m_offset{offset}
{}
@@ -209,7 +209,11 @@ namespace AZ
return nullptr;
}
const ScopeAttachment* FrameGraphAttachmentDatabase::FindScopeAttachment(const ScopeId& scopeId, const AttachmentId& attachmentId, size_t index) const
const ScopeAttachment* FrameGraphAttachmentDatabase::FindScopeAttachment(
const ScopeId& scopeId,
const AttachmentId& attachmentId,
const ImageViewDescriptor& imageViewDescriptor,
const RHI::ScopeAttachmentUsage attachmentUsage) const
{
const ScopeAttachmentPtrList* scopeAttachmentList = FindScopeAttachmentList(scopeId, attachmentId);
if (!scopeAttachmentList)
@@ -217,21 +221,93 @@ namespace AZ
return nullptr;
}
if (index >= scopeAttachmentList->size())
if (scopeAttachmentList->size() > 1)
{
AZ_Error("AttachmentDatabase", false,
"Attempting to access scope attachment [%d], but list only has [%d] elements. ScopeId: [%s]. AttachmentId: [%s]",
index,
scopeAttachmentList->size(),
scopeId.GetCStr(),
attachmentId.GetCStr());
//Find the attachment with the same view and usage
auto findIter = AZStd::find_if(scopeAttachmentList->begin(), scopeAttachmentList->end(), [&](const ScopeAttachment* scopeAttacment)
{
const ImageScopeAttachment* imageAttachment = azrtti_cast<const ImageScopeAttachment*>(scopeAttacment);
bool isSameView = imageAttachment->GetDescriptor().m_imageViewDescriptor.IsSameSubResource(imageViewDescriptor);
if (isSameView)
{
AZStd::vector<ScopeAttachmentUsageAndAccess> usageAndAccessVec = imageAttachment->GetUsageAndAccess();
auto usageAccessIter = AZStd::find_if(usageAndAccessVec.begin(), usageAndAccessVec.end(), [&](const ScopeAttachmentUsageAndAccess usageAndAccess)
{
return usageAndAccess.m_usage == attachmentUsage;
});
return usageAccessIter != usageAndAccessVec.end();
}
return false;
});
if (findIter != scopeAttachmentList->end())
{
return *findIter;
}
AZ_Error("AttachmentDatabase", false, "Couldnt find ScopeAttachment %s with the same view and usage for scope %s", attachmentId.GetCStr(), scopeId.GetCStr());
return nullptr;
}
else
{
return (*scopeAttachmentList)[0];
}
}
const ScopeAttachment* FrameGraphAttachmentDatabase::FindScopeAttachment(
const ScopeId& scopeId,
const AttachmentId& attachmentId,
const RHI::ScopeAttachmentUsage attachmentUsage) const
{
const ScopeAttachmentPtrList* scopeAttachmentList = FindScopeAttachmentList(scopeId, attachmentId);
if (!scopeAttachmentList)
{
return nullptr;
}
return (*scopeAttachmentList)[index];
}
//More than one entry indicates that the same attachment is used multiple times in a scope.
if (scopeAttachmentList->size() > 1)
{
//Find the attachment with the same usage
auto findIter = AZStd::find_if(scopeAttachmentList->begin(), scopeAttachmentList->end(), [&](const ScopeAttachment* scopeAttacment)
{
AZStd::vector<ScopeAttachmentUsageAndAccess> usageAndAccessVec = scopeAttacment->GetUsageAndAccess();
auto usageAccessIter = AZStd::find_if(usageAndAccessVec.begin(), usageAndAccessVec.end(), [&](const ScopeAttachmentUsageAndAccess usageAndAccess)
{
return usageAndAccess.m_usage == attachmentUsage;
});
return usageAccessIter != usageAndAccessVec.end();
});
if (findIter != scopeAttachmentList->end())
{
return *findIter;
}
AZ_Error("AttachmentDatabase", false, "Couldnt find ScopeAttachment %s with the same view and usage for scope %s", attachmentId.GetCStr(), scopeId.GetCStr());
return nullptr;
}
else
{
return (*scopeAttachmentList)[0];
}
}
const ScopeAttachment* FrameGraphAttachmentDatabase::FindScopeAttachment(const ScopeId& scopeId, const AttachmentId& attachmentId) const
{
const ScopeAttachmentPtrList* scopeAttachmentList = FindScopeAttachmentList(scopeId, attachmentId);
if (!scopeAttachmentList)
{
return nullptr;
}
AZ_Error( "AttachmentDatabase", scopeAttachmentList->size() > 0, "Couldnt fine Scopeattachment %s for scope %s", attachmentId.GetCStr(), scopeId.GetCStr());
return (*scopeAttachmentList)[0];
}
const AZStd::vector<ImageFrameAttachment*>& FrameGraphAttachmentDatabase::GetImageAttachments() const
{
return m_imageAttachments;
@@ -40,9 +40,8 @@ namespace AZ
return 0;
}
const BufferView* FrameGraphCompileContext::GetBufferView(const AttachmentId& attachmentId, size_t index) const
const BufferView* FrameGraphCompileContext::GetBufferView(const ScopeAttachment* scopeAttacment) const
{
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId, index);
const BufferScopeAttachment* attachment = azrtti_cast<const BufferScopeAttachment*>(scopeAttacment);
if (!attachment)
{
@@ -51,6 +50,18 @@ namespace AZ
return attachment->GetBufferView();
}
const BufferView* FrameGraphCompileContext::GetBufferView(const AttachmentId& attachmentId) const
{
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId);
return GetBufferView(scopeAttacment);
}
const BufferView* FrameGraphCompileContext::GetBufferView(const AttachmentId& attachmentId, const RHI::ScopeAttachmentUsage attachmentUsage) const
{
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId, attachmentUsage);
return GetBufferView(scopeAttacment);
}
const Buffer* FrameGraphCompileContext::GetBuffer(const AttachmentId& attachmentId) const
{
const BufferView* bufferView = GetBufferView(attachmentId);
@@ -61,9 +72,8 @@ namespace AZ
return nullptr;
}
const ImageView* FrameGraphCompileContext::GetImageView(const AttachmentId& attachmentId, size_t index) const
const ImageView* FrameGraphCompileContext::GetImageView(const ScopeAttachment* scopeAttacment) const
{
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId, index);
const ImageScopeAttachment* attachment = azrtti_cast<const ImageScopeAttachment*>(scopeAttacment);
if (!attachment)
{
@@ -72,6 +82,18 @@ namespace AZ
return attachment->GetImageView();
}
const ImageView* FrameGraphCompileContext::GetImageView(const AttachmentId& attachmentId, const ImageViewDescriptor& imageViewDescriptor, RHI::ScopeAttachmentUsage attachmentUsage) const
{
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId, imageViewDescriptor, attachmentUsage);
return GetImageView(scopeAttacment);
}
const ImageView* FrameGraphCompileContext::GetImageView(const AttachmentId& attachmentId) const
{
const ScopeAttachment* scopeAttacment = m_attachmentDatabase->FindScopeAttachment(m_scopeId, attachmentId);
return GetImageView(scopeAttacment);
}
const Image* FrameGraphCompileContext::GetImage(const AttachmentId& attachmentId) const
{
const ImageView* imageView = GetImageView(attachmentId);
@@ -112,6 +112,8 @@ namespace AZ
{
infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE);
//Un-comment this if you want to break on warnings too
//infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_WARNING, TRUE);
}
}
+1 -1
View File
@@ -72,7 +72,7 @@ namespace AZ
{
const RHI::ImageDescriptor& imageDescriptor = GetDescriptor();
size_t byteOffset = 0;
uint32_t byteOffset = 0;
if (subresourceLayouts)
{
@@ -376,7 +376,7 @@ namespace AZ
void Image::GetSubresourceLayoutsInternal(const RHI::ImageSubresourceRange& subresourceRange, RHI::ImageSubresourceLayoutPlaced* subresourceLayouts, size_t* totalSizeInBytes) const
{
const RHI::ImageDescriptor& imageDescriptor = GetDescriptor();
size_t byteOffset = 0;
uint32_t byteOffset = 0;
const uint32_t offsetAligment = 4;
for (uint16_t arraySlice = subresourceRange.m_arraySliceMin; arraySlice <= subresourceRange.m_mipSliceMax; ++arraySlice)
{
@@ -398,7 +398,7 @@ namespace AZ
layout.m_size = subresourceLayout.m_size;
}
byteOffset = RHI::AlignUp(byteOffset + static_cast<uint64_t>(subresourceLayout.m_bytesPerImage) * subresourceLayout.m_size.m_depth, offsetAligment);
byteOffset = RHI::AlignUp(byteOffset + subresourceLayout.m_bytesPerImage * subresourceLayout.m_size.m_depth, offsetAligment);
}
}
@@ -54,8 +54,8 @@ namespace AZ
}
m_descriptorSetAllocator = RHI::Ptr<DescriptorSetAllocator>(aznew DescriptorSetAllocator);
// [GFX_TODO] ATOM-679 Set a proper pool size.
const uint32_t descriptorSetsPerPool = 100;
// [GFX_TODO] ATOM-16891 - Refactor Descriptor management system
const uint32_t descriptorSetsPerPool = 20;
DescriptorSetAllocator::Descriptor allocatorDescriptor;
allocatorDescriptor.m_device = &device;
allocatorDescriptor.m_layout = m_descriptorSetLayout.get();
@@ -37,7 +37,7 @@ namespace AZ
ResourcePoolAssetType m_poolType = ResourcePoolAssetType::Unknown;
AZStd::string m_poolName = "Unknown";
size_t m_budgetInBytes = 0;
uint32_t m_budgetInBytes = 0;
// Configuration for buffer pool
RHI::HeapMemoryLevel m_heapMemoryLevel = RHI::HeapMemoryLevel::Device;
@@ -276,7 +276,8 @@ namespace AZ
{
inputIndex = imageIndex;
}
const RHI::ImageView* imageView = context.GetImageView(attachment->GetAttachmentId(), binding.m_attachmentUsageIndex);
const RHI::ImageView* imageView =
context.GetImageView(attachment->GetAttachmentId(), binding.m_unifiedScopeDesc.GetImageViewDescriptor(), binding.m_scopeAttachmentUsage);
if (binding.m_shaderImageDimensionsNameIndex.HasName())
{
@@ -315,7 +316,7 @@ namespace AZ
{
inputIndex = bufferIndex;
}
const RHI::BufferView* bufferView = context.GetBufferView(attachment->GetAttachmentId(), binding.m_attachmentUsageIndex);
const RHI::BufferView* bufferView = context.GetBufferView(attachment->GetAttachmentId(), binding.m_scopeAttachmentUsage);
m_shaderResourceGroup->SetBufferView(RHI::ShaderInputBufferIndex(inputIndex), bufferView, arrayIndex);
++bufferIndex;
}
@@ -112,12 +112,12 @@ namespace UnitTest
: AZ::RHI::ShaderStageFunction(shaderStage)
{}
void SetIndex(size_t index)
void SetIndex(uint32_t index)
{
m_index = index;
}
size_t m_index;
int32_t m_index;
ShaderByteCode m_byteCode;