From 824b588583406e8db8aa9e7123b9802437eaaf37 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Sun, 6 May 2018 10:11:29 -0700 Subject: Working on VK shader resource layout --- .../include/ShaderResourceCacheVk.h | 93 +++--- .../include/ShaderResourceLayoutVk.h | 269 ++++++---------- .../src/ShaderResourceCacheVk.cpp | 56 ++-- .../src/ShaderResourceLayoutVk.cpp | 339 +++++++++------------ Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp | 2 +- 5 files changed, 299 insertions(+), 460 deletions(-) (limited to 'Graphics/GraphicsEngineVulkan') diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h index a32ae066..a118cc6c 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h @@ -26,24 +26,22 @@ /// \file /// Declaration of Diligent::ShaderResourceCacheVk class -// http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-cache/ - // Shader resource cache stores Vk resources in a continuous chunk of memory: // // -// __________________________________________________________ -// m_pMemory | m_pResources, m_NumResources == m | -// | | | -// V | V -// | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | -// | A \ -// | | \ -// |________________________________________________| \RefCntAutoPtr -// m_pResources, m_NumResources == n \_________ -// | Object | -// --------- -// -// Nrt = m_NumTables +// ______________________________________________________________ +// m_pMemory | m_pResources, m_NumResources == m | +// | | | +// V | V +// | DescriptorSet[0] | .... | DescriptorSet[Ns-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | +// | A \ +// | | \ +// |__________________________________________________| \RefCntAutoPtr +// m_pResources, m_NumResources == n \_________ +// | Object | +// --------- +// +// Ns = m_NumSets // // // The cache is also assigned decriptor heap space to store shader visible descriptor handles (for non-dynamic resources). @@ -55,7 +53,7 @@ // | | // | TableStartOffset | TableStartOffset // | | -// | RootTable[0] | RootTable[1] | RootTable[2] | .... | RootTable[Nrt] | +// | DescriptorSet[0] | DescriptorSet[1] | DescriptorSet[2] | .... | DescriptorSet[Nrt] | // | | // | TableStartOffset | InvalidDescriptorOffset // | | @@ -71,7 +69,7 @@ // // // -// | RootTable[i] | Res[0] ... Res[n-1] | +// | DescriptorSet[i] | Res[0] ... Res[n-1] | // \ // TableStartOffset\____ // \ @@ -98,7 +96,6 @@ enum class CachedResourceType : Int32 #endif class ShaderResourceCacheVk { -#if 0 public: // This enum is used for debug purposes only enum DbgCacheContentType @@ -116,76 +113,58 @@ public: ~ShaderResourceCacheVk(); - void Initialize(IMemoryAllocator &MemAllocator, Uint32 NumTables, Uint32 TableSizes[]); - + void Initialize(IMemoryAllocator &MemAllocator, Uint32 NumSets, Uint32 SetSizes[]); +#if 0 static constexpr Uint32 InvalidDescriptorOffset = static_cast(-1); - - //http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-cache#Cache-Structure +#endif struct Resource { +#if 0 CachedResourceType Type = CachedResourceType::Unknown; // CPU descriptor handle of a cached resource in CPU-only descriptor heap // Note that for dynamic resources, this is the only available CPU descriptor handle Vk_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {0}; +#endif RefCntAutoPtr pObject; }; - class RootTable + class DescriptorSet { public: - RootTable(Uint32 NumResources, Resource *pResources) : + DescriptorSet(Uint32 NumResources, Resource *pResources) : m_NumResources(NumResources), m_pResources(pResources) {} - inline Resource& GetResource(Uint32 OffsetFromTableStart, - const Vk_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, - const SHADER_TYPE dbgRefShaderType) + inline Resource& GetResource(Uint32 OffsetFromTableStart) { - VERIFY(m_dbgHeapType == dbgDescriptorHeapType, "Incosistent descriptor heap type" ); - VERIFY(m_dbgShaderType == dbgRefShaderType, "Incosistent shader type" ); - VERIFY(OffsetFromTableStart < m_NumResources, "Root table at index is not large enough to store descriptor at offset ", OffsetFromTableStart ); return m_pResources[OffsetFromTableStart]; } inline Uint32 GetSize()const{return m_NumResources; } - // Offset from the start of the descriptor heap allocation to the start of the table - Uint32 m_TableStartOffset = InvalidDescriptorOffset; - #ifdef _DEBUG - void SetDebugAttribs(Uint32 MaxOffset, - const Vk_DESCRIPTOR_HEAP_TYPE dbgDescriptorHeapType, - const SHADER_TYPE dbgRefShaderType) + void SetDebugAttribs(Uint32 MaxOffset) { VERIFY_EXPR(m_NumResources == MaxOffset); - m_dbgHeapType = dbgDescriptorHeapType; - m_dbgShaderType = dbgRefShaderType; } - - Vk_DESCRIPTOR_HEAP_TYPE DbgGetHeapType()const{return m_dbgHeapType;} #endif const Uint32 m_NumResources = 0; private: -#ifdef _DEBUG - Vk_DESCRIPTOR_HEAP_TYPE m_dbgHeapType = Vk_DESCRIPTOR_HEAP_TYPE_NUM_TYPES; - SHADER_TYPE m_dbgShaderType = SHADER_TYPE_UNKNOWN; -#endif - Resource* const m_pResources = nullptr; }; - inline RootTable& GetRootTable(Uint32 RootIndex) + inline DescriptorSet& GetDescriptorSet(Uint32 Index) { - VERIFY_EXPR(RootIndex < m_NumTables); - return reinterpret_cast(m_pMemory)[RootIndex]; + VERIFY_EXPR(Index < m_NumSets); + return reinterpret_cast(m_pMemory)[Index]; } - inline Uint32 GetNumRootTables()const{return m_NumTables; } - + inline Uint32 GetNumDescriptorSets()const{return m_NumSets; } +#if 0 void SetDescriptorHeapSpace(DescriptorHeapAllocation &&CbcSrvUavHeapSpace, DescriptorHeapAllocation &&SamplerHeapSpace) { VERIFY(m_SamplerHeapSpace.GetCpuHandle().ptr == 0 && m_CbvSrvUavHeapSpace.GetCpuHandle().ptr == 0, "Space has already been allocated in GPU descriptor heaps"); @@ -193,7 +172,7 @@ public: Uint32 NumSamplerDescriptors = 0, NumSrvCbvUavDescriptors = 0; for (Uint32 rt = 0; rt < m_NumTables; ++rt) { - auto &Tbl = GetRootTable(rt); + auto &Tbl = GetDescriptorSet(rt); if(Tbl.m_TableStartOffset != InvalidDescriptorOffset) { if(Tbl.DbgGetHeapType() == Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV) @@ -223,7 +202,7 @@ public: template Vk_CPU_DESCRIPTOR_HANDLE GetShaderVisibleTableCPUDescriptorHandle(Uint32 RootParamInd, Uint32 OffsetFromTableStart = 0) { - auto &RootParam = GetRootTable(RootParamInd); + auto &RootParam = GetDescriptorSet(RootParamInd); VERIFY(HeapType == RootParam.DbgGetHeapType(), "Invalid descriptor heap type"); Vk_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle = {0}; @@ -256,7 +235,7 @@ public: template Vk_GPU_DESCRIPTOR_HANDLE GetShaderVisibleTableGPUDescriptorHandle(Uint32 RootParamInd, Uint32 OffsetFromTableStart = 0) { - auto &RootParam = GetRootTable(RootParamInd); + auto &RootParam = GetDescriptorSet(RootParamInd); VERIFY(RootParam.m_TableStartOffset != InvalidDescriptorOffset, "GPU descriptor handle must never be requested for dynamic resources"); VERIFY(OffsetFromTableStart < RootParam.m_NumResources, "Offset is out of range"); @@ -279,7 +258,7 @@ public: return GPUDescriptorHandle; } - +#endif #ifdef _DEBUG // Only for debug purposes: indicates what types of resources are stored in the cache DbgCacheContentType DbgGetContentType()const{return m_DbgContentType;} @@ -291,21 +270,21 @@ private: ShaderResourceCacheVk& operator = (const ShaderResourceCacheVk&) = delete; ShaderResourceCacheVk& operator = (ShaderResourceCacheVk&&) = delete; +#if 0 // Allocation in a GPU-visible sampler descriptor heap DescriptorHeapAllocation m_SamplerHeapSpace; // Allocation in a GPU-visible CBV/SRV/UAV descriptor heap DescriptorHeapAllocation m_CbvSrvUavHeapSpace; - +#endif IMemoryAllocator *m_pAllocator=nullptr; void *m_pMemory = nullptr; - Uint32 m_NumTables = 0; + Uint32 m_NumSets = 0; #ifdef _DEBUG // Only for debug purposes: indicates what types of resources are stored in the cache const DbgCacheContentType m_DbgContentType; #endif -#endif }; } diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h index 3ff225d7..8999279a 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h @@ -26,24 +26,18 @@ /// \file /// Declaration of Diligent::ShaderResourceLayoutVk class -// http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-layout/ - // All resources are stored in a single continuous chunk of memory using the following layout: // -// m_ResourceBuffer m_Samplers -// | | -// | SRV_CBV_UAV[0] ... SRV_CBV_UAV[s-1] | SRV_CBV_UAV[s] ... SRV_CBV_UAV[s+m-1] | SRV_CBV_UAV[s+m] ... SRV_CBV_UAV[s+m+d-1] || Sampler[0] ... Sampler[s'-1] | Sampler[s'] ... Sampler[s'+m'-1] | Sampler[s'+m'] ... Sampler[s'+m'+d'-1] || -// | | | || | | || -// | SHADER_VARIABLE_TYPE_STATIC | SHADER_VARIABLE_TYPE_MUTABLE | SHADER_VARIABLE_TYPE_DYNAMIC || SHADER_VARIABLE_TYPE_STATIC | SHADER_VARIABLE_TYPE_MUTABLE | SHADER_VARIABLE_TYPE_DYNAMIC || -// | | | || -// -// s == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC] -// m == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE] -// d == m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_DYNAMIC] +// 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 || +// | | | || // -// s' == m_NumSamplers[SHADER_VARIABLE_TYPE_STATIC] -// m' == m_NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE] -// d' == m_NumSamplers[SHADER_VARIABLE_TYPE_DYNAMIC] +// s == m_NumResources[SHADER_VARIABLE_TYPE_STATIC] +// m == m_NumResources[SHADER_VARIABLE_TYPE_MUTABLE] +// d == m_NumResources[SHADER_VARIABLE_TYPE_DYNAMIC] // // // Memory buffer is allocated through the allocator provided by the pipeline state. If allocation granularity > 1, fixed block @@ -51,9 +45,9 @@ // continuous memory. If allocation granularity == 1, raw allocator is used. // // -// Every SRV_CBV_UAV and Sampler structure holds a reference to D3DShaderResourceAttribs structure from ShaderResources. +// Every VkResource structure holds a reference to SPIRVShaderResourceAttribs structure from ShaderResources. // ShaderResourceLayoutVk holds shared pointer to ShaderResourcesVk instance. Note that ShaderResources::SamplerId -// references a sampler in ShaderResources, while SRV_CBV_UAV::SamplerId references a sampler in ShaderResourceLayoutVk, +// references a sampler in ShaderResources, while VkResource::SamplerId references a sampler in ShaderResourceLayoutVk, // and the two are not the same // // @@ -68,7 +62,7 @@ // |shared_ptr Ref Ref Ref // ________|__________________ ________\________________________/_________________________\_________________________________________ // | | unique_ptr | | | | | | | -// | ShaderResourceLayoutVk |--------------->| SRV_CBV_UAV[0] | SRV_CBV_UAV[1] | ... | Sampler[0] | Sampler[1] | ... | +// | ShaderResourceLayoutVk |--------------->| VkResource[0] | VkResource[1] | ... | Sampler[0] | Sampler[1] | ... | // |___________________________| |___________________|_________________|_______________|__________________|_________________|__________| // | | | A | / // | Raw ptr | |___________________SamplerId________________________| | / @@ -79,7 +73,6 @@ // | ShaderResourceCacheVk |---------------->| Resources | // |__________________________| |________________________________________________________________________| // -// http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-layout#Figure2 // Resources in the resource cache are identified by the root index and offset in the descriptor table // // @@ -100,11 +93,15 @@ // ** Resource cache is assigned, but not initialized; Initialization is performed by the root signature // +#include +#include +#include + // Set this define to 1 to use unordered_map to store shader variables. // Note that sizeof(m_VariableHash)==128 (release mode, MS compiler, x64). #define USE_VARIABLE_HASH_MAP 0 -#include "unordered_map" + #include "ShaderBase.h" #include "HashUtils.h" @@ -121,7 +118,7 @@ namespace Diligent { /// Diligent::ShaderResourceLayoutVk class -// sizeof(ShaderResourceLayoutVk)==80 (MS compiler, x64) +// sizeof(ShaderResourceLayoutVk)==?? (MS compiler, x64) class ShaderResourceLayoutVk { public: @@ -152,71 +149,69 @@ public: void Initialize(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice, const std::shared_ptr& pSrcResources, IMemoryAllocator &LayoutDataAllocator, - const SHADER_VARIABLE_TYPE *VarTypes, + const SHADER_VARIABLE_TYPE *AllowedVarTypes, Uint32 NumAllowedTypes, ShaderResourceCacheVk *pResourceCache, std::vector *pSPIRV, class PipelineLayout *pPipelineLayout); -#if 0 - // sizeof(SRV_CBV_UAV) == 32 (x64) - struct SRV_CBV_UAV : ShaderVariableD3DBase + + // sizeof(VkResource) == ?? (x64) + struct VkResource : IShaderVariable { - SRV_CBV_UAV(const SRV_CBV_UAV&) = delete; - SRV_CBV_UAV(SRV_CBV_UAV&&) = delete; - SRV_CBV_UAV& operator = (const SRV_CBV_UAV&) = delete; - SRV_CBV_UAV& operator = (SRV_CBV_UAV&&) = delete; - - static constexpr Uint32 ResTypeBits = 3; - static constexpr Uint32 RootIndBits = 16-ResTypeBits; - static constexpr Uint32 RootIndMask = (1 << RootIndBits)-1; - static constexpr Uint32 ResTypeMask = (1 << ResTypeBits)-1; - - static constexpr Uint16 InvalidRootIndex = RootIndMask; - static constexpr Uint16 MaxRootIndex = RootIndMask-1; - - static constexpr Uint32 InvalidSamplerId = 0xFFFF; - static constexpr Uint32 MaxSamplerId = InvalidSamplerId-1; - static constexpr Uint32 InvalidOffset = static_cast(-1); - - static_assert( static_cast(CachedResourceType::NumTypes) <= ResTypeMask, "3 bits is not enough to store CachedResourceType"); - - const Uint32 OffsetFromTableStart; - - // Special copy constructor. Note that sampler ID refers to the ID of the sampler - // within THIS layout, and may not be the same as in original layout - SRV_CBV_UAV(ShaderResourceLayoutVk &ParentLayout, const SRV_CBV_UAV &rhs, Uint32 SamId ) : - ResType_RootIndex(rhs.ResType_RootIndex), - SamplerId(static_cast(SamId)), - OffsetFromTableStart(rhs.OffsetFromTableStart), - ShaderVariableD3DBase(ParentLayout, rhs.Attribs) + VkResource(const VkResource&) = delete; + VkResource(VkResource&&) = delete; + VkResource& operator = (const VkResource&) = delete; + VkResource& operator = (VkResource&&) = delete; + + const Uint16 Binding; + const Uint16 DescriptorSet; + const SPIRVShaderResourceAttribs &SpirvAttribs; + ShaderResourceLayoutVk &ParentResLayout; + + VkResource(ShaderResourceLayoutVk &_ParentLayout, + const SPIRVShaderResourceAttribs &_SpirvAttribs, + uint32_t _Binding, + uint32_t _DescriptorSet) : + Binding(static_cast(_Binding)), + DescriptorSet(static_cast(_DescriptorSet)), + SpirvAttribs(_SpirvAttribs), + ParentResLayout(_ParentLayout) + { + VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds representable max value", std::numeric_limits::max() ); + VERIFY(_DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", _DescriptorSet, ") exceeds representable max value", std::numeric_limits::max()); + } + + virtual IReferenceCounters* GetReferenceCounters()const override final + { + return ParentResLayout.GetOwner().GetReferenceCounters(); + } + + virtual Atomics::Long AddRef()override final + { + return ParentResLayout.GetOwner().AddRef(); + } + + virtual Atomics::Long Release()override final { - VERIFY(SamId == InvalidSamplerId || SamId <= MaxSamplerId, "Sampler id exceeds max allowed value (", MaxSamplerId, ")" ); - VERIFY(rhs.m_ParentResLayout.m_pResources == m_ParentResLayout.m_pResources, "Incosistent resource references"); - VERIFY(IsValidOffset(), "Offset must be valid" ); - VERIFY(IsValidRootIndex(), "Root index must be valid" ); + return ParentResLayout.GetOwner().Release(); } - SRV_CBV_UAV(ShaderResourceLayoutVk &ParentLayout, - const D3DShaderResourceAttribs &_Attribs, - CachedResourceType ResType, - Uint32 RootIndex, - Uint32 _OffsetFromTableStart, - Uint32 _SamplerId) : - ResType_RootIndex( (static_cast(ResType) << RootIndBits) | (RootIndex & RootIndMask)), - SamplerId( static_cast(_SamplerId) ), - OffsetFromTableStart(_OffsetFromTableStart), - ShaderVariableD3DBase(ParentLayout, _Attribs) + void QueryInterface(const INTERFACE_ID &IID, IObject **ppInterface)override final { - VERIFY(RootIndex == InvalidRootIndex || RootIndex <= MaxRootIndex, "Root index exceeds max allowed value (", MaxRootIndex, ")" ); - VERIFY(IsValidOffset(), "Offset must be valid" ); - VERIFY(SamplerId == InvalidSamplerId || SamplerId <= MaxSamplerId, "Sampler id exceeds max allowed value (", MaxSamplerId, ")" ); + if (ppInterface == nullptr) + return; + + *ppInterface = nullptr; + if (IID == IID_ShaderVariable || IID == IID_Unknown) + { + *ppInterface = this; + (*ppInterface)->AddRef(); + } } bool IsBound(Uint32 ArrayIndex); -#endif // Non-virtual function void BindResource(IDeviceObject *pObject, Uint32 ArrayIndex, const ShaderResourceLayoutVk *dbgResLayout); -#if 0 virtual void Set(IDeviceObject *pObject)override final{ BindResource(pObject, 0, nullptr); } virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final @@ -225,6 +220,7 @@ public: BindResource(ppObjects[Elem], FirstElement+Elem, nullptr); } +#if 0 bool IsValidSampler() const{return GetSamplerId() != InvalidSamplerId;} bool IsValidRootIndex()const{return GetRootIndex() != InvalidRootIndex;} bool IsValidOffset() const{return OffsetFromTableStart != InvalidOffset; } @@ -244,12 +240,6 @@ public: } private: - const Uint16 ResType_RootIndex; // bit - // | 0 1 .... 12 | 13 14 15 | - // | | | - // | Root index | ResType | - const Uint16 SamplerId; - void CacheCB(IDeviceObject *pBuffer, ShaderResourceCacheVk::Resource& DstRes, Uint32 ArrayInd, @@ -264,55 +254,11 @@ public: Vk_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle, TViewTypeEnum dbgExpectedViewType, TBindSamplerProcType BindSamplerProc); +#endif }; - // sizeof(Sampler) == 24 (x64) - struct Sampler - { - Sampler(const Sampler&) = delete; - Sampler(Sampler&&) = delete; - Sampler& operator = (const Sampler&) = delete; - Sampler& operator = (Sampler&&) = delete; - - const D3DShaderResourceAttribs &Attribs; - ShaderResourceLayoutVk &m_ParentResLayout; - - static constexpr Uint32 InvalidRootIndex = static_cast(-1); - static constexpr Uint32 InvalidOffset = static_cast(-1); - - const Uint32 RootIndex; - const Uint32 OffsetFromTableStart; - - Sampler(ShaderResourceLayoutVk &ParentLayout, const Sampler& Sam): - Attribs(Sam.Attribs), - m_ParentResLayout(ParentLayout), - RootIndex(Sam.RootIndex), - OffsetFromTableStart(Sam.OffsetFromTableStart) - { - VERIFY(Sam.m_ParentResLayout.m_pResources == m_ParentResLayout.m_pResources, "Incosistent resource references"); - VERIFY(IsValidRootIndex(), "Root index must be valid" ); - VERIFY(IsValidOffset(), "Offset must be valid" ); - } - - Sampler(ShaderResourceLayoutVk &ParentResLayout, const D3DShaderResourceAttribs &_Attribs, Uint32 _RootIndex, Uint32 _OffsetFromTableStart) : - RootIndex(_RootIndex), - OffsetFromTableStart(_OffsetFromTableStart), - Attribs(_Attribs), - m_ParentResLayout(ParentResLayout) - { - VERIFY(IsValidRootIndex(), "Root index must be valid" ); - VERIFY(IsValidOffset(), "Offset must be valid" ); - } - - bool IsValidRootIndex()const{return RootIndex != InvalidRootIndex;} - bool IsValidOffset() const{return OffsetFromTableStart != InvalidOffset; } - - void CacheSampler(class ITextureViewVk *pTexViewVk, Uint32 ArrayIndex, Vk_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle); - }; - - void CopyStaticResourceDesriptorHandles(const ShaderResourceLayoutVk &SrcLayout); -#endif + // dbgResourceCache is only used for sanity check and as a remainder that the resource cache must be alive // while Layout is alive void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheVk *dbgResourceCache ); @@ -321,14 +267,12 @@ public: #ifdef VERIFY_SHADER_BINDINGS void dbgVerifyBindings()const; #endif -#if 0 + IObject& GetOwner(){return m_Owner;} private: void InitVariablesHashMap(); - Sampler &GetAssignedSampler(const SRV_CBV_UAV &TexSrv); - const Char* GetShaderName()const; // There is no need to use shared ptr as referenced resource cache is either part of the @@ -336,66 +280,40 @@ private: ShaderResourceCacheVk *m_pResourceCache; std::unique_ptr > m_ResourceBuffer; - Sampler* m_Samplers = nullptr; - Uint16 m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0}; - Uint16 m_NumSamplers [SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0}; + std::array m_NumResources = {}; - Uint32 GetSrvCbvUavOffset(SHADER_VARIABLE_TYPE VarType, Uint32 r)const + Uint32 GetResourceOffset(SHADER_VARIABLE_TYPE VarType, Uint32 r)const { - VERIFY_EXPR( r < m_NumCbvSrvUav[VarType] ); + 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_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC] : 0; + 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_NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE] : 0; + r += (VarType > SHADER_VARIABLE_TYPE_MUTABLE) ? m_NumResources[SHADER_VARIABLE_TYPE_MUTABLE] : 0; return r; } - SRV_CBV_UAV& GetSrvCbvUav(SHADER_VARIABLE_TYPE VarType, Uint32 r) + VkResource& GetResource(SHADER_VARIABLE_TYPE VarType, Uint32 r) { - VERIFY_EXPR( r < m_NumCbvSrvUav[VarType] ); - auto* CbvSrvUav = reinterpret_cast(m_ResourceBuffer.get()); - return CbvSrvUav[GetSrvCbvUavOffset(VarType,r)]; + VERIFY_EXPR( r < m_NumResources[VarType] ); + auto* Resoruces = reinterpret_cast(m_ResourceBuffer.get()); + return Resoruces[GetResourceOffset(VarType,r)]; } - const SRV_CBV_UAV& GetSrvCbvUav(SHADER_VARIABLE_TYPE VarType, Uint32 r)const + const VkResource& GetResource(SHADER_VARIABLE_TYPE VarType, Uint32 r)const { - VERIFY_EXPR( r < m_NumCbvSrvUav[VarType] ); - auto* CbvSrvUav = reinterpret_cast(m_ResourceBuffer.get()); - return CbvSrvUav[GetSrvCbvUavOffset(VarType,r)]; + VERIFY_EXPR( r < m_NumResources[VarType] ); + auto* Resources = reinterpret_cast(m_ResourceBuffer.get()); + return Resources[GetResourceOffset(VarType,r)]; } - SRV_CBV_UAV& GetSrvCbvUav(Uint32 r) + VkResource& GetResource(Uint32 r) { - VERIFY_EXPR( r < GetTotalSrvCbvUavCount() ); - auto* CbvSrvUav = reinterpret_cast(m_ResourceBuffer.get()); - return CbvSrvUav[r]; + VERIFY_EXPR( r < GetTotalResourceCount() ); + auto* Resources = reinterpret_cast(m_ResourceBuffer.get()); + return Resources[r]; } - Uint32 GetSamplerOffset(SHADER_VARIABLE_TYPE VarType, Uint32 s)const - { - VERIFY_EXPR( s < m_NumSamplers[VarType] ); - static_assert(SHADER_VARIABLE_TYPE_STATIC == 0, "SHADER_VARIABLE_TYPE_STATIC == 0 expected"); - s += (VarType > SHADER_VARIABLE_TYPE_STATIC) ? m_NumSamplers[SHADER_VARIABLE_TYPE_STATIC] : 0; - static_assert(SHADER_VARIABLE_TYPE_MUTABLE == 1, "SHADER_VARIABLE_TYPE_MUTABLE == 1 expected"); - s += (VarType > SHADER_VARIABLE_TYPE_MUTABLE) ? m_NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE] : 0; - return s; - } - Sampler& GetSampler(SHADER_VARIABLE_TYPE VarType, Uint32 s) - { - VERIFY_EXPR( s < m_NumSamplers[VarType] ); - return m_Samplers[GetSamplerOffset(VarType,s)]; - } - const Sampler& GetSampler(SHADER_VARIABLE_TYPE VarType, Uint32 s)const - { - VERIFY_EXPR( s < m_NumSamplers[VarType] ); - return m_Samplers[GetSamplerOffset(VarType,s)]; - } - Uint32 GetTotalSrvCbvUavCount()const + Uint32 GetTotalResourceCount()const { static_assert(SHADER_VARIABLE_TYPE_NUM_TYPES == 3, "Did you add new variable type?"); - return m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_STATIC] + m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_MUTABLE] + m_NumCbvSrvUav[SHADER_VARIABLE_TYPE_DYNAMIC]; - } - Uint32 GetTotalSamplerCount()const - { - static_assert(SHADER_VARIABLE_TYPE_NUM_TYPES == 3, "Did you add new variable type?"); - return m_NumSamplers[SHADER_VARIABLE_TYPE_STATIC] + m_NumSamplers[SHADER_VARIABLE_TYPE_MUTABLE] + m_NumSamplers[SHADER_VARIABLE_TYPE_DYNAMIC]; + return m_NumResources[SHADER_VARIABLE_TYPE_STATIC] + m_NumResources[SHADER_VARIABLE_TYPE_MUTABLE] + m_NumResources[SHADER_VARIABLE_TYPE_DYNAMIC]; } void AllocateMemory(IMemoryAllocator &Allocator); @@ -407,12 +325,13 @@ private: std::unordered_map, std::equal_to, STDAllocatorRawMem > m_VariableHash; #endif - CComPtr m_pVkDevice; + std::shared_ptr m_pLogicalDevice; + IObject &m_Owner; // We must use shared_ptr to reference ShaderResources instance, because // there may be multiple objects referencing the same set of resources - std::shared_ptr m_pResources; -#endif + std::shared_ptr m_pResources; + }; } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp index 2c779141..61cac3db 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp @@ -27,41 +27,42 @@ namespace Diligent { -#if 0 - // http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-cache#Cache-Structure - void ShaderResourceCacheVk::Initialize(IMemoryAllocator &MemAllocator, Uint32 NumTables, Uint32 TableSizes[]) + void ShaderResourceCacheVk::Initialize(IMemoryAllocator &MemAllocator, Uint32 NumSets, Uint32 SetSizes[]) { // Memory layout: - // __________________________________________________________ - // m_pMemory | m_pResources, m_NumResources | - // | | | - // V | V - // | RootTable[0] | .... | RootTable[Nrt-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | - // | A - // | | - // |________________________________________________| - // m_pResources, m_NumResources - // + // ______________________________________________________________ + // m_pMemory | m_pResources, m_NumResources == m | + // | | | + // V | V + // | DescriptorSet[0] | .... | DescriptorSet[Ns-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] | + // | A \ + // | | \ + // |__________________________________________________| \RefCntAutoPtr + // m_pResources, m_NumResources == n \_________ + // | Object | + // --------- + // + // Ns = m_NumSets VERIFY(m_pAllocator == nullptr && m_pMemory == nullptr, "Cache already initialized"); m_pAllocator = &MemAllocator; - m_NumTables = NumTables; + m_NumSets = NumSets; Uint32 TotalResources = 0; - for(Uint32 t=0; t < NumTables; ++t) - TotalResources += TableSizes[t]; - auto MemorySize = NumTables * sizeof(RootTable) + TotalResources * sizeof(Resource); + for(Uint32 t=0; t < NumSets; ++t) + TotalResources += SetSizes[t]; + auto MemorySize = NumSets * sizeof(DescriptorSet) + TotalResources * sizeof(Resource); if(MemorySize > 0) { m_pMemory = ALLOCATE( *m_pAllocator, "Memory for shader resource cache data", MemorySize); - auto *pTables = reinterpret_cast(m_pMemory); - auto *pCurrResPtr = reinterpret_cast(pTables + m_NumTables); + auto *pSets = reinterpret_cast(m_pMemory); + auto *pCurrResPtr = reinterpret_cast(pSets + m_NumSets); for(Uint32 res=0; res < TotalResources; ++res) new(pCurrResPtr + res) Resource(); - for (Uint32 t = 0; t < NumTables; ++t) + for (Uint32 t = 0; t < NumSets; ++t) { - new(&GetRootTable(t)) RootTable(TableSizes[t], TableSizes[t] > 0 ? pCurrResPtr : nullptr); - pCurrResPtr += TableSizes[t]; + new(&GetDescriptorSet(t)) DescriptorSet(SetSizes[t], SetSizes[t] > 0 ? pCurrResPtr : nullptr); + pCurrResPtr += SetSizes[t]; } VERIFY_EXPR((char*)pCurrResPtr == (char*)m_pMemory + MemorySize); } @@ -72,16 +73,15 @@ namespace Diligent if (m_pMemory) { Uint32 TotalResources = 0; - for (Uint32 t = 0; t < m_NumTables; ++t) - TotalResources += GetRootTable(t).GetSize(); - auto *pResources = reinterpret_cast( reinterpret_cast(m_pMemory) + m_NumTables); + for (Uint32 t = 0; t < m_NumSets; ++t) + TotalResources += GetDescriptorSet(t).GetSize(); + auto *pResources = reinterpret_cast( reinterpret_cast(m_pMemory) + m_NumSets); for(Uint32 res=0; res < TotalResources; ++res) pResources[res].~Resource(); - for (Uint32 t = 0; t < m_NumTables; ++t) - GetRootTable(t).~RootTable(); + for (Uint32 t = 0; t < m_NumSets; ++t) + GetDescriptorSet(t).~DescriptorSet(); m_pAllocator->Free(m_pMemory); } } -#endif } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 5493dcad..7787ef38 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -38,71 +38,61 @@ namespace Diligent { ShaderResourceLayoutVk::ShaderResourceLayoutVk(IObject &Owner, - IMemoryAllocator &ResourceLayoutDataAllocator) /*: + IMemoryAllocator &ResourceLayoutDataAllocator) : m_Owner(Owner), #if USE_VARIABLE_HASH_MAP m_VariableHash(STD_ALLOCATOR_RAW_MEM(VariableHashElemType, GetRawAllocator(), "Allocator for unordered_map")), #endif - m_ResourceBuffer(nullptr, STDDeleterRawMem(ResourceLayoutDataAllocator))*/ + m_ResourceBuffer(nullptr, STDDeleterRawMem(ResourceLayoutDataAllocator)) { } ShaderResourceLayoutVk::~ShaderResourceLayoutVk() { -#if 0 - // For some reason MS compiler generates this false warning: - // warning C4189: 'CbvSrvUav': local variable is initialized but not referenced -#pragma warning(push) -#pragma warning(disable : 4189) - auto* CbvSrvUav = reinterpret_cast(m_ResourceBuffer.get()); -#pragma warning(pop) - for(Uint32 r=0; r < GetTotalSrvCbvUavCount(); ++r) - CbvSrvUav[r].~SRV_CBV_UAV(); - - for(Uint32 s=0; s < GetTotalSamplerCount(); ++s) - m_Samplers[s].~Sampler(); -#endif + auto* Resources = reinterpret_cast(m_ResourceBuffer.get()); + for(Uint32 r=0; r < GetTotalResourceCount(); ++r) + Resources[r].~VkResource(); } -#if 0 -Vk_DESCRIPTOR_RANGE_TYPE GetDescriptorRangeType(CachedResourceType ResType) +class ResourceTypeToVkDescriptorType { - static Vk_DESCRIPTOR_RANGE_TYPE RangeTypes[(size_t)CachedResourceType::NumTypes] = {}; - static bool Initialized = false; - if (!Initialized) +public: + ResourceTypeToVkDescriptorType() { - RangeTypes[(size_t)CachedResourceType::CBV] = Vk_DESCRIPTOR_RANGE_TYPE_CBV; - RangeTypes[(size_t)CachedResourceType::TexSRV] = Vk_DESCRIPTOR_RANGE_TYPE_SRV; - RangeTypes[(size_t)CachedResourceType::BufSRV] = Vk_DESCRIPTOR_RANGE_TYPE_SRV; - RangeTypes[(size_t)CachedResourceType::TexUAV] = Vk_DESCRIPTOR_RANGE_TYPE_UAV; - RangeTypes[(size_t)CachedResourceType::BufUAV] = Vk_DESCRIPTOR_RANGE_TYPE_UAV; - RangeTypes[(size_t)CachedResourceType::Sampler] = Vk_DESCRIPTOR_RANGE_TYPE_SAMPLER; - Initialized = true; + m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageImage] = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + m_Map[SPIRVShaderResourceAttribs::ResourceType::SampledImage] = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::AtomicCounter] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateImage] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateSampler] = VK_DESCRIPTOR_TYPE_SAMPLER; } - auto Ind = static_cast(ResType); - VERIFY(Ind >= 0 && Ind < (size_t)CachedResourceType::NumTypes, "Unexpected resource type"); - return RangeTypes[Ind]; -} + + VkDescriptorType operator[](SPIRVShaderResourceAttribs::ResourceType ResType)const + { + return m_Map[static_cast(ResType)]; + } + +private: + std::array m_Map = {}; +}; void ShaderResourceLayoutVk::AllocateMemory(IMemoryAllocator &Allocator) { VERIFY( &m_ResourceBuffer.get_deleter().m_Allocator == &Allocator, "Inconsistent memory allocators" ); - Uint32 TotalSrvCbvUav = GetTotalSrvCbvUavCount(); - Uint32 TotalSamplers = GetTotalSamplerCount(); - size_t MemSize = TotalSrvCbvUav * sizeof(SRV_CBV_UAV) + TotalSamplers * sizeof(Sampler); + Uint32 TotalResource = GetTotalResourceCount(); + size_t MemSize = TotalResource * sizeof(VkResource); if(MemSize == 0) return; auto *pRawMem = ALLOCATE(Allocator, "Raw memory buffer for shader resource layout resources", MemSize); m_ResourceBuffer.reset(pRawMem); - if(TotalSamplers) - m_Samplers = reinterpret_cast(reinterpret_cast(pRawMem) + TotalSrvCbvUav); } +#if 0 // Clones layout from the reference layout maintained by the pipeline state // Root indices and descriptor table offsets must be correct // Resource cache is not initialized. -// http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-layout#Initializing-Resource-Layouts-in-a-Shader-Resource-Binding-Object ShaderResourceLayoutVk::ShaderResourceLayoutVk(IObject &Owner, const ShaderResourceLayoutVk& SrcLayout, IMemoryAllocator &ResourceLayoutDataAllocator, @@ -176,18 +166,17 @@ ShaderResourceLayoutVk::ShaderResourceLayoutVk(IObject &Owner, void ShaderResourceLayoutVk::Initialize(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice, const std::shared_ptr& pSrcResources, IMemoryAllocator &LayoutDataAllocator, - const SHADER_VARIABLE_TYPE *VarTypes, + const SHADER_VARIABLE_TYPE *AllowedVarTypes, Uint32 NumAllowedTypes, ShaderResourceCacheVk *pResourceCache, std::vector *pSPIRV, - class PipelineLayout *pPipelineLayout) + PipelineLayout *pPipelineLayout) { -#if 0 m_pResources = pSrcResources; m_pResourceCache = pResourceCache; - m_pVkDevice = pVkDevice; + m_pLogicalDevice = LogicalDevice.GetSharedPtr(); - VERIFY_EXPR( (pResourceCache != nullptr) ^ (pRootSig != nullptr) ); + VERIFY_EXPR( (pResourceCache != nullptr) ^ (pPipelineLayout != nullptr) ); Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); @@ -195,207 +184,164 @@ void ShaderResourceLayoutVk::Initialize(const VulkanUtilities::VulkanLogicalDevi m_pResources->ProcessResources( AllowedVarTypes, NumAllowedTypes, - [&](const D3DShaderResourceAttribs &CB, Uint32) + [&](const SPIRVShaderResourceAttribs &UB, Uint32) { - VERIFY_EXPR(IsAllowedType(CB.GetVariableType(), AllowedTypeBits)); - ++m_NumCbvSrvUav[CB.GetVariableType()]; + VERIFY_EXPR(IsAllowedType(UB.VarType, AllowedTypeBits)); + ++m_NumResources[UB.VarType]; }, - [&](const D3DShaderResourceAttribs& TexSRV, Uint32) + [&](const SPIRVShaderResourceAttribs& SB, Uint32) { - auto VarType = TexSRV.GetVariableType(); - VERIFY_EXPR(IsAllowedType(VarType, AllowedTypeBits)); - ++m_NumCbvSrvUav[VarType]; - if(TexSRV.IsValidSampler()) - { - auto SamplerId = TexSRV.GetSamplerId(); - const auto &SamplerAttribs = m_pResources->GetSampler(SamplerId); - VERIFY(SamplerAttribs.GetVariableType() == VarType, "Texture and sampler variable types are not conistent"); - if(!SamplerAttribs.IsStaticSampler()) - { - ++m_NumSamplers[VarType]; - } - } + VERIFY_EXPR(IsAllowedType(SB.VarType, AllowedTypeBits)); + ++m_NumResources[SB.VarType]; + }, + [&](const SPIRVShaderResourceAttribs &Img, Uint32) + { + VERIFY_EXPR(IsAllowedType(Img.VarType, AllowedTypeBits)); + ++m_NumResources[Img.VarType]; }, - [&](const D3DShaderResourceAttribs &TexUAV, Uint32) + [&](const SPIRVShaderResourceAttribs &SmplImg, Uint32) { - VERIFY_EXPR(IsAllowedType(TexUAV.GetVariableType(), AllowedTypeBits)); - ++m_NumCbvSrvUav[TexUAV.GetVariableType()]; + VERIFY_EXPR(IsAllowedType(SmplImg.VarType, AllowedTypeBits)); + ++m_NumResources[SmplImg.VarType]; }, - [&](const D3DShaderResourceAttribs &BufSRV, Uint32) + [&](const SPIRVShaderResourceAttribs &AC, Uint32) { - VERIFY_EXPR(IsAllowedType(BufSRV.GetVariableType(), AllowedTypeBits)); - ++m_NumCbvSrvUav[BufSRV.GetVariableType()]; + VERIFY_EXPR(IsAllowedType(AC.VarType, AllowedTypeBits)); + ++m_NumResources[AC.VarType]; }, - [&](const D3DShaderResourceAttribs &BufUAV, Uint32) + [&](const SPIRVShaderResourceAttribs &SepImg, Uint32) { - VERIFY_EXPR(IsAllowedType(BufUAV.GetVariableType(), AllowedTypeBits)); - ++m_NumCbvSrvUav[BufUAV.GetVariableType()]; + VERIFY_EXPR(IsAllowedType(SepImg.VarType, AllowedTypeBits)); + ++m_NumResources[SepImg.VarType]; + }, + [&](const SPIRVShaderResourceAttribs &SepSmpl, Uint32) + { + VERIFY_EXPR(IsAllowedType(SepSmpl.VarType, AllowedTypeBits)); + ++m_NumResources[SepSmpl.VarType]; } ); AllocateMemory(LayoutDataAllocator); - Uint32 CurrCbvSrvUav[SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0}; - Uint32 CurrSampler[SHADER_VARIABLE_TYPE_NUM_TYPES] = {0,0,0}; - Uint32 StaticResCacheTblSizes[4] = {0, 0, 0, 0}; + std::array CurrResInd = {}; + std::array StaticResCacheSetSizes = {}; - auto AddResource = [&](const D3DShaderResourceAttribs &Attribs, CachedResourceType ResType, Uint32 SamplerId = SRV_CBV_UAV::InvalidSamplerId) + auto AddResource = [&](const SPIRVShaderResourceAttribs &Attribs) { - Uint32 RootIndex = SRV_CBV_UAV::InvalidRootIndex; - Uint32 Offset = SRV_CBV_UAV::InvalidOffset; - Vk_DESCRIPTOR_RANGE_TYPE DescriptorRangeType = GetDescriptorRangeType(ResType); - if (pRootSig) + Uint32 Binding = 0; + Uint32 DescriptorSet = 0; + static const ResourceTypeToVkDescriptorType ResTypeToVkDescType; + VkDescriptorType DescriptorType = ResTypeToVkDescType[Attribs.Type]; + if (pPipelineLayout) { - pRootSig->AllocateResourceSlot(m_pResources->GetShaderType(), Attribs, DescriptorRangeType, RootIndex, Offset ); - VERIFY(RootIndex <= SRV_CBV_UAV::MaxRootIndex, "Root index excceeds allowed limit"); + pPipelineLayout->AllocateResourceSlot(Attribs.VarType, m_pResources->GetShaderType(), DescriptorType, Attribs.ArraySize, DescriptorSet, Binding); + VERIFY(DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", DescriptorSet, ") excceeds representable max value"); + VERIFY(Binding <= std::numeric_limits::max(), "Binding (", Binding, ") excceeds representable max value"); } else { - // If root signature is not provided - use artifial root signature to store + // If pipeline layout is not provided - use artifial layout to store // static shader resources: - // SRVs at root index Vk_DESCRIPTOR_RANGE_TYPE_SRV (0) - // UAVs at root index Vk_DESCRIPTOR_RANGE_TYPE_UAV (1) - // CBVs at root index Vk_DESCRIPTOR_RANGE_TYPE_CBV (2) - // Samplers at root index Vk_DESCRIPTOR_RANGE_TYPE_SAMPLER (3) - - // http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-layout#Initializing-Special-Resource-Layout-for-Managing-Static-Shader-Resources - + // Separate samplers at index VK_DESCRIPTOR_TYPE_SAMPLER (0) + // SampledImages at index VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER (1) + // Separate images at index VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE (2) + // Storage images at index VK_DESCRIPTOR_TYPE_STORAGE_IMAGE (3) + // Index VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER (4) is unused + // Index VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER (5) is unused + // Uniform buffers at index VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER (6) + // Storage buffers at index VK_DESCRIPTOR_TYPE_STORAGE_BUFFER (7) + // Index VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC (8) is unused + // Index VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC (9) is unused VERIFY_EXPR(m_pResourceCache != nullptr); - RootIndex = DescriptorRangeType; - Offset = Attribs.BindPoint; - // Resources in the static resource cache are indexed by the bind point - StaticResCacheTblSizes[RootIndex] = std::max(StaticResCacheTblSizes[RootIndex], Offset + Attribs.BindCount); + DescriptorSet = DescriptorType; + Binding = StaticResCacheSetSizes[DescriptorSet]; + StaticResCacheSetSizes[DescriptorSet] += Attribs.ArraySize; } - VERIFY(RootIndex != SRV_CBV_UAV::InvalidRootIndex, "Root index must be valid"); - VERIFY(Offset != SRV_CBV_UAV::InvalidOffset, "Offset must be valid"); // Static samplers are never copied, and SamplerId == InvalidSamplerId - ::new (&GetSrvCbvUav(Attribs.GetVariableType(), CurrCbvSrvUav[Attribs.GetVariableType()]++)) SRV_CBV_UAV( *this, Attribs, ResType, RootIndex, Offset, SamplerId); + ::new (&GetResource(Attribs.VarType, CurrResInd[Attribs.VarType]++)) VkResource( *this, Attribs, Binding, DescriptorSet ); }; - - m_pResources->ProcessResources( AllowedVarTypes, NumAllowedTypes, - [&](const D3DShaderResourceAttribs &CB, Uint32) + [&](const SPIRVShaderResourceAttribs &UB, Uint32) { - VERIFY_EXPR( IsAllowedType(CB.GetVariableType(), AllowedTypeBits) ); - AddResource(CB, CachedResourceType::CBV); + VERIFY_EXPR(IsAllowedType(UB.VarType, AllowedTypeBits)); + AddResource(UB); }, - [&](const D3DShaderResourceAttribs& TexSRV, Uint32) + [&](const SPIRVShaderResourceAttribs& SB, Uint32) { - auto VarType = TexSRV.GetVariableType(); - VERIFY_EXPR(IsAllowedType(VarType, AllowedTypeBits) ); - - Uint32 SamplerId = SRV_CBV_UAV::InvalidSamplerId; - if(TexSRV.IsValidSampler()) - { - const auto &SrcSamplerAttribs = m_pResources->GetSampler(TexSRV.GetSamplerId()); - VERIFY(SrcSamplerAttribs.GetVariableType() == VarType, "Inconsistent texture and sampler variable types" ); - - if (SrcSamplerAttribs.IsStaticSampler()) - { - if(pRootSig != nullptr) - pRootSig->InitStaticSampler(m_pResources->GetShaderType(), TexSRV.Name, SrcSamplerAttribs); - - // Static samplers are never copied, and SamplerId == InvalidSamplerId - } - else - { - Uint32 SamplerRootIndex = Sampler::InvalidRootIndex; - Uint32 SamplerOffset = Sampler::InvalidOffset; - if (pRootSig) - { - pRootSig->AllocateResourceSlot(m_pResources->GetShaderType(), SrcSamplerAttribs, Vk_DESCRIPTOR_RANGE_TYPE_SAMPLER, SamplerRootIndex, SamplerOffset ); - } - else - { - // If root signature is not provided, we are initializing resource cache to store - // static shader resources. - VERIFY_EXPR(m_pResourceCache != nullptr); - - // We use the following artifial root signature: - // SRVs at root index Vk_DESCRIPTOR_RANGE_TYPE_SRV (0) - // UAVs at root index Vk_DESCRIPTOR_RANGE_TYPE_UAV (1) - // CBVs at root index Vk_DESCRIPTOR_RANGE_TYPE_CBV (2) - // Samplers at root index Vk_DESCRIPTOR_RANGE_TYPE_SAMPLER (3) - // Every resource is stored at offset that equals its bind point - SamplerRootIndex = Vk_DESCRIPTOR_RANGE_TYPE_SAMPLER; - SamplerOffset = SrcSamplerAttribs.BindPoint; - // Resources in the static resource cache are indexed by the bind point - StaticResCacheTblSizes[SamplerRootIndex] = std::max(StaticResCacheTblSizes[SamplerRootIndex], SamplerOffset + SrcSamplerAttribs.BindCount); - } - VERIFY(SamplerRootIndex != Sampler::InvalidRootIndex, "Sampler root index must be valid"); - VERIFY(SamplerOffset != Sampler::InvalidOffset, "Sampler offset must be valid"); - - SamplerId = CurrSampler[VarType]; - VERIFY(SamplerId <= SRV_CBV_UAV::MaxSamplerId, "Sampler index excceeds allowed limit"); - ::new (&GetSampler(VarType, CurrSampler[VarType]++)) Sampler( *this, SrcSamplerAttribs, SamplerRootIndex, SamplerOffset ); - } - } - AddResource(TexSRV, CachedResourceType::TexSRV, SamplerId); + VERIFY_EXPR(IsAllowedType(SB.VarType, AllowedTypeBits)); + AddResource(SB); + }, + [&](const SPIRVShaderResourceAttribs &Img, Uint32) + { + VERIFY_EXPR(IsAllowedType(Img.VarType, AllowedTypeBits)); + AddResource(Img); }, - [&](const D3DShaderResourceAttribs &TexUAV, Uint32) + [&](const SPIRVShaderResourceAttribs &SmplImg, Uint32) { - VERIFY_EXPR( IsAllowedType(TexUAV.GetVariableType(), AllowedTypeBits) ); - AddResource(TexUAV, CachedResourceType::TexUAV); + VERIFY_EXPR(IsAllowedType(SmplImg.VarType, AllowedTypeBits)); + AddResource(SmplImg); }, - [&](const D3DShaderResourceAttribs &BufSRV, Uint32) + [&](const SPIRVShaderResourceAttribs &AC, Uint32) { - VERIFY_EXPR( IsAllowedType(BufSRV.GetVariableType(), AllowedTypeBits) ); - AddResource(BufSRV, CachedResourceType::BufSRV); + VERIFY_EXPR(IsAllowedType(AC.VarType, AllowedTypeBits)); + AddResource(AC); }, - [&](const D3DShaderResourceAttribs &BufUAV, Uint32) + [&](const SPIRVShaderResourceAttribs &SepImg, Uint32) { - VERIFY_EXPR( IsAllowedType(BufUAV.GetVariableType(), AllowedTypeBits) ); - AddResource(BufUAV, CachedResourceType::BufUAV); + VERIFY_EXPR(IsAllowedType(SepImg.VarType, AllowedTypeBits)); + AddResource(SepImg); + }, + + [&](const SPIRVShaderResourceAttribs &SepSmpl, Uint32) + { + VERIFY_EXPR(IsAllowedType(SepSmpl.VarType, AllowedTypeBits)); + AddResource(SepSmpl); } ); #ifdef _DEBUG for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType+1)) { - VERIFY( CurrCbvSrvUav[VarType] == m_NumCbvSrvUav[VarType], "Not all Srv/Cbv/Uavs are initialized, which result in a crash when dtor is called" ); - VERIFY( CurrSampler[VarType] == m_NumSamplers[VarType], "Not all Samplers are initialized, which result in a crash when dtor is called" ); + VERIFY( CurrResInd[VarType] == m_NumResources[VarType], "Not all resources are initialized, which result in a crash when dtor is called" ); } #endif if(m_pResourceCache) { // Initialize resource cache to store static resources - // http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-cache#Initializing-the-Cache-for-Static-Shader-Resources - // http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-cache#Initializing-Shader-Objects - VERIFY_EXPR(pRootSig == nullptr); - m_pResourceCache->Initialize(GetRawAllocator(), _countof(StaticResCacheTblSizes), StaticResCacheTblSizes); + VERIFY_EXPR(pPipelineLayout == nullptr && pSPIRV == nullptr); + m_pResourceCache->Initialize(GetRawAllocator(), static_cast(StaticResCacheSetSizes.size()), StaticResCacheSetSizes.data()); #ifdef _DEBUG - m_pResourceCache->GetRootTable(Vk_DESCRIPTOR_RANGE_TYPE_SRV).SetDebugAttribs(StaticResCacheTblSizes[Vk_DESCRIPTOR_RANGE_TYPE_SRV], Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); - m_pResourceCache->GetRootTable(Vk_DESCRIPTOR_RANGE_TYPE_UAV).SetDebugAttribs(StaticResCacheTblSizes[Vk_DESCRIPTOR_RANGE_TYPE_UAV], Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); - m_pResourceCache->GetRootTable(Vk_DESCRIPTOR_RANGE_TYPE_CBV).SetDebugAttribs(StaticResCacheTblSizes[Vk_DESCRIPTOR_RANGE_TYPE_CBV], Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_pResources->GetShaderType()); - m_pResourceCache->GetRootTable(Vk_DESCRIPTOR_RANGE_TYPE_SAMPLER).SetDebugAttribs(StaticResCacheTblSizes[Vk_DESCRIPTOR_RANGE_TYPE_SAMPLER], Vk_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + for(VkDescriptorType DescriptorType = VK_DESCRIPTOR_TYPE_SAMPLER; DescriptorType <= VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC; DescriptorType = static_cast(DescriptorType+1)) + { + m_pResourceCache->GetDescriptorSet(DescriptorType).SetDebugAttribs(StaticResCacheSetSizes[DescriptorType]); + } #endif } InitVariablesHashMap(); -#endif } -#if 0 void ShaderResourceLayoutVk::InitVariablesHashMap() { #if USE_VARIABLE_HASH_MAP - Uint32 TotalResources = GetTotalSrvCbvUavCount(); + Uint32 TotalResources = GetTotalResourceCount(); for(Uint32 r=0; r < TotalResources; ++r) { - auto &Res = GetSrvCbvUav(r); + auto &Res = GetResource(r); /* HashMapStringKey will make a copy of the string*/ m_VariableHash.insert( std::make_pair( Diligent::HashMapStringKey(Res.Name), &Res ) ); } #endif } +#if 0 #define LOG_RESOURCE_BINDING_ERROR(ResType, pResource, VarName, ShaderName, ...)\ { \ @@ -628,10 +574,11 @@ ShaderResourceLayoutVk::Sampler &ShaderResourceLayoutVk::GetAssignedSampler(cons VERIFY(SamInfo.Attribs.Name == TexSrv.Attribs.Name + D3DSamplerSuffix, "Sampler name \"", SamInfo.Attribs.Name, "\" does not match texture name \"", TexSrv.Attribs.Name, '\"'); return SamInfo; } +#endif - -void ShaderResourceLayoutVk::SRV_CBV_UAV::BindResource(IDeviceObject *pObj, Uint32 ArrayIndex, const ShaderResourceLayoutVk *dbgResLayout) +void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint32 ArrayIndex, const ShaderResourceLayoutVk *dbgResLayout) { +#if 0 auto *pResourceCache = m_ParentResLayout.m_pResourceCache; VERIFY(pResourceCache, "Resource cache is null"); VERIFY(dbgResLayout == nullptr || pResourceCache == dbgResLayout->m_pResourceCache, "Invalid resource cache"); @@ -721,24 +668,26 @@ void ShaderResourceLayoutVk::SRV_CBV_UAV::BindResource(IDeviceObject *pObj, Uint Sam.CacheSampler(nullptr, SamplerArrInd, NullHandle); } } +#endif } -bool ShaderResourceLayoutVk::SRV_CBV_UAV::IsBound(Uint32 ArrayIndex) +bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex) { - auto *pResourceCache = m_ParentResLayout.m_pResourceCache; + auto *pResourceCache = ParentResLayout.m_pResourceCache; VERIFY(pResourceCache, "Resource cache is null"); - VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize); - auto RootIndex = GetRootIndex(); - if( RootIndex < pResourceCache->GetNumRootTables() ) + if( DescriptorSet < pResourceCache->GetNumDescriptorSets() ) { - auto &RootTable = pResourceCache->GetRootTable(RootIndex); - if(OffsetFromTableStart + ArrayIndex < RootTable.GetSize()) + auto &RootTable = pResourceCache->GetDescriptorSet(DescriptorSet); + if(Binding + ArrayIndex < RootTable.GetSize()) { - auto &CachedRes = RootTable.GetResource(OffsetFromTableStart + ArrayIndex, Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, m_ParentResLayout.m_pResources->GetShaderType()); + auto &CachedRes = RootTable.GetResource(Binding + ArrayIndex); if( CachedRes.pObject != nullptr ) { +#if 0 VERIFY(CachedRes.CPUDescriptorHandle.ptr != 0 || CachedRes.pObject.RawPtr()->GetDesc().Usage == USAGE_DYNAMIC, "No relevant descriptor handle"); +#endif return true; } } @@ -747,11 +696,10 @@ bool ShaderResourceLayoutVk::SRV_CBV_UAV::IsBound(Uint32 ArrayIndex) return false; } -#endif + void ShaderResourceLayoutVk::BindResources( IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheVk *dbgResourceCache ) { -#if 0 VERIFY(dbgResourceCache == m_pResourceCache, "Resource cache does not match the cache provided at initialization"); if( !pResourceMapping ) @@ -760,11 +708,11 @@ void ShaderResourceLayoutVk::BindResources( IResourceMapping* pResourceMapping, return; } - Uint32 TotalResources = GetTotalSrvCbvUavCount(); + Uint32 TotalResources = GetTotalResourceCount(); for(Uint32 r=0; r < TotalResources; ++r) { - auto &Res = GetSrvCbvUav(r); - for(Uint32 ArrInd = 0; ArrInd < Res.Attribs.BindCount; ++ArrInd) + auto &Res = GetResource(r); + for(Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd) { if( Flags & BIND_SHADER_RESOURCES_RESET_BINDINGS ) Res.BindResource(nullptr, ArrInd, this); @@ -772,7 +720,7 @@ void ShaderResourceLayoutVk::BindResources( IResourceMapping* pResourceMapping, if( (Flags & BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED) && Res.IsBound(ArrInd) ) return; - const auto& VarName = Res.Attribs.Name; + const auto& VarName = Res.SpirvAttribs.Name; RefCntAutoPtr pObj; VERIFY_EXPR(pResourceMapping != nullptr); pResourceMapping->GetResource( VarName.c_str(), &pObj, ArrInd ); @@ -784,16 +732,14 @@ void ShaderResourceLayoutVk::BindResources( IResourceMapping* pResourceMapping, else { if( (Flags & BIND_SHADER_RESOURCES_ALL_RESOLVED) && !Res.IsBound(ArrInd) ) - LOG_ERROR_MESSAGE( "Cannot bind resource to shader variable \"", Res.Attribs.GetPrintName(ArrInd), "\": resource view not found in the resource mapping" ); + LOG_ERROR_MESSAGE( "Cannot bind resource to shader variable \"", Res.SpirvAttribs.GetPrintName(ArrInd), "\": resource view not found in the resource mapping" ); } } } -#endif } IShaderVariable* ShaderResourceLayoutVk::GetShaderVariable(const Char* Name) { -#if 0 IShaderVariable* pVar = nullptr; #if USE_VARIABLE_HASH_MAP // Name will be implicitly converted to HashMapStringKey without making a copy @@ -801,11 +747,11 @@ IShaderVariable* ShaderResourceLayoutVk::GetShaderVariable(const Char* Name) if( it != m_VariableHash.end() ) pVar = it->second; #else - Uint32 TotalResources = GetTotalSrvCbvUavCount(); + Uint32 TotalResources = GetTotalResourceCount(); for(Uint32 r=0; r < TotalResources; ++r) { - auto &Res = GetSrvCbvUav(r); - if(Res.Attribs.Name.compare(Name) == 0) + auto &Res = GetResource(r); + if(Res.SpirvAttribs.Name.compare(Name) == 0) { pVar = &Res; break; @@ -818,8 +764,6 @@ IShaderVariable* ShaderResourceLayoutVk::GetShaderVariable(const Char* Name) LOG_ERROR_MESSAGE( "Shader variable \"", Name, "\" is not found in shader \"", GetShaderName(), "\" (", GetShaderTypeLiteralName(m_pResources->GetShaderType()), "). Attempts to set the variable will be silently ignored." ); } return pVar; -#endif - return nullptr; } @@ -1067,8 +1011,6 @@ void ShaderResourceLayoutVk::dbgVerifyBindings()const } #endif -#if 0 - const Char* ShaderResourceLayoutVk::GetShaderName()const { RefCntAutoPtr pShader(&m_Owner, IID_Shader); @@ -1100,6 +1042,5 @@ const Char* ShaderResourceLayoutVk::GetShaderName()const } return ""; } -#endif } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp index 100e859d..41adb8f8 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp @@ -39,7 +39,7 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters *pRefCounters, RenderDeviceVkImpl TShaderBase(pRefCounters, pRenderDeviceVk, CreationAttribs.Desc), m_StaticResLayout(*this, GetRawAllocator()), m_DummyShaderVar(*this), - m_ConstResCache(/*ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources*/) + m_ConstResCache(ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources) { auto GLSLSource = BuildGLSLSourceString(CreationAttribs, TargetGLSLCompiler::glslang); m_SPIRV = GLSLtoSPIRV(m_Desc.ShaderType, GLSLSource.c_str()); -- cgit v1.2.3