Vulkan fixes (#4710)

* Disable partial Descriptor Set updates as Vk validation layer does not like that

Signed-off-by: moudgils <moudgils@amazon.com>

* Enable parallel encoding for Vulkan
Disable partial SRG updates for Vk as the validation layer did not like that. There is a way to just updat SRG constants but that will require more work
Fix a bunch of Vulkan validation errors (mostly the ones spammming each frame)

Signed-off-by: moudgils <moudgils@amazon.com>

* Minor feedback update

Signed-off-by: moudgils <moudgils@amazon.com>
This commit is contained in:
moudgils
2021-10-15 13:35:28 -07:00
committed by GitHub
parent f9b6afccab
commit 693d849bd1
17 changed files with 117 additions and 78 deletions
@@ -507,7 +507,8 @@ namespace AZ
}
}
//Check if buffer view data changed from previous frame.
// Check if buffer view data changed from previous frame.
// Look into making 'm_meshBuffers != meshBuffers' faster by possibly building a crc and doing a crc check.
if (m_meshBuffers.size() != meshBuffers.size() || m_meshBuffers != meshBuffers)
{
m_meshBuffers = meshBuffers;
+1 -3
View File
@@ -109,13 +109,11 @@ namespace AZ
{
if (attachment->GetFirstScopeAttachment() == nullptr)
{
//We allow the rendering to continue even if an attachment is not used.
AZ_Error(
"FrameGraph", false,
"Invalid State: attachment '%s' was added but never used!",
attachment->GetId().GetCStr());
Clear();
return ResultCode::InvalidOperation;
}
}
}
@@ -111,13 +111,19 @@ namespace AZ
{
AZStd::lock_guard<AZStd::shared_mutex> lock(m_groupsToCompileMutex);
AZ_Assert(!shaderResourceGroup.IsQueuedForCompile(), "Attempting to compile an SRG that's already been queued for compile. Only compile an SRG once per frame.");
bool isQueuedForCompile = shaderResourceGroup.IsQueuedForCompile();
AZ_Warning(
"ShaderResourceGroupPool", !isQueuedForCompile,
"Attempting to compile an SRG that's already been queued for compile. Only compile an SRG once per frame.");
CalculateGroupDataDiff(shaderResourceGroup, groupData);
if (!isQueuedForCompile)
{
CalculateGroupDataDiff(shaderResourceGroup, groupData);
shaderResourceGroup.SetData(groupData);
shaderResourceGroup.SetData(groupData);
QueueForCompileNoLock(shaderResourceGroup);
QueueForCompileNoLock(shaderResourceGroup);
}
}
void ShaderResourceGroupPool::QueueForCompile(ShaderResourceGroup& group)
@@ -55,7 +55,7 @@ namespace AZ
RHI::Ptr<BufferMemory> bufferMemory;
const VkMemoryPropertyFlags flags = ConvertHeapMemoryLevel(m_descriptor.m_heapMemoryLevel) | m_descriptor.m_additionalMemoryPropertyFlags;
RHI::Ptr<Memory> memory = GetDevice().AllocateMemory(memoryRequirements.size, memoryRequirements.memoryTypeBits, flags);
RHI::Ptr<Memory> memory = GetDevice().AllocateMemory(memoryRequirements.size, memoryRequirements.memoryTypeBits, flags, m_descriptor.m_bindFlags);
if (memory)
{
@@ -822,7 +822,7 @@ namespace AZ
{
RHI::ConstPtr<ShaderResourceGroup> shaderResourceGroup;
const auto& srgBitset = pipelineLayout.GetAZSLBindingSlotsOfIndex(index);
AZStd::vector<const ShaderResourceGroup*> shaderResourceGroupList;
AZStd::fixed_vector<const ShaderResourceGroup*, RHI::Limits::Pipeline::ShaderResourceGroupCountMax> shaderResourceGroupList;
// Collect all the SRGs that are part of this descriptor set. They could be more than
// 1, so we would need to merge their values before committing the descriptor set.
for (uint32_t bindingSlot = 0; bindingSlot < srgBitset.size(); ++bindingSlot)
@@ -696,8 +696,7 @@ namespace AZ
usageFlags |=
VK_BUFFER_USAGE_INDEX_BUFFER_BIT |
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |
VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR;
}
if (RHI::CheckBitsAny(bindFlags, BindFlags::Constant))
@@ -742,12 +741,24 @@ namespace AZ
if (RHI::CheckBitsAny(bindFlags, BindFlags::RayTracingShaderTable))
{
usageFlags |= VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
usageFlags |= VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR;
}
if (ShouldApplyDeviceAddressBit(bindFlags))
{
usageFlags |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
}
return usageFlags;
}
bool ShouldApplyDeviceAddressBit(RHI::BufferBindFlags bindFlags)
{
return RHI::CheckBitsAny(
bindFlags,
RHI::BufferBindFlags::InputAssembly | RHI::BufferBindFlags::DynamicInputAssembly | RHI::BufferBindFlags::RayTracingShaderTable);
}
VkPipelineStageFlags GetSupportedPipelineStages(RHI::PipelineStateType type)
{
// These stages don't need any special queue to be supported.
@@ -82,5 +82,6 @@ namespace AZ
VkImageUsageFlags ImageUsageFlagsOfFormatFeatureFlags(VkFormatFeatureFlags formatFeatureFlags);
VkAccessFlags GetSupportedAccessFlags(VkPipelineStageFlags pipelineStageFlags);
bool ShouldApplyDeviceAddressBit(RHI::BufferBindFlags bindFlags);
}
}
@@ -185,6 +185,9 @@ namespace AZ
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR float16Int8 = {};
VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR separateDepthStencil = {};
VkDeviceCreateInfo deviceInfo = {};
deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
// If we are running Vulkan >= 1.2, then we must use VkPhysicalDeviceVulkan12Features instead
// of VkPhysicalDeviceShaderFloat16Int8FeaturesKHR or VkPhysicalDeviceSeparateDepthStencilLayoutsFeaturesKHR.
if (majorVersion >= 1 && minorVersion >= 2)
@@ -194,7 +197,14 @@ namespace AZ
vulkan12Features.shaderFloat16 = physicalDevice.GetPhysicalDeviceVulkan12Features().shaderFloat16;
vulkan12Features.shaderInt8 = physicalDevice.GetPhysicalDeviceVulkan12Features().shaderInt8;
vulkan12Features.separateDepthStencilLayouts = physicalDevice.GetPhysicalDeviceVulkan12Features().separateDepthStencilLayouts;
vulkan12Features.descriptorBindingPartiallyBound = physicalDevice.GetPhysicalDeviceVulkan12Features().separateDepthStencilLayouts;
vulkan12Features.descriptorIndexing = physicalDevice.GetPhysicalDeviceVulkan12Features().separateDepthStencilLayouts;
vulkan12Features.descriptorBindingVariableDescriptorCount = physicalDevice.GetPhysicalDeviceVulkan12Features().separateDepthStencilLayouts;
vulkan12Features.bufferDeviceAddress = physicalDevice.GetPhysicalDeviceVulkan12Features().bufferDeviceAddress;
vulkan12Features.bufferDeviceAddressMultiDevice = physicalDevice.GetPhysicalDeviceVulkan12Features().bufferDeviceAddressMultiDevice;
vulkan12Features.runtimeDescriptorArray = physicalDevice.GetPhysicalDeviceVulkan12Features().runtimeDescriptorArray;
robustness2.pNext = &vulkan12Features;
deviceInfo.pNext = &depthClipEnabled;
}
else
{
@@ -206,11 +216,11 @@ namespace AZ
float16Int8.pNext = &separateDepthStencil;
robustness2.pNext = &float16Int8;
deviceInfo.pNext = &descriptorIndexingFeatures;
}
VkDeviceCreateInfo deviceInfo = {};
deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceInfo.pNext = &descriptorIndexingFeatures;
deviceInfo.flags = 0;
deviceInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreationInfo.size());
deviceInfo.pQueueCreateInfos = queueCreationInfo.data();
@@ -740,7 +750,7 @@ namespace AZ
vkGetPhysicalDeviceQueueFamilyProperties(nativePhysicalDevice, &queueFamilyCount, m_queueFamilyProperties.data());
}
RHI::Ptr<Memory> Device::AllocateMemory(uint64_t sizeInBytes, const uint32_t memoryTypeMask, const VkMemoryPropertyFlags flags)
RHI::Ptr<Memory> Device::AllocateMemory(uint64_t sizeInBytes, const uint32_t memoryTypeMask, const VkMemoryPropertyFlags flags, const RHI::BufferBindFlags bufferBindFlags)
{
const auto& physicalDevice = static_cast<const PhysicalDevice&>(GetPhysicalDevice());
const VkPhysicalDeviceMemoryProperties& memProp = physicalDevice.GetMemoryProperties();
@@ -770,6 +780,7 @@ namespace AZ
RHI::CheckBitsAll(memoryTypesToUseMask, memoryTypeBit))
{
memoryDesc.m_memoryTypeIndex = memoryIndex;
memoryDesc.m_bufferBindFlags = bufferBindFlags;
auto result = memory->Init(*this, memoryDesc);
if (result == RHI::ResultCode::Success)
{
@@ -100,7 +100,11 @@ namespace AZ
RHI::Ptr<CommandList> AcquireCommandList(uint32_t familyQueueIndex, VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY);
RHI::Ptr<CommandList> AcquireCommandList(RHI::HardwareQueueClass queueClass, VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY);
RHI::Ptr<Memory> AllocateMemory(uint64_t sizeInBytes, const uint32_t memoryTypeMask, const VkMemoryPropertyFlags flags);
RHI::Ptr<Memory> AllocateMemory(
uint64_t sizeInBytes,
const uint32_t memoryTypeMask,
const VkMemoryPropertyFlags flags,
const RHI::BufferBindFlags bufferBindFlags = RHI::BufferBindFlags::None);
uint32_t GetCurrentFrameIndex() const;
@@ -59,7 +59,9 @@ namespace AZ
void FrameGraphExecuteGroupMerged::BeginInternal()
{
m_commandList = AcquireCommandList(VK_COMMAND_BUFFER_LEVEL_PRIMARY);
m_commandList->BeginCommandBuffer();
m_workRequest.m_commandList = m_commandList;
}
void FrameGraphExecuteGroupMerged::EndInternal()
@@ -41,9 +41,7 @@ namespace AZ
RETURN_RESULT_IF_UNSUCCESSFUL(result);
}
// Set the command list and renderpass contexts.
m_primaryCommandList = device.AcquireCommandList(m_hardwareQueueClass);
group->SetPrimaryCommandList(*m_primaryCommandList);
// Set the renderpass contexts.
group->SetRenderPasscontexts(m_renderPassContexts);
return RHI::ResultCode::Success;
@@ -54,7 +52,8 @@ namespace AZ
AZ_Assert(m_executeGroups.size() == 1, "Too many execute groups when initializing context");
FrameGraphExecuteGroupBase* group = static_cast<FrameGraphExecuteGroupBase*>(m_executeGroups.back());
AddWorkRequest(group->GetWorkRequest());
m_workRequest.m_commandList = m_primaryCommandList;
//Merged handler will only have one commandlist.
m_workRequest.m_commandList = group->GetCommandLists()[0];
}
}
}
@@ -31,7 +31,12 @@ namespace AZ
{
return static_cast<Device&>(Base::GetDevice());
}
FrameGraphExecuter::FrameGraphExecuter()
{
SetJobPolicy(RHI::JobPolicy::Parallel);
}
RHI::ResultCode FrameGraphExecuter::InitInternal(const RHI::FrameGraphExecuterDescriptor& descriptor)
{
const RHI::ConstPtr<RHI::PlatformLimitsDescriptor> rhiPlatformLimitsDescriptor = descriptor.m_platformLimitsDescriptor;
@@ -35,6 +35,8 @@ namespace AZ
Device& GetDevice() const;
private:
FrameGraphExecuter();
//////////////////////////////////////////////////////////////////////////
// RHI::FrameGraphExecuter
RHI::ResultCode InitInternal(const RHI::FrameGraphExecuterDescriptor& descriptor) override;
@@ -7,6 +7,7 @@
*/
#include <AzCore/std/parallel/lock.h>
#include <Atom/RHI.Reflect/Bits.h>
#include <Atom/RHI.Reflect/BufferDescriptor.h>
#include <RHI/Memory.h>
#include <RHI/Conversion.h>
#include <RHI/Device.h>
@@ -31,6 +32,15 @@ namespace AZ
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = descriptor.m_sizeInBytes;
allocInfo.memoryTypeIndex = descriptor.m_memoryTypeIndex;
VkMemoryAllocateFlagsInfo memAllocInfo{};
if (ShouldApplyDeviceAddressBit(descriptor.m_bufferBindFlags))
{
memAllocInfo.flags |= VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
}
memAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
allocInfo.pNext = &memAllocInfo;
VkDeviceMemory deviceMemory;
VkResult vkResult = vkAllocateMemory(device.GetNativeDevice(), &allocInfo, nullptr, &deviceMemory);
AZ_Error(
@@ -37,6 +37,7 @@ namespace AZ
{
VkDeviceSize m_sizeInBytes = 0;
uint32_t m_memoryTypeIndex = 0;
RHI::BufferBindFlags m_bufferBindFlags = RHI::BufferBindFlags::None;
};
~Memory() = default;
@@ -38,7 +38,7 @@ namespace AZ
static RHI::Ptr<MergedShaderResourceGroupPool> Create();
using ShaderResourceGroupList = AZStd::vector<const ShaderResourceGroup*>;
using ShaderResourceGroupList = AZStd::fixed_vector<const ShaderResourceGroup*, RHI::Limits::Pipeline::ShaderResourceGroupCountMax>;
//! Finds or create a new instance of a MergedShaderResourceGroup.
//! @param shaderResourceGroupList The list of ShaderResourceGroups that are being merged.
MergedShaderResourceGroup* FindOrCreate(const ShaderResourceGroupList& shaderResourceGroupList);
@@ -115,77 +115,65 @@ namespace AZ
const RHI::ShaderResourceGroupLayout* layout = groupData.GetLayout();
if (groupData.IsResourceTypeEnabledForCompilation(static_cast<uint32_t>(RHI::ShaderResourceGroupData::ResourceTypeMask::BufferViewMask)))
for (uint32_t groupIndex = 0; groupIndex < static_cast<uint32_t>(layout->GetShaderInputListForBuffers().size()); ++groupIndex)
{
for (uint32_t groupIndex = 0; groupIndex < static_cast<uint32_t>(layout->GetShaderInputListForBuffers().size()); ++groupIndex)
{
const RHI::ShaderInputBufferIndex index(groupIndex);
auto bufViews = groupData.GetBufferViewArray(index);
uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::BufferView);
descriptorSet.UpdateBufferViews(layoutIndex, bufViews);
}
const RHI::ShaderInputBufferIndex index(groupIndex);
auto bufViews = groupData.GetBufferViewArray(index);
uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::BufferView);
descriptorSet.UpdateBufferViews(layoutIndex, bufViews);
}
if (groupData.IsResourceTypeEnabledForCompilation(static_cast<uint32_t>(RHI::ShaderResourceGroupData::ResourceTypeMask::ImageViewMask)))
auto const& shaderImageList = layout->GetShaderInputListForImages();
for (uint32_t groupIndex = 0; groupIndex < static_cast<uint32_t>(shaderImageList.size()); ++groupIndex)
{
auto const& shaderImageList = layout->GetShaderInputListForImages();
for (uint32_t groupIndex = 0; groupIndex < static_cast<uint32_t>(layout->GetShaderInputListForImages().size()); ++groupIndex)
{
const RHI::ShaderInputImageIndex index(groupIndex);
auto imgViews = groupData.GetImageViewArray(index);
uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::ImageView);
descriptorSet.UpdateImageViews(layoutIndex, imgViews, shaderImageList[groupIndex].m_type);
}
const RHI::ShaderInputImageIndex index(groupIndex);
auto imgViews = groupData.GetImageViewArray(index);
uint32_t layoutIndex =
m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::ImageView);
descriptorSet.UpdateImageViews(layoutIndex, imgViews, shaderImageList[groupIndex].m_type);
}
if (groupData.IsResourceTypeEnabledForCompilation(static_cast<uint32_t>(RHI::ShaderResourceGroupData::ResourceTypeMask::BufferViewUnboundedArrayMask)))
for (uint32_t groupIndex = 0; groupIndex < static_cast<uint32_t>(layout->GetShaderInputListForBufferUnboundedArrays().size()); ++groupIndex)
{
for (uint32_t groupIndex = 0; groupIndex < static_cast<uint32_t>(layout->GetShaderInputListForBufferUnboundedArrays().size()); ++groupIndex)
const RHI::ShaderInputBufferUnboundedArrayIndex index(groupIndex);
auto bufViews = groupData.GetBufferViewUnboundedArray(index);
if (bufViews.empty())
{
const RHI::ShaderInputBufferUnboundedArrayIndex index(groupIndex);
auto bufViews = groupData.GetBufferViewUnboundedArray(index);
if (bufViews.empty())
{
// skip empty unbounded arrays
continue;
}
uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::BufferViewUnboundedArray);
descriptorSet.UpdateBufferViews(layoutIndex, bufViews);
// skip empty unbounded arrays
continue;
}
uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::BufferViewUnboundedArray);
descriptorSet.UpdateBufferViews(layoutIndex, bufViews);
}
if (groupData.IsResourceTypeEnabledForCompilation(static_cast<uint32_t>(RHI::ShaderResourceGroupData::ResourceTypeMask::ImageViewUnboundedArrayMask)))
auto const& shaderImageUnboundeArrayList = layout->GetShaderInputListForImageUnboundedArrays();
for (uint32_t groupIndex = 0; groupIndex < static_cast<uint32_t>(shaderImageUnboundeArrayList.size()); ++groupIndex)
{
auto const& shaderImageUnboundeArrayList = layout->GetShaderInputListForImageUnboundedArrays();
for (uint32_t groupIndex = 0; groupIndex < static_cast<uint32_t>(layout->GetShaderInputListForImageUnboundedArrays().size()); ++groupIndex)
const RHI::ShaderInputImageUnboundedArrayIndex index(groupIndex);
auto imgViews = groupData.GetImageViewUnboundedArray(index);
if (imgViews.empty())
{
const RHI::ShaderInputImageUnboundedArrayIndex index(groupIndex);
auto imgViews = groupData.GetImageViewUnboundedArray(index);
if (imgViews.empty())
{
// skip empty unbounded arrays
continue;
}
uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::ImageViewUnboundedArray);
descriptorSet.UpdateImageViews(layoutIndex, imgViews, shaderImageUnboundeArrayList[groupIndex].m_type);
// skip empty unbounded arrays
continue;
}
uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::ImageViewUnboundedArray);
descriptorSet.UpdateImageViews(layoutIndex, imgViews, shaderImageUnboundeArrayList[groupIndex].m_type);
}
if (groupData.IsResourceTypeEnabledForCompilation(static_cast<uint32_t>(RHI::ShaderResourceGroupData::ResourceTypeMask::SamplerMask)))
for (uint32_t groupIndex = 0; groupIndex < static_cast<uint32_t>(layout->GetShaderInputListForSamplers().size()); ++groupIndex)
{
for (uint32_t groupIndex = 0; groupIndex < static_cast<uint32_t>(layout->GetShaderInputListForSamplers().size()); ++groupIndex)
{
const RHI::ShaderInputSamplerIndex index(groupIndex);
auto samplerArray = groupData.GetSamplerArray(index);
uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::Sampler);
descriptorSet.UpdateSamplers(layoutIndex, samplerArray);
}
const RHI::ShaderInputSamplerIndex index(groupIndex);
auto samplerArray = groupData.GetSamplerArray(index);
uint32_t layoutIndex =
m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::Sampler);
descriptorSet.UpdateSamplers(layoutIndex, samplerArray);
}
auto constantData = groupData.GetConstantData();
if (!constantData.empty() && groupData.IsResourceTypeEnabledForCompilation(static_cast<uint32_t>(RHI::ShaderResourceGroupData::ResourceTypeMask::ConstantDataMask)))
if (!constantData.empty())
{
descriptorSet.UpdateConstantData(constantData);
}