diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2019-03-07 02:58:56 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2019-03-07 02:58:56 +0000 |
| commit | bc9fc76496034a50faf3d7fe7be868d5d62f6663 (patch) | |
| tree | e9438fe09533409c57c9c63b2f69a895e2cf8615 /Graphics/GraphicsEngineVulkan | |
| parent | Merge pull request #67 from StarshipVendingMachine/android-vulkan (diff) | |
| parent | Minor comment updates (diff) | |
| download | DiligentCore-bc9fc76496034a50faf3d7fe7be868d5d62f6663.tar.gz DiligentCore-bc9fc76496034a50faf3d7fe7be868d5d62f6663.zip | |
Merged var_type_refactor into master
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
31 files changed, 1080 insertions, 679 deletions
diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt index d41b809c..c7339bef 100644 --- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt +++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt @@ -51,10 +51,10 @@ set(INTERFACE interface/BufferViewVk.h interface/CommandQueueVk.h interface/DeviceContextVk.h + interface/EngineFactoryVk.h interface/FenceVk.h interface/PipelineStateVk.h interface/RenderDeviceVk.h - interface/RenderDeviceFactoryVk.h interface/SamplerVk.h interface/ShaderVk.h interface/ShaderResourceBindingVk.h @@ -71,6 +71,7 @@ set(SRC src/CommandQueueVkImpl.cpp src/DescriptorPoolManager.cpp src/DeviceContextVkImpl.cpp + src/EngineFactoryVk.cpp src/FenceVkImpl.cpp src/VulkanDynamicHeap.cpp src/FramebufferCache.cpp @@ -79,7 +80,6 @@ set(SRC src/PipelineStateVkImpl.cpp src/RenderDeviceVkImpl.cpp src/RenderPassCache.cpp - src/RenderDeviceFactoryVk.cpp src/SamplerVkImpl.cpp src/ShaderVkImpl.cpp src/ShaderResourceBindingVkImpl.cpp diff --git a/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h b/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h index abedce7d..f7245d0a 100644 --- a/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h @@ -44,15 +44,15 @@ class BufferViewVkImpl final : public BufferViewBase<IBufferViewVk, RenderDevice public: using TBufferViewBase = BufferViewBase<IBufferViewVk, RenderDeviceVkImpl>; - BufferViewVkImpl( IReferenceCounters* pRefCounters, - RenderDeviceVkImpl* pDevice, - const BufferViewDesc& ViewDesc, - class IBuffer* pBuffer, - VulkanUtilities::BufferViewWrapper&& BuffView, - bool bIsDefaultView); + BufferViewVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pDevice, + const BufferViewDesc& ViewDesc, + class IBuffer* pBuffer, + VulkanUtilities::BufferViewWrapper&& BuffView, + bool bIsDefaultView); ~BufferViewVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject** ppInterface )override final; + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override final; virtual VkBufferView GetVkBufferView()const override final{return m_BuffView;} diff --git a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h index f3d1784b..c3afd4ee 100644 --- a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h @@ -63,7 +63,7 @@ public: VkBuffer vkBuffer); ~BufferVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject** ppInterface )override; + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override; #ifdef DEVELOPMENT void DvpVerifyDynamicAllocation(DeviceContextVkImpl* pCtx)const; @@ -104,14 +104,14 @@ public: private: friend class DeviceContextVkImpl; - virtual void CreateViewInternal( const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView )override; + virtual void CreateViewInternal(const struct BufferViewDesc& ViewDesc, IBufferView** ppView, bool bIsDefaultView)override; VulkanUtilities::BufferViewWrapper CreateView(struct BufferViewDesc &ViewDesc); Uint32 m_DynamicOffsetAlignment = 0; std::vector<VulkanDynamicAllocation, STDAllocatorRawMem<VulkanDynamicAllocation> > m_DynamicAllocations; - VulkanUtilities::BufferWrapper m_VulkanBuffer; + VulkanUtilities::BufferWrapper m_VulkanBuffer; VulkanUtilities::VulkanMemoryAllocation m_MemoryAllocation; }; diff --git a/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h b/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h index a5669f6c..3c649ab1 100644 --- a/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/CommandQueueVkImpl.h @@ -48,7 +48,7 @@ public: uint32_t QueueFamilyIndex); ~CommandQueueVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID& IID, IObject** ppInterface )override; + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override final; // Returns the fence value that will be signaled next time virtual Uint64 GetNextFenceValue()override final { return m_NextFenceValue; } diff --git a/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.h b/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.h index 24c3e157..bcb0a919 100644 --- a/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.h +++ b/Graphics/GraphicsEngineVulkan/include/DescriptorPoolManager.h @@ -41,6 +41,7 @@ class RenderDeviceVkImpl; // This class manages descriptor set allocation. // The class destructor calls DescriptorSetAllocator::FreeDescriptorSet() that moves // the set into the release queue. +// sizeof(DescriptorSetAllocation) == 32 (x64) class DescriptorSetAllocation { public: diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h index bc8c42ac..09eaa1a5 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h @@ -62,13 +62,13 @@ public: DeviceContextVkImpl(IReferenceCounters* pRefCounters, class RenderDeviceVkImpl* pDevice, bool bIsDeferred, - const EngineVkAttribs& Attribs, + const EngineVkCreateInfo& EngineCI, Uint32 ContextId, Uint32 CommandQueueId, std::shared_ptr<GenerateMipsVkHelper> GenerateMipsHelper); ~DeviceContextVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID& IID, IObject** ppInterface )override final; + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override final; virtual void SetPipelineState(IPipelineState* pPipelineState)override final; diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h index f970501a..a5aec374 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h +++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h @@ -58,16 +58,17 @@ public: const char* DbgPipelineName)const; void AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResAttribs, - VkSampler vkStaticSampler, + SHADER_RESOURCE_VARIABLE_TYPE VariableType, + VkSampler vkImmutableSampler, SHADER_TYPE ShaderType, Uint32& DescriptorSet, Uint32& Binding, Uint32& OffsetInCache, std::vector<uint32_t>& SPIRV); - Uint32 GetTotalDescriptors(SHADER_VARIABLE_TYPE VarType)const + Uint32 GetTotalDescriptors(SHADER_RESOURCE_VARIABLE_TYPE VarType)const { - VERIFY_EXPR(VarType >= 0 && VarType < SHADER_VARIABLE_TYPE_NUM_TYPES); + VERIFY_EXPR(VarType >= 0 && VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES); return m_LayoutMgr.GetDescriptorSet(VarType).TotalDescriptors; } @@ -82,7 +83,7 @@ public: VkDescriptorSetLayout GetDynamicDescriptorSetVkLayout()const { - return m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_DYNAMIC).VkLayout; + return m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC).VkLayout; } struct DescriptorSetBindInfo @@ -178,8 +179,8 @@ private: void Finalize(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice); void Release(RenderDeviceVkImpl* pRenderDeviceVk, Uint64 CommandQueueMask); - DescriptorSetLayout& GetDescriptorSet(SHADER_VARIABLE_TYPE VarType) { return m_DescriptorSetLayouts[VarType == SHADER_VARIABLE_TYPE_DYNAMIC ? 1 : 0]; } - const DescriptorSetLayout& GetDescriptorSet(SHADER_VARIABLE_TYPE VarType)const { return m_DescriptorSetLayouts[VarType == SHADER_VARIABLE_TYPE_DYNAMIC ? 1 : 0]; } + DescriptorSetLayout& GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE VarType) { return m_DescriptorSetLayouts[VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? 1 : 0]; } + const DescriptorSetLayout& GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE VarType)const { return m_DescriptorSetLayouts[VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? 1 : 0]; } bool operator == (const DescriptorSetLayoutManager& rhs)const; bool operator != (const DescriptorSetLayoutManager& rhs)const {return !(*this == rhs);} @@ -187,7 +188,8 @@ private: VkPipelineLayout GetVkPipelineLayout()const{return m_VkPipelineLayout;} void AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResAttribs, - VkSampler vkStaticSampler, + SHADER_RESOURCE_VARIABLE_TYPE VariableType, + VkSampler vkImmutableSampler, SHADER_TYPE ShaderType, Uint32& DescriptorSet, Uint32& Binding, diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h index cd7d1cab..e9be63a3 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h @@ -33,6 +33,7 @@ #include "PipelineStateBase.h" #include "PipelineLayout.h" #include "ShaderResourceLayoutVk.h" +#include "ShaderVariableVk.h" #include "FixedBlockMemoryAllocator.h" #include "SRBMemoryAllocator.h" #include "VulkanUtilities/VulkanObjectWrappers.h" @@ -44,6 +45,7 @@ namespace Diligent { class FixedBlockMemoryAllocator; +class ShaderVariableManagerVk; /// Implementation of the Diligent::IRenderDeviceVk interface class PipelineStateVkImpl final : public PipelineStateBase<IPipelineStateVk, RenderDeviceVkImpl> @@ -51,18 +53,26 @@ class PipelineStateVkImpl final : public PipelineStateBase<IPipelineStateVk, Ren public: using TPipelineStateBase = PipelineStateBase<IPipelineStateVk, RenderDeviceVkImpl>; - PipelineStateVkImpl( IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const PipelineStateDesc &PipelineDesc ); + PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const PipelineStateDesc& PipelineDesc); ~PipelineStateVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject** ppInterface )override final; + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override final; - virtual void CreateShaderResourceBinding( IShaderResourceBinding **ppShaderResourceBinding, bool InitStaticResources )override final; + virtual void CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources)override final; virtual bool IsCompatibleWith(const IPipelineState* pPSO)const override final; - virtual VkRenderPass GetVkRenderPass()const override final{return m_RenderPass;} + virtual VkRenderPass GetVkRenderPass()const override final { return m_RenderPass; } - virtual VkPipeline GetVkPipeline()const override final { return m_Pipeline; } + virtual VkPipeline GetVkPipeline() const override final { return m_Pipeline; } + + virtual void BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags)override final; + + virtual Uint32 GetStaticVariableCount(SHADER_TYPE ShaderType) const override final; + + virtual IShaderResourceVariable* GetStaticShaderVariable(SHADER_TYPE ShaderType, const Char* Name) override final; + + virtual IShaderResourceVariable* GetStaticShaderVariable(SHADER_TYPE ShaderType, Uint32 Index) override final; void CommitAndTransitionShaderResources(IShaderResourceBinding* pShaderResourceBinding, DeviceContextVkImpl* pCtxVkImpl, @@ -98,9 +108,31 @@ public: VkSubpassDescription& SubpassDesc); + void InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache)const; + private: - ShaderResourceLayoutVk* m_ShaderResourceLayouts = nullptr; - + const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd)const + { + VERIFY_EXPR(ShaderInd < m_NumShaders); + return m_ShaderResourceLayouts[m_NumShaders + ShaderInd]; + } + + const ShaderResourceCacheVk& GetStaticResCache(Uint32 ShaderInd)const + { + VERIFY_EXPR(ShaderInd < m_NumShaders); + return m_StaticResCaches[ShaderInd]; + } + + ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd)const + { + VERIFY_EXPR(ShaderInd < m_NumShaders); + return m_StaticVarsMgrs[ShaderInd]; + } + + ShaderResourceLayoutVk* m_ShaderResourceLayouts = nullptr; + ShaderResourceCacheVk* m_StaticResCaches = nullptr; + ShaderVariableManagerVk* m_StaticVarsMgrs = nullptr; + // SRB memory allocator must be declared before m_pDefaultShaderResBinding SRBMemoryAllocator m_SRBMemAllocator; @@ -109,8 +141,10 @@ private: VkRenderPass m_RenderPass = VK_NULL_HANDLE; // Render passes are managed by the render device VulkanUtilities::PipelineWrapper m_Pipeline; PipelineLayout m_PipelineLayout; - bool m_HasStaticResources = false; - bool m_HasNonStaticResources = false; + + Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; + bool m_HasStaticResources = false; + bool m_HasNonStaticResources = false; }; } diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h index 64410774..167949df 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.h @@ -55,24 +55,24 @@ class RenderDeviceVkImpl final : public RenderDeviceNextGenBase<RenderDeviceBase public: using TRenderDeviceBase = RenderDeviceNextGenBase<RenderDeviceBase<IRenderDeviceVk>, ICommandQueueVk>; - RenderDeviceVkImpl( IReferenceCounters* pRefCounters, - IMemoryAllocator& RawMemAllocator, - const EngineVkAttribs& CreationAttribs, - size_t CommandQueueCount, - ICommandQueueVk** pCmdQueues, + RenderDeviceVkImpl( IReferenceCounters* pRefCounters, + IMemoryAllocator& RawMemAllocator, + const EngineVkCreateInfo& EngineCI, + size_t CommandQueueCount, + ICommandQueueVk** pCmdQueues, std::shared_ptr<VulkanUtilities::VulkanInstance> Instance, std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice, std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice, Uint32 NumDeferredContexts ); ~RenderDeviceVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject** ppInterface )override final; + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface )override final; - virtual void CreatePipelineState( const PipelineStateDesc &PipelineDesc, IPipelineState** ppPipelineState )override final; + virtual void CreatePipelineState(const PipelineStateDesc& PipelineDesc, IPipelineState** ppPipelineState)override final; virtual void CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, IBuffer** ppBuffer)override final; - virtual void CreateShader(const ShaderCreationAttribs& ShaderCreationAttribs, IShader** ppShader)override final; + virtual void CreateShader(const ShaderCreateInfo& ShaderCreateInfo, IShader** ppShader)override final; virtual void CreateTexture(const TextureDesc& TexDesc, const TextureData* pData, ITexture** ppTexture)override final; @@ -134,7 +134,7 @@ private: std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> m_PhysicalDevice; std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> m_LogicalVkDevice; - EngineVkAttribs m_EngineAttribs; + EngineVkCreateInfo m_EngineAttribs; FramebufferCache m_FramebufferCache; RenderPassCache m_RenderPassCache; diff --git a/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h b/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h index e257506e..3f986515 100644 --- a/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h @@ -45,7 +45,7 @@ public: SamplerVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, const SamplerDesc& SamplerDesc); ~SamplerVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override; + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override; virtual VkSampler GetVkSampler()const override final{return m_VkSampler;} diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h index 451ddcb8..5719a1e4 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h @@ -48,15 +48,15 @@ public: ShaderResourceBindingVkImpl(IReferenceCounters* pRefCounters, class PipelineStateVkImpl* pPSO, bool IsPSOInternal); ~ShaderResourceBindingVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID& IID, IObject** ppInterface )override final; + virtual void QueryInterface( const INTERFACE_ID& IID, IObject** ppInterface )override final; virtual void BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags)override final; - virtual IShaderVariable* GetVariable(SHADER_TYPE ShaderType, const char* Name)override final; + virtual IShaderResourceVariable* GetVariable(SHADER_TYPE ShaderType, const char* Name)override final; virtual Uint32 GetVariableCount(SHADER_TYPE ShaderType) const override final; - virtual IShaderVariable* GetVariable(SHADER_TYPE ShaderType, Uint32 Index)override final; + virtual IShaderResourceVariable* GetVariable(SHADER_TYPE ShaderType, Uint32 Index)override final; virtual void InitializeStaticResources(const IPipelineState* pPipelineState)override final; @@ -66,8 +66,9 @@ public: private: - ShaderResourceCacheVk m_ShaderResourceCache; + ShaderResourceCacheVk m_ShaderResourceCache; ShaderVariableManagerVk* m_pShaderVarMgrs = nullptr; + // Shader variable manager index in m_pShaderVarMgrs[] array for every shader stage Int8 m_ResourceLayoutIndex[6] = {-1, -1, -1, -1, -1, -1}; bool m_bStaticResourcesInitialized = false; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h index d9d1c07f..1bedbcac 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h @@ -49,6 +49,7 @@ // Descriptor set for static and mutable resources is assigned during cache initialization // Descriptor set for dynamic resources is assigned at every draw call +#include <vector> #include "DescriptorPoolManager.h" #include "SPIRVShaderResources.h" @@ -83,7 +84,7 @@ public: ~ShaderResourceCacheVk(); static size_t GetRequiredMemorySize(Uint32 NumSets, Uint32 SetSizes[]); - void InitializeSets(IMemoryAllocator &MemAllocator, Uint32 NumSets, Uint32 SetSizes[]); + void InitializeSets(IMemoryAllocator& MemAllocator, Uint32 NumSets, Uint32 SetSizes[]); void InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, SPIRVShaderResourceAttribs::ResourceType Type); // sizeof(Resource) == 16 (x64, msvc, Release) @@ -93,13 +94,14 @@ public: Type(_Type) {} - Resource(const Resource&) = delete; - Resource(Resource&&) = delete; + Resource (const Resource&) = delete; + Resource (Resource&&) = delete; Resource& operator = (const Resource&) = delete; Resource& operator = (Resource&&) = delete; - const SPIRVShaderResourceAttribs::ResourceType Type; - RefCntAutoPtr<IDeviceObject> pObject; +/* 0 */ const SPIRVShaderResourceAttribs::ResourceType Type; +/*1-7*/ // Unused +/* 8 */ RefCntAutoPtr<IDeviceObject> pObject; VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo () const; VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo () const; @@ -108,7 +110,7 @@ public: VkDescriptorImageInfo GetSamplerDescriptorWriteInfo() const; }; - // sizeof(DescriptorSet) == 40 (x64, msvc, Release) + // sizeof(DescriptorSet) == 48 (x64, msvc, Release) class DescriptorSet { public: @@ -117,8 +119,8 @@ public: m_pResources (pResources) {} - DescriptorSet(const DescriptorSet&) = delete; - DescriptorSet(DescriptorSet&&) = delete; + DescriptorSet (const DescriptorSet&) = delete; + DescriptorSet (DescriptorSet&&) = delete; DescriptorSet& operator = (const DescriptorSet&) = delete; DescriptorSet& operator = (DescriptorSet&&) = delete; @@ -146,11 +148,12 @@ public: m_DescriptorSetAllocation = std::move(Allocation); } - const Uint32 m_NumResources = 0; +/* 0 */ const Uint32 m_NumResources = 0; private: - Resource* const m_pResources = nullptr; - DescriptorSetAllocation m_DescriptorSetAllocation; +/* 8 */ Resource* const m_pResources = nullptr; +/*16 */ DescriptorSetAllocation m_DescriptorSetAllocation; +/*48 */ // End of structure }; inline DescriptorSet& GetDescriptorSet(Uint32 Index) @@ -169,6 +172,7 @@ public: #ifdef _DEBUG // Only for debug purposes: indicates what types of resources are stored in the cache DbgCacheContentType DbgGetContentType()const{return m_DbgContentType;} + void DbgVerifyResourceInitialization()const; #endif template<bool VerifyOnly> @@ -190,7 +194,9 @@ private: #ifdef _DEBUG // Only for debug purposes: indicates what types of resources are stored in the cache - const DbgCacheContentType m_DbgContentType; + const DbgCacheContentType m_DbgContentType; + // Debug array that stores flags indicating if resources in the cache have been initialized + std::vector<std::vector<bool>> m_DbgInitializedResources; #endif }; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h index a4970680..8f7d2940 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h @@ -30,14 +30,14 @@ // // m_ResourceBuffer // | -// || VkResource[0] ... VkResource[s-1] | VkResource[s] ... VkResource[s+m-1] | VkResource[s+m] ... VkResource[s+m+d-1] || -// || | | || -// || SHADER_VARIABLE_TYPE_STATIC | SHADER_VARIABLE_TYPE_MUTABLE | SHADER_VARIABLE_TYPE_DYNAMIC || -// || | | || +// || VkResource[0] ... VkResource[s-1] | VkResource[s] ... VkResource[s+m-1] | VkResource[s+m] ... VkResource[s+m+d-1] || || +// || | | || || +// || VARIABLE_TYPE_STATIC | VARIABLE_TYPE_MUTABLE | VARIABLE_TYPE_DYNAMIC || Immutable Samplers || +// || | | || || // -// s == m_NumResources[SHADER_VARIABLE_TYPE_STATIC] -// m == m_NumResources[SHADER_VARIABLE_TYPE_MUTABLE] -// d == m_NumResources[SHADER_VARIABLE_TYPE_DYNAMIC] +// s == m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC] +// m == m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE] +// d == m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC] // // // @@ -86,17 +86,17 @@ // // // -// ShaderResourceLayoutVk is used as follows: -// * Every shader object (ShaderVkImpl) contains shader resource layout that facilitates management of static shader resources -// ** The resource layout defines artificial layout where resource binding matches the -// resource type (SPIRVShaderResourceAttribs::ResourceType) -// * Every pipeline state object (PipelineStateVkImpl) maintains shader resource layout for every active shader stage -// ** All variable types are preserved -// ** Bindings, descriptor sets and offsets are assigned during the initialization +// Every pipeline state object (PipelineStateVkImpl) keeps the following layouts: +// * One layout object per shader stage to facilitate management of static shader resources +// - Uses artificial layout where resource binding matches the resource type (SPIRVShaderResourceAttribs::ResourceType) +// * One layout object per shader stage used by SRBs to manage all resource types: +// - All variable types are preserved +// - Bindings, descriptor sets and offsets are assigned during the initialization #include <array> #include <memory> +#include "PipelineState.h" #include "ShaderBase.h" #include "HashUtils.h" #include "ShaderResourceCacheVk.h" @@ -111,8 +111,11 @@ namespace Diligent class ShaderResourceLayoutVk { public: - ShaderResourceLayoutVk(IObject& Owner, - const VulkanUtilities::VulkanLogicalDevice& LogicalDevice); + ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) : + m_LogicalDevice(LogicalDevice) + { + } + ShaderResourceLayoutVk (const ShaderResourceLayoutVk&) = delete; ShaderResourceLayoutVk (ShaderResourceLayoutVk&&) = delete; @@ -121,53 +124,68 @@ public: ~ShaderResourceLayoutVk(); - // This method is called by ShaderVkImpl class instance to initialize static - // shader resource layout and cache + // This method is called by PipelineStateVkImpl class instance to initialize static + // shader resource layout and the cache void InitializeStaticResourceLayout(std::shared_ptr<const SPIRVShaderResources> pSrcResources, IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, ShaderResourceCacheVk& StaticResourceCache); // This method is called by PipelineStateVkImpl class instance to initialize resource - // layouts for all shader stages in a pipeline. - static void Initialize(Uint32 NumShaders, + // layouts for all shader stages in the pipeline. + static void Initialize(IRenderDevice* pRenderDevice, + Uint32 NumShaders, ShaderResourceLayoutVk Layouts[], std::shared_ptr<const SPIRVShaderResources> pShaderResources[], IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, std::vector<uint32_t> SPIRVs[], class PipelineLayout& PipelineLayout); // sizeof(VkResource) == 24 (x64) struct VkResource { - VkResource(const VkResource&) = delete; - VkResource(VkResource&&) = delete; - VkResource& operator = (const VkResource&) = delete; - VkResource& operator = (VkResource&&) = delete; + VkResource (const VkResource&) = delete; + VkResource ( VkResource&&) = delete; + VkResource& operator = (const VkResource&) = delete; + VkResource& operator = ( VkResource&&) = delete; + + static constexpr const Uint32 CacheOffsetBits = 21; + static constexpr const Uint32 SamplerIndBits = 8; + static constexpr const Uint32 VariableTypeBits = 2; + static constexpr const Uint32 ImmutableSamplerFlagBits = 1; + static_assert(CacheOffsetBits + SamplerIndBits + VariableTypeBits + ImmutableSamplerFlagBits == 32, "Elements are expected to be packed into 32 bits"); + static_assert(SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES <= (1<<VariableTypeBits), "Not enough bits to represent SHADER_RESOURCE_VARIABLE_TYPE"); - static constexpr const Uint32 CacheOffsetBits = 24; - static constexpr const Uint32 SamplerIndBits = 8; static constexpr const Uint32 InvalidSamplerInd = (1 << SamplerIndBits)-1; -/* 0 */ const Uint16 Binding; -/* 2 */ const Uint16 DescriptorSet; -/* 4 */ const Uint32 CacheOffset : CacheOffsetBits; // Offset from the beginning of the cached descriptor set -/* 7 */ const Uint32 SamplerInd : SamplerIndBits; // When using combined texture samplers, index of the separate sampler - // assigned to separate image -/* 8 */ const SPIRVShaderResourceAttribs& SpirvAttribs; -/*16 */ const ShaderResourceLayoutVk& ParentResLayout; +/* 0 */ const Uint16 Binding; +/* 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 SPIRVShaderResourceAttribs& SpirvAttribs; +/* 16 */ const ShaderResourceLayoutVk& ParentResLayout; VkResource(const ShaderResourceLayoutVk& _ParentLayout, const SPIRVShaderResourceAttribs& _SpirvAttribs, + SHADER_RESOURCE_VARIABLE_TYPE _VariableType, uint32_t _Binding, uint32_t _DescriptorSet, Uint32 _CacheOffset, - Uint32 _SamplerInd)noexcept : - Binding (static_cast<decltype(Binding)>(_Binding)), - DescriptorSet (static_cast<decltype(DescriptorSet)>(_DescriptorSet)), - CacheOffset (_CacheOffset), - SamplerInd (_SamplerInd), - SpirvAttribs (_SpirvAttribs), - ParentResLayout (_ParentLayout) + Uint32 _SamplerInd, + bool _ImmutableSamplerAssigned = false)noexcept : + Binding (static_cast<decltype(Binding)>(_Binding)), + DescriptorSet (static_cast<decltype(DescriptorSet)>(_DescriptorSet)), + CacheOffset (_CacheOffset), + SamplerInd (_SamplerInd), + VariableType (_VariableType), + ImmutableSamplerAssigned (_ImmutableSamplerAssigned ? 1 : 0), + SpirvAttribs (_SpirvAttribs), + ParentResLayout (_ParentLayout) { 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) ); @@ -188,6 +206,20 @@ public: const VkDescriptorBufferInfo* pBufferInfo, const VkBufferView* pTexelBufferView)const; + bool IsImmutableSamplerAssigned() const + { + VERIFY(ImmutableSamplerAssigned == 0 || + SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, + "Immutable sampler can only be assigned to a sampled image or separate sampler"); + return ImmutableSamplerAssigned != 0; + } + + SHADER_RESOURCE_VARIABLE_TYPE GetVariableType() const + { + return static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VariableType); + } + private: void CacheUniformBuffer(IDeviceObject* pBuffer, ShaderResourceCacheVk::Resource& DstRes, @@ -231,9 +263,12 @@ public: #ifdef DEVELOPMENT bool dvpVerifyBindings(const ShaderResourceCacheVk& ResourceCache)const; + static void dvpVerifyResourceLayoutDesc(Uint32 NumShaders, + const std::shared_ptr<const SPIRVShaderResources> pShaderResources[], + const PipelineResourceLayoutDesc& ResourceLayoutDesc); #endif - Uint32 GetResourceCount(SHADER_VARIABLE_TYPE VarType)const + Uint32 GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE VarType)const { return m_NumResources[VarType]; } @@ -245,9 +280,17 @@ public: void CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache, VkDescriptorSet vkDynamicDescriptorSet)const; - const Char* GetShaderName()const; + const Char* GetShaderName()const + { + return m_pResources->GetShaderName(); + } + + SHADER_TYPE GetShaderType()const + { + return m_pResources->GetShaderType(); + } - const VkResource& GetResource(SHADER_VARIABLE_TYPE VarType, Uint32 r)const + const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r)const { VERIFY_EXPR( r < m_NumResources[VarType] ); auto* Resources = reinterpret_cast<const VkResource*>(m_ResourceBuffer.get()); @@ -257,16 +300,16 @@ public: bool IsUsingSeparateSamplers()const {return !m_pResources->IsUsingCombinedSamplers();} private: - Uint32 GetResourceOffset(SHADER_VARIABLE_TYPE VarType, Uint32 r)const + Uint32 GetResourceOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r)const { VERIFY_EXPR( r < m_NumResources[VarType] ); - static_assert(SHADER_VARIABLE_TYPE_STATIC == 0, "SHADER_VARIABLE_TYPE_STATIC == 0 expected"); - r += (VarType > SHADER_VARIABLE_TYPE_STATIC) ? m_NumResources[SHADER_VARIABLE_TYPE_STATIC] : 0; - static_assert(SHADER_VARIABLE_TYPE_MUTABLE == 1, "SHADER_VARIABLE_TYPE_MUTABLE == 1 expected"); - r += (VarType > SHADER_VARIABLE_TYPE_MUTABLE) ? m_NumResources[SHADER_VARIABLE_TYPE_MUTABLE] : 0; + static_assert(SHADER_RESOURCE_VARIABLE_TYPE_STATIC == 0, "SHADER_RESOURCE_VARIABLE_TYPE_STATIC == 0 expected"); + r += (VarType > SHADER_RESOURCE_VARIABLE_TYPE_STATIC) ? m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC] : 0; + static_assert(SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE == 1, "SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE == 1 expected"); + r += (VarType > SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE) ? m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE] : 0; return r; } - VkResource& GetResource(SHADER_VARIABLE_TYPE VarType, Uint32 r) + VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) { VERIFY_EXPR( r < m_NumResources[VarType] ); auto* Resources = reinterpret_cast<VkResource*>(m_ResourceBuffer.get()); @@ -282,26 +325,38 @@ private: Uint32 GetTotalResourceCount()const { - return m_NumResources[SHADER_VARIABLE_TYPE_NUM_TYPES]; + return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; } void AllocateMemory(std::shared_ptr<const SPIRVShaderResources> pSrcResources, IMemoryAllocator& Allocator, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes); + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + bool AllocateImmutableSamplers); - Uint32 FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg, Uint32 CurrResourceCount)const; + Uint32 FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg, + Uint32 CurrResourceCount, + SHADER_RESOURCE_VARIABLE_TYPE ImgVarType)const; + using ImmutableSamplerPtrType = RefCntAutoPtr<ISampler>; + ImmutableSamplerPtrType& GetImmutableSampler(Uint32 n)noexcept + { + VERIFY(n < m_NumImmutableSamplers, "Immutable sampler index (", n, ") is out of range. Total immutable sampler count: ", m_NumImmutableSamplers); + auto* ResourceMemoryEnd = reinterpret_cast<VkResource*>(m_ResourceBuffer.get()) + GetTotalResourceCount(); + return reinterpret_cast<ImmutableSamplerPtrType*>(ResourceMemoryEnd)[n]; + } - IObject& m_Owner; - const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; - std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer; +/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; +/* 8 */ std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer; - // We must use shared_ptr to reference ShaderResources instance, because - // there may be multiple objects referencing the same set of resources - std::shared_ptr<const SPIRVShaderResources> m_pResources; + // We must use shared_ptr to reference ShaderResources instance, because + // there may be multiple objects referencing the same set of resources +/*24 */ std::shared_ptr<const SPIRVShaderResources> m_pResources; - std::array<Uint16, SHADER_VARIABLE_TYPE_NUM_TYPES+1> m_NumResources = {}; +/*40 */ std::array<Uint16, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES+1> m_NumResources = {}; +/*48 */ Uint32 m_NumImmutableSamplers = 0; +/*56*/ // End of class }; } diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h index 92af69a3..03f5018f 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h @@ -30,7 +30,7 @@ // * ShaderVariableManagerVk keeps list of variables of specific types // * Every ShaderVariableVkImpl references VkResource from ShaderResourceLayoutVk // * ShaderVariableManagerVk keeps pointer to ShaderResourceCacheVk -// * ShaderVariableManagerVk is used by ShaderVkImpl to manage static resources and by +// * ShaderVariableManagerVk is used by PipelineStateVkImpl to manage static resources and by // ShaderResourceBindingVkImpl to manage mutable and dynamic resources // // __________________________ __________________________________________________________________________ @@ -64,31 +64,30 @@ namespace Diligent class ShaderVariableVkImpl; -// sizeof(ShaderVariableManagerVk) == 40 (x64, msvc, Release) +// sizeof(ShaderVariableManagerVk) == 32 (x64, msvc, Release) class ShaderVariableManagerVk { public: - ShaderVariableManagerVk(IObject &Owner) : - m_Owner(Owner) - {} + ShaderVariableManagerVk(IObject& Owner, + const ShaderResourceLayoutVk& SrcLayout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheVk& ResourceCache); + ~ShaderVariableManagerVk(); - void Initialize(const ShaderResourceLayoutVk& Layout, - IMemoryAllocator& Allocator, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheVk& ResourceCache); - void Destroy(IMemoryAllocator& Allocator); + void DestroyVariables(IMemoryAllocator& Allocator); ShaderVariableVkImpl* GetVariable(const Char* Name); ShaderVariableVkImpl* GetVariable(Uint32 Index); - void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags); + void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags); - static size_t GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - Uint32& NumVariables); + static size_t GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + Uint32& NumVariables); Uint32 GetVariableCount()const { return m_NumVariables; } @@ -98,12 +97,11 @@ private: Uint32 GetVariableIndex(const ShaderVariableVkImpl& Variable); IObject& m_Owner; - // Variable mgr is owned by either Shader object (in which case m_pResourceLayout points to - // static resource layout owned by the same shader object), or by SRB object (in which case - // m_pResourceLayout points to corresponding layout in pipeline state). Since SRB keeps strong - // reference to PSO, the layout is guaranteed be alive while SRB is alive - const ShaderResourceLayoutVk* m_pResourceLayout= nullptr; - ShaderResourceCacheVk* m_pResourceCache = nullptr; + // Variable mgr is owned by either Pipeline state object (in which case m_ResourceCache references + // static resource cache owned by the same PSO object), or by SRB object (in which case + // m_ResourceCache references the cache in the SRB). Thus the cache and the resource layout + // (which the variables reference) are guaranteed to be alive while the manager is alive. + ShaderResourceCacheVk& m_ResourceCache; // Memory is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block // memory allocator is used. This ensures that all resources from different shader resource bindings reside in @@ -112,12 +110,12 @@ private: Uint32 m_NumVariables = 0; #ifdef _DEBUG - IMemoryAllocator* m_pDbgAllocator = nullptr; + IMemoryAllocator& m_DbgAllocator; #endif }; // sizeof(ShaderVariableVkImpl) == 24 (x64) -class ShaderVariableVkImpl final : public IShaderVariable +class ShaderVariableVkImpl final : public IShaderResourceVariable { public: ShaderVariableVkImpl(ShaderVariableManagerVk& ParentManager, @@ -147,35 +145,33 @@ public: return m_ParentManager.m_Owner.Release(); } - void QueryInterface(const INTERFACE_ID &IID, IObject **ppInterface)override final + void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override final { if (ppInterface == nullptr) return; *ppInterface = nullptr; - if (IID == IID_ShaderVariable || IID == IID_Unknown) + if (IID == IID_ShaderResourceVariable || IID == IID_Unknown) { *ppInterface = this; (*ppInterface)->AddRef(); } } - virtual SHADER_VARIABLE_TYPE GetType()const override final + virtual SHADER_RESOURCE_VARIABLE_TYPE GetType()const override final { - return m_Resource.SpirvAttribs.VarType; + return m_Resource.GetVariableType(); } - virtual void Set(IDeviceObject *pObject)override final + virtual void Set(IDeviceObject* pObject)override final { - VERIFY_EXPR(m_ParentManager.m_pResourceCache != nullptr); - m_Resource.BindResource(pObject, 0, *m_ParentManager.m_pResourceCache); + m_Resource.BindResource(pObject, 0, m_ParentManager.m_ResourceCache); } virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final { - VERIFY_EXPR(m_ParentManager.m_pResourceCache != nullptr); for (Uint32 Elem = 0; Elem < NumElements; ++Elem) - m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, *m_ParentManager.m_pResourceCache); + m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, m_ParentManager.m_ResourceCache); } virtual Uint32 GetArraySize()const override final diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h b/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h index c21e10a2..03fc2189 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h @@ -29,9 +29,7 @@ #include "RenderDeviceVk.h" #include "ShaderVk.h" #include "ShaderBase.h" -#include "ShaderResourceLayoutVk.h" #include "SPIRVShaderResources.h" -#include "ShaderVariableVk.h" #include "RenderDeviceVkImpl.h" namespace Diligent @@ -46,55 +44,32 @@ class ShaderVkImpl final : public ShaderBase<IShaderVk, RenderDeviceVkImpl> public: using TShaderBase = ShaderBase<IShaderVk, RenderDeviceVkImpl>; - ShaderVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, const ShaderCreationAttribs &CreationAttribs); + ShaderVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pRenderDeviceVk, const ShaderCreateInfo& CreationAttribs); ~ShaderVkImpl(); - //virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override; + IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_ShaderVk, TShaderBase); - virtual void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags )override + virtual Uint32 GetResourceCount()const override final { - m_StaticVarsMgr.BindResources(pResourceMapping, Flags); + return m_pShaderResources->GetTotalResources(); } - virtual IShaderVariable* GetShaderVariable(const Char* Name)override - { - return m_StaticVarsMgr.GetVariable(Name); - } - - virtual Uint32 GetVariableCount() const override final - { - return m_StaticVarsMgr.GetVariableCount(); - } - - virtual IShaderVariable* GetShaderVariable(Uint32 Index)override final - { - return m_StaticVarsMgr.GetVariable(Index); - } + virtual ShaderResourceDesc GetResource(Uint32 Index)const override final; virtual const std::vector<uint32_t>& GetSPIRV()const override final { return m_SPIRV; } - + const std::shared_ptr<const SPIRVShaderResources>& GetShaderResources()const{return m_pShaderResources;} - const ShaderResourceLayoutVk& GetStaticResLayout()const { return m_StaticResLayout; } - const ShaderResourceCacheVk& GetStaticResCache() const { return m_StaticResCache; } - const char* GetEntryPoint() const { return m_EntryPoint.c_str(); } -#ifdef DEVELOPMENT - bool DvpVerifyStaticResourceBindings()const; -#endif - private: void MapHLSLVertexShaderInputs(); - // ShaderResources class instance must be referenced through the shared pointer, because + // SPIRVShaderResources class instance must be referenced through the shared pointer, because // it is referenced by ShaderResourceLayoutVk class instances std::shared_ptr<const SPIRVShaderResources> m_pShaderResources; - ShaderResourceLayoutVk m_StaticResLayout; - ShaderResourceCacheVk m_StaticResCache; - ShaderVariableManagerVk m_StaticVarsMgr; std::string m_EntryPoint; std::vector<uint32_t> m_SPIRV; diff --git a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h index aada3ab5..d309c638 100644 --- a/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/SwapChainVkImpl.h @@ -49,7 +49,7 @@ public: void* pNativeWndHandle); ~SwapChainVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID& IID, IObject** ppInterface )override final; + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override final; virtual void Present(Uint32 SyncInterval)override final; virtual void Resize( Uint32 NewWidth, Uint32 NewHeight )override final; diff --git a/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h b/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h index 650829e1..8989c245 100644 --- a/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/TextureViewVkImpl.h @@ -50,7 +50,7 @@ public: bool bIsDefaultView); ~TextureViewVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID& IID, IObject** ppInterface )override; + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override final; VkImageView GetVulkanImageView()const override final{return m_ImageView;} diff --git a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h index 4d040a0e..4d19fe91 100644 --- a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h +++ b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.h @@ -62,7 +62,7 @@ public: ~TextureVkImpl(); - virtual void QueryInterface( const Diligent::INTERFACE_ID& IID, IObject** ppInterface )override; + virtual void QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface)override final; virtual VkImage GetVkImage()const override final{ return m_VulkanImage; } virtual void* GetNativeHandle()override final diff --git a/Graphics/GraphicsEngineVulkan/interface/RenderDeviceFactoryVk.h b/Graphics/GraphicsEngineVulkan/interface/EngineFactoryVk.h index b5de2664..861f5514 100644 --- a/Graphics/GraphicsEngineVulkan/interface/RenderDeviceFactoryVk.h +++ b/Graphics/GraphicsEngineVulkan/interface/EngineFactoryVk.h @@ -51,23 +51,23 @@ namespace Diligent class IEngineFactoryVk { public: - virtual void CreateDeviceAndContextsVk(const EngineVkAttribs& CreationAttribs, + virtual void CreateDeviceAndContextsVk(const EngineVkCreateInfo& EngineCI, IRenderDevice **ppDevice, IDeviceContext **ppContexts, Uint32 NumDeferredContexts) = 0; //virtual void AttachToVulkanDevice(void *pVkNativeDevice, // class ICommandQueueVk *pCommandQueue, - // const EngineVkAttribs& EngineAttribs, + // const EngineVkCreateInfo& EngineCI, // IRenderDevice **ppDevice, // IDeviceContext **ppContexts, // Uint32 NumDeferredContexts) = 0; - virtual void CreateSwapChainVk(IRenderDevice *pDevice, - IDeviceContext *pImmediateContext, - const SwapChainDesc& SwapChainDesc, - void* pNativeWndHandle, - ISwapChain **ppSwapChain) = 0; + virtual void CreateSwapChainVk(IRenderDevice* pDevice, + IDeviceContext* pImmediateContext, + const SwapChainDesc& SwapChainDesc, + void* pNativeWndHandle, + ISwapChain** ppSwapChain) = 0; }; @@ -78,7 +78,7 @@ public: typedef IEngineFactoryVk* (*GetEngineFactoryVkType)(); - static bool LoadGraphicsEngineVk(GetEngineFactoryVkType &GetFactoryFunc) + static bool LoadGraphicsEngineVk(GetEngineFactoryVkType& GetFactoryFunc) { GetFactoryFunc = nullptr; std::string LibName = "GraphicsEngineVk_"; diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 0200476d..daabca38 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -45,20 +45,20 @@ namespace Diligent return ss.str(); } - DeviceContextVkImpl::DeviceContextVkImpl( IReferenceCounters* pRefCounters, - RenderDeviceVkImpl* pDeviceVkImpl, - bool bIsDeferred, - const EngineVkAttribs& Attribs, - Uint32 ContextId, - Uint32 CommandQueueId, - std::shared_ptr<GenerateMipsVkHelper> GenerateMipsHelper) : + DeviceContextVkImpl::DeviceContextVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pDeviceVkImpl, + bool bIsDeferred, + const EngineVkCreateInfo& EngineCI, + Uint32 ContextId, + Uint32 CommandQueueId, + std::shared_ptr<GenerateMipsVkHelper> GenerateMipsHelper) : TDeviceContextBase { pRefCounters, pDeviceVkImpl, ContextId, CommandQueueId, - bIsDeferred ? std::numeric_limits<decltype(m_NumCommandsToFlush)>::max() : Attribs.NumCommandsToFlushCmdBuffer, + bIsDeferred ? std::numeric_limits<decltype(m_NumCommandsToFlush)>::max() : EngineCI.NumCommandsToFlushCmdBuffer, bIsDeferred }, m_CommandBuffer { pDeviceVkImpl->GetLogicalDevice().GetEnabledGraphicsShaderStages() }, @@ -76,13 +76,13 @@ namespace Diligent { *pDeviceVkImpl, GetContextObjectName("Upload heap", bIsDeferred, ContextId), - Attribs.UploadHeapPageSize + EngineCI.UploadHeapPageSize }, m_DynamicHeap { pDeviceVkImpl->GetDynamicMemoryManager(), GetContextObjectName("Dynamic heap", bIsDeferred, ContextId), - Attribs.DynamicHeapPageSize + EngineCI.DynamicHeapPageSize }, m_DynamicDescrSetAllocator { diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index a4ab8ae3..acb6265a 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -26,7 +26,7 @@ #include "pch.h" #include <array> -#include "RenderDeviceFactoryVk.h" +#include "EngineFactoryVk.h" #include "RenderDeviceVkImpl.h" #include "DeviceContextVkImpl.h" #include "SwapChainVkImpl.h" @@ -48,31 +48,31 @@ public: return &TheFactory; } - void CreateDeviceAndContextsVk( const EngineVkAttribs& CreationAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts)override final; + void CreateDeviceAndContextsVk(const EngineVkCreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts)override final; void AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::VulkanInstance> Instance, std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice, std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice, - size_t CommandQueueCount, - ICommandQueueVk** ppCommandQueues, - const EngineVkAttribs& EngineAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts);//override final; - - void CreateSwapChainVk( IRenderDevice* pDevice, - IDeviceContext* pImmediateContext, - const SwapChainDesc& SwapChainDesc, - void* pNativeWndHandle, - ISwapChain** ppSwapChain )override final; + size_t CommandQueueCount, + ICommandQueueVk** ppCommandQueues, + const EngineVkCreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts);//override final; + + void CreateSwapChainVk(IRenderDevice* pDevice, + IDeviceContext* pImmediateContext, + const SwapChainDesc& SwapChainDesc, + void* pNativeWndHandle, + ISwapChain** ppSwapChain)override final; }; /// Creates render device and device contexts for Vulkan backend -/// \param [in] CreationAttribs - Engine creation attributes. +/// \param [in] EngineCI - Engine creation attributes. /// \param [out] ppDevice - Address of the memory location where pointer to /// the created device will be written /// \param [out] ppContexts - Address of the memory location where pointers to @@ -83,10 +83,10 @@ public: /// of deferred contexts is requested, pointers to the /// contexts are written to ppContexts array starting /// at position 1 -void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& CreationAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts) +void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts) { VERIFY( ppDevice && ppContexts, "Null pointer provided" ); if( !ppDevice || !ppContexts ) @@ -95,7 +95,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea #if 0 for (Uint32 Type = Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; Type < Vk_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; ++Type) { - auto CPUHeapAllocSize = CreationAttribs.CPUDescriptorHeapAllocationSize[Type]; + auto CPUHeapAllocSize = EngineCI.CPUDescriptorHeapAllocationSize[Type]; Uint32 MaxSize = 1 << 20; if (CPUHeapAllocSize > 1 << 20) { @@ -111,7 +111,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea } #endif - SetRawAllocator(CreationAttribs.pRawMemAllocator); + SetRawAllocator(EngineCI.pRawMemAllocator); *ppDevice = nullptr; memset(ppContexts, 0, sizeof(*ppContexts) * (1 + NumDeferredContexts)); @@ -119,10 +119,10 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea try { auto Instance = VulkanUtilities::VulkanInstance::Create( - CreationAttribs.EnableValidation, - CreationAttribs.GlobalExtensionCount, - CreationAttribs.ppGlobalExtensionNames, - reinterpret_cast<VkAllocationCallbacks*>(CreationAttribs.pVkAllocator)); + EngineCI.EnableValidation, + EngineCI.GlobalExtensionCount, + EngineCI.ppGlobalExtensionNames, + reinterpret_cast<VkAllocationCallbacks*>(EngineCI.pVkAllocator)); auto vkDevice = Instance->SelectPhysicalDevice(); auto PhysicalDevice = VulkanUtilities::VulkanPhysicalDevice::Create(vkDevice); @@ -152,20 +152,20 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea DeviceCreateInfo.queueCreateInfoCount = 1; DeviceCreateInfo.pQueueCreateInfos = &QueueInfo; VkPhysicalDeviceFeatures DeviceFeatures = {}; - DeviceFeatures.depthBiasClamp = CreationAttribs.EnabledFeatures.depthBiasClamp ? VK_TRUE : VK_FALSE; - DeviceFeatures.fillModeNonSolid = CreationAttribs.EnabledFeatures.fillModeNonSolid ? VK_TRUE : VK_FALSE; - DeviceFeatures.depthClamp = CreationAttribs.EnabledFeatures.depthClamp ? VK_TRUE : VK_FALSE; - DeviceFeatures.independentBlend = CreationAttribs.EnabledFeatures.independentBlend ? VK_TRUE : VK_FALSE; - DeviceFeatures.samplerAnisotropy = CreationAttribs.EnabledFeatures.samplerAnisotropy ? VK_TRUE : VK_FALSE; - DeviceFeatures.geometryShader = CreationAttribs.EnabledFeatures.geometryShader ? VK_TRUE : VK_FALSE; - DeviceFeatures.tessellationShader = CreationAttribs.EnabledFeatures.tessellationShader ? VK_TRUE : VK_FALSE; - DeviceFeatures.dualSrcBlend = CreationAttribs.EnabledFeatures.dualSrcBlend ? VK_TRUE : VK_FALSE; - DeviceFeatures.multiViewport = CreationAttribs.EnabledFeatures.multiViewport ? VK_TRUE : VK_FALSE; - DeviceFeatures.imageCubeArray = CreationAttribs.EnabledFeatures.imageCubeArray ? VK_TRUE : VK_FALSE; - DeviceFeatures.textureCompressionBC = CreationAttribs.EnabledFeatures.textureCompressionBC ? VK_TRUE : VK_FALSE; - DeviceFeatures.vertexPipelineStoresAndAtomics = CreationAttribs.EnabledFeatures.vertexPipelineStoresAndAtomics ? VK_TRUE : VK_FALSE; - DeviceFeatures.fragmentStoresAndAtomics = CreationAttribs.EnabledFeatures.fragmentStoresAndAtomics ? VK_TRUE : VK_FALSE; - DeviceFeatures.shaderStorageImageExtendedFormats = CreationAttribs.EnabledFeatures.shaderStorageImageExtendedFormats ? VK_TRUE : VK_FALSE; + DeviceFeatures.depthBiasClamp = EngineCI.EnabledFeatures.depthBiasClamp ? VK_TRUE : VK_FALSE; + DeviceFeatures.fillModeNonSolid = EngineCI.EnabledFeatures.fillModeNonSolid ? VK_TRUE : VK_FALSE; + DeviceFeatures.depthClamp = EngineCI.EnabledFeatures.depthClamp ? VK_TRUE : VK_FALSE; + DeviceFeatures.independentBlend = EngineCI.EnabledFeatures.independentBlend ? VK_TRUE : VK_FALSE; + DeviceFeatures.samplerAnisotropy = EngineCI.EnabledFeatures.samplerAnisotropy ? VK_TRUE : VK_FALSE; + DeviceFeatures.geometryShader = EngineCI.EnabledFeatures.geometryShader ? VK_TRUE : VK_FALSE; + DeviceFeatures.tessellationShader = EngineCI.EnabledFeatures.tessellationShader ? VK_TRUE : VK_FALSE; + DeviceFeatures.dualSrcBlend = EngineCI.EnabledFeatures.dualSrcBlend ? VK_TRUE : VK_FALSE; + DeviceFeatures.multiViewport = EngineCI.EnabledFeatures.multiViewport ? VK_TRUE : VK_FALSE; + DeviceFeatures.imageCubeArray = EngineCI.EnabledFeatures.imageCubeArray ? VK_TRUE : VK_FALSE; + DeviceFeatures.textureCompressionBC = EngineCI.EnabledFeatures.textureCompressionBC ? VK_TRUE : VK_FALSE; + DeviceFeatures.vertexPipelineStoresAndAtomics = EngineCI.EnabledFeatures.vertexPipelineStoresAndAtomics ? VK_TRUE : VK_FALSE; + DeviceFeatures.fragmentStoresAndAtomics = EngineCI.EnabledFeatures.fragmentStoresAndAtomics ? VK_TRUE : VK_FALSE; + DeviceFeatures.shaderStorageImageExtendedFormats = EngineCI.EnabledFeatures.shaderStorageImageExtendedFormats ? VK_TRUE : VK_FALSE; DeviceCreateInfo.pEnabledFeatures = &DeviceFeatures; // NULL or a pointer to a VkPhysicalDeviceFeatures structure that contains // boolean indicators of all the features to be enabled. @@ -186,7 +186,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea pCmdQueueVk = NEW_RC_OBJ(RawMemAllocator, "CommandQueueVk instance", CommandQueueVkImpl)(LogicalDevice, QueueInfo.queueFamilyIndex); std::array<ICommandQueueVk*, 1> CommandQueues = {{pCmdQueueVk}}; - AttachToVulkanDevice(Instance, std::move(PhysicalDevice), LogicalDevice, CommandQueues.size(), CommandQueues.data(), CreationAttribs, ppDevice, ppContexts, NumDeferredContexts); + AttachToVulkanDevice(Instance, std::move(PhysicalDevice), LogicalDevice, CommandQueues.size(), CommandQueues.data(), EngineCI, ppDevice, ppContexts, NumDeferredContexts); FenceDesc Desc; Desc.Name = "Command queue fence"; @@ -208,7 +208,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea /// \param [in] PhysicalDevice - pointer to the object representing physical device /// \param [in] LogicalDevice - shared pointer to a VulkanUtilities::VulkanLogicalDevice object /// \param [in] pCommandQueue - pointer to the implementation of command queue -/// \param [in] EngineAttribs - Engine creation attributes. +/// \param [in] EngineCI - Engine creation attributes. /// \param [out] ppDevice - Address of the memory location where pointer to /// the created device will be written /// \param [out] ppContexts - Address of the memory location where pointers to @@ -222,12 +222,12 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr<VulkanUtilities::VulkanInstance> Instance, std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice, std::shared_ptr<VulkanUtilities::VulkanLogicalDevice> LogicalDevice, - size_t CommandQueueCount, - ICommandQueueVk** ppCommandQueues, - const EngineVkAttribs& EngineAttribs, - IRenderDevice** ppDevice, - IDeviceContext** ppContexts, - Uint32 NumDeferredContexts) + size_t CommandQueueCount, + ICommandQueueVk** ppCommandQueues, + const EngineVkCreateInfo& EngineCI, + IRenderDevice** ppDevice, + IDeviceContext** ppContexts, + Uint32 NumDeferredContexts) { VERIFY( ppCommandQueues && ppDevice && ppContexts, "Null pointer provided" ); if(!LogicalDevice || !ppCommandQueues || !ppDevice || !ppContexts ) @@ -239,12 +239,12 @@ void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr<VulkanUtilities:: try { auto &RawMemAllocator = GetRawAllocator(); - RenderDeviceVkImpl *pRenderDeviceVk( NEW_RC_OBJ(RawMemAllocator, "RenderDeviceVkImpl instance", RenderDeviceVkImpl)(RawMemAllocator, EngineAttribs, CommandQueueCount, ppCommandQueues, Instance, std::move(PhysicalDevice), LogicalDevice, NumDeferredContexts ) ); + RenderDeviceVkImpl *pRenderDeviceVk( NEW_RC_OBJ(RawMemAllocator, "RenderDeviceVkImpl instance", RenderDeviceVkImpl)(RawMemAllocator, EngineCI, CommandQueueCount, ppCommandQueues, Instance, std::move(PhysicalDevice), LogicalDevice, NumDeferredContexts ) ); pRenderDeviceVk->QueryInterface(IID_RenderDevice, reinterpret_cast<IObject**>(ppDevice) ); std::shared_ptr<GenerateMipsVkHelper> GenerateMipsHelper(new GenerateMipsVkHelper(*pRenderDeviceVk)); - RefCntAutoPtr<DeviceContextVkImpl> pImmediateCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, false, EngineAttribs, 0, 0, GenerateMipsHelper) ); + RefCntAutoPtr<DeviceContextVkImpl> pImmediateCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, false, EngineCI, 0, 0, GenerateMipsHelper) ); // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceVk will // keep a weak reference to the context pImmediateCtxVk->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppContexts) ); @@ -252,7 +252,7 @@ void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr<VulkanUtilities:: for (Uint32 DeferredCtx = 0; DeferredCtx < NumDeferredContexts; ++DeferredCtx) { - RefCntAutoPtr<DeviceContextVkImpl> pDeferredCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, true, EngineAttribs, 1+DeferredCtx, 0, GenerateMipsHelper) ); + RefCntAutoPtr<DeviceContextVkImpl> pDeferredCtxVk( NEW_RC_OBJ(RawMemAllocator, "DeviceContextVkImpl instance", DeviceContextVkImpl)(pRenderDeviceVk, true, EngineCI, 1+DeferredCtx, 0, GenerateMipsHelper) ); // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceVk will // keep a weak reference to the context pDeferredCtxVk->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppContexts + 1 + DeferredCtx) ); @@ -293,11 +293,11 @@ void EngineFactoryVkImpl::AttachToVulkanDevice(std::shared_ptr<VulkanUtilities:: /// /// \param [out] ppSwapChain - Address of the memory location where pointer to the new /// swap chain will be written -void EngineFactoryVkImpl::CreateSwapChainVk( IRenderDevice* pDevice, - IDeviceContext* pImmediateContext, - const SwapChainDesc& SCDesc, - void* pNativeWndHandle, - ISwapChain** ppSwapChain ) +void EngineFactoryVkImpl::CreateSwapChainVk(IRenderDevice* pDevice, + IDeviceContext* pImmediateContext, + const SwapChainDesc& SCDesc, + void* pNativeWndHandle, + ISwapChain** ppSwapChain) { VERIFY( ppSwapChain, "Null pointer provided" ); if( !ppSwapChain ) diff --git a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp index fc9af5a8..4ae8243e 100644 --- a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp +++ b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp @@ -104,22 +104,13 @@ namespace Diligent std::array<RefCntAutoPtr<IPipelineState>, 4> GenerateMipsVkHelper::CreatePSOs(TEXTURE_FORMAT Fmt) { - ShaderCreationAttribs CSCreateAttribs; + ShaderCreateInfo CSCreateInfo; std::array<RefCntAutoPtr<IPipelineState>, 4> PSOs; - CSCreateAttribs.Source = g_GenerateMipsCSSource; - CSCreateAttribs.EntryPoint = "main"; - CSCreateAttribs.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL; - CSCreateAttribs.Desc.ShaderType = SHADER_TYPE_COMPUTE; - CSCreateAttribs.Desc.DefaultVariableType = SHADER_VARIABLE_TYPE_DYNAMIC; - - ShaderVariableDesc VarDesc{"CB", SHADER_VARIABLE_TYPE_STATIC}; - CSCreateAttribs.Desc.VariableDesc = &VarDesc; - CSCreateAttribs.Desc.NumVariables = 1; - - const StaticSamplerDesc StaticSampler("SrcMip", Sam_LinearClamp); - CSCreateAttribs.Desc.StaticSamplers = &StaticSampler; - CSCreateAttribs.Desc.NumStaticSamplers = 1; + CSCreateInfo.Source = g_GenerateMipsCSSource; + CSCreateInfo.EntryPoint = "main"; + CSCreateInfo.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL; + CSCreateInfo.Desc.ShaderType = SHADER_TYPE_COMPUTE; const auto& FmtAttribs = GetTextureFormatAttribs(Fmt); bool IsGamma = FmtAttribs.ComponentType == COMPONENT_TYPE_UNORM_SRGB; @@ -134,7 +125,7 @@ namespace Diligent Macros.AddShaderMacro("IMG_FORMAT", GlFmt.data()); Macros.Finalize(); - CSCreateAttribs.Macros = Macros; + CSCreateInfo.Macros = Macros; std::stringstream name_ss; name_ss << "Generate mips " << GlFmt.data(); @@ -147,16 +138,26 @@ namespace Diligent default: UNEXPECTED("Unexpected value"); } auto name = name_ss.str(); - CSCreateAttribs.Desc.Name = name.c_str(); + CSCreateInfo.Desc.Name = name.c_str(); RefCntAutoPtr<IShader> pCS; - m_DeviceVkImpl.CreateShader(CSCreateAttribs, &pCS); + m_DeviceVkImpl.CreateShader(CSCreateInfo, &pCS); PipelineStateDesc PSODesc; PSODesc.IsComputePipeline = true; PSODesc.Name = name.c_str(); PSODesc.ComputePipeline.pCS = pCS; - pCS->GetShaderVariable("CB")->Set(m_ConstantsCB); + + PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; + ShaderResourceVariableDesc VarDesc{SHADER_TYPE_COMPUTE, "CB", SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; + PSODesc.ResourceLayout.Variables = &VarDesc; + PSODesc.ResourceLayout.NumVariables = 1; + + const StaticSamplerDesc StaticSampler(SHADER_TYPE_COMPUTE, "SrcMip", Sam_LinearClamp); + PSODesc.ResourceLayout.StaticSamplers = &StaticSampler; + PSODesc.ResourceLayout.NumStaticSamplers = 1; + m_DeviceVkImpl.CreatePipelineState(PSODesc, &PSOs[NonPowOfTwo]); + PSOs[NonPowOfTwo]->GetStaticShaderVariable(SHADER_TYPE_COMPUTE, "CB")->Set(m_ConstantsCB); } return PSOs; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index 6e930bcc..d8383418 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -315,13 +315,14 @@ size_t PipelineLayout::DescriptorSetLayoutManager::GetHash()const } void PipelineLayout::DescriptorSetLayoutManager::AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResAttribs, - VkSampler vkStaticSampler, + SHADER_RESOURCE_VARIABLE_TYPE VariableType, + VkSampler vkImmutableSampler, SHADER_TYPE ShaderType, Uint32& DescriptorSet, Uint32& Binding, Uint32& OffsetInCache) { - auto& DescrSet = GetDescriptorSet(ResAttribs.VarType); + auto& DescrSet = GetDescriptorSet(VariableType); if (DescrSet.SetIndex < 0) { DescrSet.SetIndex = m_ActiveSets++; @@ -335,16 +336,15 @@ void PipelineLayout::DescriptorSetLayoutManager::AllocateResourceSlot(const SPIR VkBinding.descriptorCount = ResAttribs.ArraySize; // There are no limitations on what combinations of stages can use a descriptor binding (13.2.1) VkBinding.stageFlags = ShaderTypeToVkShaderStageFlagBit(ShaderType); - if (ResAttribs.IsImmutableSamplerAssigned()) + if (vkImmutableSampler != VK_NULL_HANDLE) { - VERIFY(vkStaticSampler != VK_NULL_HANDLE, "No static sampler provided"); // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, and // descriptorCount is not 0 and pImmutableSamplers is not NULL, pImmutableSamplers must be a valid pointer // to an array of descriptorCount valid VkSampler handles (13.2.1) - auto *pStaticSamplers = reinterpret_cast<VkSampler*>(ALLOCATE(m_MemAllocator, "Memory buffer for immutable samplers", sizeof(VkSampler) * VkBinding.descriptorCount)); + auto *pImmutableSamplers = reinterpret_cast<VkSampler*>(ALLOCATE(m_MemAllocator, "Memory buffer for immutable samplers", sizeof(VkSampler) * VkBinding.descriptorCount)); for(uint32_t s=0; s < VkBinding.descriptorCount; ++s) - pStaticSamplers[s] = vkStaticSampler; - VkBinding.pImmutableSamplers = pStaticSamplers; + pImmutableSamplers[s] = vkImmutableSampler; + VkBinding.pImmutableSamplers = pImmutableSamplers; } else VkBinding.pImmutableSamplers = nullptr; @@ -365,14 +365,18 @@ void PipelineLayout::Release(RenderDeviceVkImpl *pDeviceVkImpl, Uint64 CommandQu } void PipelineLayout::AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResAttribs, - VkSampler vkStaticSampler, + SHADER_RESOURCE_VARIABLE_TYPE VariableType, + VkSampler vkImmutableSampler, SHADER_TYPE ShaderType, Uint32& DescriptorSet, // Output parameter Uint32& Binding, // Output parameter Uint32& OffsetInCache, std::vector<uint32_t>& SPIRV) { - m_LayoutMgr.AllocateResourceSlot(ResAttribs, vkStaticSampler, ShaderType, DescriptorSet, Binding, OffsetInCache); + VERIFY( (ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) || vkImmutableSampler == VK_NULL_HANDLE, + "Immutable sampler should only be specified for combined image samplers or separate samplers"); + m_LayoutMgr.AllocateResourceSlot(ResAttribs, VariableType ,vkImmutableSampler, ShaderType, DescriptorSet, Binding, OffsetInCache); SPIRV[ResAttribs.BindingDecorationOffset] = Binding; SPIRV[ResAttribs.DescriptorSetDecorationOffset] = DescriptorSet; } @@ -387,14 +391,14 @@ std::array<Uint32, 2> PipelineLayout::GetDescriptorSetSizes(Uint32& NumSets)cons NumSets = 0; std::array<Uint32, 2> SetSizes = {}; - const auto &StaticAndMutSet = m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_STATIC); + const auto &StaticAndMutSet = m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_STATIC); if (StaticAndMutSet.SetIndex >= 0) { NumSets = std::max(NumSets, static_cast<Uint32>(StaticAndMutSet.SetIndex + 1)); SetSizes[StaticAndMutSet.SetIndex] = StaticAndMutSet.TotalDescriptors; } - const auto &DynamicSet = m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_DYNAMIC); + const auto &DynamicSet = m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC); if (DynamicSet.SetIndex >= 0) { NumSets = std::max(NumSets, static_cast<Uint32>(DynamicSet.SetIndex + 1)); @@ -416,7 +420,7 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl, // Resources are initialized by source layout when shader resource binding objects are created ResourceCache.InitializeSets(CacheMemAllocator, NumSets, SetSizes.data()); - const auto& StaticAndMutSet = m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_STATIC); + const auto& StaticAndMutSet = m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_STATIC); if (StaticAndMutSet.SetIndex >= 0) { const char* DescrSetName = "Static/Mutable Descriptor Set"; @@ -443,11 +447,11 @@ void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkI // Do not use vector::resize for BindInfo.vkSets and BindInfo.DynamicOffsets as this // causes unnecessary work to zero-initialize new elements - VERIFY(m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_STATIC).SetIndex == m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_MUTABLE).SetIndex, + VERIFY(m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_STATIC).SetIndex == m_LayoutMgr.GetDescriptorSet(SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE).SetIndex, "Static and mutable variables are expected to share the same descriptor set"); Uint32 TotalDynamicDescriptors = 0; BindInfo.SetCout = 0; - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_MUTABLE; VarType <= SHADER_VARIABLE_TYPE_DYNAMIC; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) + for(SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE; VarType <= SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType+1)) { const auto& Set = m_LayoutMgr.GetDescriptorSet(VarType); if (Set.SetIndex >= 0) @@ -456,7 +460,7 @@ void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkI if (BindInfo.SetCout > BindInfo.vkSets.size()) BindInfo.vkSets.resize(BindInfo.SetCout); VERIFY_EXPR(BindInfo.vkSets[Set.SetIndex] == VK_NULL_HANDLE); - if (VarType == SHADER_VARIABLE_TYPE_MUTABLE) + if (VarType == SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE) BindInfo.vkSets[Set.SetIndex] = ResourceCache.GetDescriptorSet(Set.SetIndex).GetVkDescriptorSet(); else { @@ -506,7 +510,7 @@ void PipelineLayout::BindDescriptorSetsWithDynamicOffsets(DeviceContextVkImpl* VERIFY_EXPR(BindInfo.pResourceCache != nullptr); #ifdef _DEBUG Uint32 TotalDynamicDescriptors = 0; - for (SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_MUTABLE; VarType <= SHADER_VARIABLE_TYPE_DYNAMIC; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType + 1)) + for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE; VarType <= SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1)) { const auto &Set = m_LayoutMgr.GetDescriptorSet(VarType); TotalDynamicDescriptors += Set.NumDynamicDescriptors; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 8fd4583c..776db721 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -49,23 +49,24 @@ VkRenderPassCreateInfo PipelineStateVkImpl::GetRenderPassCreateInfo( // Prepare render pass create info (7.1) VkRenderPassCreateInfo RenderPassCI = {}; - RenderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - RenderPassCI.pNext = nullptr; - RenderPassCI.flags = 0; // reserved for future use + RenderPassCI.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + RenderPassCI.pNext = nullptr; + RenderPassCI.flags = 0; // reserved for future use RenderPassCI.attachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets; - uint32_t AttachmentInd = 0; + + uint32_t AttachmentInd = 0; VkSampleCountFlagBits SampleCountFlags = static_cast<VkSampleCountFlagBits>(1 << (SampleCount - 1)); VkAttachmentReference* pDepthAttachmentReference = nullptr; if (DSVFormat != TEX_FORMAT_UNKNOWN) { auto& DepthAttachment = Attachments[AttachmentInd]; - DepthAttachment.flags = 0; // Allowed value VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT - DepthAttachment.format = TexFormatToVkFormat(DSVFormat); + DepthAttachment.flags = 0; // Allowed value VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT + DepthAttachment.format = TexFormatToVkFormat(DSVFormat); DepthAttachment.samples = SampleCountFlags; - DepthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area - // will be preserved. For attachments with a depth/stencil format, - // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT. + DepthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area + // will be preserved. For attachments with a depth/stencil format, + // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT. DepthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render // area are written to memory. For attachments with a depth/stencil format, // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT. @@ -86,12 +87,12 @@ VkRenderPassCreateInfo PipelineStateVkImpl::GetRenderPassCreateInfo( { auto& ColorAttachment = Attachments[AttachmentInd]; - ColorAttachment.flags = 0; // Allowed value VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT - ColorAttachment.format = TexFormatToVkFormat(RTVFormats[rt]); + ColorAttachment.flags = 0; // Allowed value VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT + ColorAttachment.format = TexFormatToVkFormat(RTVFormats[rt]); ColorAttachment.samples = SampleCountFlags; - ColorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area - // will be preserved. For attachments with a depth/stencil format, - // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_READ_BIT. + ColorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area + // will be preserved. For attachments with a depth/stencil format, + // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_READ_BIT. ColorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render // area are written to memory. For attachments with a color format, // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT. @@ -102,23 +103,23 @@ VkRenderPassCreateInfo PipelineStateVkImpl::GetRenderPassCreateInfo( auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd]; ColorAttachmentRef.attachment = AttachmentInd; - ColorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + ColorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; } - RenderPassCI.pAttachments = Attachments.data(); - RenderPassCI.subpassCount = 1; - RenderPassCI.pSubpasses = &SubpassDesc; + RenderPassCI.pAttachments = Attachments.data(); + RenderPassCI.subpassCount = 1; + RenderPassCI.pSubpasses = &SubpassDesc; RenderPassCI.dependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies. - RenderPassCI.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing - // dependencies between pairs of subpasses, or NULL if dependencyCount is zero. + RenderPassCI.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing + // dependencies between pairs of subpasses, or NULL if dependencyCount is zero. - SubpassDesc.flags = 0; // All bits for this type are defined by extensions - SubpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; // Currently, only graphics subpasses are supported. - SubpassDesc.inputAttachmentCount = 0; - SubpassDesc.pInputAttachments = nullptr; - SubpassDesc.colorAttachmentCount = NumRenderTargets; - SubpassDesc.pColorAttachments = pColorAttachmentsReference; + SubpassDesc.flags = 0; // All bits for this type are defined by extensions + SubpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; // Currently, only graphics subpasses are supported. + SubpassDesc.inputAttachmentCount = 0; + SubpassDesc.pInputAttachments = nullptr; + SubpassDesc.colorAttachmentCount = NumRenderTargets; + SubpassDesc.pColorAttachments = pColorAttachmentsReference; SubpassDesc.pResolveAttachments = nullptr; SubpassDesc.pDepthStencilAttachment = pDepthAttachmentReference; SubpassDesc.preserveAttachmentCount = 0; @@ -147,7 +148,7 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters RenderDeviceVkImpl* pDeviceVk, const PipelineStateDesc& PipelineDesc) : TPipelineStateBase(pRefCounters, pDeviceVk, PipelineDesc), - m_SRBMemAllocator(GetRawAllocator()) + m_SRBMemAllocator (GetRawAllocator()) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); @@ -155,16 +156,31 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters auto& ShaderResLayoutAllocator = GetRawAllocator(); std::array<std::shared_ptr<const SPIRVShaderResources>, MaxShadersInPipeline> ShaderResources; std::array<std::vector<uint32_t>, MaxShadersInPipeline> ShaderSPIRVs; - auto* pResLayoutRawMem = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", sizeof(ShaderResourceLayoutVk) * m_NumShaders); + auto* pResLayoutRawMem = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", sizeof(ShaderResourceLayoutVk) * m_NumShaders * 2); + auto* pStaticResCacheRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheVk", sizeof(ShaderResourceCacheVk) * m_NumShaders); + auto* pStaticVarMgrRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", sizeof(ShaderVariableManagerVk) * m_NumShaders); m_ShaderResourceLayouts = reinterpret_cast<ShaderResourceLayoutVk*>(pResLayoutRawMem); + m_StaticResCaches = reinterpret_cast<ShaderResourceCacheVk*>(pStaticResCacheRawMem); + m_StaticVarsMgrs = reinterpret_cast<ShaderVariableManagerVk*>(pStaticVarMgrRawMem); for (Uint32 s=0; s < m_NumShaders; ++s) { - new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk(*this, LogicalDevice); + new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk(LogicalDevice); auto* pShaderVk = GetShader<const ShaderVkImpl>(s); ShaderResources[s] = pShaderVk->GetShaderResources(); - ShaderSPIRVs[s] = pShaderVk->GetSPIRV(); + ShaderSPIRVs[s] = pShaderVk->GetSPIRV(); + + const auto ShaderType = pShaderVk->GetDesc().ShaderType; + const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType); + m_ResourceLayoutIndex[ShaderTypeInd] = static_cast<Int8>(s); + + auto* pStaticResLayout = new (m_ShaderResourceLayouts + m_NumShaders + s) ShaderResourceLayoutVk(LogicalDevice); + auto* pStaticResCache = new (m_StaticResCaches + s) ShaderResourceCacheVk(ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources); + pStaticResLayout->InitializeStaticResourceLayout(ShaderResources[s], ShaderResLayoutAllocator, PipelineDesc.ResourceLayout, m_StaticResCaches[s]); + + new (m_StaticVarsMgrs + s) ShaderVariableManagerVk(*this, *pStaticResLayout, GetRawAllocator(), nullptr, 0, *pStaticResCache); } - ShaderResourceLayoutVk::Initialize(m_NumShaders, m_ShaderResourceLayouts, ShaderResources.data(), GetRawAllocator(), ShaderSPIRVs.data(), m_PipelineLayout); + ShaderResourceLayoutVk::Initialize(pDeviceVk, m_NumShaders, m_ShaderResourceLayouts, ShaderResources.data(), GetRawAllocator(), + PipelineDesc.ResourceLayout, ShaderSPIRVs.data(), m_PipelineLayout); m_PipelineLayout.Finalize(LogicalDevice); if (PipelineDesc.SRBAllocationGranularity > 1) @@ -172,9 +188,9 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters std::array<size_t, MaxShadersInPipeline> ShaderVariableDataSizes = {}; for (Uint32 s = 0; s < m_NumShaders; ++s) { - std::array<SHADER_VARIABLE_TYPE, 2> AllowedVarTypes = { {SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC} }; + const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; Uint32 UnusedNumVars = 0; - ShaderVariableDataSizes[s] = ShaderVariableManagerVk::GetRequiredMemorySize(m_ShaderResourceLayouts[s], AllowedVarTypes.data(), static_cast<Uint32>(AllowedVarTypes.size()), UnusedNumVars); + ShaderVariableDataSizes[s] = ShaderVariableManagerVk::GetRequiredMemorySize(m_ShaderResourceLayouts[s], AllowedVarTypes, _countof(AllowedVarTypes), UnusedNumVars); } Uint32 NumSets = 0; @@ -231,7 +247,7 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters m_ShaderModules[s] = LogicalDevice.CreateShaderModule(ShaderModuleCI, pShaderVk->GetDesc().Name); StageCI.module = m_ShaderModules[s]; - StageCI.pName = pShaderVk->GetEntryPoint(); + StageCI.pName = pShaderVk->GetEntryPoint(); StageCI.pSpecializationInfo = nullptr; } @@ -250,9 +266,9 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; #endif PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from - PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from + PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from - PipelineCI.stage = ShaderStages[0]; + PipelineCI.stage = ShaderStages[0]; PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout(); m_Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name); @@ -279,11 +295,11 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters #endif PipelineCI.stageCount = m_NumShaders; - PipelineCI.pStages = ShaderStages.data(); - PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout(); + PipelineCI.pStages = ShaderStages.data(); + PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout(); VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {}; - std::array<VkVertexInputBindingDescription, iMaxLayoutElements> BindingDescriptions; + std::array<VkVertexInputBindingDescription, iMaxLayoutElements> BindingDescriptions; std::array<VkVertexInputAttributeDescription, iMaxLayoutElements> AttributeDescription; InputLayoutDesc_To_VkVertexInputStateCI(GraphicsPipeline.InputLayout, VertexInputStateCI, BindingDescriptions, AttributeDescription); PipelineCI.pVertexInputState = &VertexInputStateCI; @@ -412,11 +428,11 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters* pRefCounters for (Uint32 s=0; s < m_NumShaders; ++s) { const auto& Layout = m_ShaderResourceLayouts[s]; - if (Layout.GetResourceCount(SHADER_VARIABLE_TYPE_STATIC) != 0) + if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_STATIC) != 0) m_HasStaticResources = true; - if (Layout.GetResourceCount(SHADER_VARIABLE_TYPE_MUTABLE) != 0 || - Layout.GetResourceCount(SHADER_VARIABLE_TYPE_DYNAMIC) != 0) + if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE) != 0 || + Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) != 0) m_HasNonStaticResources = true; } @@ -437,11 +453,20 @@ PipelineStateVkImpl::~PipelineStateVkImpl() } auto& RawAllocator = GetRawAllocator(); - for (Uint32 s=0; s < m_NumShaders; ++s) + for (Uint32 s=0; s < m_NumShaders*2; ++s) { m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk(); } + + for (Uint32 s=0; s < m_NumShaders; ++s) + { + m_StaticResCaches[s].~ShaderResourceCacheVk(); + m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator()); + m_StaticVarsMgrs[s].~ShaderVariableManagerVk(); + } RawAllocator.Free(m_ShaderResourceLayouts); + RawAllocator.Free(m_StaticResCaches); + RawAllocator.Free(m_StaticVarsMgrs); } IMPLEMENT_QUERY_INTERFACE( PipelineStateVkImpl, IID_PipelineStateVk, TPipelineStateBase ) @@ -463,7 +488,7 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState *pPSO)const if (pPSO == this) return true; - const PipelineStateVkImpl *pPSOVk = ValidatedCast<const PipelineStateVkImpl>(pPSO); + const PipelineStateVkImpl* pPSOVk = ValidatedCast<const PipelineStateVkImpl>(pPSO); if (m_ShaderResourceLayoutHash != pPSOVk->m_ShaderResourceLayoutHash) return false; @@ -581,7 +606,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind for (Uint32 s=0; s < m_NumShaders; ++s) { const auto& Layout = m_ShaderResourceLayouts[s]; - if (Layout.GetResourceCount(SHADER_VARIABLE_TYPE_DYNAMIC) != 0) + if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) != 0) Layout.CommitDynamicResources(ResourceCache, DynamicDescrSet); } } @@ -593,4 +618,69 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind } } +void PipelineStateVkImpl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) +{ + for (Uint32 s=0; s < m_NumShaders; ++s) + { + auto ShaderType = GetStaticShaderResLayout(s).GetShaderType(); + if ((ShaderType & ShaderFlags) != 0) + { + auto& StaticVarMgr = GetStaticVarMgr(s); + StaticVarMgr.BindResources(pResourceMapping, Flags); + } + } +} + +Uint32 PipelineStateVkImpl::GetStaticVariableCount(SHADER_TYPE ShaderType) const +{ + const auto LayoutInd = m_ResourceLayoutIndex[GetShaderTypeIndex(ShaderType)]; + if (LayoutInd < 0) + return 0; + + auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); + return StaticVarMgr.GetVariableCount(); +} + +IShaderResourceVariable* PipelineStateVkImpl::GetStaticShaderVariable(SHADER_TYPE ShaderType, const Char* Name) +{ + const auto LayoutInd = m_ResourceLayoutIndex[GetShaderTypeIndex(ShaderType)]; + if (LayoutInd < 0) + return nullptr; + + auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); + return StaticVarMgr.GetVariable(Name); +} + +IShaderResourceVariable* PipelineStateVkImpl::GetStaticShaderVariable(SHADER_TYPE ShaderType, Uint32 Index) +{ + const auto LayoutInd = m_ResourceLayoutIndex[GetShaderTypeIndex(ShaderType)]; + if (LayoutInd < 0) + return nullptr; + + auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); + return StaticVarMgr.GetVariable(Index); +} + + +void PipelineStateVkImpl::InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache)const +{ + for (Uint32 s = 0; s < m_NumShaders; ++s) + { + const auto& StaticResLayout = GetStaticShaderResLayout(s); + const auto& StaticResCache = GetStaticResCache(s); +#ifdef DEVELOPMENT + if (!StaticResLayout.dvpVerifyBindings(StaticResCache)) + { + const auto* pShaderVk = GetShader<const ShaderVkImpl>(s); + LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", GetDesc().Name, "' will not be successfully initialized " + "because not all static resource bindings in shader '", pShaderVk->GetDesc().Name, "' are valid. " + "Please make sure you bind all static resources to the shader before calling InitializeStaticResources() " + "directly or indirectly by passing InitStaticResources=true to CreateShaderResourceBinding() method."); + } +#endif + const auto& ShaderResourceLayouts = GetShaderResLayout(s); + ShaderResourceLayouts.InitializeStaticResources(StaticResLayout, StaticResCache, ResourceCache); + } +} + } diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index dbf2893f..a126a937 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -39,7 +39,7 @@ namespace Diligent RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters* pRefCounters, IMemoryAllocator& RawMemAllocator, - const EngineVkAttribs& CreationAttribs, + const EngineVkCreateInfo& EngineCI, size_t CommandQueueCount, ICommandQueueVk** CmdQueues, std::shared_ptr<VulkanUtilities::VulkanInstance> Instance, @@ -66,7 +66,7 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters* m_VulkanInstance(Instance), m_PhysicalDevice(std::move(PhysicalDevice)), m_LogicalVkDevice(std::move(LogicalDevice)), - m_EngineAttribs(CreationAttribs), + m_EngineAttribs(EngineCI), m_FramebufferCache(*this), m_RenderPassCache(*this), m_DescriptorSetAllocator @@ -75,18 +75,18 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters* "Main descriptor pool", std::vector<VkDescriptorPoolSize> { - {VK_DESCRIPTOR_TYPE_SAMPLER, CreationAttribs.MainDescriptorPoolSize.NumSeparateSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, CreationAttribs.MainDescriptorPoolSize.NumCombinedSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, CreationAttribs.MainDescriptorPoolSize.NumSampledImageDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, CreationAttribs.MainDescriptorPoolSize.NumStorageImageDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, CreationAttribs.MainDescriptorPoolSize.NumUniformTexelBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, CreationAttribs.MainDescriptorPoolSize.NumStorageTexelBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, CreationAttribs.MainDescriptorPoolSize.NumUniformBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, CreationAttribs.MainDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, CreationAttribs.MainDescriptorPoolSize.NumUniformBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, CreationAttribs.MainDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumSeparateSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumCombinedSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.MainDescriptorPoolSize.NumSampledImageDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.MainDescriptorPoolSize.NumStorageImageDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformTexelBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageTexelBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, }, - CreationAttribs.MainDescriptorPoolSize.MaxDescriptorSets, + EngineCI.MainDescriptorPoolSize.MaxDescriptorSets, true }, m_DynamicDescriptorPool @@ -95,27 +95,27 @@ RenderDeviceVkImpl :: RenderDeviceVkImpl(IReferenceCounters* "Dynamic descriptor pool", std::vector<VkDescriptorPoolSize> { - {VK_DESCRIPTOR_TYPE_SAMPLER, CreationAttribs.DynamicDescriptorPoolSize.NumSeparateSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, CreationAttribs.DynamicDescriptorPoolSize.NumCombinedSamplerDescriptors}, - {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, CreationAttribs.DynamicDescriptorPoolSize.NumSampledImageDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, CreationAttribs.DynamicDescriptorPoolSize.NumStorageImageDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, CreationAttribs.DynamicDescriptorPoolSize.NumUniformTexelBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, CreationAttribs.DynamicDescriptorPoolSize.NumStorageTexelBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, CreationAttribs.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, - //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, CreationAttribs.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, CreationAttribs.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, - {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, CreationAttribs.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumSeparateSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumCombinedSamplerDescriptors}, + {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumSampledImageDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumStorageImageDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformTexelBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageTexelBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, + //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, }, - CreationAttribs.DynamicDescriptorPoolSize.MaxDescriptorSets, + EngineCI.DynamicDescriptorPoolSize.MaxDescriptorSets, false // Pools can only be reset }, m_TransientCmdPoolMgr(*this, "Transient command buffer pool manager", CmdQueues[0]->GetQueueFamilyIndex(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT), - m_MemoryMgr("Global resource memory manager", *m_LogicalVkDevice, *m_PhysicalDevice, GetRawAllocator(), CreationAttribs.DeviceLocalMemoryPageSize, CreationAttribs.HostVisibleMemoryPageSize, CreationAttribs.DeviceLocalMemoryReserveSize, CreationAttribs.HostVisibleMemoryReserveSize), + m_MemoryMgr("Global resource memory manager", *m_LogicalVkDevice, *m_PhysicalDevice, GetRawAllocator(), EngineCI.DeviceLocalMemoryPageSize, EngineCI.HostVisibleMemoryPageSize, EngineCI.DeviceLocalMemoryReserveSize, EngineCI.HostVisibleMemoryReserveSize), m_DynamicMemoryManager { GetRawAllocator(), *this, - CreationAttribs.DynamicHeapSize, + EngineCI.DynamicHeapSize, ~Uint64{0} } { @@ -433,12 +433,12 @@ void RenderDeviceVkImpl :: CreateBuffer(const BufferDesc& BuffDesc, const Buffer } -void RenderDeviceVkImpl :: CreateShader(const ShaderCreationAttribs &ShaderCreationAttribs, IShader **ppShader) +void RenderDeviceVkImpl :: CreateShader(const ShaderCreateInfo& ShaderCI, IShader **ppShader) { - CreateDeviceObject( "shader", ShaderCreationAttribs.Desc, ppShader, + CreateDeviceObject( "shader", ShaderCI.Desc, ppShader, [&]() { - ShaderVkImpl *pShaderVk( NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderVkImpl instance", ShaderVkImpl)(this, ShaderCreationAttribs ) ); + ShaderVkImpl *pShaderVk( NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderVkImpl instance", ShaderVkImpl)(this, ShaderCI) ); pShaderVk->QueryInterface( IID_Shader, reinterpret_cast<IObject**>(ppShader) ); OnCreateDeviceObject( pShaderVk ); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp index 02a98d11..0193bb55 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp @@ -21,7 +21,6 @@ * of the possibility of such damages. */ -#include <array> #include "pch.h" #include "ShaderResourceBindingVkImpl.h" #include "PipelineStateVkImpl.h" @@ -31,8 +30,8 @@ namespace Diligent { -ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl( IReferenceCounters* pRefCounters, PipelineStateVkImpl* pPSO, bool IsPSOInternal) : - TBase( pRefCounters, pPSO, IsPSOInternal ), +ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pRefCounters, PipelineStateVkImpl* pPSO, bool IsPSOInternal) : + TBase (pRefCounters, pPSO, IsPSOInternal), m_ShaderResourceCache(ShaderResourceCacheVk::DbgCacheContentType::SRBResources) { auto* ppShaders = pPSO->GetShaders(); @@ -44,31 +43,32 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl( IReferenceCounters* pR auto& ResourceCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0); pPSO->GetPipelineLayout().InitResourceCache(pRenderDeviceVkImpl, m_ShaderResourceCache, ResourceCacheDataAllocator, pPSO->GetDesc().Name); - auto *pVarMgrsRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", m_NumShaders * sizeof(ShaderVariableManagerVk)); + auto* pVarMgrsRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", m_NumShaders * sizeof(ShaderVariableManagerVk)); m_pShaderVarMgrs = reinterpret_cast<ShaderVariableManagerVk*>(pVarMgrsRawMem); for (Uint32 s = 0; s < m_NumShaders; ++s) { - auto *pShader = ppShaders[s]; + auto* pShader = ppShaders[s]; auto ShaderType = pShader->GetDesc().ShaderType; auto ShaderInd = GetShaderTypeIndex(ShaderType); - - auto &VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); + m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s); + + auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); - const auto &SrcLayout = pPSO->GetShaderResLayout(s); + const auto& SrcLayout = pPSO->GetShaderResLayout(s); // Use source layout to initialize resource memory in the cache SrcLayout.InitializeResourceMemoryInCache(m_ShaderResourceCache); // Create shader variable manager in place - new (m_pShaderVarMgrs + s) ShaderVariableManagerVk(*this); - // Initialize vars manager to reference mutable and dynamic variables // Note that the cache has space for all variable types - std::array<SHADER_VARIABLE_TYPE, 2> VarTypes = {{SHADER_VARIABLE_TYPE_MUTABLE, SHADER_VARIABLE_TYPE_DYNAMIC}}; - m_pShaderVarMgrs[s].Initialize(SrcLayout, VarDataAllocator, VarTypes.data(), static_cast<Uint32>(VarTypes.size()), m_ShaderResourceCache); - - m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s); + const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; + new (m_pShaderVarMgrs + s) ShaderVariableManagerVk(*this, SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes), m_ShaderResourceCache); } +#ifdef _DEBUG + m_ShaderResourceCache.DbgVerifyResourceInitialization(); +#endif + } ShaderResourceBindingVkImpl::~ShaderResourceBindingVkImpl() @@ -76,8 +76,8 @@ ShaderResourceBindingVkImpl::~ShaderResourceBindingVkImpl() PipelineStateVkImpl* pPSO = ValidatedCast<PipelineStateVkImpl>(m_pPSO); for(Uint32 s = 0; s < m_NumShaders; ++s) { - auto &VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); - m_pShaderVarMgrs[s].Destroy(VarDataAllocator); + auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); + m_pShaderVarMgrs[s].DestroyVariables(VarDataAllocator); m_pShaderVarMgrs[s].~ShaderVariableManagerVk(); } @@ -101,13 +101,14 @@ void ShaderResourceBindingVkImpl::BindResources(Uint32 ShaderFlags, IResourceMap } } -IShaderVariable* ShaderResourceBindingVkImpl::GetVariable(SHADER_TYPE ShaderType, const char *Name) +IShaderResourceVariable* ShaderResourceBindingVkImpl::GetVariable(SHADER_TYPE ShaderType, const char* Name) { auto ShaderInd = GetShaderTypeIndex(ShaderType); auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd]; if (ResLayoutInd < 0) { - LOG_WARNING_MESSAGE("Unable to find mutable/dynamic variable '", Name, "': shader stage ", GetShaderTypeLiteralName(ShaderType), " is inactive"); + LOG_WARNING_MESSAGE("Unable to find mutable/dynamic variable '", Name, "': shader stage ", GetShaderTypeLiteralName(ShaderType), + " is inactive in Pipeline State '", m_pPSO->GetDesc().Name, "'."); return nullptr; } return m_pShaderVarMgrs[ResLayoutInd].GetVariable(Name); @@ -119,19 +120,21 @@ Uint32 ShaderResourceBindingVkImpl::GetVariableCount(SHADER_TYPE ShaderType) con auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd]; if (ResLayoutInd < 0) { - LOG_WARNING_MESSAGE("Unable to get the number of mutable/dynamic variables: shader stage ", GetShaderTypeLiteralName(ShaderType), " is inactive"); + LOG_WARNING_MESSAGE("Unable to get the number of mutable/dynamic variables: shader stage ", GetShaderTypeLiteralName(ShaderType), + " is inactive in Pipeline State '", m_pPSO->GetDesc().Name, "'."); return 0; } return m_pShaderVarMgrs[ResLayoutInd].GetVariableCount(); } -IShaderVariable* ShaderResourceBindingVkImpl::GetVariable(SHADER_TYPE ShaderType, Uint32 Index) +IShaderResourceVariable* ShaderResourceBindingVkImpl::GetVariable(SHADER_TYPE ShaderType, Uint32 Index) { auto ShaderInd = GetShaderTypeIndex(ShaderType); auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd]; if (ResLayoutInd < 0) { - LOG_ERROR("Unable to get mutable/dynamic variable at index ", Index, ": shader stage ", GetShaderTypeLiteralName(ShaderType), " is inactive"); + LOG_WARNING_MESSAGE("Unable to get mutable/dynamic variable at index ", Index, ": shader stage ", GetShaderTypeLiteralName(ShaderType), + " is inactive in Pipeline State '", m_pPSO->GetDesc().Name, "'."); return nullptr; } return m_pShaderVarMgrs[ResLayoutInd].GetVariable(Index); @@ -151,28 +154,13 @@ void ShaderResourceBindingVkImpl::InitializeStaticResources(const IPipelineState } else { - DEV_CHECK_ERR(pPipelineState->IsCompatibleWith(GetPipelineState()), "The pipeline state is not compatible with this SRB"); + DEV_CHECK_ERR(pPipelineState->IsCompatibleWith(GetPipelineState()), "The pipeline state '", pPipelineState->GetDesc().Name, "' " + "is not compatible with the pipeline state '", m_pPSO->GetDesc().Name, "' this SRB was created from and cannot be " + "used to initialize static resources."); } auto* pPSOVK = ValidatedCast<const PipelineStateVkImpl>(pPipelineState); - for (Uint32 s = 0; s < m_NumShaders; ++s) - { - const auto* pShaderVk = pPSOVK->GetShader<const ShaderVkImpl>(s); -#ifdef DEVELOPMENT - if (!pShaderVk->DvpVerifyStaticResourceBindings()) - { - LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", pPSOVK->GetDesc().Name, "' will not be successfully initialized " - "because not all static resource bindings in shader '", pShaderVk->GetDesc().Name, "' are valid. " - "Please make sure you bind all static resources to the shader before calling InitializeStaticResources() " - "directly or indirectly by passing InitStaticResources=true to CreateShaderResourceBinding() method."); - } -#endif - const auto& StaticResLayout = pShaderVk->GetStaticResLayout(); - const auto& StaticResCache = pShaderVk->GetStaticResCache(); - const auto& ShaderResourceLayouts = pPSOVK->GetShaderResLayout(s); - ShaderResourceLayouts.InitializeStaticResources(StaticResLayout, StaticResCache, m_ShaderResourceCache); - } - + pPSOVK->InitializeStaticSRBResources(m_ShaderResourceCache); m_bStaticResourcesInitialized = true; } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index 98d4e424..2bfa922e 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -38,7 +38,7 @@ namespace Diligent size_t ShaderResourceCacheVk::GetRequiredMemorySize(Uint32 NumSets, Uint32 SetSizes[]) { Uint32 TotalResources = 0; - for(Uint32 t=0; t < NumSets; ++t) + for (Uint32 t=0; t < NumSets; ++t) TotalResources += SetSizes[t]; auto MemorySize = NumSets * sizeof(DescriptorSet) + TotalResources * sizeof(Resource); return MemorySize; @@ -57,22 +57,28 @@ void ShaderResourceCacheVk::InitializeSets(IMemoryAllocator& MemAllocator, Uint3 // Ns = m_NumSets VERIFY(m_pAllocator == nullptr && m_pMemory == nullptr, "Cache already initialized"); - m_pAllocator = &MemAllocator; - m_NumSets = NumSets; + m_pAllocator = &MemAllocator; + m_NumSets = NumSets; m_TotalResources = 0; - for(Uint32 t=0; t < NumSets; ++t) + for (Uint32 t=0; t < NumSets; ++t) m_TotalResources += SetSizes[t]; auto MemorySize = NumSets * sizeof(DescriptorSet) + m_TotalResources * sizeof(Resource); VERIFY_EXPR(MemorySize == GetRequiredMemorySize(NumSets, SetSizes)); +#ifdef _DEBUG + m_DbgInitializedResources.resize(m_NumSets); +#endif if (MemorySize > 0) { m_pMemory = ALLOCATE( *m_pAllocator, "Memory for shader resource cache data", MemorySize); - auto *pSets = reinterpret_cast<DescriptorSet*>(m_pMemory); - auto *pCurrResPtr = reinterpret_cast<Resource*>(pSets + m_NumSets); + auto* pSets = reinterpret_cast<DescriptorSet*>(m_pMemory); + auto* pCurrResPtr = reinterpret_cast<Resource*>(pSets + m_NumSets); for (Uint32 t = 0; t < NumSets; ++t) { new(&GetDescriptorSet(t)) DescriptorSet(SetSizes[t], SetSizes[t] > 0 ? pCurrResPtr : nullptr); pCurrResPtr += SetSizes[t]; +#ifdef _DEBUG + m_DbgInitializedResources[t].resize(SetSizes[t]); +#endif } VERIFY_EXPR((char*)pCurrResPtr == (char*)m_pMemory + MemorySize); } @@ -80,17 +86,33 @@ void ShaderResourceCacheVk::InitializeSets(IMemoryAllocator& MemAllocator, Uint3 void ShaderResourceCacheVk::InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, SPIRVShaderResourceAttribs::ResourceType Type) { - auto &DescrSet = GetDescriptorSet(Set); + auto& DescrSet = GetDescriptorSet(Set); for (Uint32 res = 0; res < ArraySize; ++res) + { new(&DescrSet.GetResource(Offset + res)) Resource{Type}; +#ifdef _DEBUG + m_DbgInitializedResources[Set][Offset + res] = true; +#endif + } } +#ifdef _DEBUG +void ShaderResourceCacheVk::DbgVerifyResourceInitialization()const +{ + for (const auto &SetFlags : m_DbgInitializedResources) + { + for (auto ResInitialized : SetFlags) + VERIFY(ResInitialized, "Not all resources in the cache have been initialized. This is a bug."); + } +} +#endif + ShaderResourceCacheVk::~ShaderResourceCacheVk() { if (m_pMemory) { - auto *pResources = GetFirstResourcePtr(); - for(Uint32 res=0; res < m_TotalResources; ++res) + auto* pResources = GetFirstResourcePtr(); + for (Uint32 res=0; res < m_TotalResources; ++res) pResources[res].~Resource(); for (Uint32 t = 0; t < m_NumSets; ++t) GetDescriptorSet(t).~DescriptorSet(); @@ -282,7 +304,7 @@ VkDescriptorBufferInfo ShaderResourceCacheVk::Resource::GetUniformBufferDescript // If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER or VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, the offset member // of each element of pBufferInfo must be a multiple of VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment (13.2.4) DescrBuffInfo.offset = 0; - DescrBuffInfo.range = pBuffVk->GetDesc().uiSizeInBytes; + DescrBuffInfo.range = pBuffVk->GetDesc().uiSizeInBytes; return DescrBuffInfo; } @@ -324,11 +346,13 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteIn VkDescriptorImageInfo DescrImgInfo; DescrImgInfo.sampler = VK_NULL_HANDLE; + VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || !IsImmutableSampler, + "Immutable sampler can't be assigned to separarate image or storage image"); if (Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !IsImmutableSampler) { // Immutable samplers are permanently bound into the set layout; later binding a sampler // into an immutable sampler slot in a descriptor set is not allowed (13.2.1) - auto *pSamplerVk = ValidatedCast<const SamplerVkImpl>(pTexViewVk->GetSampler()); + auto* pSamplerVk = ValidatedCast<const SamplerVkImpl>(pTexViewVk->GetSampler()); if (pSamplerVk != nullptr) { // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, @@ -340,7 +364,7 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteIn #ifdef DEVELOPMENT else { - LOG_ERROR_MESSAGE("No sampler assigned to texture view '", pTexViewVk->GetDesc().Name, "'"); + LOG_ERROR_MESSAGE("No sampler is assigned to texture view '", pTexViewVk->GetDesc().Name, "'"); } #endif } @@ -384,8 +408,8 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetSamplerDescriptorWrite auto* pSamplerVk = pObject.RawPtr<const SamplerVkImpl>(); VkDescriptorImageInfo DescrImgInfo; // For VK_DESCRIPTOR_TYPE_SAMPLER, only the sample member of each element of VkWriteDescriptorSet::pImageInfo is accessed (13.2.4) - DescrImgInfo.sampler = pSamplerVk->GetVkSampler(); - DescrImgInfo.imageView = VK_NULL_HANDLE; + DescrImgInfo.sampler = pSamplerVk->GetVkSampler(); + DescrImgInfo.imageView = VK_NULL_HANDLE; DescrImgInfo.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; return DescrImgInfo; } @@ -404,11 +428,11 @@ Uint32 ShaderResourceCacheVk::GetDynamicBufferOffsets(DeviceContextVkImpl *pCtxV // In each descriptor set, all uniform buffers for every shader stage come first, // followed by all storage buffers for every shader stage, followed by all other resources Uint32 OffsetInd = 0; - for(Uint32 set=0; set < m_NumSets; ++set) + for (Uint32 set=0; set < m_NumSets; ++set) { const auto& DescrSet = GetDescriptorSet(set); Uint32 res = 0; - while(res < DescrSet.GetSize()) + while (res < DescrSet.GetSize()) { const auto& Res = DescrSet.GetResource(res); if (Res.Type != SPIRVShaderResourceAttribs::ResourceType::UniformBuffer) diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 8915d67f..e65aaa91 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -32,29 +32,80 @@ #include "SamplerVkImpl.h" #include "ShaderVkImpl.h" #include "PipelineLayout.h" +#include "ShaderResourceVariableBase.h" +#include "StringTools.h" #include "PipelineStateVkImpl.h" namespace Diligent { -ShaderResourceLayoutVk::ShaderResourceLayoutVk(IObject& Owner, - const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) : - m_Owner(Owner), - m_LogicalDevice(LogicalDevice) +static Int32 FindImmutableSampler(SHADER_TYPE ShaderType, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SPIRVShaderResourceAttribs& Attribs, + const char* SamplerSuffix) { + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage) + { + SamplerSuffix = nullptr; + } + else if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + { + // Use SamplerSuffix. If HLSL-style combined images samplers are not used, + // SamplerSuffix will be null and we will be looking for the sampler itself. + } + else + { + UNEXPECTED("Immutable sampler can only be assigned to a sampled image or separate sampler"); + return -1; + } + + for (Uint32 s=0; s < ResourceLayoutDesc.NumStaticSamplers; ++s) + { + const auto& StSam = ResourceLayoutDesc.StaticSamplers[s]; + if ( ((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(Attribs.Name, StSam.SamplerOrTextureName, SamplerSuffix) ) + return s; + } + + return -1; +} + +static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE ShaderType, + const SPIRVShaderResourceAttribs& Attribs, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const char* CombinedSamplerSuffix) +{ + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + { + // Use texture or sampler name to derive separate sampler type + // When HLSL-style combined image samplers are not used, CombinedSamplerSuffix is null + return GetShaderVariableType(ShaderType, ResourceLayoutDesc.DefaultVariableType, ResourceLayoutDesc.Variables, ResourceLayoutDesc.NumVariables, + [&](const char* VarName) + { + return StreqSuff(Attribs.Name, VarName, CombinedSamplerSuffix); + }); + } + else + { + return GetShaderVariableType(ShaderType, Attribs.Name, ResourceLayoutDesc); + } } + ShaderResourceLayoutVk::~ShaderResourceLayoutVk() { - auto* Resources = reinterpret_cast<VkResource*>(m_ResourceBuffer.get()); for (Uint32 r=0; r < GetTotalResourceCount(); ++r) - Resources[r].~VkResource(); + GetResource(r).~VkResource(); + + for(Uint32 s=0; s < m_NumImmutableSamplers; ++s) + GetImmutableSampler(s).~ImmutableSamplerPtrType(); } void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderResources> pSrcResources, IMemoryAllocator& Allocator, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes) + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + bool AllocateImmutableSamplers) { VERIFY(!m_ResourceBuffer, "Memory has already been initialized"); VERIFY_EXPR(!m_pResources); @@ -62,50 +113,93 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderRes m_pResources = std::move(pSrcResources); - Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); (void)AllowedTypeBits; - - // Count number of resources to allocate all needed memory + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + const auto ShaderType = m_pResources->GetShaderType(); + const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix(); + // Count the number of resources to allocate all needed memory m_pResources->ProcessResources( - AllowedVarTypes, NumAllowedTypes, - [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) { - VERIFY_EXPR(IsAllowedType(ResAttribs.VarType, AllowedTypeBits)); - VERIFY( Uint32{m_NumResources[ResAttribs.VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds max representable value"); - ++m_NumResources[ResAttribs.VarType]; + auto VarType = FindShaderVariableType(ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); + if (IsAllowedType(VarType, AllowedTypeBits)) + { + // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app + + VERIFY( Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds Uint16 maximum representable value"); + ++m_NumResources[VarType]; + } } ); Uint32 TotalResources = 0; - for (SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) + for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType+1)) { TotalResources += m_NumResources[VarType]; } - VERIFY(TotalResources <= Uint32{std::numeric_limits<Uint16>::max()}, "Total number of resources exceeds Uint16 max representable value" ); - m_NumResources[SHADER_VARIABLE_TYPE_NUM_TYPES] = static_cast<Uint16>(TotalResources); + VERIFY(TotalResources <= Uint32{std::numeric_limits<Uint16>::max()}, "Total number of resources exceeds Uint16 maximum representable value" ); + m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES] = static_cast<Uint16>(TotalResources); - size_t MemSize = TotalResources * sizeof(VkResource); + m_NumImmutableSamplers = 0; + if (AllocateImmutableSamplers) + { + for (Uint32 s=0; s < ResourceLayoutDesc.NumStaticSamplers; ++s) + { + const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[s]; + if ((StSamDesc.ShaderStages & ShaderType) != 0) + ++m_NumImmutableSamplers; + } + } + + size_t MemSize = TotalResources * sizeof(VkResource) + m_NumImmutableSamplers * sizeof(ImmutableSamplerPtrType); + static_assert( (sizeof(VkResource) % sizeof(void*)) == 0, "sizeof(VkResource) must be multiple of sizeof(void*)" ); if (MemSize == 0) return; auto* pRawMem = ALLOCATE(Allocator, "Raw memory buffer for shader resource layout resources", MemSize); m_ResourceBuffer = std::unique_ptr<void, STDDeleterRawMem<void> >(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; + } } + void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<const SPIRVShaderResources> pSrcResources, IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, ShaderResourceCacheVk& StaticResourceCache) { - auto AllowedVarType = SHADER_VARIABLE_TYPE_STATIC; - AllocateMemory(std::move(pSrcResources), LayoutDataAllocator, &AllowedVarType, 1); + const auto AllowedVarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; + // We do not need immutable samplers in static shader resource layout as they + // are relevant only when the main layout is initialized + constexpr bool AllocateImmutableSamplers = false; + AllocateMemory(std::move(pSrcResources), LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers); - std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES> CurrResInd = {}; + std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES> CurrResInd = {}; Uint32 StaticResCacheSize = 0; + const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); + const auto ShaderType = m_pResources->GetShaderType(); + const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix(); + m_pResources->ProcessResources( - &AllowedVarType, 1, [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) { + auto VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); + if (!IsAllowedType(VarType, AllowedTypeBits)) + return; + + Int32 SrcImmutableSamplerInd = -1; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + { + // Only search for the immutable sampler for combined image samplers and separate samplers + SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix); + // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app + } + Uint32 Binding = Attribs.Type; Uint32 DescriptorSet = 0; Uint32 CacheOffset = StaticResCacheSize; @@ -115,43 +209,132 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) { // Separate samplers are enumerated before separate images, so the sampler - // assigned to this separate image must already be created. - SamplerInd = FindAssignedSampler(Attribs, CurrResInd[Attribs.VarType]); + // assigned to this separate image must have already been created. + SamplerInd = FindAssignedSampler(Attribs, CurrResInd[VarType], VarType); } - ::new (&GetResource(Attribs.VarType, CurrResInd[Attribs.VarType]++)) VkResource(*this, Attribs, Binding, DescriptorSet, CacheOffset, SamplerInd); + ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); } ); #ifdef _DEBUG - for (SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType + 1)) + for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1)) { - VERIFY(CurrResInd[VarType] == m_NumResources[VarType], "Not all resources are initialized, which will cause a crash when dtor is called"); + VERIFY(CurrResInd[VarType] == m_NumResources[VarType], "Not all resources have been initialized, which will cause a crash when dtor is called"); } #endif StaticResourceCache.InitializeSets(GetRawAllocator(), 1, &StaticResCacheSize); InitializeResourceMemoryInCache(StaticResourceCache); +#ifdef _DEBUG + StaticResourceCache.DbgVerifyResourceInitialization(); +#endif } +#ifdef DEVELOPMENT +void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32 NumShaders, + const std::shared_ptr<const SPIRVShaderResources> pShaderResources[], + const PipelineResourceLayoutDesc& ResourceLayoutDesc) +{ + for (Uint32 v = 0; v < ResourceLayoutDesc.NumVariables; ++v) + { + const auto& VarDesc = ResourceLayoutDesc.Variables[v]; + if (VarDesc.ShaderStages == SHADER_TYPE_UNKNOWN) + { + LOG_WARNING_MESSAGE("No allowed shader stages are specified for ", GetShaderVariableTypeLiteralName(VarDesc.Type), " variable '", VarDesc.Name, "'."); + continue; + } + + bool VariableFound = false; + for (Uint32 s=0; s < NumShaders && !VariableFound; ++s) + { + const auto& Resources = *pShaderResources[s]; + if ( (VarDesc.ShaderStages & Resources.GetShaderType()) != 0 ) + { + for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) + { + const auto& ResAttribs = Resources.GetResource(res); + VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0); + } + } + } + if (!VariableFound) + { + LOG_WARNING_MESSAGE(GetShaderVariableTypeLiteralName(VarDesc.Type), " variable '", VarDesc.Name, "' is not found in any of the designated shader stages (", GetShaderStagesString(VarDesc.ShaderStages), ")"); + } + } -void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, + for (Uint32 sam = 0; sam < ResourceLayoutDesc.NumStaticSamplers; ++sam) + { + const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[sam]; + if (StSamDesc.ShaderStages == SHADER_TYPE_UNKNOWN) + { + LOG_WARNING_MESSAGE("No allowed shader stages are specified for static sampler '", StSamDesc.SamplerOrTextureName, "'."); + continue; + } + + bool SamplerFound = false; + for (Uint32 s=0; s < NumShaders && !SamplerFound; ++s) + { + const auto& Resources = *pShaderResources[s]; + if ( (StSamDesc.ShaderStages & Resources.GetShaderType()) == 0 ) + continue; + + // 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) + for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i) + { + const auto& SmplImg = Resources.GetSmpldImg(i); + SamplerFound = (strcmp(SmplImg.Name, StSamDesc.SamplerOrTextureName) == 0); + } + + if (!SamplerFound) + { + // Check if static sampler 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(); + for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i) + { + const auto& SepSmpl = Resources.GetSepSmplr(i); + SamplerFound = StreqSuff(SepSmpl.Name, StSamDesc.SamplerOrTextureName, CombinedSamplerSuffix); + } + } + } + + if (!SamplerFound) + { + LOG_WARNING_MESSAGE("Static sampler '", StSamDesc.SamplerOrTextureName, "' is not found in any of the designated shader stages (", GetShaderStagesString(StSamDesc.ShaderStages), ")"); + } + } +} +#endif + +void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice, + Uint32 NumShaders, ShaderResourceLayoutVk Layouts[], std::shared_ptr<const SPIRVShaderResources> pShaderResources[], IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, std::vector<uint32_t> SPIRVs[], class PipelineLayout& PipelineLayout) { - SHADER_VARIABLE_TYPE* AllowedVarTypes = nullptr; - Uint32 NumAllowedTypes = 0; - Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); +#ifdef DEVELOPMENT + dvpVerifyResourceLayoutDesc(NumShaders, pShaderResources, ResourceLayoutDesc); +#endif + + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; + const Uint32 NumAllowedTypes = 0; + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); for (Uint32 s=0; s < NumShaders; ++s) { - Layouts[s].AllocateMemory(std::move(pShaderResources[s]), LayoutDataAllocator, AllowedVarTypes, NumAllowedTypes); + constexpr bool AllocateImmutableSamplers = true; + Layouts[s].AllocateMemory(std::move(pShaderResources[s]), LayoutDataAllocator, ResourceLayoutDesc, AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers); } VERIFY_EXPR(NumShaders <= MaxShadersInPipeline); - std::array<std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES>, MaxShadersInPipeline> CurrResInd = {}; + std::array<std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES>, MaxShadersInPipeline> CurrResInd = {}; + std::array<Uint32, MaxShadersInPipeline> CurrImmutableSamplerInd = {}; #ifdef _DEBUG std::unordered_map<Uint32, std::pair<Uint32, Uint32>> dbgBindings_CacheOffsets; #endif @@ -159,22 +342,45 @@ void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, auto AddResource = [&](Uint32 ShaderInd, ShaderResourceLayoutVk& ResLayout, const SPIRVShaderResources& Resources, - const SPIRVShaderResourceAttribs& Attribs, - Uint32 SamplerInd = VkResource::InvalidSamplerInd) + const SPIRVShaderResourceAttribs& Attribs) { - Uint32 Binding = 0; + const auto ShaderType = Resources.GetShaderType(); + const SHADER_RESOURCE_VARIABLE_TYPE VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, Resources.GetCombinedSamplerSuffix()); + if (!IsAllowedType(VarType, AllowedTypeBits)) + return; + + Uint32 Binding = 0; Uint32 DescriptorSet = 0; - Uint32 CacheOffset = 0; + Uint32 CacheOffset = 0; + Uint32 SamplerInd = VkResource::InvalidSamplerInd; + + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) + { + // Separate samplers are enumerated before separate images, so the sampler + // assigned to this separate image must have already been created. + SamplerInd = ResLayout.FindAssignedSampler(Attribs, CurrResInd[ShaderInd][VarType], VarType); + } - auto* pImmutableSampler = Resources.GetImmutableSampler(Attribs); VkSampler vkImmutableSampler = VK_NULL_HANDLE; - if (pImmutableSampler != nullptr) - vkImmutableSampler = ValidatedCast<SamplerVkImpl>(pImmutableSampler)->GetVkSampler(); - + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + { + // Only search for the immutable sampler for combined image samplers and separate samplers + Int32 SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, Resources.GetCombinedSamplerSuffix()); + if (SrcImmutableSamplerInd >= 0) + { + auto& ImmutableSampler = ResLayout.GetImmutableSampler(CurrImmutableSamplerInd[ShaderInd]++); + VERIFY(!ImmutableSampler, "Immutable sampler has already been initialized!"); + const auto& ImmutableSamplerDesc = ResourceLayoutDesc.StaticSamplers[SrcImmutableSamplerInd].Desc; + pRenderDevice->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler); + vkImmutableSampler = ImmutableSampler.RawPtr<SamplerVkImpl>()->GetVkSampler(); + } + } + auto& ShaderSPIRV = SPIRVs[ShaderInd]; - PipelineLayout.AllocateResourceSlot(Attribs, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset, ShaderSPIRV); - VERIFY(DescriptorSet <= std::numeric_limits<decltype(VkResource::DescriptorSet)>::max(), "Descriptor set (", DescriptorSet, ") excceeds max representable value"); - VERIFY(Binding <= std::numeric_limits<decltype(VkResource::Binding)>::max(), "Binding (", Binding, ") excceeds max representable value"); + PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset, ShaderSPIRV); + VERIFY(DescriptorSet <= std::numeric_limits<decltype(VkResource::DescriptorSet)>::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value"); + VERIFY(Binding <= std::numeric_limits<decltype(VkResource::Binding)> ::max(), "Binding (", Binding, ") excceeds maximum representable value"); #ifdef _DEBUG // Verify that bindings and cache offsets monotonically increase in every descriptor set @@ -187,8 +393,8 @@ void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, dbgBindings_CacheOffsets[DescriptorSet] = std::make_pair(Binding, CacheOffset); #endif - auto& ResInd = CurrResInd[ShaderInd][Attribs.VarType]; - ::new (&ResLayout.GetResource(Attribs.VarType, ResInd++)) VkResource(ResLayout, Attribs, Binding, DescriptorSet, CacheOffset, SamplerInd); + auto& ResInd = CurrResInd[ShaderInd][VarType]; + ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource(ResLayout, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, vkImmutableSampler != VK_NULL_HANDLE ? 1 : 0); }; // First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set @@ -199,7 +405,8 @@ void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n) { const auto& UB = Resources.GetUB(n); - if (IsAllowedType(UB.VarType, AllowedTypeBits)) + auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc); + if (IsAllowedType(VarType, AllowedTypeBits)) { AddResource(s, Layout, Resources, UB); } @@ -214,7 +421,8 @@ void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n) { const auto& SB = Resources.GetSB(n); - if (IsAllowedType(SB.VarType, AllowedTypeBits)) + auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc); + if (IsAllowedType(VarType, AllowedTypeBits)) { AddResource(s, Layout, Resources, SB); } @@ -227,50 +435,40 @@ void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, auto& Layout = Layouts[s]; const auto& Resources = *Layout.m_pResources; Resources.ProcessResources( - AllowedVarTypes, NumAllowedTypes, - [&](const SPIRVShaderResourceAttribs& UB, Uint32) { VERIFY_EXPR(UB.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer); - VERIFY_EXPR(IsAllowedType(UB.VarType, AllowedTypeBits)); // Skip }, [&](const SPIRVShaderResourceAttribs& SB, Uint32) { VERIFY_EXPR(SB.Type == SPIRVShaderResourceAttribs::ResourceType::StorageBuffer); - VERIFY_EXPR(IsAllowedType(SB.VarType, AllowedTypeBits)); // Skip }, [&](const SPIRVShaderResourceAttribs& Img, Uint32) { VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer); - VERIFY_EXPR(IsAllowedType(Img.VarType, AllowedTypeBits)); AddResource(s, Layout, Resources, Img); }, [&](const SPIRVShaderResourceAttribs& SmplImg, Uint32) { VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); - VERIFY_EXPR(IsAllowedType(SmplImg.VarType, AllowedTypeBits)); AddResource(s, Layout, Resources, SmplImg); }, [&](const SPIRVShaderResourceAttribs& AC, Uint32) { VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter); - VERIFY_EXPR(IsAllowedType(AC.VarType, AllowedTypeBits)); AddResource(s, Layout, Resources, AC); }, [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32) { VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); - VERIFY_EXPR(IsAllowedType(SepSmpl.VarType, AllowedTypeBits)); AddResource(s, Layout, Resources, SepSmpl); }, [&](const SPIRVShaderResourceAttribs& SepImg, Uint32) { VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); - VERIFY_EXPR(IsAllowedType(SepImg.VarType, AllowedTypeBits)); - Uint32 SamplerInd = Layout.FindAssignedSampler(SepImg, CurrResInd[s][SepImg.VarType]); - AddResource(s, Layout, Resources, SepImg, SamplerInd); + AddResource(s, Layout, Resources, SepImg); } ); } @@ -279,16 +477,18 @@ void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders, for (Uint32 s = 0; s < NumShaders; ++s) { auto& Layout = Layouts[s]; - for (SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType + 1)) + for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1)) { - VERIFY(CurrResInd[s][VarType] == Layout.m_NumResources[VarType], "Not all resources are initialized, which will cause a crash when dtor is called"); + VERIFY(CurrResInd[s][VarType] == Layout.m_NumResources[VarType], "Not all resources have been initialized, which will cause a crash when dtor is called. This is a bug."); } } #endif } -Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg, Uint32 CurrResourceCount)const +Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg, + Uint32 CurrResourceCount, + SHADER_RESOURCE_VARIABLE_TYPE ImgVarType)const { VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); @@ -296,17 +496,16 @@ Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttr if (m_pResources->IsUsingCombinedSamplers() && SepImg.IsValidSepSamplerAssigned()) { const auto& SepSampler = m_pResources->GetSepSmplr(SepImg.GetAssignedSepSamplerInd()); - DEV_CHECK_ERR(SepImg.VarType == SepSampler.VarType, - "The type (", GetShaderVariableTypeLiteralName(SepImg.VarType),") of separate image variable '", SepImg.Name, - "' is not consistent with the type (", GetShaderVariableTypeLiteralName(SepSampler.VarType), - ") of the separate sampler '", SepSampler.Name, "' that is assigned to it."); - for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd) { - const auto& Res = GetResource(SepSampler.VarType, SamplerInd); + const auto& Res = GetResource(ImgVarType, SamplerInd); if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0) { + DEV_CHECK_ERR(ImgVarType == Res.GetVariableType(), + "The type (", GetShaderVariableTypeLiteralName(ImgVarType),") of separate image variable '", SepImg.Name, + "' is not consistent with the type (", GetShaderVariableTypeLiteralName(Res.GetVariableType()), + ") of the separate sampler '", SepSampler.Name, "' that is assigned to it."); break; } } @@ -319,9 +518,11 @@ Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttr return SamplerInd; } + + #define LOG_RESOURCE_BINDING_ERROR(ResType, pResource, VarName, ShaderName, ...)\ { \ - const auto &ResName = pResource->GetDesc().Name; \ + const auto& ResName = pResource->GetDesc().Name; \ LOG_ERROR_MESSAGE( "Failed to bind ", ResType, " '", ResName, "' to variable '", VarName, \ "' in shader '", ShaderName, "'. ", __VA_ARGS__ ); \ } @@ -335,17 +536,17 @@ void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet VERIFY_EXPR(vkDescrSet != VK_NULL_HANDLE); VkWriteDescriptorSet WriteDescrSet; - WriteDescrSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - WriteDescrSet.pNext = nullptr; - WriteDescrSet.dstSet = vkDescrSet; - WriteDescrSet.dstBinding = Binding; - WriteDescrSet.dstArrayElement = ArrayElement; - WriteDescrSet.descriptorCount = 1; + WriteDescrSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + WriteDescrSet.pNext = nullptr; + WriteDescrSet.dstSet = vkDescrSet; + WriteDescrSet.dstBinding = Binding; + WriteDescrSet.dstArrayElement = ArrayElement; + WriteDescrSet.descriptorCount = 1; // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding. // The type of the descriptor also controls which array the descriptors are taken from. (13.2.4) - WriteDescrSet.descriptorType = PipelineLayout::GetVkDescriptorType(SpirvAttribs); - WriteDescrSet.pImageInfo = pImageInfo; - WriteDescrSet.pBufferInfo = pBufferInfo; + WriteDescrSet.descriptorType = PipelineLayout::GetVkDescriptorType(SpirvAttribs); + WriteDescrSet.pImageInfo = pImageInfo; + WriteDescrSet.pBufferInfo = pBufferInfo; WriteDescrSet.pTexelBufferView = pTexelBufferView; ParentResLayout.m_LogicalDevice.UpdateDescriptorSets(1, &WriteDescrSet, 0, nullptr); @@ -360,14 +561,16 @@ bool ShaderResourceLayoutVk::VkResource::UpdateCachedResource(ShaderResourceCach // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type RefCntAutoPtr<IDeviceObject> pResource(pObject, InterfaceId); - if(pResource) + if (pResource) { - if (SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr) + if (GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr) { if (DstRes.pObject != pResource) { - auto VarTypeStr = GetShaderVariableTypeLiteralName(SpirvAttribs.VarType); - LOG_ERROR_MESSAGE("Non-null resource is already bound to ", VarTypeStr, " shader variable '", SpirvAttribs.GetPrintName(ArrayInd), "' in shader '", ParentResLayout.GetShaderName(), "'. Attempring to bind another resource is an error and will be ignored. Use another shader resource binding instance or label the variable as dynamic."); + auto VarTypeStr = GetShaderVariableTypeLiteralName(GetVariableType()); + LOG_ERROR_MESSAGE("Non-null resource is already bound to ", VarTypeStr, " shader variable '", SpirvAttribs.GetPrintName(ArrayInd), + "' in shader '", ParentResLayout.GetShaderName(), "'. Attempring to bind another resource is an error and will be ignored. " + "Use another shader resource binding instance or label the variable as dynamic."); } // Do not update resource if one is already bound unless it is dynamic. This may be @@ -408,7 +611,7 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject* // Do not update descriptor for a dynamic uniform buffer. All dynamic resource // descriptors are updated at once by CommitDynamicResources() when SRB is committed. - if (vkDescrSet != VK_NULL_HANDLE && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC) + if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) { VkDescriptorBufferInfo DescrBuffInfo = DstRes.GetUniformBufferDescriptorWriteInfo(); UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, &DescrBuffInfo, nullptr); @@ -440,7 +643,7 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* // Do not update descriptor for a dynamic storage buffer. All dynamic resource // descriptors are updated at once by CommitDynamicResources() when SRB is committed. - if (vkDescrSet != VK_NULL_HANDLE && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC) + if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) { VkDescriptorBufferInfo DescrBuffInfo = DstRes.GetStorageBufferDescriptorWriteInfo(); UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, &DescrBuffInfo, nullptr); @@ -470,8 +673,8 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* const auto dbgExpectedViewType = IsStorageBuffer ? BUFFER_VIEW_UNORDERED_ACCESS : BUFFER_VIEW_SHADER_RESOURCE; if (ViewType != dbgExpectedViewType) { - const auto *ExpectedViewTypeName = GetViewTypeLiteralName(dbgExpectedViewType); - const auto *ActualViewTypeName = GetViewTypeLiteralName(ViewType); + const auto* ExpectedViewTypeName = GetViewTypeLiteralName(dbgExpectedViewType); + const auto* ActualViewTypeName = GetViewTypeLiteralName(ViewType); LOG_RESOURCE_BINDING_ERROR("Texture view", pBuffViewVk, SpirvAttribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "Incorrect view type: ", ExpectedViewTypeName, " is expected, but ", ActualViewTypeName, " is provided."); DstRes.pObject.Release(); @@ -481,7 +684,7 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* // Do not update descriptor for a dynamic texel buffer. All dynamic resource descriptors // are updated at once by CommitDynamicResources() when SRB is committed. - if (vkDescrSet != VK_NULL_HANDLE && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC) + if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) { VkBufferView BuffView = pBuffViewVk->GetVkBufferView(); UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, nullptr, &BuffView); @@ -511,46 +714,51 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* const auto dbgExpectedViewType = IsStorageImage ? TEXTURE_VIEW_UNORDERED_ACCESS : TEXTURE_VIEW_SHADER_RESOURCE; if (ViewType != dbgExpectedViewType) { - const auto *ExpectedViewTypeName = GetViewTypeLiteralName(dbgExpectedViewType); - const auto *ActualViewTypeName = GetViewTypeLiteralName(ViewType); + const auto* ExpectedViewTypeName = GetViewTypeLiteralName(dbgExpectedViewType); + const auto* ActualViewTypeName = GetViewTypeLiteralName(ViewType); LOG_RESOURCE_BINDING_ERROR("Texture view", pTexViewVk, SpirvAttribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "Incorrect view type: ", ExpectedViewTypeName, " is expected, but ", ActualViewTypeName, " is provided."); DstRes.pObject.Release(); return; } - if (SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !SpirvAttribs.IsImmutableSamplerAssigned()) + if (SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !IsImmutableSamplerAssigned()) { if(pTexViewVk->GetSampler() == nullptr) { - LOG_RESOURCE_BINDING_ERROR("resource", pTexView, SpirvAttribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "No sampler assigned to texture view '", pTexViewVk->GetDesc().Name, "'"); + LOG_RESOURCE_BINDING_ERROR("resource", pTexView, SpirvAttribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "No sampler is assigned to texture view '", pTexViewVk->GetDesc().Name, "'"); } } #endif // Do not update descriptor for a dynamic image. All dynamic resource descriptors // are updated at once by CommitDynamicResources() when SRB is committed. - if (vkDescrSet != VK_NULL_HANDLE && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC) + if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) { - VkDescriptorImageInfo DescrImgInfo = DstRes.GetImageDescriptorWriteInfo(SpirvAttribs.IsImmutableSamplerAssigned()); + VkDescriptorImageInfo DescrImgInfo = DstRes.GetImageDescriptorWriteInfo(IsImmutableSamplerAssigned()); UpdateDescriptorHandle(vkDescrSet, ArrayInd, &DescrImgInfo, nullptr, nullptr); } if (SamplerInd != InvalidSamplerInd) { - VERIFY_EXPR(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); - VERIFY_EXPR(!SpirvAttribs.IsImmutableSamplerAssigned()); - auto* pSampler = pTexViewVk->GetSampler(); - const auto& SamplerAttribs = ParentResLayout.GetResource(SpirvAttribs.VarType, SamplerInd); - if (pSampler != nullptr) - { - CacheSampler(SamplerAttribs, pSampler); - } - else + VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage, + "Only separate images can be assigned separate samplers when using HLSL-style combined samplers."); + VERIFY(!IsImmutableSamplerAssigned(), "Separate image can't be assigned an immutable sampler."); + const auto& SamplerAttribs = ParentResLayout.GetResource(GetVariableType(), SamplerInd); + VERIFY_EXPR(SamplerAttribs.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); + if (!SamplerAttribs.IsImmutableSamplerAssigned()) { - LOG_ERROR_MESSAGE( "Failed to bind sampler to sampler variable '", SamplerAttribs.SpirvAttribs.Name, - "' assigned to separate image '", SpirvAttribs.GetPrintName(ArrayInd), "' in shader '", - ParentResLayout.GetShaderName(), "': no sampler is set in texture view '", pTexViewVk->GetDesc().Name, '\''); \ + auto* pSampler = pTexViewVk->GetSampler(); + if (pSampler != nullptr) + { + CacheSampler(SamplerAttribs, pSampler); + } + else + { + LOG_ERROR_MESSAGE( "Failed to bind sampler to sampler variable '", SamplerAttribs.SpirvAttribs.Name, + "' assigned to separate image '", SpirvAttribs.GetPrintName(ArrayInd), "' in shader '", + ParentResLayout.GetShaderName(), "': no sampler is set in texture view '", pTexViewVk->GetDesc().Name, '\''); \ + } } } } @@ -562,12 +770,13 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject* Uint32 ArrayInd)const { VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected"); + VERIFY(!IsImmutableSamplerAssigned(), "This separate sampler is assigned an immutable sampler"); if (UpdateCachedResource(DstRes, ArrayInd, pSampler, IID_Sampler, "sampler")) { // Do not update descriptor for a dynamic sampler. All dynamic resource descriptors // are updated at once by CommitDynamicResources() when SRB is committed. - if (vkDescrSet != VK_NULL_HANDLE && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC) + if (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) { VkDescriptorImageInfo DescrImgInfo = DstRes.GetSamplerDescriptorWriteInfo(); UpdateDescriptorHandle(vkDescrSet, ArrayInd, &DescrImgInfo, nullptr, nullptr); @@ -576,16 +785,16 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject* } -void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache)const +void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache)const { VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize); - auto &DstDescrSet = ResourceCache.GetDescriptorSet(DescriptorSet); + auto& DstDescrSet = ResourceCache.GetDescriptorSet(DescriptorSet); auto vkDescrSet = DstDescrSet.GetVkDescriptorSet(); #ifdef _DEBUG if (ResourceCache.DbgGetContentType() == ShaderResourceCacheVk::DbgCacheContentType::SRBResources) { - if(SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_STATIC || SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_MUTABLE) + if(VariableType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC || VariableType == SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE) { VERIFY(vkDescrSet != VK_NULL_HANDLE, "Static and mutable variables must have valid vulkan descriptor set assigned"); // Dynamic variables do not have vulkan descriptor set only until they are assigned one the first time @@ -626,6 +835,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint3 CacheImage(pObj, DstRes, vkDescrSet, ArrayIndex, [&](const VkResource& SeparateSampler, ISampler* pSampler) { + VERIFY(!SeparateSampler.IsImmutableSamplerAssigned(), "This separate sampler is assigned an immutable sampler '", SeparateSampler.SpirvAttribs.Name, "'"); VERIFY_EXPR(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); DEV_CHECK_ERR(SeparateSampler.SpirvAttribs.ArraySize == 1 || SeparateSampler.SpirvAttribs.ArraySize == SpirvAttribs.ArraySize, "Array size (", SeparateSampler.SpirvAttribs.ArraySize,") of separate sampler variable '", @@ -638,7 +848,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint3 break; case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler: - if (!SpirvAttribs.IsImmutableSamplerAssigned()) + if (!IsImmutableSamplerAssigned()) { CacheSeparateSampler(pObj, DstRes, vkDescrSet, ArrayIndex); } @@ -655,7 +865,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint3 } else { - if (DstRes.pObject && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC) + if (DstRes.pObject && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) { LOG_ERROR_MESSAGE( "Shader variable '", SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "' is not dynamic but being unbound. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or label shader variable as dynamic if you need to bind another resource." ); } @@ -670,10 +880,10 @@ bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const Shader if (DescriptorSet < ResourceCache.GetNumDescriptorSets()) { - auto& Set = ResourceCache.GetDescriptorSet(DescriptorSet); + const auto& Set = ResourceCache.GetDescriptorSet(DescriptorSet); if (CacheOffset + ArrayIndex < Set.GetSize()) { - auto& CachedRes = Set.GetResource(CacheOffset + ArrayIndex); + const auto& CachedRes = Set.GetResource(CacheOffset + ArrayIndex); return CachedRes.pObject != nullptr; } } @@ -686,21 +896,21 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou const ShaderResourceCacheVk& SrcResourceCache, ShaderResourceCacheVk& DstResourceCache)const { - auto NumStaticResources = m_NumResources[SHADER_VARIABLE_TYPE_STATIC]; - VERIFY(NumStaticResources == SrcLayout.m_NumResources[SHADER_VARIABLE_TYPE_STATIC], "Inconsistent number of static resources"); + auto NumStaticResources = m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC]; + VERIFY(NumStaticResources == SrcLayout.m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC], "Inconsistent number of static resources"); VERIFY(SrcLayout.m_pResources->GetShaderType() == m_pResources->GetShaderType(), "Incosistent shader types"); // Static shader resources are stored in one large continuous descriptor set for (Uint32 r=0; r < NumStaticResources; ++r) { // Get resource attributes - auto &DstRes = GetResource(SHADER_VARIABLE_TYPE_STATIC, r); - const auto &SrcRes = SrcLayout.GetResource(SHADER_VARIABLE_TYPE_STATIC, r); + const auto& DstRes = GetResource(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, r); + const auto& SrcRes = SrcLayout.GetResource(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, r); VERIFY(SrcRes.Binding == SrcRes.SpirvAttribs.Type, "Unexpected binding"); VERIFY(SrcRes.SpirvAttribs.ArraySize == DstRes.SpirvAttribs.ArraySize, "Inconsistent array size"); if (DstRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && - DstRes.SpirvAttribs.IsImmutableSamplerAssigned()) + DstRes.IsImmutableSamplerAssigned()) continue; // Skip immutable samplers for (Uint32 ArrInd = 0; ArrInd < DstRes.SpirvAttribs.ArraySize; ++ArrInd) @@ -710,11 +920,11 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou const auto& SrcCachedRes = SrcCachedSet.GetResource(SrcOffset); IDeviceObject* pObject = SrcCachedRes.pObject.RawPtr<IDeviceObject>(); if (!pObject) - LOG_ERROR_MESSAGE("No resource assigned to static shader variable '", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); + LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'."); auto DstOffset = DstRes.CacheOffset + ArrInd; IDeviceObject* pCachedResource = DstResourceCache.GetDescriptorSet(DstRes.DescriptorSet).GetResource(DstOffset).pObject; - if(pCachedResource != pObject) + if (pCachedResource != pObject) { VERIFY(pCachedResource == nullptr, "Static resource has already been initialized, and the resource to be assigned from the shader does not match previously assigned resource"); DstRes.BindResource(pObject, ArrInd, DstResourceCache); @@ -728,21 +938,21 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou bool ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& ResourceCache)const { bool BindingsOK = true; - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) + for(SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType+1)) { for(Uint32 r=0; r < m_NumResources[VarType]; ++r) { const auto& Res = GetResource(VarType, r); - VERIFY(Res.SpirvAttribs.VarType == VarType, "Unexpected variable type"); + VERIFY(Res.GetVariableType() == VarType, "Unexpected variable type"); for(Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd) { const auto& CachedDescrSet = ResourceCache.GetDescriptorSet(Res.DescriptorSet); const auto& CachedRes = CachedDescrSet.GetResource(Res.CacheOffset + ArrInd); VERIFY(CachedRes.Type == Res.SpirvAttribs.Type, "Inconsistent types"); if (CachedRes.pObject == nullptr && - !(Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.SpirvAttribs.IsImmutableSamplerAssigned())) + !(Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.IsImmutableSamplerAssigned())) { - LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.SpirvAttribs.VarType), " variable '", Res.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); + LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.GetVariableType()), " variable '", Res.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'"); BindingsOK = false; } #ifdef _DEBUG @@ -752,11 +962,11 @@ bool ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& Reso VERIFY(vkDescSet == VK_NULL_HANDLE, "Static resource cache should never have vulkan descriptor set"); else if (dbgCacheContentType == ShaderResourceCacheVk::DbgCacheContentType::SRBResources) { - if (VarType == SHADER_VARIABLE_TYPE_STATIC || VarType == SHADER_VARIABLE_TYPE_MUTABLE) + if (VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC || VarType == SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE) { VERIFY(vkDescSet != VK_NULL_HANDLE, "Static and mutable variables must have valid vulkan descriptor set assigned"); } - else if (VarType == SHADER_VARIABLE_TYPE_DYNAMIC) + else if (VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) { VERIFY(vkDescSet == VK_NULL_HANDLE, "Dynamic variables must not be assigned a vulkan descriptor set"); } @@ -771,38 +981,6 @@ bool ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& Reso } #endif - -const Char* ShaderResourceLayoutVk::GetShaderName()const -{ - RefCntAutoPtr<IShader> pShader(&m_Owner, IID_Shader); - if (pShader) - { - return pShader->GetDesc().Name; - } - else - { - RefCntAutoPtr<IPipelineState> pPSO(&m_Owner, IID_PipelineState); - if (pPSO) - { - auto *pPSOVk = pPSO.RawPtr<PipelineStateVkImpl>(); - auto *ppShaders = pPSOVk->GetShaders(); - auto NumShaders = pPSOVk->GetNumShaders(); - for (Uint32 s = 0; s < NumShaders; ++s) - { - const auto &ShaderDesc = ppShaders[s]->GetDesc(); - if(ShaderDesc.ShaderType == m_pResources->GetShaderType()) - return ShaderDesc.Name; - } - UNEXPECTED("Shader not found"); - } - else - { - UNEXPECTED("Shader resource layout owner must be a shader or a pipeline state"); - } - } - return ""; -} - void ShaderResourceLayoutVk::InitializeResourceMemoryInCache(ShaderResourceCacheVk& ResourceCache)const { auto TotalResources = GetTotalResourceCount(); @@ -816,19 +994,19 @@ void ShaderResourceLayoutVk::InitializeResourceMemoryInCache(ShaderResourceCache void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache, VkDescriptorSet vkDynamicDescriptorSet)const { - Uint32 NumDynamicResources = m_NumResources[SHADER_VARIABLE_TYPE_DYNAMIC]; + Uint32 NumDynamicResources = m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC]; VERIFY(NumDynamicResources != 0, "This shader resource layout does not contain dynamic resources"); VERIFY_EXPR(vkDynamicDescriptorSet != VK_NULL_HANDLE); #ifdef _DEBUG - static constexpr size_t ImgUpdateBatchSize = 4; - static constexpr size_t BuffUpdateBatchSize = 2; - static constexpr size_t TexelBuffUpdateBatchSize = 2; + static constexpr size_t ImgUpdateBatchSize = 4; + static constexpr size_t BuffUpdateBatchSize = 2; + static constexpr size_t TexelBuffUpdateBatchSize = 2; static constexpr size_t WriteDescriptorSetBatchSize = 2; #else - static constexpr size_t ImgUpdateBatchSize = 128; - static constexpr size_t BuffUpdateBatchSize = 64; - static constexpr size_t TexelBuffUpdateBatchSize = 32; + static constexpr size_t ImgUpdateBatchSize = 128; + static constexpr size_t BuffUpdateBatchSize = 64; + static constexpr size_t TexelBuffUpdateBatchSize = 32; static constexpr size_t WriteDescriptorSetBatchSize = 32; #endif @@ -839,9 +1017,9 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& std::array<VkWriteDescriptorSet, WriteDescriptorSetBatchSize> WriteDescrSetArr; Uint32 ResNum = 0, ArrElem = 0; - auto DescrImgIt = DescrImgInfoArr.begin(); - auto DescrBuffIt = DescrBuffInfoArr.begin(); - auto BuffViewIt = DescrBuffViewArr.begin(); + auto DescrImgIt = DescrImgInfoArr.begin(); + auto DescrBuffIt = DescrBuffInfoArr.begin(); + auto BuffViewIt = DescrBuffViewArr.begin(); auto WriteDescrSetIt = WriteDescrSetArr.begin(); #ifdef _DEBUG @@ -850,8 +1028,8 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& while(ResNum < NumDynamicResources) { - const auto& Res = GetResource(SHADER_VARIABLE_TYPE_DYNAMIC, ResNum); - VERIFY_EXPR(Res.SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_DYNAMIC); + const auto& Res = GetResource(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC, ResNum); + VERIFY_EXPR(Res.GetVariableType() == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC); #ifdef _DEBUG if(DynamicDescrSetIndex < 0) DynamicDescrSetIndex = Res.DescriptorSet; @@ -871,11 +1049,11 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& WriteDescrSetIt->descriptorType = PipelineLayout::GetVkDescriptorType(Res.SpirvAttribs); // For every resource type, try to batch as many descriptor updates as we can - switch(Res.SpirvAttribs.Type) + switch (Res.SpirvAttribs.Type) { case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt); - while(ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) + while (ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *DescrBuffIt = CachedRes.GetUniformBufferDescriptorWriteInfo(); @@ -886,7 +1064,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& case SPIRVShaderResourceAttribs::ResourceType::StorageBuffer: WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt); - while(ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) + while (ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *DescrBuffIt = CachedRes.GetStorageBufferDescriptorWriteInfo(); @@ -898,7 +1076,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer: case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer: WriteDescrSetIt->pTexelBufferView = &(*BuffViewIt); - while(ArrElem < Res.SpirvAttribs.ArraySize && BuffViewIt != DescrBuffViewArr.end()) + while (ArrElem < Res.SpirvAttribs.ArraySize && BuffViewIt != DescrBuffViewArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); *BuffViewIt = CachedRes.GetBufferViewWriteInfo(); @@ -914,7 +1092,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& while (ArrElem < Res.SpirvAttribs.ArraySize && DescrImgIt != DescrImgInfoArr.end()) { const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem); - *DescrImgIt = CachedRes.GetImageDescriptorWriteInfo(Res.SpirvAttribs.IsImmutableSamplerAssigned()); + *DescrImgIt = CachedRes.GetImageDescriptorWriteInfo(Res.IsImmutableSamplerAssigned()); ++DescrImgIt; ++ArrElem; } @@ -928,7 +1106,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler: // Immutable samplers are permanently bound into the set layout; later binding a sampler // into an immutable sampler slot in a descriptor set is not allowed (13.2.1) - if (!Res.SpirvAttribs.IsImmutableSamplerAssigned()) + if (!Res.IsImmutableSamplerAssigned()) { WriteDescrSetIt->pImageInfo = &(*DescrImgIt); while (ArrElem < Res.SpirvAttribs.ArraySize && DescrImgIt != DescrImgInfoArr.end()) @@ -951,13 +1129,13 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& } WriteDescrSetIt->descriptorCount = ArrElem - WriteDescrSetIt->dstArrayElement; - if(ArrElem == Res.SpirvAttribs.ArraySize) + if (ArrElem == Res.SpirvAttribs.ArraySize) { ArrElem = 0; ++ResNum; } // descriptorCount == 0 for immutable separate samplers - if(WriteDescrSetIt->descriptorCount > 0) + if (WriteDescrSetIt->descriptorCount > 0) ++WriteDescrSetIt; // If we ran out of space in any of the arrays or if we processed all resources, @@ -969,7 +1147,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& WriteDescrSetIt == WriteDescrSetArr.end()) { auto DescrWriteCount = static_cast<Uint32>(std::distance(WriteDescrSetArr.begin(), WriteDescrSetIt)); - if(DescrWriteCount > 0) + if (DescrWriteCount > 0) m_LogicalDevice.UpdateDescriptorSets(DescrWriteCount, WriteDescrSetArr.data(), 0, nullptr); DescrImgIt = DescrImgInfoArr.begin(); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp index 485ca318..9d6bbf96 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp @@ -24,53 +24,55 @@ #include "pch.h" #include "ShaderVariableVk.h" +#include "ShaderResourceVariableBase.h" namespace Diligent { -size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - Uint32& NumVariables) +size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + Uint32& NumVariables) { NumVariables = 0; - Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + const bool UsingSeparateSamplers = Layout.IsUsingSeparateSamplers(); + for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType+1)) { if (IsAllowedType(VarType, AllowedTypeBits)) { auto NumResources = Layout.GetResourceCount(VarType); - if (Layout.IsUsingSeparateSamplers()) - NumVariables += NumResources; - else + for (Uint32 r=0; r < NumResources; ++r) { - // When using HLSL-style combined image samplers, we need to skip separate samplers - for( Uint32 r=0; r < NumResources; ++r ) - { - const auto& SrcRes = Layout.GetResource(VarType, r); - if (SrcRes.SpirvAttribs.Type != SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) - ++NumVariables; - } + const auto& SrcRes = Layout.GetResource(VarType, r); + + // When using HLSL-style combined image samplers, we need to skip separate samplers. + // Also always skip immutable separate samplers. + if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + (!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned()) ) + continue; + + ++NumVariables; } } } - return NumVariables*sizeof(ShaderVariableVkImpl); + return NumVariables * sizeof(ShaderVariableVkImpl); } // Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes -void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& SrcLayout, - IMemoryAllocator& Allocator, - const SHADER_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheVk& ResourceCache) -{ - m_pResourceLayout = &SrcLayout; - m_pResourceCache = &ResourceCache; +ShaderVariableManagerVk::ShaderVariableManagerVk(IObject& Owner, + const ShaderResourceLayoutVk& SrcLayout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheVk& ResourceCache) : + m_Owner(Owner), + m_ResourceCache(ResourceCache) #ifdef _DEBUG - m_pDbgAllocator = &Allocator; + , m_DbgAllocator(Allocator) #endif - +{ const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); VERIFY_EXPR(m_NumVariables == 0); auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables); @@ -78,23 +80,26 @@ void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& SrcLayout if(m_NumVariables == 0) return; - auto *pRawMem = ALLOCATE(Allocator, "Raw memory buffer for shader variables", MemSize); + auto* pRawMem = ALLOCATE(Allocator, "Raw memory buffer for shader variables", MemSize); m_pVariables = reinterpret_cast<ShaderVariableVkImpl*>(pRawMem); Uint32 VarInd = 0; - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1)) + const bool UsingSeparateSamplers = SrcLayout.IsUsingSeparateSamplers(); + for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType+1)) { if (!IsAllowedType(VarType, AllowedTypeBits)) continue; Uint32 NumResources = SrcLayout.GetResourceCount(VarType); - for( Uint32 r=0; r < NumResources; ++r ) + for (Uint32 r=0; r < NumResources; ++r) { const auto& SrcRes = SrcLayout.GetResource(VarType, r); - if (!SrcLayout.IsUsingSeparateSamplers() && SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + // Skip separate samplers when using combined HLSL-style image samplers. Also always skip immutable separate samplers. + if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + (!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned()) ) continue; - ::new (m_pVariables + VarInd) ShaderVariableVkImpl(*this, SrcRes ); + ::new (m_pVariables + VarInd) ShaderVariableVkImpl(*this, SrcRes); ++VarInd; } } @@ -103,16 +108,16 @@ void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& SrcLayout ShaderVariableManagerVk::~ShaderVariableManagerVk() { - VERIFY(m_pVariables == nullptr, "Destroy() has not been called"); + VERIFY(m_pVariables == nullptr, "DestroyVariables() has not been called"); } -void ShaderVariableManagerVk::Destroy(IMemoryAllocator &Allocator) +void ShaderVariableManagerVk::DestroyVariables(IMemoryAllocator& Allocator) { - VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor"); + VERIFY(&m_DbgAllocator == &Allocator, "Incosistent alloctor"); - if(m_pVariables != nullptr) + if (m_pVariables != nullptr) { - for(Uint32 v=0; v < m_NumVariables; ++v) + for (Uint32 v=0; v < m_NumVariables; ++v) m_pVariables[v].~ShaderVariableVkImpl(); Allocator.Free(m_pVariables); m_pVariables = nullptr; @@ -124,7 +129,7 @@ ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) ShaderVariableVkImpl* pVar = nullptr; for (Uint32 v = 0; v < m_NumVariables; ++v) { - auto &Var = m_pVariables[v]; + auto& Var = m_pVariables[v]; const auto& Res = Var.m_Resource; if (strcmp(Res.SpirvAttribs.Name, Name) == 0) { @@ -167,11 +172,9 @@ Uint32 ShaderVariableManagerVk::GetVariableIndex(const ShaderVariableVkImpl& Var } } -void ShaderVariableManagerVk::BindResources( IResourceMapping* pResourceMapping, Uint32 Flags) +void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) { - VERIFY_EXPR(m_pResourceCache != nullptr); - - if( !pResourceMapping ) + if (!pResourceMapping) { LOG_ERROR_MESSAGE( "Failed to bind resources: resource mapping is null" ); return; @@ -180,34 +183,35 @@ void ShaderVariableManagerVk::BindResources( IResourceMapping* pResourceMapping, if ( (Flags & BIND_SHADER_RESOURCES_UPDATE_ALL) == 0 ) Flags |= BIND_SHADER_RESOURCES_UPDATE_ALL; - for(Uint32 v=0; v < m_NumVariables; ++v) + for (Uint32 v=0; v < m_NumVariables; ++v) { - auto &Var = m_pVariables[v]; + auto& Var = m_pVariables[v]; const auto& Res = Var.m_Resource; - // Skip immutable separate samplers - if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.SpirvAttribs.IsImmutableSamplerAssigned()) - continue; + // There should be no immutable separate samplers + VERIFY(Res.SpirvAttribs.Type != SPIRVShaderResourceAttribs::ResourceType::SeparateSampler || !Res.IsImmutableSamplerAssigned(), + "There must be no shader resource variables for immutable separate samplers"); - if ( (Flags & (1 << Res.SpirvAttribs.VarType)) == 0 ) + if ( (Flags & (1 << Res.GetVariableType())) == 0 ) continue; for (Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd) { - if( (Flags & BIND_SHADER_RESOURCES_KEEP_EXISTING) && Res.IsBound(ArrInd, *m_pResourceCache) ) + if ( (Flags & BIND_SHADER_RESOURCES_KEEP_EXISTING) && Res.IsBound(ArrInd, m_ResourceCache) ) continue; const auto* VarName = Res.SpirvAttribs.Name; RefCntAutoPtr<IDeviceObject> pObj; pResourceMapping->GetResource( VarName, &pObj, ArrInd ); - if( pObj ) + if (pObj) { - Res.BindResource(pObj, ArrInd, *m_pResourceCache); + Res.BindResource(pObj, ArrInd, m_ResourceCache); } else { - if( (Flags & BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED) && !Res.IsBound(ArrInd, *m_pResourceCache) ) - LOG_ERROR_MESSAGE( "Unable to bind resource to shader variable '", Res.SpirvAttribs.GetPrintName(ArrInd), "': resource is not found in the resource mapping" ); + if ( (Flags & BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED) && !Res.IsBound(ArrInd, m_ResourceCache) ) + LOG_ERROR_MESSAGE( "Unable to bind resource to shader variable '", Res.SpirvAttribs.GetPrintName(ArrInd), "': resource is not found in the resource mapping. " + "Do not use BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED flag to suppress the message if this is not an issue." ); } } } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp index fef2d052..9ec51af6 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp @@ -37,13 +37,10 @@ namespace Diligent { -ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters, - RenderDeviceVkImpl* pRenderDeviceVk, - const ShaderCreationAttribs& CreationAttribs) : - TShaderBase (pRefCounters, pRenderDeviceVk, CreationAttribs.Desc), - m_StaticResLayout (*this, pRenderDeviceVk->GetLogicalDevice()), - m_StaticResCache (ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources), - m_StaticVarsMgr (*this) +ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pRenderDeviceVk, + const ShaderCreateInfo& CreationAttribs) : + TShaderBase(pRefCounters, pRenderDeviceVk, CreationAttribs.Desc) { if (CreationAttribs.Source != nullptr || CreationAttribs.FilePath != nullptr) { @@ -95,10 +92,6 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters, { MapHLSLVertexShaderInputs(); } - - m_StaticResLayout.InitializeStaticResourceLayout(m_pShaderResources, GetRawAllocator(), m_StaticResCache); - // m_StaticResLayout only contains static resources, so reference all of them - m_StaticVarsMgr.Initialize(m_StaticResLayout, GetRawAllocator(), nullptr, 0, m_StaticResCache); } void ShaderVkImpl::MapHLSLVertexShaderInputs() @@ -134,14 +127,63 @@ void ShaderVkImpl::MapHLSLVertexShaderInputs() ShaderVkImpl::~ShaderVkImpl() { - m_StaticVarsMgr.Destroy(GetRawAllocator()); } -#ifdef DEVELOPMENT -bool ShaderVkImpl::DvpVerifyStaticResourceBindings()const +ShaderResourceDesc ShaderVkImpl::GetResource(Uint32 Index)const { - return m_StaticResLayout.dvpVerifyBindings(m_StaticResCache); + auto ResCount = GetResourceCount(); + DEV_CHECK_ERR(Index < ResCount, "Resource index (", Index, ") is out of range"); + ShaderResourceDesc ResourceDesc; + if (Index < ResCount) + { + const auto& SPIRVResource = m_pShaderResources->GetResource(Index); + ResourceDesc.Name = SPIRVResource.Name; + ResourceDesc.ArraySize = SPIRVResource.ArraySize; + static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 9, "Please update switch statement below"); + switch (SPIRVResource.Type) + { + case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer: + ResourceDesc.Type = SHADER_RESOURCE_TYPE_CONSTANT_BUFFER; + break; + + case SPIRVShaderResourceAttribs::ResourceType::StorageBuffer: + 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 '", SPIRVResource.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; + + default: + UNEXPECTED("Unknown SPIRV resource type"); + } + } + return ResourceDesc; } -#endif } diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp index 5fccdad8..57b55f15 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanDynamicHeap.cpp @@ -165,22 +165,22 @@ VulkanDynamicMemoryManager::MasterBlock VulkanDynamicMemoryManager::AllocateMast Block = TBase::AllocateMasterBlock(SizeInBytes, Alignment); if (!Block.IsValid()) { - LOG_ERROR_MESSAGE("Space in dynamic heap is exausted! After idling for ", std::fixed, std::setprecision(1), IdleDuration.count()*1000.0, " ms still no space is available. Increase the size of the heap by setting EngineVkAttribs::DynamicHeapSize to a greater value or optimize dynamic resource usage"); + LOG_ERROR_MESSAGE("Space in dynamic heap is exausted! After idling for ", std::fixed, std::setprecision(1), IdleDuration.count()*1000.0, " ms still no space is available. Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage"); } else { - LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced idling the GPU. Increase the size of the heap by setting EngineVkAttribs::DynamicHeapSize to a greater value or optimize dynamic resource usage"); + LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced idling the GPU. Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage"); } } else { if(SleepIterations == 0) { - LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted forcing mid-frame shrinkage. Increase the size of the heap buffer by setting EngineVkAttribs::DynamicHeapSize to a greater value or optimize dynamic resource usage"); + LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted forcing mid-frame shrinkage. Increase the size of the heap buffer by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage"); } else { - LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced wait time of ", std::fixed, std::setprecision(1), IdleDuration.count()*1000.0, " ms. Increase the size of the heap by setting EngineVkAttribs::DynamicHeapSize to a greater value or optimize dynamic resource usage"); + LOG_WARNING_MESSAGE("Space in dynamic heap is almost exausted. Allocation forced wait time of ", std::fixed, std::setprecision(1), IdleDuration.count()*1000.0, " ms. Increase the size of the heap by setting EngineVkCreateInfo::DynamicHeapSize to a greater value or optimize dynamic resource usage"); } } } |
