From f8be662d357be9dcbb4b298d93b43d29ae93ce04 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 27 Oct 2020 19:08:28 -0700 Subject: A number of updates/fixes to PSO refactor merge --- .../include/PipelineLayout.hpp | 1 + .../include/PipelineStateVkImpl.hpp | 6 +- .../include/RenderDeviceVkImpl.hpp | 5 + .../include/ShaderResourceBindingVkImpl.hpp | 1 + .../include/ShaderResourceLayoutVk.hpp | 104 ++++---- .../GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 28 ++- .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 2 + .../src/PipelineStateVkImpl.cpp | 164 ++++++------- .../src/RenderDeviceVkImpl.cpp | 2 +- .../src/ShaderResourceLayoutVk.cpp | 268 ++++++++++----------- .../src/VulkanUtilities/VulkanInstance.cpp | 2 +- .../src/VulkanUtilities/VulkanPhysicalDevice.cpp | 2 +- 12 files changed, 286 insertions(+), 299 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp index 8a0fab15..f9f51920 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp @@ -136,6 +136,7 @@ public: // set by the same Vulkan command. If there are no dynamic descriptors, this // function also binds descriptor sets rightaway. void PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl, + VkPipelineBindPoint BindPoint, const ShaderResourceCacheVk& ResourceCache, DescriptorSetBindInfo& BindInfo, VkDescriptorSet VkDynamicDescrSet) const; diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index a02c8d74..6aa4e073 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -129,10 +129,11 @@ public: private: using TShaderStages = ShaderResourceLayoutVk::TShaderStages; - template + template void InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector& vkShaderStages, - std::vector& ShaderModules); + std::vector& ShaderModules, + InitPSODescType InitPSODesc); void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages); @@ -170,6 +171,7 @@ private: // Resource layout index in m_ShaderResourceLayouts array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; + static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above"); bool m_HasStaticResources = false; bool m_HasNonStaticResources = false; diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 9ceed3e4..6abe5213 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -197,6 +197,11 @@ public: IDXCompiler* GetDxCompiler() const { return m_pDxCompiler.get(); } + Uint32 GetShaderGroupHandleSize() const + { + return GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupHandleSize; + } + private: template void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState); diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp index 68401f52..0b427640 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp @@ -84,6 +84,7 @@ private: // Resource layout index in m_ShaderResourceCache array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; + static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above"); bool m_bStaticResourcesInitialized = false; Uint8 m_NumShaders = 0; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index e5cddb0c..a0e40615 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -44,20 +44,9 @@ // d == m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] // // +// Every ShaderVariableVkImpl variable managed by ShaderVariableManagerVk keeps a reference to corresponding VkResource. // -// * Every VkResource structure holds a reference to SPIRVShaderResourceAttribs structure from SPIRVShaderResources. -// * ShaderResourceLayoutVk keeps a shared pointer to SPIRVShaderResources instance. -// * Every ShaderVariableVkImpl variable managed by ShaderVariableManagerVk keeps a reference to corresponding VkResource. -// -// -// ______________________ ________________________________________________________________________ -// | | unique_ptr | | | | | | | | -// | SPIRVShaderResources |--------------->| UBs | SBs | StrgImgs | SmplImgs | ACs | SepSamplers | SepImgs | -// |______________________| |________|_________|__________|__________|_______|_____________|_________| -// A A A -// | | | -// |shared_ptr Ref Ref -// ________|__________________ ________\____________________|_____________________________________________ +// ___________________________ ___________________________________________________________________________ // | | unique_ptr | | | | | // | ShaderResourceLayoutVk |--------------->| VkResource[0] | VkResource[1] | ... | VkResource[s+m+d-1] | // |___________________________| |___________________|_________________|_______________|_____________________| @@ -99,13 +88,14 @@ #include #include +#include #include "PipelineState.h" #include "ShaderBase.hpp" #include "HashUtils.hpp" #include "ShaderResourceCacheVk.hpp" -#include "SPIRVShaderResources.hpp" #include "VulkanUtilities/VulkanLogicalDevice.hpp" +#include "StringPool.hpp" namespace Diligent { @@ -113,7 +103,7 @@ namespace Diligent class ShaderVkImpl; /// Diligent::ShaderResourceLayoutVk class -// sizeof(ShaderResourceLayoutVk)==72 (MS compiler, x64) +// sizeof(ShaderResourceLayoutVk)==40 (MS compiler, x64) class ShaderResourceLayoutVk { public: @@ -134,6 +124,9 @@ public: ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) noexcept : m_LogicalDevice{LogicalDevice} { +#if defined(_MSC_VER) && defined(_WIN64) + static_assert(sizeof(*this) == 40, "Unexpected sizeof(ShaderResourceLayoutVk)."); +#endif } // clang-format off @@ -181,20 +174,27 @@ public: static constexpr const Uint32 InvalidSamplerInd = (1 << SamplerIndBits)-1; + static constexpr const Uint32 ResourceDimBits = 7; + static constexpr const Uint32 IsMSFlagBits = 8 - ResourceDimBits; + static_assert(RESOURCE_DIM_NUM_DIMENSIONS <= (1 << ResourceDimBits), "Not enough bits to represent RESOURCE_DIMENSION"); + using ResourceType = SPIRVShaderResourceAttribs::ResourceType; /* 0 */ const Uint16 Binding; -/* 2 */ const Uint16 ArraySize; +/* 2 */ const Uint16 DescriptorSet; + /* 4.0 */ const Uint32 CacheOffset : CacheOffsetBits; // Offset from the beginning of the cached descriptor set /* 6.5 */ const Uint32 SamplerInd : SamplerIndBits; // When using combined texture samplers, index of the separate sampler // assigned to separate image /* 7.5 */ const Uint32 VariableType : VariableTypeBits; /* 7.7 */ const Uint32 ImmutableSamplerAssigned : ImmutableSamplerFlagBits; -/* 8 */ const Uint8 DescriptorSet; -/* 9 */ const ResourceType Type; -/* 10.0*/ const Uint8 ResourceDim : 7; -/* 10.7*/ const Uint8 IsMS : 1; +/* 8 */ const Uint16 ArraySize; + +/* 10 */ const ResourceType Type; +/* 11.0*/ const Uint8 ResourceDim : ResourceDimBits; +/* 11.7*/ const Uint8 IsMS : IsMSFlagBits; + /* 16 */ const char* const Name; /* 24 */ const ShaderResourceLayoutVk& ParentResLayout; // clang-format on @@ -203,8 +203,8 @@ public: const char* _Name, Uint16 _ArraySize, ResourceType _Type, - Uint8 _ResourceDim, - Uint8 _IsMS, + RESOURCE_DIMENSION _ResourceDim, + bool _IsMS, SHADER_RESOURCE_VARIABLE_TYPE _VariableType, uint32_t _Binding, uint32_t _DescriptorSet, @@ -218,20 +218,28 @@ public: SamplerInd {_SamplerInd }, VariableType {_VariableType }, ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U}, - Name {_Name }, - ArraySize {_ArraySize }, - Type {_Type }, - ResourceDim {_ResourceDim }, - IsMS {_IsMS }, - ParentResLayout {_ParentLayout } + ArraySize {_ArraySize }, + Type {_Type }, + ResourceDim {_ResourceDim }, + IsMS {_IsMS ? 1U : 0U}, + Name {_Name }, + ParentResLayout {_ParentLayout } // clang-format on { - VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits)); - VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits)); - VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max()); +#if defined(_MSC_VER) && defined(_WIN64) + static_assert(sizeof(*this) == 32, "Unexpected sizeof(VkResource)"); +#endif + // clang-format off + VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits) ); + VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits) ); + VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max() ); VERIFY(_DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits::max()); + VERIFY(_VariableType < (1 << VariableTypeBits), "Variable type (", Uint32{_VariableType}, ") exceeds max representable value ", (1 << VariableTypeBits) ); + VERIFY(_ResourceDim < (1 << ResourceDimBits), "Resource dimension (", Uint32{_ResourceDim}, ") exceeds max representable value ", (1 << ResourceDimBits) ); + // clang-format on } + // Checks if a resource is bound in ResourceCache at the given ArrayIndex bool IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const; @@ -273,7 +281,10 @@ public: return Name; } - ShaderResourceDesc GetResourceDesc() const; + ShaderResourceDesc GetResourceDesc() const + { + return ShaderResourceDesc{Name, SPIRVShaderResourceAttribs::GetShaderResourceType(Type), ArraySize}; + } RESOURCE_DIMENSION GetResourceDimension() const { @@ -403,14 +414,16 @@ private: return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; } + static constexpr Uint32 InvalidResourceIndex = ~0u; + using ResourceNameToIndex_t = std::unordered_map; - void AllocateMemory(const std::vector& Shaders, - IMemoryAllocator& Allocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ResourceNameToIndex_t& UniqueNames, - bool AllocateImmutableSamplers); + StringPool AllocateMemory(const std::vector& Shaders, + IMemoryAllocator& Allocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ResourceNameToIndex_t& UniqueNames, + bool AllocateImmutableSamplers); using ImmutableSamplerPtrType = RefCntAutoPtr; ImmutableSamplerPtrType& GetImmutableSampler(Uint32 n) noexcept @@ -422,16 +435,15 @@ private: // clang-format off /* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; -/* 8 */ std::unique_ptr > m_ResourceBuffer; // AZ TODO: use linear allocator -/*24 */ StringPool m_StringPool; +/* 8 */ std::unique_ptr > m_ResourceBuffer; -/*48 */ std::array m_NumResources = {}; +/*24 */ std::array m_NumResources = {}; -/*56 */ Uint32 m_NumImmutableSamplers = 0; -/*60 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; -/*64 */ bool m_IsUsingSeparateSamplers = false; +/*32 */ Uint16 m_NumImmutableSamplers = 0; +/*34 */ bool m_IsUsingSeparateSamplers = false; +/*36 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; -/*72 */ // End of class +/*40 */ // End of class // clang-format on }; diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index fcb64973..189b1073 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -252,22 +252,26 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E GetFeatureState(EngineCI.Features.Feature, IsFeatureSupported, FeatureName); \ } while (false) - ENABLE_FEATURE(DeviceExtFeatures.MeshShader.taskShader != VK_FALSE && DeviceExtFeatures.MeshShader.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are"); + const auto& MeshShaderFeats = DeviceExtFeatures.MeshShader; + ENABLE_FEATURE(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are"); + const auto& ShaderFloat16Int8Feats = DeviceExtFeatures.ShaderFloat16Int8; // clang-format off - ENABLE_FEATURE(DeviceExtFeatures.ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are"); - ENABLE_FEATURE(DeviceExtFeatures.ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are"); + ENABLE_FEATURE(ShaderFloat16Int8Feats.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are"); + ENABLE_FEATURE(ShaderFloat16Int8Feats.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are"); // clang-format on + const auto& Storage16BitFeats = DeviceExtFeatures.Storage16Bit; // clang-format off - ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is"); - ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is"); - ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are"); + ENABLE_FEATURE(Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is"); + ENABLE_FEATURE(Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is"); + ENABLE_FEATURE(Storage16BitFeats.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are"); // clang-format on + const auto& Storage8BitFeats = DeviceExtFeatures.Storage8Bit; // clang-format off - ENABLE_FEATURE(DeviceExtFeatures.Storage8Bit.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); - ENABLE_FEATURE(DeviceExtFeatures.Storage8Bit.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); + ENABLE_FEATURE(Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); + ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); // clang-format on ENABLE_FEATURE((DeviceExtFeatures.RayTracing.rayTracing != VK_FALSE && DeviceExtFeatures.Spirv14) || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is"); @@ -286,7 +290,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // Mesh shader if (EngineCI.Features.MeshShaders != DEVICE_FEATURE_STATE_DISABLED) { - EnabledExtFeats.MeshShader = DeviceExtFeatures.MeshShader; + EnabledExtFeats.MeshShader = MeshShaderFeats; VERIFY_EXPR(EnabledExtFeats.MeshShader.taskShader != VK_FALSE && EnabledExtFeats.MeshShader.meshShader != VK_FALSE); VERIFY(PhysicalDevice->IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME), "VK_NV_mesh_shader extension must be supported as it has already been checked by VulkanPhysicalDevice and " @@ -299,7 +303,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E if (EngineCI.Features.ShaderFloat16 != DEVICE_FEATURE_STATE_DISABLED || EngineCI.Features.ShaderInt8 != DEVICE_FEATURE_STATE_DISABLED) { - EnabledExtFeats.ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8; + EnabledExtFeats.ShaderFloat16Int8 = ShaderFloat16Int8Feats; VERIFY_EXPR(EnabledExtFeats.ShaderFloat16Int8.shaderFloat16 != VK_FALSE || EnabledExtFeats.ShaderFloat16Int8.shaderInt8 != VK_FALSE); VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME), "VK_KHR_shader_float16_int8 extension must be supported as it has already been checked by VulkanPhysicalDevice " @@ -324,7 +328,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // clang-format on { // clang-format off - EnabledExtFeats.Storage16Bit = DeviceExtFeatures.Storage16Bit; + EnabledExtFeats.Storage16Bit = Storage16BitFeats; VERIFY_EXPR(EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.storageBuffer16BitAccess != VK_FALSE); VERIFY_EXPR(EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.uniformAndStorageBuffer16BitAccess != VK_FALSE); VERIFY_EXPR(EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.storageInputOutput16 != VK_FALSE); @@ -360,7 +364,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E // clang-format on { // clang-format off - EnabledExtFeats.Storage8Bit = DeviceExtFeatures.Storage8Bit; + EnabledExtFeats.Storage8Bit = Storage8BitFeats; VERIFY_EXPR(EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage8Bit.storageBuffer8BitAccess != VK_FALSE); VERIFY_EXPR(EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage8Bit.uniformAndStorageBuffer8BitAccess != VK_FALSE); // clang-format on diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index d0e37670..c24ed496 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -433,6 +433,7 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl, } void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl, + VkPipelineBindPoint BindPoint, const ShaderResourceCacheVk& ResourceCache, DescriptorSetBindInfo& BindInfo, VkDescriptorSet VkDynamicDescrSet) const @@ -478,6 +479,7 @@ void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkIm BindInfo.DynamicOffsetCount = TotalDynamicDescriptors; if (TotalDynamicDescriptors > BindInfo.DynamicOffsets.size()) BindInfo.DynamicOffsets.resize(TotalDynamicDescriptors); + BindInfo.BindPoint = BindPoint; BindInfo.pResourceCache = &ResourceCache; #ifdef DILIGENT_DEBUG BindInfo.pDbgPipelineLayout = this; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index c7b9e05f..11be4dba 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -129,11 +129,11 @@ void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& } -void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk, - std::vector& Stages, - const PipelineLayout& Layout, - const PipelineStateDesc& PSODesc, - VulkanUtilities::PipelineWrapper& Pipeline) +static void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + VulkanUtilities::PipelineWrapper& Pipeline) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); @@ -154,13 +154,13 @@ void CreateComputePipeline(RenderDeviceVkImpl* pDevice } -void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk, - std::vector& Stages, - const PipelineLayout& Layout, - const PipelineStateDesc& PSODesc, - const GraphicsPipelineDesc& GraphicsPipeline, - VulkanUtilities::PipelineWrapper& Pipeline, - RefCntAutoPtr& pRenderPass) +static void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + const GraphicsPipelineDesc& GraphicsPipeline, + VulkanUtilities::PipelineWrapper& Pipeline, + RefCntAutoPtr& pRenderPass) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); @@ -338,13 +338,13 @@ void CreateGraphicsPipeline(RenderDeviceVkImpl* pDevic } -void CreateRayTracingPipeline(RenderDeviceVkImpl* pDeviceVk, - std::vector& Stages, - const std::vector& ShaderGroups, - const PipelineLayout& Layout, - const PipelineStateDesc& PSODesc, - const RayTracingPipelineDesc& RayTracingPipeline, - VulkanUtilities::PipelineWrapper& Pipeline) +static void CreateRayTracingPipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const std::vector& ShaderGroups, + const PipelineLayout& Layout, + const PipelineStateDesc& PSODesc, + const RayTracingPipelineDesc& RayTracingPipeline, + VulkanUtilities::PipelineWrapper& Pipeline) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); @@ -410,16 +410,18 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i) { + const auto& GeneralShader = CreateInfo.pGeneralShaders[i]; + VkRayTracingShaderGroupCreateInfoKHR Group = {}; Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; - Group.generalShader = ShaderToIndex(CreateInfo.pGeneralShaders[i].pShader); + Group.generalShader = ShaderToIndex(GeneralShader.pShader); Group.closestHitShader = VK_SHADER_UNUSED_KHR; Group.anyHitShader = VK_SHADER_UNUSED_KHR; Group.intersectionShader = VK_SHADER_UNUSED_KHR; - bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pGeneralShaders[i].Name)}, GroupIndex++).second; + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(GeneralShader.Name)}, GroupIndex++).second; if (!IsUniqueName) LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].Name must be unique"); @@ -428,16 +430,18 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i) { + const auto& TriHitShader = CreateInfo.pTriangleHitShaders[i]; + VkRayTracingShaderGroupCreateInfoKHR Group = {}; Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; Group.generalShader = VK_SHADER_UNUSED_KHR; - Group.closestHitShader = ShaderToIndex(CreateInfo.pTriangleHitShaders[i].pClosestHitShader); - Group.anyHitShader = ShaderToIndex(CreateInfo.pTriangleHitShaders[i].pAnyHitShader); + Group.closestHitShader = ShaderToIndex(TriHitShader.pClosestHitShader); + Group.anyHitShader = ShaderToIndex(TriHitShader.pAnyHitShader); Group.intersectionShader = VK_SHADER_UNUSED_KHR; - bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pTriangleHitShaders[i].Name)}, GroupIndex++).second; + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(TriHitShader.Name)}, GroupIndex++).second; if (!IsUniqueName) LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must be unique"); @@ -446,23 +450,25 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i) { + const auto& ProcHitShader = CreateInfo.pProceduralHitShaders[i]; + VkRayTracingShaderGroupCreateInfoKHR Group = {}; Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR; Group.generalShader = VK_SHADER_UNUSED_KHR; - Group.intersectionShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pIntersectionShader); - Group.closestHitShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pClosestHitShader); - Group.anyHitShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pAnyHitShader); + Group.intersectionShader = ShaderToIndex(ProcHitShader.pIntersectionShader); + Group.closestHitShader = ShaderToIndex(ProcHitShader.pClosestHitShader); + Group.anyHitShader = ShaderToIndex(ProcHitShader.pAnyHitShader); - bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pProceduralHitShaders[i].Name)}, GroupIndex++).second; + bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(ProcHitShader.Name)}, GroupIndex++).second; if (!IsUniqueName) LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].Name must be unique"); ShaderGroups.push_back(Group); } - VERIFY_EXPR(Uint32(CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount) == GroupIndex); + VERIFY_EXPR(Uint32{CreateInfo.GeneralShaderCount} + Uint32{CreateInfo.TriangleHitShaderCount} + Uint32{CreateInfo.ProceduralHitShaderCount} == GroupIndex); #ifdef DILIGENT_DEVELOPMENT Uint32 ShaderIndex2 = 0; @@ -474,7 +480,7 @@ void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& if (iter != UniqueShaders.end()) VERIFY_EXPR(iter->second == ShaderIndex2); else - UNEXPECTED("shader is not used in ray tracing shader groups"); + UNEXPECTED("Shader '", pShader->GetDesc().Name, "' is not used in ray tracing shader groups"); ++ShaderIndex2; } @@ -630,10 +636,11 @@ void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre m_ShaderResourceLayoutHash = m_PipelineLayout.GetHash(); } -template +template void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector& vkShaderStages, - std::vector& ShaderModules) + std::vector& ShaderModules, + InitPSODescType InitPSODesc) { m_ResourceLayoutIndex.fill(-1); @@ -668,7 +675,7 @@ void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& for (Uint32 s = 0; s < NumShaderStages; ++s) new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]}; - InitializePipelineDesc(CreateInfo, MemPool); + InitPSODesc(CreateInfo, MemPool, ShaderStages); // It is important to construct all objects before initializing them because if an exception is thrown, // destructors will be called for all objects @@ -691,7 +698,12 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* std::vector vkShaderStages; std::vector ShaderModules; - InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules, + [this](const GraphicsPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages /*ShaderStages*/) // + { + InitializePipelineDesc(CreateInfo, MemPool); + } // + ); CreateGraphicsPipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass); } @@ -714,7 +726,12 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* p std::vector vkShaderStages; std::vector ShaderModules; - InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules, + [this](const ComputePipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages /*ShaderStages*/) // + { + InitializePipelineDesc(CreateInfo, MemPool); + } // + ); CreateComputePipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); } @@ -733,57 +750,24 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* { try { - m_ResourceLayoutIndex.fill(-1); - - TShaderStages ShaderStages; - ExtractShaders(CreateInfo, ShaderStages); - - const auto ShaderGroupHandleSize = pDeviceVk->GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupHandleSize; - TNameToGroupIndexMap NameToGroupIndex; - LinearAllocator MemPool{GetRawAllocator()}; - - const auto NumShaderStages = GetNumShaderStages(); - VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); - - MemPool.AddSpace(NumShaderStages); - MemPool.AddSpace(NumShaderStages * 2); - MemPool.AddSpace(NumShaderStages); - - ReserveSpaceForPipelineDesc(CreateInfo, ShaderGroupHandleSize, MemPool); - - MemPool.Reserve(); - - const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); - - m_StaticResCaches = MemPool.ConstructArray(NumShaderStages, ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources); - - // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct(). - auto* Ptr = MemPool.ReleaseOwnership(); - VERIFY_EXPR(Ptr == m_StaticResCaches); - (void)Ptr; - - m_ShaderResourceLayouts = MemPool.ConstructArray(NumShaderStages * 2, LogicalDevice); - - m_StaticVarsMgrs = MemPool.Allocate(NumShaderStages); - for (Uint32 s = 0; s < NumShaderStages; ++s) - new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]}; - - std::vector ShaderGroups; - BuildRTPipelineDescription(CreateInfo, NameToGroupIndex, ShaderGroups, ShaderStages, MemPool); - InitializePipelineDesc(CreateInfo, ShaderGroupHandleSize, std::move(NameToGroupIndex), MemPool); - - // It is important to construct all objects before initializing them because if an exception is thrown, - // destructors will be called for all objects - - InitResourceLayouts(CreateInfo, ShaderStages); - - // Create shader modules and initialize shader stages std::vector vkShaderStages; std::vector ShaderModules; - InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages); + + std::vector ShaderGroups; + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules, + [&](const RayTracingPipelineStateCreateInfo& CreateInfo, LinearAllocator& MemPool, TShaderStages& ShaderStages) // + { + TNameToGroupIndexMap NameToGroupIndex; + BuildRTPipelineDescription(CreateInfo, NameToGroupIndex, ShaderGroups, ShaderStages, MemPool); + InitializePipelineDesc(CreateInfo, std::move(NameToGroupIndex), MemPool); + } // + ); CreateRayTracingPipeline(pDeviceVk, vkShaderStages, ShaderGroups, m_PipelineLayout, m_Desc, GetRayTracingPipelineDesc(), m_Pipeline); + const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); + const auto ShaderGroupHandleSize = pDeviceVk->GetShaderGroupHandleSize(); + auto err = LogicalDevice.GetRayTracingShaderGroupHandles(m_Pipeline, 0, static_cast(ShaderGroups.size()), ShaderGroupHandleSize, &m_pRayTracingPipelineData->Shaders[0]); VERIFY(err == VK_SUCCESS, "Failed to get shader group handles"); (void)err; @@ -978,20 +962,22 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind } } - VERIFY_EXPR(pDescrSetBindInfo != nullptr); + + VkPipelineBindPoint BindPoint = VK_PIPELINE_BIND_POINT_MAX_ENUM; switch (m_Desc.PipelineType) { // clang-format off case PIPELINE_TYPE_GRAPHICS: - case PIPELINE_TYPE_MESH: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; break; - case PIPELINE_TYPE_COMPUTE: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; break; - case PIPELINE_TYPE_RAY_TRACING: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; break; - default: UNEXPECTED("unknown pipeline type"); - // clang-format on + case PIPELINE_TYPE_MESH: BindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; break; + case PIPELINE_TYPE_COMPUTE: BindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; break; + case PIPELINE_TYPE_RAY_TRACING: BindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; break; + // clang-format on + default: UNEXPECTED("Unknown pipeline type"); } + VERIFY_EXPR(pDescrSetBindInfo != nullptr); // Prepare descriptor sets, and also bind them if there are no dynamic descriptors - m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, ResourceCache, *pDescrSetBindInfo, DynamicDescrSet); + m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, BindPoint, ResourceCache, *pDescrSetBindInfo, DynamicDescrSet); // Dynamic descriptor sets are not released individually. Instead, all dynamic descriptor pools // are released at the end of the frame by DeviceContextVkImpl::FinishFrame(). } @@ -1036,7 +1022,7 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY if (LayoutInd < 0) return nullptr; - auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); + const auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); return StaticVarMgr.GetVariable(Index); } diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index 3199a014..4d2c01e3 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -81,7 +81,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* sizeof(FramebufferVkImpl), sizeof(BottomLevelASVkImpl), sizeof(TopLevelASVkImpl), - sizeof(ShaderBindingTableVkImpl) + sizeof(ShaderBindingTableVkImpl), } }, m_VulkanInstance {Instance }, diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 16b6bee3..499c35ef 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -95,10 +95,10 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader) : - Type{Stage} + Type{Stage}, + Shaders{{pShader}}, + SPIRVs{{pShader->GetSPIRV()}} { - Shaders.push_back(pShader); - SPIRVs.push_back(pShader->GetSPIRV()); } void ShaderResourceLayoutVk::ShaderStageInfo::Append(const ShaderVkImpl* pShader) @@ -123,13 +123,13 @@ ShaderResourceLayoutVk::~ShaderResourceLayoutVk() GetImmutableSampler(s).~ImmutableSamplerPtrType(); } -void ShaderResourceLayoutVk::AllocateMemory(const std::vector& Shaders, - IMemoryAllocator& Allocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ResourceNameToIndex_t& UniqueNames, - bool AllocateImmutableSamplers) +StringPool ShaderResourceLayoutVk::AllocateMemory(const std::vector& Shaders, + IMemoryAllocator& Allocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ResourceNameToIndex_t& UniqueNames, + bool AllocateImmutableSamplers) { VERIFY(!m_ResourceBuffer, "Memory has already been initialized"); VERIFY_EXPR(Shaders.size() > 0); @@ -143,16 +143,18 @@ void ShaderResourceLayoutVk::AllocateMemory(const std::vectorGetShaderResources(); - const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); - VERIFY_EXPR(pResources->GetShaderType() == m_ShaderType); - pResources->ProcessResources( + const auto& Resources = *Shaders[s]->GetShaderResources(); + const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); + VERIFY(Resources.GetShaderType() == m_ShaderType, "Unexpected shader type"); + VERIFY(m_IsUsingSeparateSamplers == !Resources.IsUsingCombinedSamplers(), "All shaders in the stage must either use or not use combined image samplers"); + + Resources.ProcessResources( [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) // { auto VarType = FindShaderVariableType(m_ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); if (IsAllowedType(VarType, AllowedTypeBits)) { - bool IsUniqueName = UniqueNames.emplace(HashMapStringKey{ResAttribs.Name}, ~0u).second; + bool IsUniqueName = UniqueNames.emplace(HashMapStringKey{ResAttribs.Name}, InvalidResourceIndex).second; if (IsUniqueName) { StringPoolSize += strlen(ResAttribs.Name) + 1; @@ -165,11 +167,8 @@ void ShaderResourceLayoutVk::AllocateMemory(const std::vectorIsUsingCombinedSamplers()); } - m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - Uint32 TotalResources = 0; for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) { @@ -189,19 +188,26 @@ void ShaderResourceLayoutVk::AllocateMemory(const std::vector>(pRawMem, Allocator); - for (Uint32 s = 0; s < m_NumImmutableSamplers; ++s) - { - // We need to initialize immutable samplers - auto& UninitializedImmutableSampler = GetImmutableSampler(s); - new (std::addressof(UninitializedImmutableSampler)) ImmutableSamplerPtrType; - } + MemPool.AddSpace(TotalResources); + MemPool.AddSpace(m_NumImmutableSamplers); + MemPool.AddSpace(StringPoolSize); + + MemPool.Reserve(); + + auto* pResources = MemPool.Allocate(TotalResources); + auto* pImtblSamplers = MemPool.ConstructArray(m_NumImmutableSamplers); + auto* pStringData = MemPool.ConstructArray(StringPoolSize); + + m_ResourceBuffer = std::unique_ptr>(MemPool.Release(), Allocator); + + VERIFY_EXPR(m_ResourceBuffer.get() == pResources); + VERIFY_EXPR(m_NumImmutableSamplers == 0 || pImtblSamplers == std::addressof(GetImmutableSampler(0))); + + StringPool stringPool; + stringPool.AssignMemory(pStringData, StringPoolSize); + return stringPool; } @@ -254,18 +260,19 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vector CurrResInd = {}; Uint32 StaticResCacheSize = 0; const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); - for (auto* pShader : Shaders) + for (const auto* pShader : Shaders) { - auto pResources = pShader->GetShaderResources(); - const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); - pResources->ProcessResources( + const auto& Resources = *pShader->GetShaderResources(); + const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); + Resources.ProcessResources( [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) // { auto VarType = FindShaderVariableType(m_ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); @@ -275,7 +282,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vectorsecond == ~0u) + if (ResIter->second == InvalidResourceIndex) { Int32 SrcImmutableSamplerInd = -1; if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || @@ -296,14 +303,26 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vectorsecond = CurrResInd[VarType]; - ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, m_StringPool.CopyString(Attribs.Name), Attribs.ArraySize, - Attribs.Type, Attribs.ResourceDim, Attribs.IsMS, VarType, - Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); + ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource // + { + *this, + stringPool.CopyString(Attribs.Name), + Attribs.ArraySize, + Attribs.Type, + Attribs.GetResourceDimension(), + Attribs.IsMultisample(), + VarType, + Binding, + DescriptorSet, + CacheOffset, + SamplerInd, + SrcImmutableSamplerInd >= 0 // + }; } else { @@ -325,7 +344,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vectorGetShaderResources(); - if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0) + const auto& Resources = *Stage.Shaders[i]->GetShaderResources(); + VERIFY_EXPR(Resources.GetShaderType() == Stage.Type); + + for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) { - for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) - { - const auto& ResAttribs = Resources.GetResource(res); - VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0); - } + const auto& ResAttribs = Resources.GetResource(res); + VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0); } } } @@ -431,15 +452,17 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& bool SamplerFound = false; for (size_t s = 0; s < ShaderStages.size() && !SamplerFound; ++s) { - auto& Shaders = ShaderStages[s].Shaders; - for (size_t j = 0; j < Shaders.size() && !SamplerFound; ++j) + const auto& Stage = ShaderStages[s]; + if ((Stage.Type & ImtblSamDesc.ShaderStages) == 0) + continue; + + for (size_t j = 0; j < Stage.Shaders.size() && !SamplerFound; ++j) { - const auto& Resources = *Shaders[j]->GetShaderResources(); - if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0) - continue; + const auto& Resources = *Stage.Shaders[j]->GetShaderResources(); + VERIFY_EXPR(Resources.GetShaderType() == Stage.Type); // Irrespective of whether HLSL-style combined image samplers are used, - // a static sampler can be assigned to GLSL sampled image (i.e. sampler2D g_tex) + // an immutable sampler can be assigned to GLSL sampled image (i.e. sampler2D g_tex) for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i) { const auto& SmplImg = Resources.GetSmpldImg(i); @@ -448,7 +471,7 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& if (!SamplerFound) { - // Check if static sampler is assigned to a separate sampler. + // Check if immutable is assigned to a separate sampler. // In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler". // Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "". const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); @@ -486,15 +509,21 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende #endif std::array ResourceNameToIndexArray; - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; - const Uint32 NumAllowedTypes = 0; - const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - constexpr bool AllocateImmutableSamplers = true; + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; + const Uint32 NumAllowedTypes = 0; + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + + constexpr bool AllocateImmutableSamplers = true; + + std::vector stringPools; + stringPools.reserve(ShaderStages.size()); for (size_t s = 0; s < ShaderStages.size(); ++s) { - Layouts[s].AllocateMemory(ShaderStages[s].Shaders, LayoutDataAllocator, ResourceLayoutDesc, - AllowedVarTypes, NumAllowedTypes, ResourceNameToIndexArray[s], AllocateImmutableSamplers); + stringPools.emplace_back( + Layouts[s].AllocateMemory(ShaderStages[s].Shaders, LayoutDataAllocator, ResourceLayoutDesc, + AllowedVarTypes, NumAllowedTypes, ResourceNameToIndexArray[s], + AllocateImmutableSamplers)); } //VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE); @@ -504,7 +533,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende std::unordered_map> dbgBindings_CacheOffsets; #endif - auto AddResource = [&](Uint32 ShaderInd, + auto AddResource = [&](const Uint32 ShaderInd, ShaderResourceLayoutVk& ResLayout, const SPIRVShaderResources& Resources, const SPIRVShaderResourceAttribs& Attribs, @@ -519,7 +548,8 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende auto ResIter = ResourceNameToIndex.find(HashMapStringKey{Attribs.Name}); VERIFY_EXPR(ResIter != ResourceNameToIndex.end()); - if (ResIter->second == ~0u) + const VkResource* pResource = nullptr; + if (ResIter->second == InvalidResourceIndex) { // add new resource Uint32 Binding = 0; @@ -554,9 +584,6 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende VERIFY(DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value"); VERIFY(Binding <= std::numeric_limits::max(), "Binding (", Binding, ") excceeds maximum representable value"); - SPIRV[Attribs.BindingDecorationOffset] = Binding; - SPIRV[Attribs.DescriptorSetDecorationOffset] = DescriptorSet; - #ifdef DILIGENT_DEBUG // Verify that bindings and cache offsets monotonically increase in every descriptor set auto Binding_OffsetIt = dbgBindings_CacheOffsets.find(DescriptorSet); @@ -570,24 +597,37 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende auto& ResInd = CurrResInd[ShaderInd][VarType]; ResIter->second = ResInd; - ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource(ResLayout, ResLayout.m_StringPool.CopyString(Attribs.Name), Attribs.ArraySize, - Attribs.Type, Attribs.ResourceDim, Attribs.IsMS, VarType, - Binding, DescriptorSet, CacheOffset, SamplerInd, vkImmutableSampler != VK_NULL_HANDLE ? 1 : 0); + + pResource = ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource // + { + ResLayout, + stringPools[ShaderInd].CopyString(Attribs.Name), + Attribs.ArraySize, + Attribs.Type, + Attribs.GetResourceDimension(), + Attribs.IsMultisample(), + VarType, + Binding, + DescriptorSet, + CacheOffset, + SamplerInd, + vkImmutableSampler != VK_NULL_HANDLE // + }; } else { // merge with existing - auto& ExistingRes = ResLayout.GetResource(VarType, ResIter->second); + pResource = &ResLayout.GetResource(VarType, ResIter->second); - VERIFY_EXPR(ExistingRes.VariableType == VarType); - VERIFY_EXPR(ExistingRes.Type == Attribs.Type); - VERIFY_EXPR(ExistingRes.ResourceDim == Attribs.ResourceDim); - VERIFY_EXPR(ExistingRes.IsMS == Attribs.IsMS); - VERIFY_EXPR(ExistingRes.ArraySize == Attribs.ArraySize); - - SPIRV[Attribs.BindingDecorationOffset] = ExistingRes.Binding; - SPIRV[Attribs.DescriptorSetDecorationOffset] = ExistingRes.DescriptorSet; + VERIFY_EXPR(pResource->VariableType == VarType); + VERIFY_EXPR(pResource->Type == Attribs.Type); + VERIFY_EXPR(pResource->ResourceDim == Attribs.ResourceDim); + VERIFY_EXPR(pResource->IsMS == Attribs.IsMS); + VERIFY_EXPR(pResource->ArraySize == Attribs.ArraySize); } + VERIFY_EXPR(pResource != nullptr); + SPIRV[Attribs.BindingDecorationOffset] = pResource->Binding; + SPIRV[Attribs.DescriptorSetDecorationOffset] = pResource->DescriptorSet; }; // First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set @@ -707,7 +747,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende // Some immutable samplers may never be initialized if they are not present in shaders VERIFY_EXPR(CurrImmutableSamplerInd[s] <= Layout.m_NumImmutableSamplers); - VERIFY_EXPR(Layout.m_StringPool.GetRemainingSize() == 0); + VERIFY_EXPR(stringPools[s].GetRemainingSize() == 0); } #endif } @@ -1184,72 +1224,6 @@ bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const Shader return false; } -ShaderResourceDesc ShaderResourceLayoutVk::VkResource::GetResourceDesc() const -{ - ShaderResourceDesc ResourceDesc; - ResourceDesc.Name = Name; - ResourceDesc.ArraySize = ArraySize; - - static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below"); - switch (Type) - { - case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_CONSTANT_BUFFER; - break; - - case SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer: - // Read-only storage buffers map to buffer SRV - // https://github.com/KhronosGroup/SPIRV-Cross/wiki/Reflection-API-user-guide#read-write-vs-read-only-resources-for-hlsl - ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::StorageImage: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_UAV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::SampledImage: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_SRV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::AtomicCounter: - LOG_WARNING_MESSAGE("There is no appropriate shader resource type for atomic counter resource '", Name, "'"); - ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::SeparateImage: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_SRV; - break; - - case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_SAMPLER; - break; - - case SPIRVShaderResourceAttribs::ResourceType::InputAttachment: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT; - break; - - case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure: - ResourceDesc.Type = SHADER_RESOURCE_TYPE_ACCEL_STRUCT; - break; - - default: - UNEXPECTED("Unknown SPIRV resource type"); - } - return ResourceDesc; -} - void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayoutVk& SrcLayout, const ShaderResourceCacheVk& SrcResourceCache, diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp index 825bf872..405149a5 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp @@ -192,7 +192,7 @@ VulkanInstance::VulkanInstance(uint32_t ApiVersion, uint32_t MaxApiVersion = 0; vkEnumerateInstanceVersion(&MaxApiVersion); ApiVersion = std::min(ApiVersion, MaxApiVersion); - LOG_INFO_MESSAGE("Used Vulkan API version ", VK_VERSION_MAJOR(ApiVersion), ".", VK_VERSION_MINOR(ApiVersion)); + LOG_INFO_MESSAGE("Using Vulkan API version ", VK_VERSION_MAJOR(ApiVersion), ".", VK_VERSION_MINOR(ApiVersion)); } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp index b66ac8af..a80d7f73 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp @@ -198,7 +198,7 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice, m_ExtProperties.RayTracing.shaderGroupBaseAlignment = RayTracingNV.shaderGroupBaseAlignment; m_ExtProperties.RayTracing.maxGeometryCount = RayTracingNV.maxGeometryCount; m_ExtProperties.RayTracing.maxInstanceCount = RayTracingNV.maxInstanceCount; - m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount / 3; + m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount; m_ExtProperties.RayTracing.maxDescriptorSetAccelerationStructures = RayTracingNV.maxDescriptorSetAccelerationStructures; m_ExtProperties.RayTracing.shaderGroupHandleCaptureReplaySize = 0; } -- cgit v1.2.3