summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2021-02-05 21:35:37 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-03-19 00:31:35 +0000
commit78fa6c94992a6d1a140da1354448a004e62c9683 (patch)
treec21183a39d58ba9ccc89d9d8ea6fe1aa9de2ec35 /Graphics/GraphicsEngineVulkan
parentMerged master (diff)
downloadDiligentCore-78fa6c94992a6d1a140da1354448a004e62c9683.tar.gz
DiligentCore-78fa6c94992a6d1a140da1354448a004e62c9683.zip
merged with resource_signature
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp12
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp5
-rw-r--r--Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp21
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp3
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp52
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp254
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp24
10 files changed, 223 insertions, 154 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp b/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp
index fc7b6e63..ae77ccaa 100644
--- a/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.hpp
@@ -88,7 +88,7 @@ public:
return *this;
}
- operator bool() const
+ explicit operator bool() const
{
return Set != VK_NULL_HANDLE;
}
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp
index eed3507d..25bbcb6b 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp
@@ -82,7 +82,7 @@ public:
Uint32 DescrSetIndex = ~0U;
Uint32 BindingIndex = ~0U;
- operator bool() const
+ explicit operator bool() const
{
return Signature != nullptr && Type != SHADER_RESOURCE_TYPE_UNKNOWN;
}
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp
index 56a07507..11c440b3 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp
@@ -125,7 +125,8 @@ public:
static_assert((1u << _DescrTypeBits) >= static_cast<Uint32>(DescriptorType::Count), "Not enough bits to store DescriptorType values");
static_assert((1u << _DescrSetBits) >= MAX_DESCRIPTOR_SETS, "Not enough bits to store descriptor set index");
- static_assert((1u << _BindingIndexBits) >= MAX_DESCRIPTOR_SETS, "Not enough bits to store resource binding index");
+ static_assert((1u << _BindingIndexBits) >= MAX_RESOURCES_IN_SIGNATURE, "Not enough bits to store resource binding index");
+ static_assert((1u << _SamplerIndBits) >= MAX_RESOURCES_IN_SIGNATURE, "Not enough bits to store sampler resource index");
public:
static constexpr Uint32 InvalidSamplerInd = (1u << _SamplerIndBits) - 1;
@@ -175,6 +176,7 @@ public:
DescriptorType GetDescriptorType() const { return static_cast<DescriptorType>(DescrType); }
bool IsImmutableSamplerAssigned() const { return ImtblSamplerAssigned != 0; }
+ bool IsCombinedWithSampler() const { return SamplerInd != InvalidSamplerInd; }
};
const ResourceAttribs& GetResourceAttribs(Uint32 ResIndex) const
@@ -234,6 +236,7 @@ public:
/// Implementation of IPipelineResourceSignature::IsCompatibleWith.
virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineResourceSignature* pPRS) const override final
{
+ VERIFY_EXPR(pPRS != nullptr);
return IsCompatibleWith(*ValidatedCast<const PipelineResourceSignatureVkImpl>(pPRS));
}
@@ -256,6 +259,10 @@ public:
Uint32 ResIndex,
ShaderResourceCacheVk& ResourceCache) const;
+ bool IsBound(Uint32 ArrayIndex,
+ Uint32 ResIndex,
+ ShaderResourceCacheVk& ResourceCache) const;
+
// Commits dynamic resources from ResourceCache to vkDynamicDescriptorSet
void CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache,
VkDescriptorSet vkDynamicDescriptorSet) const;
@@ -285,6 +292,7 @@ private:
CACHE_GROUP_DYN_UB = 0, // Uniform buffer with dynamic offset
CACHE_GROUP_DYN_SB, // Storage buffer with dynamic offset
CACHE_GROUP_OTHER, // Other resource type
+ CACHE_GROUP_COUNT_PER_Type,
CACHE_GROUP_DYN_UB_STAT_VAR = CACHE_GROUP_DYN_UB, // Uniform buffer with dynamic offset, static variable
CACHE_GROUP_DYN_SB_STAT_VAR = CACHE_GROUP_DYN_SB, // Storage buffer with dynamic offset, static variable
@@ -296,7 +304,7 @@ private:
CACHE_GROUP_COUNT
};
- static_assert(CACHE_GROUP_COUNT == 3 * MAX_DESCRIPTOR_SETS, "Inconsistent cache group count");
+ static_assert(CACHE_GROUP_COUNT == CACHE_GROUP_COUNT_PER_Type * MAX_DESCRIPTOR_SETS, "Inconsistent cache group count");
using CacheOffsetsType = std::array<Uint32, CACHE_GROUP_COUNT>; // [dynamic uniform buffers, dynamic storage buffers, other] x [descriptor sets] including ArraySize
using BindingCountType = std::array<Uint32, CACHE_GROUP_COUNT>; // [dynamic uniform buffers, dynamic storage buffers, other] x [descriptor sets] not counting ArraySize
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
index d65c85ac..f00f0ec4 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
@@ -126,8 +126,9 @@ private:
void InitPipelineLayout(const PipelineStateCreateInfo& CreateInfo,
TShaderStages& ShaderStages);
- void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
- TShaderStages& ShaderStages);
+ void CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo,
+ const TShaderStages& ShaderStages,
+ IPipelineResourceSignature** ppSignature);
void Destruct();
diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
index 77c5153b..26845497 100644
--- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
@@ -278,6 +278,9 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is");
// clang-format on
+ const auto& DescrIndexingFeats = DeviceExtFeatures.DescriptorIndexing;
+ ENABLE_FEATURE(DescrIndexingFeats.runtimeDescriptorArray != VK_FALSE, ShaderResourceRuntimeArray, "shader resource runtime array is");
+
ENABLE_FEATURE(DeviceExtFeatures.AccelStruct.accelerationStructure != VK_FALSE && DeviceExtFeatures.RayTracingPipeline.rayTracingPipeline != VK_FALSE, RayTracing, "Ray tracing is");
#undef FeatureSupport
@@ -401,6 +404,17 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
DeviceExtensions.push_back(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME);
}
+ if (EngineCI.Features.ShaderResourceRuntimeArray != DEVICE_FEATURE_STATE_DISABLED ||
+ EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED)
+ {
+ DeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); // required for VK_EXT_descriptor_indexing
+ DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
+
+ EnabledExtFeats.DescriptorIndexing = DescrIndexingFeats;
+
+ *NextExt = &EnabledExtFeats.DescriptorIndexing;
+ NextExt = &EnabledExtFeats.DescriptorIndexing.pNext;
+ }
// Ray tracing
if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED)
@@ -414,8 +428,6 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
VERIFY_EXPR(DeviceExtFeatures.Spirv14);
}
- DeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); // required for VK_EXT_descriptor_indexing
- DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); // required for VK_KHR_acceleration_structure
DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); // required for VK_KHR_acceleration_structure
DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); // required for VK_KHR_acceleration_structure
DeviceExtensions.push_back(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME); // required for ray tracing
@@ -424,7 +436,6 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
EnabledExtFeats.AccelStruct = DeviceExtFeatures.AccelStruct;
EnabledExtFeats.RayTracingPipeline = DeviceExtFeatures.RayTracingPipeline;
EnabledExtFeats.BufferDeviceAddress = DeviceExtFeatures.BufferDeviceAddress;
- EnabledExtFeats.DescriptorIndexing = DeviceExtFeatures.DescriptorIndexing;
// disable unused features
EnabledExtFeats.AccelStruct.accelerationStructureCaptureReplay = false;
@@ -441,8 +452,6 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
NextExt = &EnabledExtFeats.AccelStruct.pNext;
*NextExt = &EnabledExtFeats.RayTracingPipeline;
NextExt = &EnabledExtFeats.RayTracingPipeline.pNext;
- *NextExt = &EnabledExtFeats.DescriptorIndexing;
- NextExt = &EnabledExtFeats.DescriptorIndexing.pNext;
*NextExt = &EnabledExtFeats.BufferDeviceAddress;
NextExt = &EnabledExtFeats.BufferDeviceAddress.pNext;
}
@@ -452,7 +461,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
}
#if defined(_MSC_VER) && defined(_WIN64)
- static_assert(sizeof(DeviceFeatures) == 32, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
+ static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
#endif
DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data();
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp
index 151e3d66..b7aaaa26 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp
@@ -157,6 +157,9 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, PIPELINE_TYPE Pipel
size_t PipelineLayoutVk::GetHash() const
{
+ if (m_SignatureCount == 0)
+ return 0;
+
size_t hash = 0;
HashCombine(hash, m_SignatureCount);
for (Uint32 i = 0; i < m_SignatureCount; ++i)
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp
index 72e3e8e3..03c610d1 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp
@@ -33,7 +33,6 @@
#include "SamplerVkImpl.hpp"
#include "TextureViewVkImpl.hpp"
#include "TopLevelASVkImpl.hpp"
-#include "BasicMath.hpp"
#include "DynamicLinearAllocator.hpp"
#include "SPIRVShaderResources.hpp"
@@ -64,7 +63,7 @@ inline bool ResourcesCompatible(const PipelineResourceDesc& lhs, const PipelineR
lhs.ArraySize == rhs.ArraySize &&
lhs.ResourceType == rhs.ResourceType &&
lhs.VarType == rhs.VarType &&
- lhs.Flags == lhs.Flags;
+ lhs.Flags == rhs.Flags;
// clang-format on
}
@@ -250,12 +249,12 @@ inline PipelineResourceSignatureVkImpl::CACHE_GROUP PipelineResourceSignatureVkI
if (WithDynamicOffset && !UseTexelBuffer)
{
if (Res.ResourceType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER)
- return static_cast<CACHE_GROUP>(SetId * 3 + CACHE_GROUP_DYN_UB);
+ return static_cast<CACHE_GROUP>(SetId * CACHE_GROUP_COUNT_PER_Type + CACHE_GROUP_DYN_UB);
if (Res.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV || Res.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV)
- return static_cast<CACHE_GROUP>(SetId * 3 + CACHE_GROUP_DYN_SB);
+ return static_cast<CACHE_GROUP>(SetId * CACHE_GROUP_COUNT_PER_Type + CACHE_GROUP_DYN_SB);
}
- return static_cast<CACHE_GROUP>(SetId * 3 + CACHE_GROUP_OTHER);
+ return static_cast<CACHE_GROUP>(SetId * CACHE_GROUP_COUNT_PER_Type + CACHE_GROUP_OTHER);
}
inline PipelineResourceSignatureVkImpl::DESCRIPTOR_SET_ID PipelineResourceSignatureVkImpl::VarTypeToDescriptorSetId(SHADER_RESOURCE_VARIABLE_TYPE VarType)
@@ -475,7 +474,7 @@ void PipelineResourceSignatureVkImpl::CreateSetLayouts(const CacheOffsetsType& C
VERIFY(i == 0 || ResDesc.VarType >= m_Desc.Resources[i - 1].VarType, "Resources must be sorted by variable type");
// If all resources are dynamic, then the signature contains only one descriptor set layout with index 0,
- // so remap SetIdx to the actual descriptor set index.
+ // so remap SetId to the actual descriptor set index.
VERIFY_EXPR(DSMapping[SetId] < MAX_DESCRIPTOR_SETS);
// The sampler may not be yet initialized, but this is OK as all resources are initialized
@@ -694,6 +693,9 @@ Uint32 PipelineResourceSignatureVkImpl::FindAssignedSampler(const PipelineResour
size_t PipelineResourceSignatureVkImpl::CalculateHash() const
{
+ if (m_Desc.NumResources == 0 && m_Desc.NumImmutableSamplers == 0)
+ return 0;
+
size_t Hash = ComputeHash(m_Desc.NumResources, m_Desc.NumImmutableSamplers, m_Desc.BindingIndex);
for (Uint32 i = 0; i < m_Desc.NumResources; ++i)
@@ -940,8 +942,11 @@ void PipelineResourceSignatureVkImpl::InitializeStaticSRBResources(ShaderResourc
if (!pObject)
LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", GetShaderResourcePrintName(ResDesc, ArrInd), "' in pipeline resource signature '", m_Desc.Name, "'.");
- const auto DstCacheOffset = Attr.CacheOffset(DstCacheType) + ArrInd;
- IDeviceObject* pCachedResource = DstDescrSet.GetResource(DstCacheOffset).pObject;
+ const auto DstCacheOffset = Attr.CacheOffset(DstCacheType) + ArrInd;
+ auto& DstCachedRes = DstDescrSet.GetResource(DstCacheOffset);
+ VERIFY_EXPR(SrcCachedRes.Type == DstCachedRes.Type);
+
+ IDeviceObject* pCachedResource = DstCachedRes.pObject;
if (pCachedResource != pObject)
{
VERIFY(pCachedResource == nullptr, "Static resource has already been initialized, and the new resource does not match previously assigned resource");
@@ -1209,7 +1214,9 @@ private:
void BindResourceHelper::BindResource(IDeviceObject* pObj) const
{
#ifdef DILIGENT_DEBUG
- if (ResourceCache.GetContentType() == PipelineResourceSignatureVkImpl::CacheContentType::SRB)
+ using CacheContentType = PipelineResourceSignatureVkImpl::CacheContentType;
+
+ if (ResourceCache.GetContentType() == CacheContentType::SRB)
{
if (ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC || ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE)
{
@@ -1217,7 +1224,7 @@ void BindResourceHelper::BindResource(IDeviceObject* pObj) const
// Dynamic variables do not have vulkan descriptor set only until they are assigned one the first time
}
}
- else if (ResourceCache.GetContentType() == PipelineResourceSignatureVkImpl::CacheContentType::Signature)
+ else if (ResourceCache.GetContentType() == CacheContentType::Signature)
{
VERIFY(vkDescrSet == VK_NULL_HANDLE, "Static shader resource cache should not have vulkan descriptor set allocation");
}
@@ -1512,7 +1519,7 @@ void BindResourceHelper::CacheImage(IDeviceObject* pTexView) const
UpdateDescriptorHandle(&DescrImgInfo, nullptr, nullptr);
}
- if (Attribs.SamplerInd != PipelineResourceSignatureVkImpl::ResourceAttribs::InvalidSamplerInd)
+ if (Attribs.IsCombinedWithSampler())
{
VERIFY(DstRes.Type == DescriptorType::SeparateImage,
"Only separate images can be assigned separate samplers when using HLSL-style combined samplers.");
@@ -1690,6 +1697,29 @@ void PipelineResourceSignatureVkImpl::BindResource(IDeviceObject* pObj,
Helper.BindResource(pObj);
}
+bool PipelineResourceSignatureVkImpl::IsBound(Uint32 ArrayIndex,
+ Uint32 ResIndex,
+ ShaderResourceCacheVk& ResourceCache) const
+{
+ const auto& ResDesc = GetResourceDesc(ResIndex);
+ const auto& Attribs = GetResourceAttribs(ResIndex);
+ const Uint32 CacheOffset = Attribs.CacheOffset(ResourceCache.GetContentType());
+
+ VERIFY_EXPR(ArrayIndex < ResDesc.ArraySize);
+
+ if (Attribs.DescrSet < ResourceCache.GetNumDescriptorSets())
+ {
+ const auto& Set = ResourceCache.GetDescriptorSet(Attribs.DescrSet);
+ if (CacheOffset + ArrayIndex < Set.GetSize())
+ {
+ const auto& CachedRes = Set.GetResource(CacheOffset + ArrayIndex);
+ return CachedRes.pObject != nullptr;
+ }
+ }
+
+ return false;
+}
+
#ifdef DILIGENT_DEVELOPMENT
bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVShaderResourceAttribs& SPIRVAttribs,
Uint32 ResIndex,
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index f54c8e27..841e6cdc 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -731,130 +731,145 @@ RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc(
return RPDesc;
}
-void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& CreateInfo,
- TShaderStages& ShaderStages)
+void PipelineStateVkImpl::CreateDefaultSignature(const PipelineStateCreateInfo& CreateInfo,
+ const TShaderStages& ShaderStages,
+ IPipelineResourceSignature** ppSignature)
{
- std::array<IPipelineResourceSignature*, MAX_RESOURCE_SIGNATURES> Signatures = {};
- RefCntAutoPtr<IPipelineResourceSignature> pImplicitSignature;
-
- Uint32 SignatureCount = CreateInfo.ResourceSignaturesCount;
-
- for (Uint32 i = 0; i < SignatureCount; ++i)
+ struct UniqueResource
{
- Signatures[i] = CreateInfo.ppResourceSignatures[i];
- }
+ const SPIRVShaderResourceAttribs* const Attribs;
+ const Uint32 DescIndex;
+ };
+ using ResourceNameToIndex_t = std::unordered_map<HashMapStringKey, UniqueResource, HashMapStringKey::Hasher>;
- const auto& LayoutDesc = CreateInfo.PSODesc.ResourceLayout;
+ const auto& LayoutDesc = CreateInfo.PSODesc.ResourceLayout;
+ std::vector<PipelineResourceDesc> Resources;
+ ResourceNameToIndex_t UniqueNames;
+ const char* pCombinedSamplerSuffix = nullptr;
- if (SignatureCount == 0 || CreateInfo.ppResourceSignatures == nullptr)
+ for (auto& Stage : ShaderStages)
{
- struct UniqueResource
- {
- const SPIRVShaderResourceAttribs* const Attribs;
- const Uint32 DescIndex;
- };
- using ResourceNameToIndex_t = std::unordered_map<HashMapStringKey, UniqueResource, HashMapStringKey::Hasher>;
-
- std::vector<PipelineResourceDesc> Resources;
- ResourceNameToIndex_t UniqueNames;
- const char* pCombinedSamplerSuffix = nullptr;
-
- for (auto& Stage : ShaderStages)
+ // Variables in all shader stages are separate in implicit layout
+ UniqueNames.clear();
+ for (auto* pShader : Stage.Shaders)
{
- // Variables in all shader stages are separate in implicit layout
- UniqueNames.clear();
- for (auto* pShader : Stage.Shaders)
- {
- const auto DefaultVarType = LayoutDesc.DefaultVariableType;
- const auto& ShaderResources = *pShader->GetShaderResources();
+ const auto DefaultVarType = LayoutDesc.DefaultVariableType;
+ const auto& ShaderResources = *pShader->GetShaderResources();
- ShaderResources.ProcessResources(
- [&](const SPIRVShaderResourceAttribs& Res, Uint32) //
+ ShaderResources.ProcessResources(
+ [&](const SPIRVShaderResourceAttribs& Res, Uint32) //
+ {
+ // We can't skip immutable samplers because immutable sampler arrays have to be defined
+ // as both resource and sampler.
+ //if (Res.Type == SPIRVShaderResourceAttribs::SeparateSampler &&
+ // FindImmutableSampler(LayoutDesc.ImmutableSamplers, LayoutDesc.NumImmutableSamplers, Stage.Type, Res.Name,
+ // ShaderResources.GetCombinedSamplerSuffix()) >= 0)
+ //{
+ // // Skip separate immutable samplers - they are not resources
+ // return;
+ //}
+
+ auto IterAndAssigned = UniqueNames.emplace(HashMapStringKey{Res.Name}, UniqueResource{&Res, static_cast<Uint32>(Resources.size())});
+ if (IterAndAssigned.second)
{
- // We can't skip immutable samplers because immutable sampler arrays have to be defined
- // as both resource and sampler.
- //if (Res.Type == SPIRVShaderResourceAttribs::SeparateSampler &&
- // FindImmutableSampler(LayoutDesc.ImmutableSamplers, LayoutDesc.NumImmutableSamplers, Stage.Type, Res.Name,
- // ShaderResources.GetCombinedSamplerSuffix()) >= 0)
- //{
- // // Skip separate immutable samplers - they are not resources
- // return;
- //}
-
- auto IterAndAssigned = UniqueNames.emplace(HashMapStringKey{Res.Name}, UniqueResource{&Res, static_cast<Uint32>(Resources.size())});
- if (IterAndAssigned.second)
- {
- SHADER_RESOURCE_TYPE Type;
- PIPELINE_RESOURCE_FLAGS Flags;
- GetShaderResourceTypeAndFlags(Res.Type, Type, Flags);
-
- Resources.emplace_back(Stage.Type, Res.Name, Res.ArraySize, Type, DefaultVarType, Flags);
- }
- else
+ if (Res.ArraySize == 0)
{
- VerifyResourceMerge(*IterAndAssigned.first->second.Attribs, Res);
+ LOG_ERROR_AND_THROW("Is shader '", pShader->GetDesc().Name, "' resource '", Res.Name, "' uses runtime sized array, ",
+ "you must explicitlly set resource signature to specify array size");
}
- });
- // merge combined sampler suffixes
- if (ShaderResources.IsUsingCombinedSamplers() && ShaderResources.GetNumSepSmplrs() > 0)
- {
- if (pCombinedSamplerSuffix != nullptr)
- {
- if (strcmp(pCombinedSamplerSuffix, ShaderResources.GetCombinedSamplerSuffix()) != 0)
- LOG_ERROR_AND_THROW("CombinedSamplerSuffix is not compatible between shaders");
+ SHADER_RESOURCE_TYPE Type;
+ PIPELINE_RESOURCE_FLAGS Flags;
+ GetShaderResourceTypeAndFlags(Res.Type, Type, Flags);
+
+ Resources.emplace_back(Stage.Type, Res.Name, Res.ArraySize, Type, DefaultVarType, Flags);
}
else
{
- pCombinedSamplerSuffix = ShaderResources.GetCombinedSamplerSuffix();
+ VerifyResourceMerge(*IterAndAssigned.first->second.Attribs, Res);
}
+ });
+
+ // merge combined sampler suffixes
+ if (ShaderResources.IsUsingCombinedSamplers() && ShaderResources.GetNumSepSmplrs() > 0)
+ {
+ if (pCombinedSamplerSuffix != nullptr)
+ {
+ if (strcmp(pCombinedSamplerSuffix, ShaderResources.GetCombinedSamplerSuffix()) != 0)
+ LOG_ERROR_AND_THROW("CombinedSamplerSuffix is not compatible between shaders");
+ }
+ else
+ {
+ pCombinedSamplerSuffix = ShaderResources.GetCombinedSamplerSuffix();
}
+ }
- for (Uint32 i = 0; i < LayoutDesc.NumVariables; ++i)
+ for (Uint32 i = 0; i < LayoutDesc.NumVariables; ++i)
+ {
+ const auto& Var = LayoutDesc.Variables[i];
+ if (Var.ShaderStages & Stage.Type)
{
- const auto& Var = LayoutDesc.Variables[i];
- if (Var.ShaderStages & Stage.Type)
+ auto Iter = UniqueNames.find(HashMapStringKey{Var.Name});
+ if (Iter != UniqueNames.end())
{
- auto Iter = UniqueNames.find(HashMapStringKey{Var.Name});
- if (Iter != UniqueNames.end())
+ auto& Res = Resources[Iter->second.DescIndex];
+ Res.VarType = Var.Type;
+
+ // Apply new variable type to sampler too
+ if (ShaderResources.IsUsingCombinedSamplers() && Res.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV)
{
- auto& Res = Resources[Iter->second.DescIndex];
- Res.VarType = Var.Type;
-
- // Apply new variable type to sampler too
- if (ShaderResources.IsUsingCombinedSamplers() && Res.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV)
- {
- String SampName = String{Var.Name} + ShaderResources.GetCombinedSamplerSuffix();
- auto SampIter = UniqueNames.find(HashMapStringKey{SampName.c_str()});
- if (SampIter != UniqueNames.end())
- Resources[SampIter->second.DescIndex].VarType = Var.Type;
- }
+ String SampName = String{Var.Name} + ShaderResources.GetCombinedSamplerSuffix();
+ auto SampIter = UniqueNames.find(HashMapStringKey{SampName.c_str()});
+ if (SampIter != UniqueNames.end())
+ Resources[SampIter->second.DescIndex].VarType = Var.Type;
}
}
}
}
}
+ }
- if (Resources.size())
- {
- String SignName = String{"Implicit signature for PSO '"} + m_Desc.Name + '\'';
+ if (Resources.size())
+ {
+ String SignName = String{"Implicit signature for PSO '"} + m_Desc.Name + '\'';
+
+ PipelineResourceSignatureDesc ResSignDesc;
+ ResSignDesc.Name = SignName.c_str();
+ ResSignDesc.Resources = Resources.data();
+ ResSignDesc.NumResources = static_cast<Uint32>(Resources.size());
+ ResSignDesc.ImmutableSamplers = LayoutDesc.ImmutableSamplers;
+ ResSignDesc.NumImmutableSamplers = LayoutDesc.NumImmutableSamplers;
+ ResSignDesc.BindingIndex = 0;
+ ResSignDesc.SRBAllocationGranularity = CreateInfo.PSODesc.SRBAllocationGranularity;
+ ResSignDesc.UseCombinedTextureSamplers = pCombinedSamplerSuffix != nullptr;
+ ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix;
+
+ GetDevice()->CreatePipelineResourceSignature(ResSignDesc, ppSignature, true);
+
+ if (*ppSignature == nullptr)
+ LOG_ERROR_AND_THROW("Failed to create resource signature for pipeline state");
+ }
+}
- PipelineResourceSignatureDesc ResSignDesc;
- ResSignDesc.Name = SignName.c_str();
- ResSignDesc.Resources = Resources.data();
- ResSignDesc.NumResources = static_cast<Uint32>(Resources.size());
- ResSignDesc.ImmutableSamplers = LayoutDesc.ImmutableSamplers;
- ResSignDesc.NumImmutableSamplers = LayoutDesc.NumImmutableSamplers;
- ResSignDesc.BindingIndex = 0;
- ResSignDesc.SRBAllocationGranularity = CreateInfo.PSODesc.SRBAllocationGranularity;
- ResSignDesc.UseCombinedTextureSamplers = pCombinedSamplerSuffix != nullptr;
- ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix;
+void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& CreateInfo,
+ TShaderStages& ShaderStages)
+{
+ std::array<IPipelineResourceSignature*, MAX_RESOURCE_SIGNATURES> Signatures = {};
+ RefCntAutoPtr<IPipelineResourceSignature> pImplicitSignature;
- GetDevice()->CreatePipelineResourceSignature(ResSignDesc, &pImplicitSignature, true);
+ Uint32 SignatureCount = CreateInfo.ResourceSignaturesCount;
- if (pImplicitSignature == nullptr)
- LOG_ERROR_AND_THROW("Failed to create resource signature for pipeline state");
+ for (Uint32 i = 0; i < SignatureCount; ++i)
+ {
+ Signatures[i] = CreateInfo.ppResourceSignatures[i];
+ }
+ if (SignatureCount == 0 || CreateInfo.ppResourceSignatures == nullptr)
+ {
+ CreateDefaultSignature(CreateInfo, ShaderStages, &pImplicitSignature);
+ if (pImplicitSignature != nullptr)
+ {
+ VERIFY_EXPR(pImplicitSignature->GetDesc().BindingIndex == 0);
Signatures[0] = pImplicitSignature;
SignatureCount = 1;
}
@@ -883,13 +898,13 @@ void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& Crea
#endif
pShaderResources->ProcessResources(
- [&](const SPIRVShaderResourceAttribs& Res, Uint32) //
+ [&](const SPIRVShaderResourceAttribs& SPIRVAttribs, Uint32) //
{
- auto Info = m_PipelineLayout.GetResourceInfo(Res.Name, ShaderType);
- if (!Info && Res.Type == SPIRVShaderResourceAttribs::SeparateSampler)
+ auto Info = m_PipelineLayout.GetResourceInfo(SPIRVAttribs.Name, ShaderType);
+ if (!Info && SPIRVAttribs.Type == SPIRVShaderResourceAttribs::SeparateSampler)
{
- DEV_CHECK_ERR(Res.ArraySize == 1, "Immutable sampler arrays must also be added to resource list");
- Info = m_PipelineLayout.GetImmutableSamplerInfo(Res.Name, ShaderType);
+ DEV_CHECK_ERR(SPIRVAttribs.ArraySize == 1, "Immutable sampler arrays must also be added to resource list");
+ Info = m_PipelineLayout.GetImmutableSamplerInfo(SPIRVAttribs.Name, ShaderType);
if (Info)
{
VERIFY(Info.BindingIndex != ~0u && Info.DescrSetIndex != ~0u,
@@ -899,23 +914,41 @@ void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& Crea
}
if (!Info)
{
- LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Res.Name,
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", SPIRVAttribs.Name,
"' that is not present in any pipeline resource signature that is used to create pipeline state '",
m_Desc.Name, "'.");
}
SHADER_RESOURCE_TYPE Type;
PIPELINE_RESOURCE_FLAGS Flags;
- GetShaderResourceTypeAndFlags(Res.Type, Type, Flags);
+ GetShaderResourceTypeAndFlags(SPIRVAttribs.Type, Type, Flags);
if (Type != Info.Type)
{
- LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Res.Name,
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", SPIRVAttribs.Name,
"' and type '", GetShaderResourceTypeLiteralName(Type), "' that is not compatible with type '",
GetShaderResourceTypeLiteralName(Info.Type), "' in pipeline resource signature '", Info.Signature->GetDesc().Name, "'.");
}
- SPIRV[Res.BindingDecorationOffset] = Info.BindingIndex;
- SPIRV[Res.DescriptorSetDecorationOffset] = Info.DescrSetIndex;
+ if (Info.ResIndex != ~0u)
+ {
+ const auto& ResDesc = Info.Signature->GetResourceDesc(Info.ResIndex);
+
+ if ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER))
+ {
+ LOG_ERROR_AND_THROW("AZ TODO");
+ }
+
+ // ArraySize == 0 means that used runtime sized array and ArraySize in resource signature may be any non-zero value.
+ if (SPIRVAttribs.ArraySize > 0 && ResDesc.ArraySize != SPIRVAttribs.ArraySize)
+ {
+ LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", SPIRVAttribs.Name,
+ "' and array size (", SPIRVAttribs.ArraySize, ") that is not compatible with array size '",
+ ResDesc.ArraySize, "' in pipeline resource signature '", Info.Signature->GetDesc().Name, "'.");
+ }
+ }
+
+ SPIRV[SPIRVAttribs.BindingDecorationOffset] = Info.BindingIndex;
+ SPIRV[SPIRVAttribs.DescriptorSetDecorationOffset] = Info.DescrSetIndex;
#ifdef DILIGENT_DEVELOPMENT
m_ResInfo.emplace_back(Info);
@@ -1055,13 +1088,12 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const
if (lhs.GetSignatureCount() != rhs.GetSignatureCount())
return false;
- if (lhs.GetSignatureCount() == 0)
- return true;
-
- if (lhs.GetSignatureCount() == 1)
- return lhs.GetSignature(0)->IsCompatibleWith(*rhs.GetSignature(0));
-
- return false;
+ for (Uint32 s = 0, SigCount = lhs.GetSignatureCount(); s < SigCount; ++s)
+ {
+ if (!lhs.GetSignature(s)->IsCompatibleWith(*rhs.GetSignature(s)))
+ return false;
+ }
+ return true;
}
#ifdef DILIGENT_DEVELOPMENT
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index cc255fba..c61e28ed 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -251,7 +251,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
Features.DurationQueries = DEVICE_FEATURE_STATE_ENABLED;
#if defined(_MSC_VER) && defined(_WIN64)
- static_assert(sizeof(DeviceFeatures) == 32, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary).");
+ static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary).");
#endif
const auto& vkDeviceLimits = m_PhysicalDevice->GetProperties().limits;
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
index 73cff300..9628fbd7 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
@@ -256,32 +256,18 @@ void ShaderVariableVkImpl::SetArray(IDeviceObject* const* ppObjects,
bool ShaderVariableVkImpl::IsBound(Uint32 ArrayIndex) const
{
- const auto& ResourceCache = m_ParentManager.m_ResourceCache;
- const auto& ResDesc = GetDesc();
- const auto& Attribs = GetAttribs();
- const Uint32 CacheOffset = Attribs.CacheOffset(ResourceCache.GetContentType());
-
- VERIFY_EXPR(ArrayIndex < ResDesc.ArraySize);
-
- if (Attribs.DescrSet < ResourceCache.GetNumDescriptorSets())
- {
- const auto& Set = ResourceCache.GetDescriptorSet(Attribs.DescrSet);
- if (CacheOffset + ArrayIndex < Set.GetSize())
- {
- const auto& CachedRes = Set.GetResource(CacheOffset + ArrayIndex);
- return CachedRes.pObject != nullptr;
- }
- }
+ auto* pSignature = m_ParentManager.m_pSignature;
+ auto& ResourceCache = m_ParentManager.m_ResourceCache;
- return false;
+ return pSignature->IsBound(ArrayIndex, m_ResIndex, ResourceCache);
}
void ShaderVariableVkImpl::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex) const
{
- auto* pSign = m_ParentManager.m_pSignature;
+ auto* pSignature = m_ParentManager.m_pSignature;
auto& ResourceCache = m_ParentManager.m_ResourceCache;
- pSign->BindResource(pObj, ArrayIndex, m_ResIndex, ResourceCache);
+ pSignature->BindResource(pObj, ArrayIndex, m_ResIndex, ResourceCache);
}
} // namespace Diligent