summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-05-26 18:28:15 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-05-26 18:28:15 +0000
commit4ebef0135340b21bcdacf9b59a67995ee6a07ec7 (patch)
tree6611a1a4f678213d586959e718edfad6f4b953e0 /Graphics/GraphicsEngineVulkan
parentImplemented dynamic descriptor resource descriptors update (diff)
downloadDiligentCore-4ebef0135340b21bcdacf9b59a67995ee6a07ec7.tar.gz
DiligentCore-4ebef0135340b21bcdacf9b59a67995ee6a07ec7.zip
Reworked Vulkan shader resource layout: separated variables from layout resources
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/CMakeLists.txt2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h24
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h24
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h21
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h156
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h150
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h9
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp78
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp77
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp244
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp176
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp19
12 files changed, 540 insertions, 440 deletions
diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
index b4a317df..fff5b003 100644
--- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt
+++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INCLUDE
include/ShaderResourceBindingVkImpl.h
include/ShaderResourceCacheVk.h
include/ShaderResourceLayoutVk.h
+ include/ShaderVariableVk.h
include/SwapChainVkImpl.h
include/TextureVkImpl.h
include/TextureViewVkImpl.h
@@ -79,6 +80,7 @@ set(SRC
src/ShaderResourceBindingVkImpl.cpp
src/ShaderResourceCacheVk.cpp
src/ShaderResourceLayoutVk.cpp
+ src/ShaderVariableVk.cpp
src/SwapChainVkImpl.cpp
src/TextureVkImpl.cpp
src/TextureViewVkImpl.cpp
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h
index 3b7166e2..b857054c 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h
@@ -71,18 +71,17 @@ public:
const PipelineLayout& GetPipelineLayout()const{return m_PipelineLayout;}
- const ShaderResourceLayoutVk& GetShaderResLayout(SHADER_TYPE ShaderType)const
+ const ShaderResourceLayoutVk& GetShaderResLayout(Uint32 ShaderInd)const
{
- auto ShaderInd = GetShaderTypeIndex(ShaderType);
- VERIFY_EXPR(m_pShaderResourceLayouts[ShaderInd] != nullptr);
- return *m_pShaderResourceLayouts[ShaderInd];
+ VERIFY_EXPR(ShaderInd < m_NumShaders);
+ return m_ShaderResourceLayouts[ShaderInd];
}
IMemoryAllocator& GetResourceCacheDataAllocator(){return m_ResourceCacheDataAllocator;}
- IMemoryAllocator& GetShaderResourceLayoutDataAllocator(Uint32 ActiveShaderInd)
+ IMemoryAllocator& GetShaderVariableDataAllocator(Uint32 ActiveShaderInd)
{
VERIFY_EXPR(ActiveShaderInd < m_NumShaders);
- auto *pAllocator = m_ResLayoutDataAllocators.GetAllocator(ActiveShaderInd);
+ auto *pAllocator = m_VariableDataAllocators.GetAllocator(ActiveShaderInd);
return pAllocator != nullptr ? *pAllocator : GetRawAllocator();
}
@@ -92,16 +91,16 @@ private:
void CreateRenderPass(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice);
- void ParseResourceLayoutAndCreateShader(IShader *pShader);
+ void ParseResourceLayoutAndCreateShader(IShader *pShader, Uint32 LayoutInd);
DummyShaderVariable m_DummyVar;
// Looks like there may be a bug in msvc: when allocators are declared as
// an array and if an exception is thrown from constructor, the app crashes
- class ResLayoutDataAllocators
+ class VariableDataAllocators
{
public:
- ~ResLayoutDataAllocators()
+ ~VariableDataAllocators()
{
for(size_t i=0; i < _countof(m_pAllocators); ++i)
if(m_pAllocators[i] != nullptr)
@@ -111,7 +110,7 @@ private:
{
VERIFY_EXPR(NumActiveShaders <= _countof(m_pAllocators) );
for(Uint32 i=0; i < NumActiveShaders; ++i)
- m_pAllocators[i] = NEW_POOL_OBJECT(AdaptiveFixedBlockAllocator, "Shader resource layout data allocator", GetRawAllocator(), SRBAllocationGranularity);
+ m_pAllocators[i] = NEW_POOL_OBJECT(AdaptiveFixedBlockAllocator, "Shader variable data allocator", GetRawAllocator(), SRBAllocationGranularity);
}
AdaptiveFixedBlockAllocator *GetAllocator(Uint32 ActiveShaderInd)
{
@@ -120,9 +119,10 @@ private:
}
private:
AdaptiveFixedBlockAllocator *m_pAllocators[5] = {};
- }m_ResLayoutDataAllocators; // Allocators must be defined before default SRB
+ }m_VariableDataAllocators; // Allocators must be defined before default SRB
+
+ ShaderResourceLayoutVk* m_ShaderResourceLayouts = nullptr;
- std::array<ShaderResourceLayoutVk*, 6> m_pShaderResourceLayouts = {};
AdaptiveFixedBlockAllocator m_ResourceCacheDataAllocator; // Use separate allocator for every shader stage
std::array<VulkanUtilities::ShaderModuleWrapper, 6> m_ShaderModules;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h
index 5dd36dcc..079fdee0 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h
@@ -31,7 +31,7 @@
#include "ShaderResourceBindingBase.h"
#include "ShaderBase.h"
#include "ShaderResourceCacheVk.h"
-#include "ShaderResourceLayoutVk.h"
+#include "ShaderVariableVk.h"
namespace Diligent
{
@@ -51,32 +51,16 @@ public:
virtual IShaderVariable *GetVariable(SHADER_TYPE ShaderType, const char *Name)override;
- ShaderResourceLayoutVk& GetResourceLayout(SHADER_TYPE ResType)
- {
- auto ShaderInd = GetShaderTypeIndex(ResType);
- auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd];
- VERIFY(ResLayoutInd >= 0, "Shader resource layout is not initialized");
- VERIFY_EXPR(ResLayoutInd < (Int32)m_NumShaders);
- return m_pResourceLayouts[ResLayoutInd];
- }
ShaderResourceCacheVk& GetResourceCache(){return m_ShaderResourceCache;}
-#ifdef VERIFY_SHADER_BINDINGS
- void dbgVerifyResourceBindings(const PipelineStateVkImpl *pPSO);
-#endif
-
bool StaticResourcesInitialized()const{return m_bStaticResourcesInitialized;}
- void InitializeStaticResources(const PipelineStateVkImpl *pPSO);
-
- // Updates dynamic resource descriptors in the descriptor set, for every layout.
- // The set is assigned to the resource cache by PipelineLayout::AllocateDynamicDescriptorSet().
- void CommitDynamicResources();
+ void SetStaticResourcesInitialized(){m_bStaticResourcesInitialized = true;}
private:
ShaderResourceCacheVk m_ShaderResourceCache;
- ShaderResourceLayoutVk* m_pResourceLayouts = nullptr;
- // Resource layout index in m_ResourceLayouts[] array for every shader stage
+ 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;
Uint32 m_NumShaders = 0;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h
index b4fe5972..c5f22aee 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h
@@ -88,6 +88,11 @@ public:
struct Resource
{
+ Resource(const Resource&) = delete;
+ Resource(Resource&&) = delete;
+ Resource& operator = (const Resource&) = delete;
+ Resource& operator = (Resource&&) = delete;
+
const SPIRVShaderResourceAttribs::ResourceType Type;
RefCntAutoPtr<IDeviceObject> pObject;
void* vkDescriptor = nullptr;
@@ -106,10 +111,15 @@ public:
m_pResources(pResources)
{}
- inline Resource& GetResource(Uint32 OffsetFromTableStart)
+ inline Resource& GetResource(Uint32 CacheOffset)
+ {
+ VERIFY(CacheOffset < m_NumResources, "Offset ", CacheOffset, " is out of range" );
+ return m_pResources[CacheOffset];
+ }
+ inline const Resource& GetResource(Uint32 CacheOffset)const
{
- VERIFY(OffsetFromTableStart < m_NumResources, "Root table at index is not large enough to store descriptor at offset ", OffsetFromTableStart );
- return m_pResources[OffsetFromTableStart];
+ VERIFY(CacheOffset < m_NumResources, "Offset ", CacheOffset, " is out of range" );
+ return m_pResources[CacheOffset];
}
inline Uint32 GetSize()const{return m_NumResources; }
@@ -137,6 +147,11 @@ public:
VERIFY_EXPR(Index < m_NumSets);
return reinterpret_cast<DescriptorSet*>(m_pMemory)[Index];
}
+ inline const DescriptorSet& GetDescriptorSet(Uint32 Index)const
+ {
+ VERIFY_EXPR(Index < m_NumSets);
+ return reinterpret_cast<const DescriptorSet*>(m_pMemory)[Index];
+ }
inline Uint32 GetNumDescriptorSets()const{return m_NumSets; }
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h
index 5cb2de31..389246af 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h
@@ -90,12 +90,6 @@
#include <array>
#include <memory>
-#include <unordered_map>
-
-// 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 "ShaderBase.h"
#include "HashUtils.h"
@@ -111,20 +105,13 @@ namespace Diligent
{
/// Diligent::ShaderResourceLayoutVk class
-// sizeof(ShaderResourceLayoutVk)==72 (MS compiler, x64)
+// sizeof(ShaderResourceLayoutVk)==56 (MS compiler, x64)
class ShaderResourceLayoutVk
{
public:
- ShaderResourceLayoutVk(IObject &Owner, IMemoryAllocator &ResourceLayoutDataAllocator);
-
- // This constructor is used by ShaderResourceBindingVkImpl to clone layout from the reference layout in PipelineStateVkImpl.
- // Descriptor sets and bindings must be correct. Resource cache is assigned, but not initialized.
- ShaderResourceLayoutVk(IObject &Owner,
- const ShaderResourceLayoutVk& SrcLayout,
- IMemoryAllocator &ResourceLayoutDataAllocator,
- const SHADER_VARIABLE_TYPE *AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheVk &ResourceCache);
+ ShaderResourceLayoutVk(IObject& Owner,
+ const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
+ IMemoryAllocator& ResourceLayoutDataAllocator);
ShaderResourceLayoutVk (const ShaderResourceLayoutVk&) = delete;
ShaderResourceLayoutVk (ShaderResourceLayoutVk&&) = delete;
@@ -139,17 +126,16 @@ public:
// - PipelineStateVkImpl class instance to reference all types of resources (static, mutable, dynamic).
// Root indices and descriptor table offsets are assigned during the initialization;
// no shader resource cache is provided
- void Initialize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
- const std::shared_ptr<const SPIRVShaderResources>& pSrcResources,
+ void Initialize(const std::shared_ptr<const SPIRVShaderResources>& pSrcResources,
IMemoryAllocator& LayoutDataAllocator,
const SHADER_VARIABLE_TYPE* AllowedVarTypes,
Uint32 NumAllowedTypes,
- ShaderResourceCacheVk* pResourceCache,
+ ShaderResourceCacheVk* pStaticResourceCache,
std::vector<uint32_t>* pSPIRV,
class PipelineLayout* pPipelineLayout);
- // sizeof(VkResource) == 32 (x64)
- struct VkResource : IShaderVariable
+ // sizeof(VkResource) == 24 (x64)
+ struct VkResource
{
VkResource(const VkResource&) = delete;
VkResource(VkResource&&) = delete;
@@ -160,9 +146,9 @@ public:
const Uint16 DescriptorSet;
const Uint32 CacheOffset; // Offset from the beginning of the cached descriptor set
const SPIRVShaderResourceAttribs &SpirvAttribs;
- ShaderResourceLayoutVk &ParentResLayout;
+ const ShaderResourceLayoutVk &ParentResLayout;
- VkResource(ShaderResourceLayoutVk& _ParentLayout,
+ VkResource(const ShaderResourceLayoutVk& _ParentLayout,
const SPIRVShaderResourceAttribs& _SpirvAttribs,
uint32_t _Binding,
uint32_t _DescriptorSet,
@@ -187,47 +173,13 @@ public:
{
}
- 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
- {
- return ParentResLayout.GetOwner().Release();
- }
-
- void QueryInterface(const INTERFACE_ID &IID, IObject **ppInterface)override final
- {
- if (ppInterface == nullptr)
- return;
-
- *ppInterface = nullptr;
- if (IID == IID_ShaderVariable || IID == IID_Unknown)
- {
- *ppInterface = this;
- (*ppInterface)->AddRef();
- }
- }
-
- bool IsBound(Uint32 ArrayIndex);
- // Non-virtual function
- void BindResource(IDeviceObject *pObject, Uint32 ArrayIndex, const ShaderResourceLayoutVk *dbgResLayout);
- virtual void Set(IDeviceObject *pObject)override final{ BindResource(pObject, 0, nullptr); }
+ // Checks if a resource is bound in ResourceCache at the given ArrayIndex
+ bool IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache)const;
+
+ // Binds a resource pObject in the ResourceCache
+ void BindResource(IDeviceObject *pObject, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache)const;
- virtual void SetArray(IDeviceObject* const* ppObjects, Uint32 FirstElement, Uint32 NumElements)override final
- {
- for(Uint32 Elem = 0; Elem < NumElements; ++Elem)
- BindResource(ppObjects[Elem], FirstElement+Elem, nullptr);
- }
-
- // Updates dynamic resource descriptors in the descriptor set. The set is assigned
- // to the resource cache by PipelineLayout::AllocateDynamicDescriptorSet().
+ // Updates resource descriptor in the descriptor set
inline void UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
uint32_t ArrayElement,
const VkDescriptorImageInfo* pImageInfo,
@@ -238,57 +190,62 @@ public:
void CacheBuffer(IDeviceObject* pBuffer,
ShaderResourceCacheVk::Resource& DstRes,
VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd);
+ Uint32 ArrayInd)const;
void CacheTexelBuffer(IDeviceObject* pBufferView,
ShaderResourceCacheVk::Resource& DstRes,
VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd);
+ Uint32 ArrayInd)const;
void CacheImage(IDeviceObject* pTexView,
ShaderResourceCacheVk::Resource& DstRes,
VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd);
+ Uint32 ArrayInd)const;
void CacheSeparateSampler(IDeviceObject* pSampler,
ShaderResourceCacheVk::Resource& DstRes,
VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd);
+ Uint32 ArrayInd)const;
bool UpdateCachedResource(ShaderResourceCacheVk::Resource& DstRes,
Uint32 ArrayInd,
IDeviceObject* pObject,
INTERFACE_ID InterfaceId,
- const char* ResourceName);
+ const char* ResourceName)const;
};
- void InitializeStaticResources(const ShaderResourceLayoutVk &SrcLayout);
-
- // 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 );
- VkResource* GetShaderVariable( const Char* Name );
+ // Copies static resources from SrcResourceCache defined by SrcLayout
+ // to DstResourceCache defined by this layout
+ void InitializeStaticResources(const ShaderResourceLayoutVk& SrcLayout,
+ ShaderResourceCacheVk& SrcResourceCache,
+ ShaderResourceCacheVk& DstResourceCache)const;
#ifdef VERIFY_SHADER_BINDINGS
- void dbgVerifyBindings()const;
+ void dbgVerifyBindings(const ShaderResourceCacheVk& ResourceCache)const;
#endif
- IObject& GetOwner(){return m_Owner;}
-
Uint32 GetResourceCount(SHADER_VARIABLE_TYPE VarType)const
{
return m_NumResources[VarType];
}
- void InitializeResourcesInCache();
+ // Initializes resource slots in the ResourceCache
+ void InitializeResourceMemoryInCache(ShaderResourceCacheVk& ResourceCache)const;
- void CommitDynamicResources();
-
-private:
- void InitVariablesHashMap();
+ // Updates dynamic resource descriptors in the ResourceCache. The descriptor set is assigned
+ // to the resource cache by PipelineLayout::AllocateDynamicDescriptorSet().
+ void CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache)const;
const Char* GetShaderName()const;
+ const VkResource& GetResource(SHADER_VARIABLE_TYPE VarType, Uint32 r)const
+ {
+ VERIFY_EXPR( r < m_NumResources[VarType] );
+ auto* Resources = reinterpret_cast<const VkResource*>(m_ResourceBuffer.get());
+ return Resources[GetResourceOffset(VarType,r)];
+ }
+
+private:
Uint32 GetResourceOffset(SHADER_VARIABLE_TYPE VarType, Uint32 r)const
{
VERIFY_EXPR( r < m_NumResources[VarType] );
@@ -304,16 +261,11 @@ private:
auto* Resources = reinterpret_cast<VkResource*>(m_ResourceBuffer.get());
return Resources[GetResourceOffset(VarType,r)];
}
- const VkResource& GetResource(SHADER_VARIABLE_TYPE VarType, Uint32 r)const
+
+ const VkResource& GetResource(Uint32 r)const
{
- VERIFY_EXPR( r < m_NumResources[VarType] );
+ VERIFY_EXPR(r < GetTotalResourceCount());
auto* Resources = reinterpret_cast<const VkResource*>(m_ResourceBuffer.get());
- return Resources[GetResourceOffset(VarType,r)];
- }
- VkResource& GetResource(Uint32 r)
- {
- VERIFY_EXPR( r < GetTotalResourceCount() );
- auto* Resources = reinterpret_cast<VkResource*>(m_ResourceBuffer.get());
return Resources[r];
}
@@ -325,28 +277,16 @@ private:
void AllocateMemory(IMemoryAllocator &Allocator);
-
- // There is no need to use shared ptr as referenced resource cache is either part of the
- // parent ShaderVkImpl object or ShaderResourceBindingVkImpl object
- ShaderResourceCacheVk *m_pResourceCache = nullptr;
-
- std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer;
- std::array<Uint16, SHADER_VARIABLE_TYPE_NUM_TYPES> m_NumResources = {};
-
-#if USE_VARIABLE_HASH_MAP
- // Hash map to look up shader variables by name.
- // Note that sizeof(m_VariableHash)==128 (release mode, MS compiler, x64).
- typedef std::pair<HashMapStringKey, IShaderVariable*> VariableHashElemType;
- std::unordered_map<HashMapStringKey, IShaderVariable*, std::hash<HashMapStringKey>, std::equal_to<HashMapStringKey>, STDAllocatorRawMem<VariableHashElemType> > m_VariableHash;
-#endif
- std::shared_ptr<const VulkanUtilities::VulkanLogicalDevice> m_pLogicalDevice;
+ IObject& m_Owner;
+ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice;
+ std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer;
- 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<const SPIRVShaderResources> m_pResources;
+ std::shared_ptr<const SPIRVShaderResources> m_pResources;
+ std::array<Uint16, SHADER_VARIABLE_TYPE_NUM_TYPES> m_NumResources = {};
};
}
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h
new file mode 100644
index 00000000..13fef274
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.h
@@ -0,0 +1,150 @@
+/* Copyright 2015-2018 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include <memory>
+#include <unordered_map>
+
+// 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 "ShaderResourceLayoutVk.h"
+
+namespace Diligent
+{
+
+class ShaderVariableVkImpl;
+
+class ShaderVariableManagerVk
+{
+public:
+ ShaderVariableManagerVk(IObject &Owner) :
+ m_Owner(Owner)
+ {}
+ ~ShaderVariableManagerVk();
+
+ void Initialize(const ShaderResourceLayoutVk& Layout,
+ IMemoryAllocator& Allocator,
+ const SHADER_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ ShaderResourceCacheVk& ResourceCache);
+ void Destroy(IMemoryAllocator& Allocator);
+
+ ShaderVariableVkImpl* GetVariable(const Char* Name);
+
+ void BindResources( IResourceMapping* pResourceMapping, Uint32 Flags);
+
+private:
+ friend ShaderVariableVkImpl;
+
+#if USE_VARIABLE_HASH_MAP
+ void InitVariablesHashMap();
+
+ // Hash map to look up shader variables by name.
+ // Note that sizeof(m_VariableHash)==128 (release mode, MS compiler, x64).
+ typedef std::pair<HashMapStringKey, IShaderVariable*> VariableHashElemType;
+ std::unordered_map<HashMapStringKey, IShaderVariable*, std::hash<HashMapStringKey>, std::equal_to<HashMapStringKey>, STDAllocatorRawMem<VariableHashElemType> > m_VariableHash;
+#endif
+
+ IObject& m_Owner;
+ const ShaderResourceLayoutVk* m_pResourceLayout= nullptr;
+ ShaderResourceCacheVk* m_pResourceCache = nullptr;
+ ShaderVariableVkImpl* m_pVariables = nullptr;
+ Uint32 m_NumVariables = 0;
+#ifdef _DEBUG
+ IMemoryAllocator* m_pDbgAllocator = nullptr;
+#endif
+};
+
+// sizeof(ShaderVariableVkImpl) == 24 (x64)
+class ShaderVariableVkImpl : public IShaderVariable
+{
+public:
+ ShaderVariableVkImpl(ShaderVariableManagerVk& ParentManager,
+ const ShaderResourceLayoutVk::VkResource& Resource) :
+ m_ParentManager(ParentManager),
+ m_Resource(Resource)
+ {}
+
+ ShaderVariableVkImpl(const ShaderVariableVkImpl&) = delete;
+ ShaderVariableVkImpl(ShaderVariableVkImpl&&) = delete;
+ ShaderVariableVkImpl& operator= (const ShaderVariableVkImpl&) = delete;
+ ShaderVariableVkImpl& operator= (ShaderVariableVkImpl&&) = delete;
+
+
+ virtual IReferenceCounters* GetReferenceCounters()const override final
+ {
+ return m_ParentManager.m_Owner.GetReferenceCounters();
+ }
+
+ virtual Atomics::Long AddRef()override final
+ {
+ return m_ParentManager.m_Owner.AddRef();
+ }
+
+ virtual Atomics::Long Release()override final
+ {
+ return m_ParentManager.m_Owner.Release();
+ }
+
+ void QueryInterface(const INTERFACE_ID &IID, IObject **ppInterface)override final
+ {
+ if (ppInterface == nullptr)
+ return;
+
+ *ppInterface = nullptr;
+ if (IID == IID_ShaderVariable || IID == IID_Unknown)
+ {
+ *ppInterface = this;
+ (*ppInterface)->AddRef();
+ }
+ }
+
+ virtual void Set(IDeviceObject *pObject)override final
+ {
+ VERIFY_EXPR(m_ParentManager.m_pResourceCache != nullptr);
+ m_Resource.BindResource(pObject, 0, *m_ParentManager.m_pResourceCache);
+ }
+
+ 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);
+ }
+
+ const ShaderResourceLayoutVk::VkResource& GetResource()const
+ {
+ return m_Resource;
+ }
+
+private:
+ friend ShaderVariableManagerVk;
+
+ ShaderVariableManagerVk& m_ParentManager;
+ const ShaderResourceLayoutVk::VkResource& m_Resource;
+};
+
+}
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h b/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h
index d7852c37..e70adf59 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderVkImpl.h
@@ -31,6 +31,7 @@
#include "ShaderBase.h"
#include "ShaderResourceLayoutVk.h"
#include "SPIRVShaderResources.h"
+#include "ShaderVariableVk.h"
#ifdef _DEBUG
# define VERIFY_SHADER_BINDINGS
@@ -63,8 +64,9 @@ public:
}
const std::shared_ptr<const SPIRVShaderResources>& GetShaderResources()const{return m_pShaderResources;}
- const ShaderResourceLayoutVk& GetConstResLayout()const{return m_StaticResLayout;}
-
+ const ShaderResourceLayoutVk& GetStaticResLayout()const{return m_StaticResLayout;}
+ ShaderResourceCacheVk& GetStaticResCache(){return m_StaticResCache;}
+
#ifdef VERIFY_SHADER_BINDINGS
void DbgVerifyStaticResourceBindings();
#endif
@@ -77,7 +79,8 @@ private:
// it is referenced by ShaderResourceLayoutVk class instances
std::shared_ptr<const SPIRVShaderResources> m_pShaderResources;
ShaderResourceLayoutVk m_StaticResLayout;
- ShaderResourceCacheVk m_ConstResCache;
+ ShaderResourceCacheVk m_StaticResCache;
+ ShaderVariableManagerVk m_StaticVarsMgr;
std::vector<uint32_t> m_SPIRV;
};
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index f9075de9..ad625d0b 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -36,24 +36,17 @@
namespace Diligent
{
-void PipelineStateVkImpl::ParseResourceLayoutAndCreateShader(IShader *pShader)
+void PipelineStateVkImpl::ParseResourceLayoutAndCreateShader(IShader *pShader, Uint32 LayoutInd)
{
VERIFY_EXPR(pShader);
- auto ShaderType = pShader->GetDesc().ShaderType;
- auto ShaderInd = GetShaderTypeIndex(ShaderType);
auto *pShaderVk = ValidatedCast<ShaderVkImpl>(pShader);
- VERIFY(m_pShaderResourceLayouts[ShaderInd] == nullptr, "Shader resource layout has already been initialized");
-
auto pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(pShaderVk->GetDevice());
const auto &LogicalDevice = pDeviceVkImpl->GetLogicalDevice();
- auto &ShaderResLayoutAllocator = GetRawAllocator();
-
- auto *pRawMem = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", sizeof(ShaderResourceLayoutVk));
- m_pShaderResourceLayouts[ShaderInd] = new (pRawMem) ShaderResourceLayoutVk(*this, GetRawAllocator());
+
std::vector<uint32_t> SPIRV = pShaderVk->GetSPIRV();
- m_pShaderResourceLayouts[ShaderInd]->Initialize(LogicalDevice, pShaderVk->GetShaderResources(), GetRawAllocator(), nullptr, 0, nullptr, &SPIRV, &m_PipelineLayout);
+ m_ShaderResourceLayouts[LayoutInd].Initialize(pShaderVk->GetShaderResources(), GetRawAllocator(), nullptr, 0, nullptr, &SPIRV, &m_PipelineLayout);
VkShaderModuleCreateInfo ShaderModuleCI = {};
ShaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
@@ -61,7 +54,7 @@ void PipelineStateVkImpl::ParseResourceLayoutAndCreateShader(IShader *pShader)
ShaderModuleCI.flags = 0;
ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t);
ShaderModuleCI.pCode = SPIRV.data();
- m_ShaderModules[ShaderInd] = LogicalDevice.CreateShaderModule(ShaderModuleCI, m_Desc.Name);
+ m_ShaderModules[LayoutInd] = LogicalDevice.CreateShaderModule(ShaderModuleCI, m_Desc.Name);
}
@@ -160,6 +153,12 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters *pRefCounters, Ren
m_pDefaultShaderResBinding(nullptr, STDDeleter<ShaderResourceBindingVkImpl, FixedBlockMemoryAllocator>(pDeviceVk->GetSRBAllocator()) )
{
const auto &LogicalDevice = pDeviceVk->GetLogicalDevice();
+ auto &ShaderResLayoutAllocator = GetRawAllocator();
+ auto *pRawMem = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", sizeof(ShaderResourceLayoutVk) * m_NumShaders);
+ m_ShaderResourceLayouts = reinterpret_cast<ShaderResourceLayoutVk*>(pRawMem);
+ for(Uint32 s=0; s < m_NumShaders; ++s)
+ new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk(*this, LogicalDevice, GetRawAllocator());
+
if (PipelineDesc.IsComputePipeline)
{
auto &ComputePipeline = PipelineDesc.ComputePipeline;
@@ -182,7 +181,7 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters *pRefCounters, Ren
CSStage.flags = 0; // reserved for future use
CSStage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
- ParseResourceLayoutAndCreateShader(ComputePipeline.pCS);
+ ParseResourceLayoutAndCreateShader(ComputePipeline.pCS, 0);
CSStage.module = m_ShaderModules[CSInd];
m_PipelineLayout.Finalize(LogicalDevice);
@@ -233,7 +232,7 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters *pRefCounters, Ren
default: UNEXPECTED("Unknown shader type");
}
- ParseResourceLayoutAndCreateShader(pShader);
+ ParseResourceLayoutAndCreateShader(pShader, s);
StageCI.module = m_ShaderModules[GetShaderTypeIndex(ShaderType)];
StageCI.pName = "main"; // entry point
@@ -371,18 +370,16 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters *pRefCounters, Ren
}
if(PipelineDesc.SRBAllocationGranularity > 1)
- m_ResLayoutDataAllocators.Init(m_NumShaders, PipelineDesc.SRBAllocationGranularity);
+ m_VariableDataAllocators.Init(m_NumShaders, PipelineDesc.SRBAllocationGranularity);
bool HasStaticResources = false;
bool HasNonStaticResources = false;
- for (auto *pLayout : m_pShaderResourceLayouts)
+ for (Uint32 s=0; s < m_NumShaders; ++s)
{
- if (pLayout != nullptr)
- {
- HasStaticResources = pLayout->GetResourceCount(SHADER_VARIABLE_TYPE_STATIC) != 0;
- HasNonStaticResources = pLayout->GetResourceCount(SHADER_VARIABLE_TYPE_MUTABLE) != 0 ||
- pLayout->GetResourceCount(SHADER_VARIABLE_TYPE_DYNAMIC) != 0;
- }
+ const auto &Layout = m_ShaderResourceLayouts[s];
+ HasStaticResources = Layout.GetResourceCount(SHADER_VARIABLE_TYPE_STATIC) != 0;
+ HasNonStaticResources = Layout.GetResourceCount(SHADER_VARIABLE_TYPE_MUTABLE) != 0 ||
+ Layout.GetResourceCount(SHADER_VARIABLE_TYPE_DYNAMIC) != 0;
}
// If there are only static resources, create default shader resource binding
@@ -412,15 +409,12 @@ PipelineStateVkImpl::~PipelineStateVkImpl()
}
}
- auto &ShaderResLayoutAllocator = GetRawAllocator();
- for (auto *pLayout : m_pShaderResourceLayouts)
+ for (Uint32 s=0; s < m_NumShaders; ++s)
{
- if (pLayout != nullptr)
- {
- pLayout->~ShaderResourceLayoutVk();
- ShaderResLayoutAllocator.Free(pLayout);
- }
+ m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk();
}
+ auto &ShaderResLayoutAllocator = GetRawAllocator();
+ ShaderResLayoutAllocator.Free(m_ShaderResourceLayouts);
}
IMPLEMENT_QUERY_INTERFACE( PipelineStateVkImpl, IID_PipelineStateVk, TPipelineStateBase )
@@ -525,15 +519,30 @@ ShaderResourceCacheVk* PipelineStateVkImpl::CommitAndTransitionShaderResources(I
}
#endif
+ auto &ResourceCache = pResBindingVkImpl->GetResourceCache();
+
// First time only, copy static shader resources to the cache
if(!pResBindingVkImpl->StaticResourcesInitialized())
- pResBindingVkImpl->InitializeStaticResources(this);
-
+ {
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ auto *pShaderVk = ValidatedCast<ShaderVkImpl>( m_ppShaders[s] );
#ifdef VERIFY_SHADER_BINDINGS
- pResBindingVkImpl->dbgVerifyResourceBindings(this);
+ pShaderVk->DbgVerifyStaticResourceBindings();
#endif
+ auto &StaticResLayout = pShaderVk->GetStaticResLayout();
+ auto &StaticResCache = pShaderVk->GetStaticResCache();
+ m_ShaderResourceLayouts[s].InitializeStaticResources(StaticResLayout, StaticResCache, ResourceCache);
+ }
+ pResBindingVkImpl->SetStaticResourcesInitialized();
+ }
- auto &ResourceCache = pResBindingVkImpl->GetResourceCache();
+#ifdef VERIFY_SHADER_BINDINGS
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ m_ShaderResourceLayouts[s].dbgVerifyBindings(ResourceCache);
+ }
+#endif
if(CommitResources)
{
@@ -550,7 +559,10 @@ ShaderResourceCacheVk* PipelineStateVkImpl::CommitAndTransitionShaderResources(I
// Allocate vulkan descriptor set for dynamic resources
m_PipelineLayout.AllocateDynamicDescriptorSet(pDeviceVkImpl, pCtxVkImpl, ResourceCache);
// Commit all dynamic resource descriptors
- pResBindingVkImpl->CommitDynamicResources();
+ for(Uint32 s=0; s < m_NumShaders; ++s)
+ {
+ m_ShaderResourceLayouts[s].CommitDynamicResources(ResourceCache);
+ }
// Bind descriptor sets
m_PipelineLayout.BindDescriptorSets(pCtxVkImpl, m_Desc.IsComputePipeline, ResourceCache);
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
index b320d5ba..844c830b 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
@@ -21,6 +21,7 @@
* of the possibility of such damages.
*/
+#include <array>
#include "pch.h"
#include "ShaderResourceBindingVkImpl.h"
#include "PipelineStateVkImpl.h"
@@ -39,11 +40,11 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl( IReferenceCounters *pR
auto *pRenderDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(pPSO->GetDevice());
// This only allocate memory and initialize descriptor sets in the resource cache
- // Resources will be initialized by InitializeResourcesInCache()
+ // Resources will be initialized by InitializeResourceMemoryInCache()
pPSO->GetPipelineLayout().InitResourceCache(pRenderDeviceVkImpl, m_ShaderResourceCache, pPSO->GetResourceCacheDataAllocator());
- auto *pResLayoutRawMem = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutVk", m_NumShaders * sizeof(ShaderResourceLayoutVk));
- m_pResourceLayouts = reinterpret_cast<ShaderResourceLayoutVk*>(pResLayoutRawMem);
+ 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)
{
@@ -51,11 +52,13 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl( IReferenceCounters *pR
auto ShaderType = pShader->GetDesc().ShaderType;
auto ShaderInd = GetShaderTypeIndex(ShaderType);
- auto &ShaderResLayoutDataAllocator = pPSO->GetShaderResourceLayoutDataAllocator(s);
+ auto &VarDataAllocator = pPSO->GetShaderVariableDataAllocator(s);
- const auto &SrcLayout = pPSO->GetShaderResLayout(ShaderType);
- new (m_pResourceLayouts + s) ShaderResourceLayoutVk(*this, SrcLayout, ShaderResLayoutDataAllocator, nullptr, 0, m_ShaderResourceCache);
- m_pResourceLayouts[s].InitializeResourcesInCache();
+ const auto &SrcLayout = pPSO->GetShaderResLayout(s);
+ new (m_pShaderVarMgrs + s) ShaderVariableManagerVk(*this);
+ 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);
+ SrcLayout.InitializeResourceMemoryInCache(m_ShaderResourceCache);
m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
}
@@ -63,10 +66,15 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl( IReferenceCounters *pR
ShaderResourceBindingVkImpl::~ShaderResourceBindingVkImpl()
{
- for(Uint32 l = 0; l < m_NumShaders; ++l)
- m_pResourceLayouts[l].~ShaderResourceLayoutVk();
+ PipelineStateVkImpl* pPSO = ValidatedCast<PipelineStateVkImpl>(m_pPSO);
+ for(Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ auto &VarDataAllocator = pPSO->GetShaderVariableDataAllocator(s);
+ m_pShaderVarMgrs[s].Destroy(VarDataAllocator);
+ m_pShaderVarMgrs[s].~ShaderVariableManagerVk();
+ }
- GetRawAllocator().Free(m_pResourceLayouts);
+ GetRawAllocator().Free(m_pShaderVarMgrs);
}
IMPLEMENT_QUERY_INTERFACE( ShaderResourceBindingVkImpl, IID_ShaderResourceBindingVk, TBase )
@@ -80,7 +88,7 @@ void ShaderResourceBindingVkImpl::BindResources(Uint32 ShaderFlags, IResourceMap
auto ResLayoutInd = m_ResourceLayoutIndex[ShaderInd];
if(ResLayoutInd >= 0)
{
- m_pResourceLayouts[ResLayoutInd].BindResources(pResMapping, Flags, &m_ShaderResourceCache);
+ m_pShaderVarMgrs[ResLayoutInd].BindResources(pResMapping, Flags);
}
}
}
@@ -95,8 +103,8 @@ IShaderVariable *ShaderResourceBindingVkImpl::GetVariable(SHADER_TYPE ShaderType
LOG_ERROR_MESSAGE("Failed to find shader variable \"", Name,"\" in shader resource binding: shader type ", GetShaderTypeLiteralName(ShaderType), " is not initialized");
return ValidatedCast<PipelineStateVkImpl>(GetPipelineState())->GetDummyShaderVar();
}
- auto *pVar = m_pResourceLayouts[ResLayoutInd].GetShaderVariable(Name);
- if(pVar->SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_STATIC)
+ auto *pVar = m_pShaderVarMgrs[ResLayoutInd].GetVariable(Name);
+ if(pVar->GetResource().SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_STATIC)
{
LOG_ERROR_MESSAGE("Static shader variable \"", Name, "\" must not be accessed through shader resource binding object. Static variable should be set through shader objects.");
pVar = nullptr;
@@ -108,47 +116,4 @@ IShaderVariable *ShaderResourceBindingVkImpl::GetVariable(SHADER_TYPE ShaderType
return pVar;
}
-#ifdef VERIFY_SHADER_BINDINGS
-void ShaderResourceBindingVkImpl::dbgVerifyResourceBindings(const PipelineStateVkImpl *pPSO)
-{
- auto *pRefPSO = GetPipelineState();
- if (pPSO->IsIncompatibleWith(pRefPSO))
- {
- LOG_ERROR("Shader resource binding is incompatible with the pipeline state \"", pPSO->GetDesc().Name, '\"');
- return;
- }
- for(Uint32 l = 0; l < m_NumShaders; ++l)
- m_pResourceLayouts[l].dbgVerifyBindings();
-}
-#endif
-
-void ShaderResourceBindingVkImpl::InitializeStaticResources(const PipelineStateVkImpl *pPSO)
-{
- VERIFY(!StaticResourcesInitialized(), "Static resources have already been initialized");
- VERIFY(pPSO == GetPipelineState(), "Invalid pipeline state provided");
-
- auto NumShaders = pPSO->GetNumShaders();
- auto ppShaders = pPSO->GetShaders();
- // Copy static resources
- for (Uint32 s = 0; s < NumShaders; ++s)
- {
- auto *pShader = ValidatedCast<ShaderVkImpl>( ppShaders[s] );
-#ifdef VERIFY_SHADER_BINDINGS
- pShader->DbgVerifyStaticResourceBindings();
-#endif
- auto &ConstResLayout = pShader->GetConstResLayout();
- GetResourceLayout(pShader->GetDesc().ShaderType).InitializeStaticResources(ConstResLayout);
- }
-
- m_bStaticResourcesInitialized = true;
-}
-
-void ShaderResourceBindingVkImpl::CommitDynamicResources()
-{
- for (Uint32 s=0; s < m_NumShaders; ++s)
- {
- m_pResourceLayouts[s].CommitDynamicResources();
- }
-}
-
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index 1b273233..0885f6a8 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -37,9 +37,11 @@
namespace Diligent
{
-ShaderResourceLayoutVk::ShaderResourceLayoutVk(IObject &Owner,
- IMemoryAllocator &ResourceLayoutDataAllocator) :
+ShaderResourceLayoutVk::ShaderResourceLayoutVk(IObject& Owner,
+ const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
+ IMemoryAllocator& ResourceLayoutDataAllocator) :
m_Owner(Owner),
+ m_LogicalDevice(LogicalDevice),
#if USE_VARIABLE_HASH_MAP
m_VariableHash(STD_ALLOCATOR_RAW_MEM(VariableHashElemType, GetRawAllocator(), "Allocator for unordered_map<HashMapStringKey, IShaderVariable*>")),
#endif
@@ -66,67 +68,17 @@ void ShaderResourceLayoutVk::AllocateMemory(IMemoryAllocator &Allocator)
m_ResourceBuffer.reset(pRawMem);
}
-// Clones layout from the reference layout maintained by the pipeline state
-// Descriptor sets and bindings must be correct
-// Resource cache is not initialized.
-ShaderResourceLayoutVk::ShaderResourceLayoutVk(IObject &Owner,
- const ShaderResourceLayoutVk& SrcLayout,
- IMemoryAllocator &ResourceLayoutDataAllocator,
- const SHADER_VARIABLE_TYPE *AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheVk &ResourceCache) :
- ShaderResourceLayoutVk(Owner, ResourceLayoutDataAllocator)
-{
- m_pLogicalDevice = SrcLayout.m_pLogicalDevice;
- m_pResources = SrcLayout.m_pResources;
- m_pResourceCache = &ResourceCache;
-
- 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))
- {
- m_NumResources[VarType] = IsAllowedType(VarType, AllowedTypeBits) ? SrcLayout.m_NumResources[VarType] : 0;
- }
-
- AllocateMemory(ResourceLayoutDataAllocator);
-
- Uint32 CurrResInd[SHADER_VARIABLE_TYPE_NUM_TYPES] = {};
- for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1))
- {
- if( !IsAllowedType(VarType, AllowedTypeBits))
- continue;
-
- Uint32 NumResources = SrcLayout.m_NumResources[VarType];
- VERIFY_EXPR(NumResources == m_NumResources[VarType]);
- for( Uint32 r=0; r < NumResources; ++r )
- {
- const auto &SrcRes = SrcLayout.GetResource(VarType, r);
- ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource( *this, SrcRes );
- }
- }
-
-#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))
- {
- VERIFY_EXPR(CurrResInd[VarType] == m_NumResources[VarType] );
- }
-#endif
-}
-
-
-void ShaderResourceLayoutVk::Initialize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
- const std::shared_ptr<const SPIRVShaderResources>& pSrcResources,
+void ShaderResourceLayoutVk::Initialize(const std::shared_ptr<const SPIRVShaderResources>& pSrcResources,
IMemoryAllocator& LayoutDataAllocator,
const SHADER_VARIABLE_TYPE* AllowedVarTypes,
Uint32 NumAllowedTypes,
- ShaderResourceCacheVk* pResourceCache,
+ ShaderResourceCacheVk* pStaticResourceCache,
std::vector<uint32_t>* pSPIRV,
PipelineLayout* pPipelineLayout)
{
m_pResources = pSrcResources;
- m_pResourceCache = pResourceCache;
- m_pLogicalDevice = LogicalDevice.GetSharedPtr();
- VERIFY_EXPR( (pResourceCache != nullptr) ^ (pPipelineLayout != nullptr && pSPIRV != nullptr) );
+ VERIFY_EXPR( (pStaticResourceCache != nullptr) ^ (pPipelineLayout != nullptr && pSPIRV != nullptr) );
Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
@@ -206,7 +158,7 @@ void ShaderResourceLayoutVk::Initialize(const VulkanUtilities::VulkanLogicalDevi
// Atomic counters at index SPIRVShaderResourceAttribs::ResourceType::AtomicCounter (6)
// Separate images at index SPIRVShaderResourceAttribs::ResourceType::SeparateImage (7)
// Separate samplers at index SPIRVShaderResourceAttribs::ResourceType::SeparateSampler (8)
- VERIFY_EXPR(m_pResourceCache != nullptr);
+ VERIFY_EXPR(pStaticResourceCache != nullptr);
DescriptorSet = Attribs.Type;
CacheOffset = StaticResCacheSetSizes[DescriptorSet];
@@ -266,37 +218,23 @@ void ShaderResourceLayoutVk::Initialize(const VulkanUtilities::VulkanLogicalDevi
}
#endif
- if(m_pResourceCache)
+ if(pStaticResourceCache)
{
// Initialize resource cache to store static resources
VERIFY_EXPR(pPipelineLayout == nullptr && pSPIRV == nullptr);
- m_pResourceCache->InitializeSets(GetRawAllocator(), static_cast<Uint32>(StaticResCacheSetSizes.size()), StaticResCacheSetSizes.data());
- InitializeResourcesInCache();
+ pStaticResourceCache->InitializeSets(GetRawAllocator(), static_cast<Uint32>(StaticResCacheSetSizes.size()), StaticResCacheSetSizes.data());
+ InitializeResourceMemoryInCache(*pStaticResourceCache);
#ifdef _DEBUG
for(SPIRVShaderResourceAttribs::ResourceType ResType = SPIRVShaderResourceAttribs::ResourceType::UniformBuffer;
ResType < SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes;
ResType = static_cast<SPIRVShaderResourceAttribs::ResourceType>(ResType +1))
{
- VERIFY_EXPR(m_pResourceCache->GetDescriptorSet(ResType).GetSize() == StaticResCacheSetSizes[ResType]);
+ VERIFY_EXPR(pStaticResourceCache->GetDescriptorSet(ResType).GetSize() == StaticResCacheSetSizes[ResType]);
}
#endif
}
-
- InitVariablesHashMap();
}
-void ShaderResourceLayoutVk::InitVariablesHashMap()
-{
-#if USE_VARIABLE_HASH_MAP
- Uint32 TotalResources = GetTotalResourceCount();
- for(Uint32 r=0; r < TotalResources; ++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
-}
#define LOG_RESOURCE_BINDING_ERROR(ResType, pResource, VarName, ShaderName, ...)\
{ \
@@ -325,14 +263,14 @@ void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet
WriteDescrSet.pBufferInfo = pBufferInfo;
WriteDescrSet.pTexelBufferView = pTexelBufferView;
- ParentResLayout.m_pLogicalDevice->UpdateDescriptorSets(1, &WriteDescrSet, 0, nullptr);
+ ParentResLayout.m_LogicalDevice.UpdateDescriptorSets(1, &WriteDescrSet, 0, nullptr);
}
bool ShaderResourceLayoutVk::VkResource::UpdateCachedResource(ShaderResourceCacheVk::Resource& DstRes,
Uint32 ArrayInd,
IDeviceObject* pObject,
INTERFACE_ID InterfaceId,
- const char* ResourceName)
+ const char* ResourceName)const
{
// We cannot use ValidatedCast<> here as the resource retrieved from the
// resource mapping can be of wrong type
@@ -365,7 +303,7 @@ bool ShaderResourceLayoutVk::VkResource::UpdateCachedResource(ShaderResourceCach
void ShaderResourceLayoutVk::VkResource::CacheBuffer(IDeviceObject* pBuffer,
ShaderResourceCacheVk::Resource& DstRes,
VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd)
+ Uint32 ArrayInd)const
{
VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer ||
SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageBuffer,
@@ -399,7 +337,7 @@ void ShaderResourceLayoutVk::VkResource::CacheBuffer(IDeviceObject*
void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* pBufferView,
ShaderResourceCacheVk::Resource& DstRes,
VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd)
+ Uint32 ArrayInd)const
{
VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer ||
SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer,
@@ -438,7 +376,7 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject* pTexView,
ShaderResourceCacheVk::Resource& DstRes,
VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd)
+ Uint32 ArrayInd)const
{
VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ||
SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage ||
@@ -485,7 +423,7 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject* pSampler,
ShaderResourceCacheVk::Resource& DstRes,
VkDescriptorSet vkDescrSet,
- Uint32 ArrayInd)
+ Uint32 ArrayInd)const
{
VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected");
@@ -502,17 +440,14 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject*
}
-void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint32 ArrayIndex, const ShaderResourceLayoutVk *dbgResLayout)
+void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache)const
{
- auto *pResourceCache = ParentResLayout.m_pResourceCache;
- VERIFY(pResourceCache, "Resource cache is null");
- VERIFY(dbgResLayout == nullptr || pResourceCache == dbgResLayout->m_pResourceCache, "Invalid resource cache");
VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize);
- auto &DstDescrSet = pResourceCache->GetDescriptorSet(DescriptorSet);
+ auto &DstDescrSet = ResourceCache.GetDescriptorSet(DescriptorSet);
auto vkDescrSet = DstDescrSet.GetVkDescriptorSet();
#ifdef _DEBUG
- if (pResourceCache->DbgGetContentType() == ShaderResourceCacheVk::DbgCacheContentType::SRBResources)
+ if (ResourceCache.DbgGetContentType() == ShaderResourceCacheVk::DbgCacheContentType::SRBResources)
{
if(SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_STATIC || SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_MUTABLE)
{
@@ -520,7 +455,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint3
// Dynamic variables do not have vulkan descriptor set only until they are assigned one the first time
}
}
- else if (pResourceCache->DbgGetContentType() == ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources)
+ else if (ResourceCache.DbgGetContentType() == ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources)
{
VERIFY(vkDescrSet == VK_NULL_HANDLE, "Static shader resource cache should not have vulkan descriptor set allocation");
}
@@ -573,15 +508,13 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint3
}
}
-bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex)
+bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache)const
{
- auto *pResourceCache = ParentResLayout.m_pResourceCache;
- VERIFY(pResourceCache, "Resource cache is null");
VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize);
- if( DescriptorSet < pResourceCache->GetNumDescriptorSets() )
+ if( DescriptorSet < ResourceCache.GetNumDescriptorSets() )
{
- auto &Set = pResourceCache->GetDescriptorSet(DescriptorSet);
+ auto &Set = ResourceCache.GetDescriptorSet(DescriptorSet);
if(CacheOffset + ArrayIndex < Set.GetSize())
{
auto &CachedRes = Set.GetResource(CacheOffset + ArrayIndex);
@@ -593,90 +526,10 @@ bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex)
}
-
-void ShaderResourceLayoutVk::BindResources( IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheVk *dbgResourceCache )
+void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayoutVk& SrcLayout,
+ ShaderResourceCacheVk& SrcResourceCache,
+ ShaderResourceCacheVk& DstResourceCache)const
{
- VERIFY(dbgResourceCache == m_pResourceCache, "Resource cache does not match the cache provided at initialization");
-
- if( !pResourceMapping )
- {
- LOG_ERROR_MESSAGE( "Failed to bind resources in shader \"", GetShaderName(), "\": resource mapping is null" );
- return;
- }
-
- Uint32 TotalResources = GetTotalResourceCount();
- for(Uint32 r=0; r < TotalResources; ++r)
- {
- 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);
-
- if( (Flags & BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED) && Res.IsBound(ArrInd) )
- return;
-
- const auto* VarName = Res.SpirvAttribs.Name;
- RefCntAutoPtr<IDeviceObject> pObj;
- VERIFY_EXPR(pResourceMapping != nullptr);
- pResourceMapping->GetResource( VarName, &pObj, ArrInd );
- if( pObj )
- {
- // Call non-virtual function
- Res.BindResource(pObj, ArrInd, this);
- }
- else
- {
- if( (Flags & BIND_SHADER_RESOURCES_ALL_RESOLVED) && !Res.IsBound(ArrInd) )
- LOG_ERROR_MESSAGE( "Cannot bind resource to shader variable \"", Res.SpirvAttribs.GetPrintName(ArrInd), "\": resource view not found in the resource mapping" );
- }
- }
- }
-}
-
-ShaderResourceLayoutVk::VkResource* ShaderResourceLayoutVk::GetShaderVariable(const Char* Name)
-{
- ShaderResourceLayoutVk::VkResource* pVar = nullptr;
-#if USE_VARIABLE_HASH_MAP
- // Name will be implicitly converted to HashMapStringKey without making a copy
- auto it = m_VariableHash.find( Name );
- if( it != m_VariableHash.end() )
- pVar = it->second;
-#else
- Uint32 TotalResources = GetTotalResourceCount();
- for(Uint32 r=0; r < TotalResources; ++r)
- {
- auto &Res = GetResource(r);
- if(strcmp(Res.SpirvAttribs.Name, Name) == 0)
- {
- pVar = &Res;
- break;
- }
- }
-#endif
-
- if(pVar == nullptr)
- {
- 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;
-}
-
-
-void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayoutVk &SrcLayout)
-{
- if (!m_pResourceCache)
- {
- LOG_ERROR("Resource layout has no resource cache");
- return;
- }
-
- if (!SrcLayout.m_pResourceCache)
- {
- LOG_ERROR("Src layout has no resource cache");
- return;
- }
-
auto NumStaticResources = m_NumResources[SHADER_VARIABLE_TYPE_STATIC];
VERIFY(NumStaticResources == SrcLayout.m_NumResources[SHADER_VARIABLE_TYPE_STATIC], "Inconsistent number of static resources");
VERIFY(SrcLayout.m_pResources->GetShaderType() == m_pResources->GetShaderType(), "Incosistent shader types");
@@ -707,16 +560,16 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou
for(Uint32 ArrInd = 0; ArrInd < DstRes.SpirvAttribs.ArraySize; ++ArrInd)
{
auto SrcOffset = SrcRes.CacheOffset + ArrInd;
- IDeviceObject *pObject = SrcLayout.m_pResourceCache->GetDescriptorSet(SrcRes.DescriptorSet).GetResource(SrcOffset).pObject;
+ IDeviceObject* pObject = SrcResourceCache.GetDescriptorSet(SrcRes.DescriptorSet).GetResource(SrcOffset).pObject;
if (!pObject)
LOG_ERROR_MESSAGE("No resource assigned to static shader variable \"", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\".");
auto DstOffset = DstRes.CacheOffset + ArrInd;
- IDeviceObject *pCachedResource = m_pResourceCache->GetDescriptorSet(DstRes.DescriptorSet).GetResource(DstOffset).pObject;
+ IDeviceObject* pCachedResource = DstResourceCache.GetDescriptorSet(DstRes.DescriptorSet).GetResource(DstOffset).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.SetArray(&pObject, ArrInd, 1);
+ DstRes.BindResource(pObject, ArrInd, DstResourceCache);
}
}
}
@@ -724,10 +577,8 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou
#ifdef VERIFY_SHADER_BINDINGS
-void ShaderResourceLayoutVk::dbgVerifyBindings()const
+void ShaderResourceLayoutVk::dbgVerifyBindings(const ShaderResourceCacheVk& ResourceCache)const
{
- VERIFY(m_pResourceCache, "Resource cache is null");
-
for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1))
{
for(Uint32 r=0; r < m_NumResources[VarType]; ++r)
@@ -736,7 +587,7 @@ void ShaderResourceLayoutVk::dbgVerifyBindings()const
VERIFY(Res.SpirvAttribs.VarType == VarType, "Unexpected variable type");
for(Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd)
{
- auto &CachedDescrSet = m_pResourceCache->GetDescriptorSet(Res.DescriptorSet);
+ 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 &&
@@ -746,7 +597,7 @@ void ShaderResourceLayoutVk::dbgVerifyBindings()const
}
#ifdef _DEBUG
auto vkDescSet = CachedDescrSet.GetVkDescriptorSet();
- auto dbgCacheContentType = m_pResourceCache->DbgGetContentType();
+ auto dbgCacheContentType = ResourceCache.DbgGetContentType();
if(dbgCacheContentType == ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources)
VERIFY(vkDescSet == VK_NULL_HANDLE, "Static resource cache should never have vulkan descriptor set");
else if (dbgCacheContentType == ShaderResourceCacheVk::DbgCacheContentType::SRBResources)
@@ -776,11 +627,10 @@ const Char* ShaderResourceLayoutVk::GetShaderName()const
}
else
{
- RefCntAutoPtr<IShaderResourceBinding> pSRB(&m_Owner, IID_ShaderResourceBinding);
- if(pSRB)
+ RefCntAutoPtr<IPipelineState> pPSO(&m_Owner, IID_PipelineState);
+ if(pPSO)
{
- auto *pPSO = pSRB->GetPipelineState();
- auto *pPSOVk = ValidatedCast<PipelineStateVkImpl>(pPSO);
+ auto *pPSOVk = pPSO.RawPtr<PipelineStateVkImpl>();
auto *ppShaders = pPSOVk->GetShaders();
auto NumShaders = pPSOVk->GetNumShaders();
for (Uint32 s = 0; s < NumShaders; ++s)
@@ -793,25 +643,23 @@ const Char* ShaderResourceLayoutVk::GetShaderName()const
}
else
{
- UNEXPECTED("Owner is expected to be a shader or a shader resource binding");
+ UNEXPECTED("Shader resource layout owner must be a shader or a pipeline state");
}
}
return "";
}
-void ShaderResourceLayoutVk::InitializeResourcesInCache()
+void ShaderResourceLayoutVk::InitializeResourceMemoryInCache(ShaderResourceCacheVk& ResourceCache)const
{
- VERIFY_EXPR(m_pResourceCache);
for(Uint32 r = 0; r < GetTotalResourceCount(); ++r)
{
const auto& Res = GetResource(r);
- m_pResourceCache->InitializeResources(Res.DescriptorSet, Res.CacheOffset, Res.SpirvAttribs.ArraySize, Res.SpirvAttribs.Type);
+ ResourceCache.InitializeResources(Res.DescriptorSet, Res.CacheOffset, Res.SpirvAttribs.ArraySize, Res.SpirvAttribs.Type);
}
}
-void ShaderResourceLayoutVk::CommitDynamicResources()
+void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache)const
{
- VERIFY_EXPR(m_pResourceCache);
Uint32 NumDynamicResources = m_NumResources[SHADER_VARIABLE_TYPE_DYNAMIC];
if(NumDynamicResources == 0)
return;
@@ -836,7 +684,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources()
{
const auto& Res = GetResource(SHADER_VARIABLE_TYPE_DYNAMIC, r);
VERIFY_EXPR(Res.SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_DYNAMIC);
- auto& SetResources = m_pResourceCache->GetDescriptorSet(Res.DescriptorSet);
+ auto& SetResources = ResourceCache.GetDescriptorSet(Res.DescriptorSet);
auto vkSet = SetResources.GetVkDescriptorSet();
VERIFY(vkSet != VK_NULL_HANDLE, "Vulkan descriptor set must not be null");
switch(Res.SpirvAttribs.Type)
@@ -845,7 +693,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources()
case SPIRVShaderResourceAttribs::ResourceType::StorageBuffer:
for (Uint32 i = 0; i < Res.SpirvAttribs.ArraySize; ++i)
{
- auto CachedRes = SetResources.GetResource(Res.CacheOffset + i);
+ const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + i);
VkDescriptorBufferInfo DescrBuffInfo = CachedRes.GetBufferDescriptorWriteInfo();
Res.UpdateDescriptorHandle(vkSet, i, nullptr, &DescrBuffInfo, nullptr);
}
@@ -855,7 +703,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources()
case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer:
for (Uint32 i = 0; i < Res.SpirvAttribs.ArraySize; ++i)
{
- auto CachedRes = SetResources.GetResource(Res.CacheOffset + i);
+ const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + i);
VkBufferView BuffView = CachedRes.GetBufferViewWriteInfo();
Res.UpdateDescriptorHandle(vkSet, i, nullptr, nullptr, &BuffView);
}
@@ -866,7 +714,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources()
case SPIRVShaderResourceAttribs::ResourceType::SampledImage:
for (Uint32 i = 0; i < Res.SpirvAttribs.ArraySize; ++i)
{
- auto CachedRes = SetResources.GetResource(Res.CacheOffset + i);
+ const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + i);
VkDescriptorImageInfo DescrImgInfo = CachedRes.GetImageDescriptorWriteInfo(Res.SpirvAttribs.StaticSamplerInd >= 0);
Res.UpdateDescriptorHandle(vkSet, i, &DescrImgInfo, nullptr, nullptr);
}
@@ -882,7 +730,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources()
{
if(Res.SpirvAttribs.StaticSamplerInd < 0)
{
- auto CachedRes = SetResources.GetResource(Res.CacheOffset + i);
+ const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + i);
VkDescriptorImageInfo DescrImgInfo = CachedRes.GetSamplerDescriptorWriteInfo();
Res.UpdateDescriptorHandle(vkSet, i, &DescrImgInfo, nullptr, nullptr);
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
new file mode 100644
index 00000000..6f6f7d9e
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
@@ -0,0 +1,176 @@
+/* Copyright 2015-2018 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+
+#include "ShaderVariableVk.h"
+
+namespace Diligent
+{
+
+
+
+// Clones layout from the reference layout maintained by the pipeline state
+// Descriptor sets and bindings must be correct
+// Resource cache is not initialized.
+void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& SrcLayout,
+ IMemoryAllocator& Allocator,
+ const SHADER_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ ShaderResourceCacheVk& ResourceCache)
+{
+ m_pResourceLayout = &SrcLayout;
+ m_pResourceCache = &ResourceCache;
+#ifdef _DEBUG
+ m_pDbgAllocator = &Allocator;
+#endif
+
+ VERIFY_EXPR(m_NumVariables == 0);
+ m_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))
+ {
+ m_NumVariables += IsAllowedType(VarType, AllowedTypeBits) ? SrcLayout.GetResourceCount(VarType) : 0;
+ }
+
+ auto *pRawMem = ALLOCATE(Allocator, "Raw memory buffer for shader variables", m_NumVariables*sizeof(ShaderVariableVkImpl));
+ 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))
+ {
+ if( !IsAllowedType(VarType, AllowedTypeBits))
+ continue;
+
+ Uint32 NumResources = SrcLayout.GetResourceCount(VarType);
+ for( Uint32 r=0; r < NumResources; ++r )
+ {
+ const auto &SrcRes = SrcLayout.GetResource(VarType, r);
+ ::new (m_pVariables + VarInd) ShaderVariableVkImpl(*this, SrcRes );
+ ++VarInd;
+ }
+ }
+ VERIFY_EXPR(VarInd == m_NumVariables);
+
+#if USE_VARIABLE_HASH_MAP
+ InitVariablesHashMap();
+#endif
+}
+
+ShaderVariableManagerVk::~ShaderVariableManagerVk()
+{
+ VERIFY(m_pVariables == nullptr, "Destroy() has not been called");
+}
+
+void ShaderVariableManagerVk::Destroy(IMemoryAllocator &Allocator)
+{
+ VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor");
+
+ for(Uint32 v=0; v < m_NumVariables; ++v)
+ m_pVariables[v].~ShaderVariableVkImpl();
+ Allocator.Free(m_pVariables);
+ m_pVariables = nullptr;
+}
+
+ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name)
+{
+ ShaderVariableVkImpl* pVar = nullptr;
+#if USE_VARIABLE_HASH_MAP
+ // Name will be implicitly converted to HashMapStringKey without making a copy
+ auto it = m_VariableHash.find(Name);
+ if (it != m_VariableHash.end())
+ pVar = it->second;
+#else
+ for (Uint32 v = 0; v < m_NumVariables; ++v)
+ {
+ auto &Var = m_pVariables[v];
+ const auto& Res = Var.m_Resource;
+ if (strcmp(Res.SpirvAttribs.Name, Name) == 0)
+ {
+ pVar = &Var;
+ break;
+ }
+ }
+#endif
+
+ if (pVar == nullptr)
+ {
+ LOG_ERROR_MESSAGE("Shader variable \"", Name, "\" is not found in shader \"", m_pResourceLayout->GetShaderName(), "\". Attempts to set the variable will be silently ignored.");
+ }
+ return pVar;
+}
+
+
+
+void ShaderVariableManagerVk::BindResources( IResourceMapping* pResourceMapping, Uint32 Flags)
+{
+ VERIFY_EXPR(m_pResourceCache != nullptr);
+
+ if( !pResourceMapping )
+ {
+ LOG_ERROR_MESSAGE( "Failed to bind resources: resource mapping is null" );
+ return;
+ }
+
+ for(Uint32 v=0; v < m_NumVariables; ++v)
+ {
+ auto &Var = m_pVariables[v];
+ const auto& Res = Var.m_Resource;
+ for(Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd)
+ {
+ if( Flags & BIND_SHADER_RESOURCES_RESET_BINDINGS )
+ Res.BindResource(nullptr, ArrInd, *m_pResourceCache);
+
+ if( (Flags & BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED) && Res.IsBound(ArrInd, *m_pResourceCache) )
+ return;
+
+ const auto* VarName = Res.SpirvAttribs.Name;
+ RefCntAutoPtr<IDeviceObject> pObj;
+ pResourceMapping->GetResource( VarName, &pObj, ArrInd );
+ if( pObj )
+ {
+ Res.BindResource(pObj, ArrInd, *m_pResourceCache);
+ }
+ else
+ {
+ if( (Flags & BIND_SHADER_RESOURCES_ALL_RESOLVED) && !Res.IsBound(ArrInd, *m_pResourceCache) )
+ LOG_ERROR_MESSAGE( "Cannot bind resource to shader variable \"", Res.SpirvAttribs.GetPrintName(ArrInd), "\": resource view not found in the resource mapping" );
+ }
+ }
+ }
+}
+
+#if USE_VARIABLE_HASH_MAP
+void ShaderVariableManagerVk::InitVariablesHashMap()
+{
+ Uint32 TotalResources = GetTotalResourceCount();
+ for (Uint32 r = 0; r < TotalResources; ++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
+
+}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
index ae6c745d..b568c3d6 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
@@ -21,6 +21,7 @@
* of the possibility of such damages.
*/
+#include <array>
#include "pch.h"
#include "ShaderVkImpl.h"
@@ -37,9 +38,10 @@ namespace Diligent
ShaderVkImpl::ShaderVkImpl(IReferenceCounters *pRefCounters, RenderDeviceVkImpl *pRenderDeviceVk, const ShaderCreationAttribs &CreationAttribs) :
TShaderBase(pRefCounters, pRenderDeviceVk, CreationAttribs.Desc),
- m_StaticResLayout(*this, GetRawAllocator()),
+ m_StaticResLayout(*this, pRenderDeviceVk->GetLogicalDevice(), GetRawAllocator()),
m_DummyShaderVar(*this),
- m_ConstResCache(ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources)
+ m_StaticResCache(ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources),
+ m_StaticVarsMgr(*this)
{
auto GLSLSource = BuildGLSLSourceString(CreationAttribs, TargetGLSLCompiler::glslang);
m_SPIRV = GLSLtoSPIRV(m_Desc.ShaderType, GLSLSource.c_str());
@@ -59,29 +61,32 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters *pRefCounters, RenderDeviceVkImpl
// Clone only static resources that will be set directly in the shader
// http://diligentgraphics.com/diligent-engine/architecture/Vk/shader-resource-layout#Initializing-Special-Resource-Layout-for-Managing-Static-Shader-Resources
- SHADER_VARIABLE_TYPE VarTypes[] = {SHADER_VARIABLE_TYPE_STATIC};
- m_StaticResLayout.Initialize(pRenderDeviceVk->GetLogicalDevice(), m_pShaderResources, GetRawAllocator(), VarTypes, _countof(VarTypes), &m_ConstResCache, nullptr, nullptr);
+ std::array<SHADER_VARIABLE_TYPE, 1> VarTypes = {SHADER_VARIABLE_TYPE_STATIC};
+ m_StaticResLayout.Initialize(m_pShaderResources, GetRawAllocator(),
+ VarTypes.data(), static_cast<Uint32>(VarTypes.size()), &m_StaticResCache, nullptr, nullptr);
+ m_StaticVarsMgr.Initialize(m_StaticResLayout, GetRawAllocator(), nullptr, 0, m_StaticResCache);
}
ShaderVkImpl::~ShaderVkImpl()
{
+ m_StaticVarsMgr.Destroy(GetRawAllocator());
}
void ShaderVkImpl::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags)
{
- m_StaticResLayout.BindResources(pResourceMapping, Flags, &m_ConstResCache);
+ m_StaticVarsMgr.BindResources(pResourceMapping, Flags);
}
IShaderVariable* ShaderVkImpl::GetShaderVariable(const Char* Name)
{
- IShaderVariable *pVar = m_StaticResLayout.GetShaderVariable(Name);
+ IShaderVariable *pVar = m_StaticVarsMgr.GetVariable(Name);
return (pVar != nullptr) ? pVar : &m_DummyShaderVar;
}
#ifdef VERIFY_SHADER_BINDINGS
void ShaderVkImpl::DbgVerifyStaticResourceBindings()
{
- m_StaticResLayout.dbgVerifyBindings();
+ m_StaticResLayout.dbgVerifyBindings(m_StaticResCache);
}
#endif