diff options
| author | azhirnov <zh1dron@gmail.com> | 2021-02-05 21:35:37 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2021-03-19 00:31:35 +0000 |
| commit | 78fa6c94992a6d1a140da1354448a004e62c9683 (patch) | |
| tree | c21183a39d58ba9ccc89d9d8ea6fe1aa9de2ec35 /Graphics/GraphicsEngineVulkan | |
| parent | Merged master (diff) | |
| download | DiligentCore-78fa6c94992a6d1a140da1354448a004e62c9683.tar.gz DiligentCore-78fa6c94992a6d1a140da1354448a004e62c9683.zip | |
merged with resource_signature
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
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 |
