summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-06-12 16:45:57 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-06-12 16:45:57 +0000
commit4027a75f1f7bd089fb3f1b39ce29e413d8b23a62 (patch)
tree3f5ba7d069466c8744948128c22b8755b9a81d71 /Graphics/GraphicsEngineVulkan
parentUpdated static shader resource cache to use one descriptor set instead of ind... (diff)
downloadDiligentCore-4027a75f1f7bd089fb3f1b39ce29e413d8b23a62.tar.gz
DiligentCore-4027a75f1f7bd089fb3f1b39ce29e413d8b23a62.zip
Made uniform and storage buffer descriptors dynamic in pipeline layout
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineLayout.h22
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h7
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h37
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp46
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp116
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp60
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp301
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp10
10 files changed, 366 insertions, 237 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h
index 1ac1e384..cc797677 100644
--- a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h
@@ -33,6 +33,7 @@
#include "VulkanDynamicHeap.h"
#include "VulkanUtilities/VulkanObjectWrappers.h"
#include "VulkanUtilities/VulkanMemoryManager.h"
+#include "VulkanDynamicHeap.h"
namespace Diligent
{
@@ -67,6 +68,7 @@ public:
// void DbgVerifyDynamicAllocation(Uint32 ContextId);
//#endif
+ Uint32 GetDynamicOffset(Uint32 CtxId)const{return 0;}
VkBuffer GetVkBuffer()const override final
{
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h
index b8bdddfc..556fab20 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h
@@ -99,10 +99,11 @@ private:
DescriptorSetLayout& operator = (const DescriptorSetLayout&) = delete;
DescriptorSetLayout& operator = (DescriptorSetLayout&&) = delete;
- uint32_t TotalDescriptors = 0;
- int8_t SetIndex = -1;
- uint16_t NumLayoutBindings = 0;
- VkDescriptorSetLayoutBinding* pBindings = nullptr;
+ uint32_t TotalDescriptors = 0;
+ int8_t SetIndex = -1;
+ uint8_t NumDynamicDescriptors = 0; // Total number of uniform and storage buffers, counting all array elements
+ uint16_t NumLayoutBindings = 0;
+ VkDescriptorSetLayoutBinding* pBindings = nullptr;
VulkanUtilities::DescriptorSetLayoutWrapper VkLayout;
~DescriptorSetLayout();
@@ -138,12 +139,13 @@ private:
size_t GetHash()const;
VkPipelineLayout GetVkPipelineLayout()const{return m_VkPipelineLayout;}
- void AllocateResourceSlot(const SPIRVShaderResourceAttribs &ResAttribs,
- VkSampler vkStaticSampler,
- SHADER_TYPE ShaderType,
- Uint32 &DescriptorSet,
- Uint32 &Binding,
- Uint32 &OffsetInCache);
+ void AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResAttribs,
+ VkSampler vkStaticSampler,
+ SHADER_TYPE ShaderType,
+ Uint32& DescriptorSet,
+ Uint32& Binding,
+ Uint32& OffsetInCache);
+
private:
IMemoryAllocator &m_MemAllocator;
VulkanUtilities::PipelineLayoutWrapper m_VkPipelineLayout;
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h
index 44950419..0b0393dd 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.h
@@ -91,8 +91,6 @@ private:
void CreateRenderPass(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice);
- void ParseResourceLayoutAndCreateShader(IShader *pShader, Uint32 LayoutInd);
-
DummyShaderVariable m_DummyVar;
// Looks like there may be a bug in msvc: when allocators are declared as
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h
index 192e06cc..b5dbb2b7 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h
@@ -173,8 +173,15 @@ public:
template<bool VerifyOnly>
void TransitionResources(DeviceContextVkImpl *pCtxVkImpl);
+ void GetDynamicBufferOffset(Uint32 CtxId, std::vector<uint32_t>& Offsets)const;
+
private:
+ Resource* GetFirstResourcePtr()
+ {
+ return reinterpret_cast<Resource*>(reinterpret_cast<DescriptorSet*>(m_pMemory) + m_NumSets);
+ }
+
IMemoryAllocator* m_pAllocator = nullptr;
void* m_pMemory = nullptr;
Uint32 m_NumSets = 0;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h
index bd843797..3f6e335e 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h
@@ -126,19 +126,20 @@ public:
~ShaderResourceLayoutVk();
- // The method is called by
- // - ShaderVkImpl class instance to initialize static resource layout and initialize shader resource cache
- // to hold static resources
- // - PipelineStateVkImpl class instance to reference all types of resources (static, mutable, dynamic).
- // Descriptor sets, bindings and cache offsets are assigned during the initialization;
- // no shader resource cache must be provided
- void Initialize(const std::shared_ptr<const SPIRVShaderResources>& pSrcResources,
- IMemoryAllocator& LayoutDataAllocator,
- const SHADER_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheVk* pStaticResourceCache,
- std::vector<uint32_t>* pSPIRV,
- class PipelineLayout* pPipelineLayout);
+ // This method is called by ShaderVkImpl class instance to initialize static
+ // shader resource layout and cache
+ void InitializeStaticResourceLayout(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
+ IMemoryAllocator& LayoutDataAllocator,
+ ShaderResourceCacheVk& StaticResourceCache);
+
+ // This method is called by PipelineStateVkImpl class instance to initialize resource
+ // layouts for all shader stages in a pipeline.
+ static void Initialize(Uint32 NumShaders,
+ ShaderResourceLayoutVk Layouts[],
+ std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
+ IMemoryAllocator& LayoutDataAllocator,
+ std::vector<uint32_t> SPIRVs[],
+ class PipelineLayout& PipelineLayout);
// sizeof(VkResource) == 24 (x64)
struct VkResource
@@ -272,11 +273,13 @@ private:
Uint32 GetTotalResourceCount()const
{
- static_assert(SHADER_VARIABLE_TYPE_NUM_TYPES == 3, "Did you add new variable type?");
- return m_NumResources[SHADER_VARIABLE_TYPE_STATIC] + m_NumResources[SHADER_VARIABLE_TYPE_MUTABLE] + m_NumResources[SHADER_VARIABLE_TYPE_DYNAMIC];
+ return m_NumResources[SHADER_VARIABLE_TYPE_NUM_TYPES];
}
- void AllocateMemory(IMemoryAllocator &Allocator);
+ void AllocateMemory(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
+ IMemoryAllocator& Allocator,
+ const SHADER_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes);
IObject& m_Owner;
@@ -287,7 +290,7 @@ private:
// there may be multiple objects referencing the same set of resources
std::shared_ptr<const SPIRVShaderResources> m_pResources;
- std::array<Uint16, SHADER_VARIABLE_TYPE_NUM_TYPES> m_NumResources = {};
+ std::array<Uint16, SHADER_VARIABLE_TYPE_NUM_TYPES+1> m_NumResources = {};
};
}
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
index e5d356f9..f3e0ac2b 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
@@ -61,8 +61,8 @@ public:
ResourceTypeToVkDescriptorType()
{
static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 9, "Please add corresponding decriptor type");
- m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageImage] = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
@@ -99,6 +99,12 @@ void PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::AddBinding
ReserveMemory(NumLayoutBindings + 1, MemAllocator);
pBindings[NumLayoutBindings++] = Binding;
TotalDescriptors += Binding.descriptorCount;
+ if(Binding.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
+ Binding.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
+ {
+ VERIFY(NumDynamicDescriptors + Binding.descriptorCount <= std::numeric_limits<decltype(NumDynamicDescriptors)>::max(), "Number of dynamic descriptors exceeds max representable value");
+ NumDynamicDescriptors += static_cast<decltype(NumDynamicDescriptors)>(Binding.descriptorCount);
+ }
}
size_t PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::GetMemorySize(Uint32 NumBindings)
@@ -197,9 +203,10 @@ PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::~DescriptorSetL
bool PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::operator == (const DescriptorSetLayout& rhs)const
{
- if(TotalDescriptors != rhs.TotalDescriptors ||
- SetIndex != rhs.SetIndex ||
- NumLayoutBindings != rhs.NumLayoutBindings)
+ if(TotalDescriptors != rhs.TotalDescriptors ||
+ SetIndex != rhs.SetIndex ||
+ NumDynamicDescriptors != rhs.NumDynamicDescriptors ||
+ NumLayoutBindings != rhs.NumLayoutBindings)
return false;
for(uint32_t b=0; b < NumLayoutBindings; ++b)
@@ -222,7 +229,7 @@ bool PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::operator =
size_t PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::GetHash()const
{
- size_t Hash = ComputeHash(SetIndex, NumLayoutBindings, TotalDescriptors);
+ size_t Hash = ComputeHash(SetIndex, NumLayoutBindings, TotalDescriptors, NumDynamicDescriptors);
for (uint32_t b = 0; b < NumLayoutBindings; ++b)
{
const auto &B = pBindings[b];
@@ -308,12 +315,12 @@ size_t PipelineLayout::DescriptorSetLayoutManager::GetHash()const
return Hash;
}
-void PipelineLayout::DescriptorSetLayoutManager::AllocateResourceSlot(const SPIRVShaderResourceAttribs &ResAttribs,
- VkSampler vkStaticSampler,
- SHADER_TYPE ShaderType,
- Uint32 &DescriptorSet,
- Uint32 &Binding,
- Uint32 &OffsetInCache)
+void PipelineLayout::DescriptorSetLayoutManager::AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResAttribs,
+ VkSampler vkStaticSampler,
+ SHADER_TYPE ShaderType,
+ Uint32& DescriptorSet,
+ Uint32& Binding,
+ Uint32& OffsetInCache)
{
auto& DescrSet = GetDescriptorSet(ResAttribs.VarType);
if (DescrSet.SetIndex < 0)
@@ -427,6 +434,9 @@ void PipelineLayout::BindDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
VERIFY(m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_STATIC).SetIndex == m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_MUTABLE).SetIndex,
"Static and mutable variables are expected to share the same descriptor set");
+#ifdef _DEBUG
+ Uint32 TotalDynamicDescriptors = 0;
+#endif
for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_MUTABLE; VarType <= SHADER_VARIABLE_TYPE_DYNAMIC; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1))
{
const auto &Set = m_LayoutMgr.GetDescriptorSet(VarType);
@@ -437,6 +447,9 @@ void PipelineLayout::BindDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
vkSets[Set.SetIndex] = ResourceCache.GetDescriptorSet(Set.SetIndex).GetVkDescriptorSet();
VERIFY(vkSets[Set.SetIndex] != VK_NULL_HANDLE, "Descriptor set must not be null");
}
+#ifdef _DEBUG
+ TotalDynamicDescriptors += Set.NumDynamicDescriptors;
+#endif
}
#ifdef _DEBUG
@@ -444,6 +457,10 @@ void PipelineLayout::BindDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
VERIFY(vkSets[i] != VK_NULL_HANDLE, "Descriptor set must not be null");
#endif
+ std::vector<uint32_t> DynamicOffsets;
+ ResourceCache.GetDynamicBufferOffset(pCtxVkImpl->GetContextId(), DynamicOffsets);
+ VERIFY(DynamicOffsets.size() == TotalDynamicDescriptors, "Incorrect size of dynamic descriptor array");
+
auto& CmdBuffer = pCtxVkImpl->GetCommandBuffer();
// vkCmdBindDescriptorSets causes the sets numbered [firstSet .. firstSet+descriptorSetCount-1] to use the
// bindings stored in pDescriptorSets[0 .. descriptorSetCount-1] for subsequent rendering commands
@@ -453,7 +470,10 @@ void PipelineLayout::BindDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
m_LayoutMgr.GetVkPipelineLayout(),
0, // First set
SetCount,
- vkSets.data());
+ vkSets.data(),
+ // dynamicOffsetCount must equal the total number of dynamic descriptors in the sets being bound (13.2.5)
+ static_cast<uint32_t>(DynamicOffsets.size()),
+ DynamicOffsets.data());
}
}
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 8874b0b7..357c8b12 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -36,28 +36,6 @@
namespace Diligent
{
-void PipelineStateVkImpl::ParseResourceLayoutAndCreateShader(IShader *pShader, Uint32 LayoutInd)
-{
- VERIFY_EXPR(pShader);
-
- auto *pShaderVk = ValidatedCast<ShaderVkImpl>(pShader);
-
- auto pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(pShaderVk->GetDevice());
- const auto &LogicalDevice = pDeviceVkImpl->GetLogicalDevice();
-
- std::vector<uint32_t> SPIRV = pShaderVk->GetSPIRV();
- m_ShaderResourceLayouts[LayoutInd].Initialize(pShaderVk->GetShaderResources(), GetRawAllocator(), nullptr, 0, nullptr, &SPIRV, &m_PipelineLayout);
-
- VkShaderModuleCreateInfo ShaderModuleCI = {};
- ShaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
- ShaderModuleCI.pNext = NULL;
- ShaderModuleCI.flags = 0;
- ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t);
- ShaderModuleCI.pCode = SPIRV.data();
- m_ShaderModules[LayoutInd] = LogicalDevice.CreateShaderModule(ShaderModuleCI, m_Desc.Name);
-}
-
-
void PipelineStateVkImpl::CreateRenderPass(const VulkanUtilities::VulkanLogicalDevice &LogicalDevice)
{
// NOTE: framebuffer cache and clear commands assume that depth buffer
@@ -153,12 +131,61 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters *pRefCounters, Ren
m_pDefaultShaderResBinding(nullptr, STDDeleter<ShaderResourceBindingVkImpl, FixedBlockMemoryAllocator>(pDeviceVk->GetSRBAllocator()) )
{
const auto &LogicalDevice = pDeviceVk->GetLogicalDevice();
+
+ // Initialize shader resource layouts
auto &ShaderResLayoutAllocator = GetRawAllocator();
+ std::array<std::shared_ptr<const SPIRVShaderResources>, MaxShadersInPipeline> ShaderResources;
+ std::array<std::vector<uint32_t>, MaxShadersInPipeline> ShaderSPIRVs;
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());
+ auto *pShaderVk = ValidatedCast<ShaderVkImpl>(m_ppShaders[s]);
+ ShaderResources[s] = pShaderVk->GetShaderResources();
+ ShaderSPIRVs[s] = pShaderVk->GetSPIRV();
+ }
+ ShaderResourceLayoutVk::Initialize(m_NumShaders, m_ShaderResourceLayouts, ShaderResources.data(), GetRawAllocator(), ShaderSPIRVs.data(), m_PipelineLayout);
+ m_PipelineLayout.Finalize(LogicalDevice);
+
+ // Create shader modules and initialize shader stages
+ std::array<VkPipelineShaderStageCreateInfo, MaxShadersInPipeline> ShaderStages = {};
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ auto *pShader = m_ppShaders[s];
+ auto ShaderType = pShader->GetDesc().ShaderType;
+
+ auto &StageCI = ShaderStages[s];
+ StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+ StageCI.pNext = nullptr;
+ StageCI.flags = 0; // reserved for future use
+ switch (ShaderType)
+ {
+ case SHADER_TYPE_VERTEX: StageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; break;
+ case SHADER_TYPE_HULL: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break;
+ case SHADER_TYPE_DOMAIN: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break;
+ case SHADER_TYPE_GEOMETRY: StageCI.stage = VK_SHADER_STAGE_GEOMETRY_BIT; break;
+ case SHADER_TYPE_PIXEL: StageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; break;
+ case SHADER_TYPE_COMPUTE: StageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT; break;
+ default: UNEXPECTED("Unknown shader type");
+ }
+
+ VkShaderModuleCreateInfo ShaderModuleCI = {};
+ ShaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ ShaderModuleCI.pNext = nullptr;
+ ShaderModuleCI.flags = 0;
+ const auto& SPIRV = ShaderSPIRVs[s];
+ ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t);
+ ShaderModuleCI.pCode = SPIRV.data();
+ m_ShaderModules[s] = LogicalDevice.CreateShaderModule(ShaderModuleCI, m_Desc.Name);
+
+ StageCI.module = m_ShaderModules[s];
+ StageCI.pName = "main"; // entry point
+ StageCI.pSpecializationInfo = nullptr;
+ }
+
+ // Create pipeline
if (m_Desc.IsComputePipeline)
{
auto &ComputePipeline = m_Desc.ComputePipeline;
@@ -175,21 +202,9 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters *pRefCounters, Ren
PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from
- auto &CSStage = PipelineCI.stage;
- CSStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- CSStage.pNext = nullptr;
- CSStage.flags = 0; // reserved for future use
- CSStage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
-
- ParseResourceLayoutAndCreateShader(ComputePipeline.pCS, 0);
- CSStage.module = m_ShaderModules[0];
-
- m_PipelineLayout.Finalize(LogicalDevice);
+ PipelineCI.stage = ShaderStages[0];
PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout();
- CSStage.pName = "main";
- CSStage.pSpecializationInfo = nullptr;
-
m_Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name);
}
else
@@ -208,37 +223,8 @@ PipelineStateVkImpl :: PipelineStateVkImpl(IReferenceCounters *pRefCounters, Ren
#endif
PipelineCI.stageCount = m_NumShaders;
- std::vector<VkPipelineShaderStageCreateInfo> Stages(PipelineCI.stageCount);
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- auto *pShader = m_ppShaders[s];
- auto ShaderType = pShader->GetDesc().ShaderType;
-
- auto &StageCI = Stages[s];
- StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
- StageCI.pNext = nullptr;
- StageCI.flags = 0; // reserved for future use
- switch(ShaderType)
- {
- case SHADER_TYPE_VERTEX: StageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; break;
- case SHADER_TYPE_HULL: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break;
- case SHADER_TYPE_DOMAIN: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break;
- case SHADER_TYPE_GEOMETRY: StageCI.stage = VK_SHADER_STAGE_GEOMETRY_BIT; break;
- case SHADER_TYPE_PIXEL: StageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; break;
- default: UNEXPECTED("Unknown shader type");
- }
-
- ParseResourceLayoutAndCreateShader(pShader, s);
-
- StageCI.module = m_ShaderModules[s];
- StageCI.pName = "main"; // entry point
- StageCI.pSpecializationInfo = nullptr;
- }
-
- m_PipelineLayout.Finalize(LogicalDevice);
+ PipelineCI.pStages = ShaderStages.data();
PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout();
-
- PipelineCI.pStages = Stages.data();
VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {};
std::array<VkVertexInputBindingDescription, iMaxLayoutElements> BindingDescriptions;
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
index e6297171..74a20524 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
@@ -78,7 +78,7 @@ ShaderResourceCacheVk::~ShaderResourceCacheVk()
{
if (m_pMemory)
{
- auto *pResources = reinterpret_cast<Resource*>( reinterpret_cast<DescriptorSet*>(m_pMemory) + m_NumSets);
+ auto *pResources = GetFirstResourcePtr();
for(Uint32 res=0; res < m_TotalResources; ++res)
pResources[res].~Resource();
for (Uint32 t = 0; t < m_NumSets; ++t)
@@ -91,7 +91,7 @@ ShaderResourceCacheVk::~ShaderResourceCacheVk()
template<bool VerifyOnly>
void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl *pCtxVkImpl)
{
- auto *pResources = reinterpret_cast<Resource*>(reinterpret_cast<DescriptorSet*>(m_pMemory) + m_NumSets);
+ auto *pResources = GetFirstResourcePtr();
for (Uint32 res = 0; res < m_TotalResources; ++res)
{
auto &Res = pResources[res];
@@ -284,4 +284,60 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetSamplerDescriptorWrite
return DescrImgInfo;
}
+void ShaderResourceCacheVk::GetDynamicBufferOffset(Uint32 CtxId, std::vector<uint32_t>& Offsets)const
+{
+ Offsets.clear();
+
+ // If any of the sets being bound include dynamic uniform or storage buffers, then
+ // pDynamicOffsets includes one element for each array element in each dynamic descriptor
+ // type binding in each set. Values are taken from pDynamicOffsets in an order such that
+ // all entries for set N come before set N+1; within a set, entries are ordered by the binding
+ // numbers (unclear if this is SPIRV binding or VkDescriptorSetLayoutBinding number) in the
+ // descriptor set layouts; and within a binding array, elements are in order. (13.2.5)
+
+ // In each descriptor set, all uniform buffers for every shader stage come first,
+ // followed by all storage buffers for every shader stage, followed by all other resources
+ for(Uint32 set=0; set < m_NumSets; ++set)
+ {
+ const auto& DescrSet = GetDescriptorSet(set);
+ Uint32 res = 0;
+ while(res < DescrSet.GetSize())
+ {
+ const auto& Res = DescrSet.GetResource(res);
+ if(Res.Type != SPIRVShaderResourceAttribs::ResourceType::UniformBuffer)
+ break;
+
+ const auto* pBufferVk = Res.pObject.RawPtr<const BufferVkImpl>();
+ auto Offset = pBufferVk->GetDynamicOffset(CtxId);
+ Offsets.emplace_back(Offset);
+
+ ++res;
+ }
+
+ while (res < DescrSet.GetSize())
+ {
+ const auto& Res = DescrSet.GetResource(res);
+ if (Res.Type != SPIRVShaderResourceAttribs::ResourceType::StorageBuffer)
+ break;
+
+ const auto* pBufferVkView = Res.pObject.RawPtr<const BufferViewVkImpl>();
+ const auto* pBufferVk = pBufferVkView->GetBufferVk();
+ auto Offset = pBufferVk->GetDynamicOffset(CtxId);
+ Offsets.emplace_back(Offset);
+
+ ++res;
+ }
+
+#ifdef _DEBUG
+ for(; res < DescrSet.GetSize(); ++res)
+ {
+ const auto& Res = DescrSet.GetResource(res);
+ VERIFY(Res.Type != SPIRVShaderResourceAttribs::ResourceType::UniformBuffer &&
+ Res.Type != SPIRVShaderResourceAttribs::ResourceType::StorageBuffer,
+ "All uniform and storage buffers are expected to go first in the beginning of each descriptor set");
+ }
+#endif
+ }
+}
+
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index 288270b0..f98e7b16 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -53,11 +53,41 @@ ShaderResourceLayoutVk::~ShaderResourceLayoutVk()
Resources[r].~VkResource();
}
-void ShaderResourceLayoutVk::AllocateMemory(IMemoryAllocator &Allocator)
+void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
+ IMemoryAllocator& Allocator,
+ const SHADER_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes)
{
+ VERIFY(!m_ResourceBuffer, "Memory has already been initialized");
+ VERIFY_EXPR(!m_pResources);
+ VERIFY_EXPR(pSrcResources);
+
+ m_pResources = std::move(pSrcResources);
+
+ Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+
+ // Count number of resources to allocate all needed memory
+ m_pResources->ProcessResources(
+ AllowedVarTypes, NumAllowedTypes,
+
+ [&](const SPIRVShaderResourceAttribs &ResAttribs, Uint32)
+ {
+ VERIFY_EXPR(IsAllowedType(ResAttribs.VarType, AllowedTypeBits));
+ VERIFY( Uint32{m_NumResources[ResAttribs.VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds max representable value");
+ ++m_NumResources[ResAttribs.VarType];
+ }
+ );
+
+ Uint32 TotalResources = 0;
+ for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1))
+ {
+ TotalResources += m_NumResources[VarType];
+ }
+ VERIFY(TotalResources <= Uint32{std::numeric_limits<Uint16>::max()}, "Total number of resources exceeds Uint16 max representable value" );
+ m_NumResources[SHADER_VARIABLE_TYPE_NUM_TYPES] = static_cast<Uint16>(TotalResources);
+
VERIFY( &m_ResourceBuffer.get_deleter().m_Allocator == &Allocator, "Inconsistent memory allocators" );
- Uint32 TotalResource = GetTotalResourceCount();
- size_t MemSize = TotalResource * sizeof(VkResource);
+ size_t MemSize = TotalResources * sizeof(VkResource);
if(MemSize == 0)
return;
@@ -65,156 +95,185 @@ void ShaderResourceLayoutVk::AllocateMemory(IMemoryAllocator &Allocator)
m_ResourceBuffer.reset(pRawMem);
}
-void ShaderResourceLayoutVk::Initialize(const std::shared_ptr<const SPIRVShaderResources>& pSrcResources,
- IMemoryAllocator& LayoutDataAllocator,
- const SHADER_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheVk* pStaticResourceCache,
- std::vector<uint32_t>* pSPIRV,
- PipelineLayout* pPipelineLayout)
+void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
+ IMemoryAllocator& LayoutDataAllocator,
+ ShaderResourceCacheVk& StaticResourceCache)
{
- m_pResources = pSrcResources;
+ auto AllowedVarType = SHADER_VARIABLE_TYPE_STATIC;
+ AllocateMemory(std::move(pSrcResources), LayoutDataAllocator, &AllowedVarType, 1);
- VERIFY_EXPR( (pStaticResourceCache != nullptr) ^ (pPipelineLayout != nullptr && pSPIRV != nullptr) );
-
- Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+ std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES> CurrResInd = {};
+ Uint32 StaticResCacheSize = 0;
- // Count number of resources to allocate all needed memory
m_pResources->ProcessResources(
- AllowedVarTypes, NumAllowedTypes,
-
- [&](const SPIRVShaderResourceAttribs &UB, Uint32)
- {
- VERIFY_EXPR(IsAllowedType(UB.VarType, AllowedTypeBits));
- ++m_NumResources[UB.VarType];
- },
- [&](const SPIRVShaderResourceAttribs& SB, Uint32)
+ &AllowedVarType, 1,
+ [&](const SPIRVShaderResourceAttribs &Attribs, Uint32)
{
- 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 SPIRVShaderResourceAttribs &SmplImg, Uint32)
- {
- VERIFY_EXPR(IsAllowedType(SmplImg.VarType, AllowedTypeBits));
- ++m_NumResources[SmplImg.VarType];
- },
- [&](const SPIRVShaderResourceAttribs &AC, Uint32)
- {
- VERIFY_EXPR(IsAllowedType(AC.VarType, AllowedTypeBits));
- ++m_NumResources[AC.VarType];
- },
- [&](const SPIRVShaderResourceAttribs &SepImg, Uint32)
- {
- VERIFY_EXPR(IsAllowedType(SepImg.VarType, AllowedTypeBits));
- ++m_NumResources[SepImg.VarType];
- },
- [&](const SPIRVShaderResourceAttribs &SepSmpl, Uint32)
- {
- VERIFY_EXPR(IsAllowedType(SepSmpl.VarType, AllowedTypeBits));
- ++m_NumResources[SepSmpl.VarType];
+ Uint32 Binding = Attribs.Type;
+ Uint32 DescriptorSet = 0;
+ Uint32 CacheOffset = StaticResCacheSize;
+ StaticResCacheSize += Attribs.ArraySize;
+ ::new (&GetResource(Attribs.VarType, CurrResInd[Attribs.VarType]++)) VkResource(*this, Attribs, Binding, DescriptorSet, CacheOffset);
}
);
+#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(CurrResInd[VarType] == m_NumResources[VarType], "Not all resources are initialized, which will cause a crash when dtor is called");
+ }
+#endif
+
+ StaticResourceCache.InitializeSets(GetRawAllocator(), 1, &StaticResCacheSize);
+ InitializeResourceMemoryInCache(StaticResourceCache);
+}
- AllocateMemory(LayoutDataAllocator);
- std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES> CurrResInd = {};
- Uint32 StaticResCacheSize = 0;
+void ShaderResourceLayoutVk::Initialize(Uint32 NumShaders,
+ ShaderResourceLayoutVk Layouts[],
+ std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
+ IMemoryAllocator& LayoutDataAllocator,
+ std::vector<uint32_t> SPIRVs[],
+ class PipelineLayout& PipelineLayout)
+{
+ SHADER_VARIABLE_TYPE* AllowedVarTypes = nullptr;
+ Uint32 NumAllowedTypes = 0;
+ Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
- auto AddResource = [&](const SPIRVShaderResourceAttribs &Attribs)
+ for(Uint32 s=0; s < NumShaders; ++s)
+ {
+ Layouts[s].AllocateMemory(std::move(pShaderResources[s]), LayoutDataAllocator, AllowedVarTypes, NumAllowedTypes);
+ }
+
+ VERIFY_EXPR(NumShaders <= MaxShadersInPipeline);
+ std::array<std::array<Uint32, SHADER_VARIABLE_TYPE_NUM_TYPES>, MaxShadersInPipeline> CurrResInd = {};
+#ifdef _DEBUG
+ std::unordered_map<Uint32, std::pair<Uint32, Uint32>> dbgBindings_CacheOffsets;
+#endif
+
+ auto AddResource = [&](Uint32 ShaderInd,
+ ShaderResourceLayoutVk& ResLayout,
+ const SPIRVShaderResources& Resources,
+ const SPIRVShaderResourceAttribs& Attribs)
{
Uint32 Binding = 0;
Uint32 DescriptorSet = 0;
Uint32 CacheOffset = 0;
- if (pPipelineLayout)
- {
- VERIFY_EXPR(pSPIRV != nullptr);
- auto *pStaticSampler = m_pResources->GetStaticSampler(Attribs);
- VkSampler vkStaticSampler = VK_NULL_HANDLE;
- if(pStaticSampler != nullptr)
- vkStaticSampler = ValidatedCast<SamplerVkImpl>(pStaticSampler)->GetVkSampler();
- pPipelineLayout->AllocateResourceSlot(Attribs, vkStaticSampler, m_pResources->GetShaderType(), DescriptorSet, Binding, CacheOffset, *pSPIRV);
- VERIFY(DescriptorSet <= std::numeric_limits<decltype(VkResource::DescriptorSet)>::max(), "Descriptor set (", DescriptorSet, ") excceeds representable max value");
- VERIFY(Binding <= std::numeric_limits<decltype(VkResource::Binding)>::max(), "Binding (", Binding, ") excceeds representable max value");
- }
- else
- {
- // If pipeline layout is not provided - use artifial layout to store
- // static shader resources in one large continuous descriptor set
- VERIFY_EXPR(pStaticResourceCache != nullptr);
- DescriptorSet = 0;
- CacheOffset = StaticResCacheSize;
- Binding = Attribs.Type;
- StaticResCacheSize += Attribs.ArraySize;
+ auto* pStaticSampler = Resources.GetStaticSampler(Attribs);
+ VkSampler vkStaticSampler = VK_NULL_HANDLE;
+ if (pStaticSampler != nullptr)
+ vkStaticSampler = ValidatedCast<SamplerVkImpl>(pStaticSampler)->GetVkSampler();
+
+ auto& ShaderSPIRV = SPIRVs[ShaderInd];
+ PipelineLayout.AllocateResourceSlot(Attribs, vkStaticSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset, ShaderSPIRV);
+ VERIFY(DescriptorSet <= std::numeric_limits<decltype(VkResource::DescriptorSet)>::max(), "Descriptor set (", DescriptorSet, ") excceeds max representable value");
+ VERIFY(Binding <= std::numeric_limits<decltype(VkResource::Binding)>::max(), "Binding (", Binding, ") excceeds max representable value");
+
+#ifdef _DEBUG
+ // Verify that bindings and cache offsets monotonically increase in every descriptor set
+ auto Binding_OffsetIt = dbgBindings_CacheOffsets.find(DescriptorSet);
+ if(Binding_OffsetIt != dbgBindings_CacheOffsets.end())
+ {
+ VERIFY(Binding > Binding_OffsetIt->second.first, "Binding for descriptor set ", DescriptorSet, " is not strictly monotonic");
+ VERIFY(CacheOffset > Binding_OffsetIt->second.second, "Cache offset for descriptor set ", DescriptorSet, " is not strictly monotonic");
}
+ dbgBindings_CacheOffsets[DescriptorSet] = std::make_pair(Binding, CacheOffset);
+#endif
- ::new (&GetResource(Attribs.VarType, CurrResInd[Attribs.VarType]++)) VkResource( *this, Attribs, Binding, DescriptorSet, CacheOffset);
+ auto& ResInd = CurrResInd[ShaderInd][Attribs.VarType];
+ ::new (&ResLayout.GetResource(Attribs.VarType, ResInd++)) VkResource(ResLayout, Attribs, Binding, DescriptorSet, CacheOffset);
};
- m_pResources->ProcessResources(
- AllowedVarTypes, NumAllowedTypes,
-
- [&](const SPIRVShaderResourceAttribs &UB, Uint32)
- {
- VERIFY_EXPR(IsAllowedType(UB.VarType, AllowedTypeBits));
- AddResource(UB);
- },
- [&](const SPIRVShaderResourceAttribs& SB, Uint32)
- {
- VERIFY_EXPR(IsAllowedType(SB.VarType, AllowedTypeBits));
- AddResource(SB);
- },
- [&](const SPIRVShaderResourceAttribs &Img, Uint32)
- {
- VERIFY_EXPR(IsAllowedType(Img.VarType, AllowedTypeBits));
- AddResource(Img);
- },
- [&](const SPIRVShaderResourceAttribs &SmplImg, Uint32)
- {
- VERIFY_EXPR(IsAllowedType(SmplImg.VarType, AllowedTypeBits));
- AddResource(SmplImg);
- },
- [&](const SPIRVShaderResourceAttribs &AC, Uint32)
- {
- VERIFY_EXPR(IsAllowedType(AC.VarType, AllowedTypeBits));
- AddResource(AC);
- },
- [&](const SPIRVShaderResourceAttribs &SepImg, Uint32)
+ // First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set
+ for (Uint32 s = 0; s < NumShaders; ++s)
+ {
+ auto& Layout = Layouts[s];
+ const auto& Resources = *Layout.m_pResources;
+ for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n)
{
- VERIFY_EXPR(IsAllowedType(SepImg.VarType, AllowedTypeBits));
- AddResource(SepImg);
- },
+ const auto& UB = Resources.GetUB(n);
+ if (IsAllowedType(UB.VarType, AllowedTypeBits))
+ {
+ AddResource(s, Layout, Resources, UB);
+ }
+ }
+ }
- [&](const SPIRVShaderResourceAttribs &SepSmpl, Uint32)
+ // Second, process all storage buffers
+ for (Uint32 s = 0; s < NumShaders; ++s)
+ {
+ auto& Layout = Layouts[s];
+ const auto& Resources = *Layout.m_pResources;
+ for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n)
{
- VERIFY_EXPR(IsAllowedType(SepSmpl.VarType, AllowedTypeBits));
- AddResource(SepSmpl);
+ const auto& SB = Resources.GetSB(n);
+ if (IsAllowedType(SB.VarType, AllowedTypeBits))
+ {
+ AddResource(s, Layout, Resources, SB);
+ }
}
- );
+ }
-#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))
+ // Finally, process all other resource types
+ for (Uint32 s = 0; s < NumShaders; ++s)
{
- VERIFY( CurrResInd[VarType] == m_NumResources[VarType], "Not all resources are initialized, which will cause a crash when dtor is called" );
+ auto& Layout = Layouts[s];
+ const auto& Resources = *Layout.m_pResources;
+ Resources.ProcessResources(
+ AllowedVarTypes, NumAllowedTypes,
+
+ [&](const SPIRVShaderResourceAttribs &UB, Uint32)
+ {
+ VERIFY_EXPR(IsAllowedType(UB.VarType, AllowedTypeBits));
+ // Skip
+ },
+ [&](const SPIRVShaderResourceAttribs& SB, Uint32)
+ {
+ VERIFY_EXPR(IsAllowedType(SB.VarType, AllowedTypeBits));
+ // Skip
+ },
+ [&](const SPIRVShaderResourceAttribs &Img, Uint32)
+ {
+ VERIFY_EXPR(IsAllowedType(Img.VarType, AllowedTypeBits));
+ AddResource(s, Layout, Resources, Img);
+ },
+ [&](const SPIRVShaderResourceAttribs &SmplImg, Uint32)
+ {
+ VERIFY_EXPR(IsAllowedType(SmplImg.VarType, AllowedTypeBits));
+ AddResource(s, Layout, Resources, SmplImg);
+ },
+ [&](const SPIRVShaderResourceAttribs &AC, Uint32)
+ {
+ VERIFY_EXPR(IsAllowedType(AC.VarType, AllowedTypeBits));
+ AddResource(s, Layout, Resources, AC);
+ },
+ [&](const SPIRVShaderResourceAttribs &SepImg, Uint32)
+ {
+ VERIFY_EXPR(IsAllowedType(SepImg.VarType, AllowedTypeBits));
+ AddResource(s, Layout, Resources, SepImg);
+ },
+
+ [&](const SPIRVShaderResourceAttribs &SepSmpl, Uint32)
+ {
+ VERIFY_EXPR(IsAllowedType(SepSmpl.VarType, AllowedTypeBits));
+ AddResource(s, Layout, Resources, SepSmpl);
+ }
+ );
}
-#endif
- if(pStaticResourceCache)
+#ifdef _DEBUG
+ for (Uint32 s = 0; s < NumShaders; ++s)
{
- // Initialize resource cache to store static resources
- VERIFY_EXPR(pPipelineLayout == nullptr && pSPIRV == nullptr);
- pStaticResourceCache->InitializeSets(GetRawAllocator(), 1, &StaticResCacheSize);
- InitializeResourceMemoryInCache(*pStaticResourceCache);
+ auto& Layout = Layouts[s];
+ for (SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType + 1))
+ {
+ VERIFY(CurrResInd[s][VarType] == Layout.m_NumResources[VarType], "Not all resources are initialized, which will cause a crash when dtor is called");
+ }
}
+#endif
}
-
#define LOG_RESOURCE_BINDING_ERROR(ResType, pResource, VarName, ShaderName, ...)\
{ \
const auto &ResName = pResource->GetDesc().Name; \
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
index bfcf2a4a..ed1eabc0 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
@@ -59,13 +59,9 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters *pRefCounters, RenderDeviceVkImpl
auto *pResources = new (pRawMem) SPIRVShaderResources(Allocator, pRenderDeviceVk, m_SPIRV, m_Desc);
m_pShaderResources.reset(pResources, STDDeleterRawMem<SPIRVShaderResources>(Allocator));
- // Clone only static resources that will be set directly through the shader object
- 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(), VarTypes.data(),
- static_cast<Uint32>(VarTypes.size()), m_StaticResCache);
+ m_StaticResLayout.InitializeStaticResourceLayout(m_pShaderResources, GetRawAllocator(), m_StaticResCache);
+ // m_StaticResLayout only contains static resources, so reference all of them
+ m_StaticVarsMgr.Initialize(m_StaticResLayout, GetRawAllocator(), nullptr, 0, m_StaticResCache);
}
ShaderVkImpl::~ShaderVkImpl()