summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-10-08 18:45:01 +0000
committerazhirnov <zh1dron@gmail.com>2020-10-08 18:46:35 +0000
commit2b396d236ab33dfe9c0defbe401d354ed3fb34f9 (patch)
tree575243bb9aa6215725a8b16a7747c103c1eda852 /Graphics/GraphicsEngineVulkan
parentUpdated PipelineState[D3D11,D3D12,Vk]Impl to allocate single chunk of memory ... (diff)
downloadDiligentCore-2b396d236ab33dfe9c0defbe401d354ed3fb34f9.tar.gz
DiligentCore-2b396d236ab33dfe9c0defbe401d354ed3fb34f9.zip
removed strong references to shaders in PSO
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp15
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp118
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp3
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp22
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp602
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp8
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp346
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp23
9 files changed, 595 insertions, 544 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
index d1732211..303496bb 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
@@ -56,6 +56,7 @@ class PipelineStateVkImpl final : public PipelineStateBase<IPipelineStateVk, Ren
{
public:
using TPipelineStateBase = PipelineStateBase<IPipelineStateVk, RenderDeviceVkImpl>;
+ using ShaderSPIRVs_t = std::vector<std::vector<uint32_t>>;
PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const PipelineStateCreateInfo& CreateInfo);
~PipelineStateVkImpl();
@@ -104,7 +105,7 @@ public:
const ShaderResourceLayoutVk& GetShaderResLayout(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < m_NumShaderTypes);
return m_ShaderResourceLayouts[ShaderInd];
}
@@ -127,19 +128,19 @@ public:
private:
const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
- return m_ShaderResourceLayouts[m_NumShaders + ShaderInd];
+ VERIFY_EXPR(ShaderInd < m_NumShaderTypes);
+ return m_ShaderResourceLayouts[m_NumShaderTypes + ShaderInd];
}
const ShaderResourceCacheVk& GetStaticResCache(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < m_NumShaderTypes);
return m_StaticResCaches[ShaderInd];
}
ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < m_NumShaderTypes);
return m_StaticVarsMgrs[ShaderInd];
}
@@ -150,14 +151,12 @@ private:
// SRB memory allocator must be declared before m_pDefaultShaderResBinding
SRBMemoryAllocator m_SRBMemAllocator;
- std::array<VulkanUtilities::ShaderModuleWrapper, MAX_SHADERS_IN_PIPELINE> m_ShaderModules = {};
-
VulkanUtilities::PipelineWrapper m_Pipeline;
PipelineLayout m_PipelineLayout;
// Resource layout index in m_ShaderResourceLayouts array for every shader stage,
// indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex)
- std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1};
+ std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex;
bool m_HasStaticResources = false;
bool m_HasNonStaticResources = false;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
index 026bb9da..85230b02 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
@@ -81,7 +81,7 @@ private:
// Resource layout index in m_ShaderResourceCache array for every shader stage,
// indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex)
- std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1};
+ std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex;
bool m_bStaticResourcesInitialized = false;
Uint8 m_NumShaders = 0;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
index a6d20641..28defd0f 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
@@ -115,6 +115,9 @@ namespace Diligent
class ShaderResourceLayoutVk
{
public:
+ using ShaderStages_t = std::vector<std::pair<SHADER_TYPE, IShader*>>;
+ using ShaderSPIRVs_t = std::vector<std::vector<uint32_t>>;
+
ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) :
m_LogicalDevice{LogicalDevice}
{
@@ -131,23 +134,22 @@ public:
// This method is called by PipelineStateVkImpl class instance to initialize static
// shader resource layout and the cache
- void InitializeStaticResourceLayout(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- ShaderResourceCacheVk& StaticResourceCache);
+ void InitializeStaticResourceLayout(IShader* pShader,
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ ShaderResourceCacheVk& StaticResourceCache);
// This method is called by PipelineStateVkImpl class instance to initialize resource
// layouts for all shader stages in the pipeline.
- static void Initialize(IRenderDevice* pRenderDevice,
- Uint32 NumShaders,
- ShaderResourceLayoutVk Layouts[],
- std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- std::vector<uint32_t> SPIRVs[],
- class PipelineLayout& PipelineLayout,
- bool VerifyVariables,
- bool VerifyStaticSamplers);
+ static void Initialize(IRenderDevice* pRenderDevice,
+ const ShaderStages_t& ShaderStages,
+ ShaderResourceLayoutVk Layouts[],
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ ShaderSPIRVs_t& SPIRVs,
+ class PipelineLayout& PipelineLayout,
+ bool VerifyVariables,
+ bool VerifyStaticSamplers);
// sizeof(VkResource) == 24 (x64)
struct VkResource
@@ -175,33 +177,21 @@ public:
/* 7.5 */ const Uint32 VariableType : VariableTypeBits;
/* 7.7 */ const Uint32 ImmutableSamplerAssigned : ImmutableSamplerFlagBits;
-/* 8 */ const SPIRVShaderResourceAttribs& SpirvAttribs;
-/* 16 */ const ShaderResourceLayoutVk& ParentResLayout;
-
- VkResource(const ShaderResourceLayoutVk& _ParentLayout,
- const SPIRVShaderResourceAttribs& _SpirvAttribs,
- SHADER_RESOURCE_VARIABLE_TYPE _VariableType,
- uint32_t _Binding,
- uint32_t _DescriptorSet,
- Uint32 _CacheOffset,
- Uint32 _SamplerInd,
- bool _ImmutableSamplerAssigned = false)noexcept :
- Binding {static_cast<decltype(Binding)>(_Binding) },
- DescriptorSet {static_cast<decltype(DescriptorSet)>(_DescriptorSet)},
- CacheOffset {_CacheOffset },
- SamplerInd {_SamplerInd },
- VariableType {_VariableType },
- ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U},
- SpirvAttribs {_SpirvAttribs },
- ParentResLayout {_ParentLayout }
- {
- VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits) );
- VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits) );
- VERIFY(_Binding <= std::numeric_limits<decltype(Binding)>::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits<decltype(Binding)>::max() );
- VERIFY(_DescriptorSet <= std::numeric_limits<decltype(DescriptorSet)>::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits<decltype(DescriptorSet)>::max());
- }
+/* 8 */ const SPIRVShaderResourceAttribs SpirvAttribs;
+/* 16 */ const ShaderResourceLayoutVk& ParentResLayout;
// clang-format on
+ VkResource(const ShaderResourceLayoutVk& _ParentLayout,
+ const SPIRVShaderResourceAttribs& _SpirvAttribs,
+ SHADER_RESOURCE_VARIABLE_TYPE _VariableType,
+ uint32_t _Binding,
+ uint32_t _DescriptorSet,
+ Uint32 _CacheOffset,
+ Uint32 _SamplerInd,
+ bool _ImmutableSamplerAssigned = false) noexcept;
+
+ ~VkResource();
+
// Checks if a resource is bound in ResourceCache at the given ArrayIndex
bool IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const;
@@ -279,11 +269,10 @@ public:
#ifdef DILIGENT_DEVELOPMENT
bool dvpVerifyBindings(const ShaderResourceCacheVk& ResourceCache) const;
- static void dvpVerifyResourceLayoutDesc(Uint32 NumShaders,
- const std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- bool VerifyVariables,
- bool VerifyStaticSamplers);
+ static void dvpVerifyResourceLayoutDesc(const ShaderStages_t& ShaderStages,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ bool VerifyVariables,
+ bool VerifyStaticSamplers);
#endif
Uint32 GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
@@ -300,13 +289,10 @@ public:
const Char* GetShaderName() const
{
- return m_pResources->GetShaderName();
+ return ""; // AZ TODO
}
- SHADER_TYPE GetShaderType() const
- {
- return m_pResources->GetShaderType();
- }
+ SHADER_TYPE GetShaderType() const { return m_ShaderType; }
const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const
{
@@ -315,7 +301,7 @@ public:
return Resources[GetResourceOffset(VarType, r)];
}
- bool IsUsingSeparateSamplers() const { return !m_pResources->IsUsingCombinedSamplers(); }
+ bool IsUsingSeparateSamplers() const { return m_IsUsingSeparateSamplers; }
private:
Uint32 GetResourceOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const
@@ -346,16 +332,12 @@ private:
return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES];
}
- void AllocateMemory(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
- IMemoryAllocator& Allocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- bool AllocateImmutableSamplers);
-
- Uint32 FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg,
- Uint32 CurrResourceCount,
- SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) const;
+ void AllocateMemory(IShader* pShader,
+ IMemoryAllocator& Allocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ bool AllocateImmutableSamplers);
using ImmutableSamplerPtrType = RefCntAutoPtr<ISampler>;
ImmutableSamplerPtrType& GetImmutableSampler(Uint32 n) noexcept
@@ -366,16 +348,16 @@ private:
}
// clang-format off
-/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice;
-/* 8 */ std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer;
+/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice;
+/* 8 */ std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer;
+
+/*24 */ std::array<Uint16, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES+1> m_NumResources = {};
- // We must use shared_ptr to reference ShaderResources instance, because
- // there may be multiple objects referencing the same set of resources
-/*24 */ std::shared_ptr<const SPIRVShaderResources> m_pResources;
+/*32 */ Uint32 m_NumImmutableSamplers = 0;
+/*36 */ bool m_IsUsingSeparateSamplers = false;
+/*37 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN;
-/*40 */ std::array<Uint16, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES+1> m_NumResources = {};
-/*48 */ Uint32 m_NumImmutableSamplers = 0;
-/*56*/ // End of class
+/*40 */ // End of class
// clang-format on
};
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
index dbba5b7e..1e6749f1 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
@@ -82,4 +82,7 @@ ATTACHMENT_STORE_OP VkAttachmentStoreOpToAttachmentStoreOp(VkAttachmentStoreOp V
VkPipelineStageFlags PipelineStageFlagsToVkPipelineStageFlags(PIPELINE_STAGE_FLAGS PipelineStageFlags);
VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags);
+
+VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType);
+
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
index 2fd063c9..6ed84171 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
@@ -40,28 +40,6 @@
namespace Diligent
{
-
-static VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType)
-{
- static_assert(SHADER_TYPE_LAST == 0x080, "Please update the switch below to handle the new shader type");
- switch (ShaderType)
- {
- // clang-format off
- case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT;
- case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
- case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
- case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT;
- case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT;
- case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT;
- case SHADER_TYPE_AMPLIFICATION: return VK_SHADER_STAGE_TASK_BIT_NV;
- case SHADER_TYPE_MESH: return VK_SHADER_STAGE_MESH_BIT_NV;
- // clang-format on
- default:
- UNEXPECTED("Unknown shader type");
- return VK_SHADER_STAGE_VERTEX_BIT;
- }
-}
-
class ResourceTypeToVkDescriptorType
{
public:
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 75dd3263..29d16239 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -129,352 +129,376 @@ RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc(
return RPDesc;
}
-static std::vector<uint32_t> StripReflection(const std::vector<uint32_t>& OriginalSPIRV)
+static bool StripReflection(std::vector<uint32_t>& SPIRV)
{
#if DILIGENT_NO_HLSL
- return OriginalSPIRV;
+ return false;
#else
std::vector<uint32_t> StrippedSPIRV;
spvtools::Optimizer SpirvOptimizer(SPV_ENV_VULKAN_1_0);
// Decorations defined in SPV_GOOGLE_hlsl_functionality1 are the only instructions
// removed by strip-reflect-info pass. SPIRV offsets become INVALID after this operation.
SpirvOptimizer.RegisterPass(spvtools::CreateStripReflectInfoPass());
- auto res = SpirvOptimizer.Run(OriginalSPIRV.data(), OriginalSPIRV.size(), &StrippedSPIRV);
- if (!res)
+ if (SpirvOptimizer.Run(SPIRV.data(), SPIRV.size(), &StrippedSPIRV))
{
- // Optimized SPIRV may be invalid
- StrippedSPIRV.clear();
+ SPIRV = std::move(StrippedSPIRV);
+ return true;
}
- return StrippedSPIRV;
+ else
+ return false;
#endif
}
-PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters,
- RenderDeviceVkImpl* pDeviceVk,
- const PipelineStateCreateInfo& CreateInfo) :
- TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc},
- m_SRBMemAllocator{GetRawAllocator()}
+static void InitializeShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
+ const PipelineStateVkImpl::ShaderStages_t& ShaderStages,
+ PipelineStateVkImpl::ShaderSPIRVs_t& ShaderSPIRVs,
+ std::vector<VulkanUtilities::ShaderModuleWrapper>& ShaderModules,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages)
{
- m_ResourceLayoutIndex.fill(-1);
-
- const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+ VERIFY_EXPR(ShaderStages.size() == ShaderSPIRVs.size());
- std::array<std::shared_ptr<const SPIRVShaderResources>, MAX_SHADERS_IN_PIPELINE> ShaderResources;
- std::array<std::vector<uint32_t>, MAX_SHADERS_IN_PIPELINE> ShaderSPIRVs;
-
- // clang-format off
- static_assert((sizeof(ShaderResourceLayoutVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutVk) is expected to be a multiple of sizeof(void*)");
- static_assert((sizeof(ShaderResourceCacheVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheVk) is expected to be a multiple of sizeof(void*)");
- static_assert((sizeof(ShaderVariableManagerVk) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerVk) is expected to be a multiple of sizeof(void*)");
- // clang-format on
- const auto MemSize = (sizeof(ShaderResourceLayoutVk) * 2 + sizeof(ShaderResourceCacheVk) + sizeof(ShaderVariableManagerVk)) * m_NumShaders;
- auto* const pRawMem =
- ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutVk, ShaderResourceCacheVk, and ShaderVariableManagerVk arrays", MemSize);
-
- m_ShaderResourceLayouts = reinterpret_cast<ShaderResourceLayoutVk*>(pRawMem);
- m_StaticResCaches = reinterpret_cast<ShaderResourceCacheVk*>(m_ShaderResourceLayouts + m_NumShaders * 2);
- m_StaticVarsMgrs = reinterpret_cast<ShaderVariableManagerVk*>(m_StaticResCaches + m_NumShaders);
-
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk{LogicalDevice};
- auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
- ShaderResources[s] = pShaderVk->GetShaderResources();
- ShaderSPIRVs[s] = pShaderVk->GetSPIRV();
-
- const auto ShaderType = pShaderVk->GetDesc().ShaderType;
- const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType);
- m_ResourceLayoutIndex[ShaderTypeInd] = static_cast<Int8>(s);
-
- auto* pStaticResLayout = new (m_ShaderResourceLayouts + m_NumShaders + s) ShaderResourceLayoutVk{LogicalDevice};
- auto* pStaticResCache = new (m_StaticResCaches + s) ShaderResourceCacheVk{ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources};
- pStaticResLayout->InitializeStaticResourceLayout(ShaderResources[s], GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]);
-
- new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, *pStaticResLayout, GetRawAllocator(), nullptr, 0, *pStaticResCache};
- }
- ShaderResourceLayoutVk::Initialize(pDeviceVk, m_NumShaders, m_ShaderResourceLayouts, ShaderResources.data(), GetRawAllocator(),
- m_Desc.ResourceLayout, ShaderSPIRVs.data(), m_PipelineLayout,
- (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0,
- (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0);
- m_PipelineLayout.Finalize(LogicalDevice);
+ auto* pShaderVk = ValidatedCast<ShaderVkImpl>(ShaderStages[s].second);
+ auto& SPIRV = ShaderSPIRVs[s];
+ const auto ShaderType = ShaderStages[s].first;
- if (m_Desc.SRBAllocationGranularity > 1)
- {
- std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderVariableDataSizes = {};
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
+ VkPipelineShaderStageCreateInfo StageCI = {};
- Uint32 UnusedNumVars = 0;
- ShaderVariableDataSizes[s] = ShaderVariableManagerVk::GetRequiredMemorySize(m_ShaderResourceLayouts[s], AllowedVarTypes, _countof(AllowedVarTypes), UnusedNumVars);
- }
-
- Uint32 NumSets = 0;
- auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets);
- auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data());
-
- m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, m_NumShaders, ShaderVariableDataSizes.data(), 1, &CacheMemorySize);
- }
-
- // Create shader modules and initialize shader stages
- std::array<VkPipelineShaderStageCreateInfo, MAX_SHADERS_IN_PIPELINE> ShaderStages = {};
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
- auto ShaderType = pShaderVk->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)
- {
- // clang-format off
- 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;
- case SHADER_TYPE_AMPLIFICATION: StageCI.stage = VK_SHADER_STAGE_TASK_BIT_NV; break;
- case SHADER_TYPE_MESH: StageCI.stage = VK_SHADER_STAGE_MESH_BIT_NV; break;
- default: UNEXPECTED("Unknown shader type");
- // clang-format on
- }
+ StageCI.stage = ShaderTypeToVkShaderStageFlagBit(ShaderType);
VkShaderModuleCreateInfo ShaderModuleCI = {};
ShaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
ShaderModuleCI.pNext = nullptr;
ShaderModuleCI.flags = 0;
- const auto& SPIRV = ShaderSPIRVs[s];
// We have to strip reflection instructions to fix the follownig validation error:
// SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string
// Optimizer also performs validation and may catch problems with the byte code.
- auto StrippedSPIRV = StripReflection(SPIRV);
- if (!StrippedSPIRV.empty())
- {
- ShaderModuleCI.codeSize = StrippedSPIRV.size() * sizeof(uint32_t);
- ShaderModuleCI.pCode = StrippedSPIRV.data();
- }
- else
- {
+ if (!StripReflection(SPIRV))
LOG_ERROR("Failed to strip reflection information from shader '", pShaderVk->GetDesc().Name, "'. This may indicate a problem with the byte code.");
- ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t);
- ShaderModuleCI.pCode = SPIRV.data();
- }
- m_ShaderModules[s] = LogicalDevice.CreateShaderModule(ShaderModuleCI, pShaderVk->GetDesc().Name);
+ ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t);
+ ShaderModuleCI.pCode = SPIRV.data();
+
+ ShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, pShaderVk->GetDesc().Name));
- StageCI.module = m_ShaderModules[s];
+ StageCI.module = ShaderModules.back();
StageCI.pName = pShaderVk->GetEntryPoint();
StageCI.pSpecializationInfo = nullptr;
+
+ Stages.push_back(StageCI);
}
- // Create pipeline
- if (m_Desc.IsComputePipeline())
- {
- auto& ComputePipeline = m_Desc.ComputePipeline;
+ VERIFY_EXPR(ShaderModules.size() == Stages.size());
+}
+
+
+static void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages,
+ const PipelineLayout& Layout,
+ const PipelineStateDesc& Desc,
+ VulkanUtilities::PipelineWrapper& Pipeline)
+{
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+
+ VkComputePipelineCreateInfo PipelineCI = {};
+
+ PipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
+ PipelineCI.pNext = nullptr;
+#ifdef DILIGENT_DEBUG
+ PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
+#endif
+ PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
+ PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from
- if (ComputePipeline.pCS == nullptr)
- LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc");
+ PipelineCI.stage = Stages[0];
+ PipelineCI.layout = Layout.GetVkPipelineLayout();
- VkComputePipelineCreateInfo PipelineCI = {};
+ Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, Desc.Name);
+}
+
+
+static void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages,
+ const PipelineLayout& Layout,
+ const PipelineStateDesc& Desc,
+ VulkanUtilities::PipelineWrapper& Pipeline,
+ RefCntAutoPtr<IRenderPass>& pRenderPass)
+{
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+ const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
+ auto& GraphicsPipeline = Desc.GraphicsPipeline;
+ auto& RPCache = pDeviceVk->GetImplicitRenderPassCache();
+
+ if (pRenderPass == nullptr)
+ {
+ RenderPassCache::RenderPassCacheKey Key{
+ GraphicsPipeline.NumRenderTargets,
+ GraphicsPipeline.SmplDesc.Count,
+ GraphicsPipeline.RTVFormats,
+ GraphicsPipeline.DSVFormat};
+ pRenderPass = RPCache.GetRenderPass(Key);
+ }
+
+ VkGraphicsPipelineCreateInfo PipelineCI = {};
- PipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
- PipelineCI.pNext = nullptr;
+ PipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+ PipelineCI.pNext = nullptr;
#ifdef DILIGENT_DEBUG
- PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
+ PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
#endif
- PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
- PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from
- PipelineCI.stage = ShaderStages[0];
- PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout();
+ PipelineCI.stageCount = static_cast<Uint32>(Stages.size());
+ PipelineCI.pStages = Stages.data();
+ PipelineCI.layout = Layout.GetVkPipelineLayout();
+
+ VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {};
+
+ std::array<VkVertexInputBindingDescription, MAX_LAYOUT_ELEMENTS> BindingDescriptions;
+ std::array<VkVertexInputAttributeDescription, MAX_LAYOUT_ELEMENTS> AttributeDescription;
+ InputLayoutDesc_To_VkVertexInputStateCI(GraphicsPipeline.InputLayout, VertexInputStateCI, BindingDescriptions, AttributeDescription);
+ PipelineCI.pVertexInputState = &VertexInputStateCI;
- m_Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name);
+
+ VkPipelineInputAssemblyStateCreateInfo InputAssemblyCI = {};
+
+ InputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ InputAssemblyCI.pNext = nullptr;
+ InputAssemblyCI.flags = 0; // reserved for future use
+ InputAssemblyCI.primitiveRestartEnable = VK_FALSE;
+ PipelineCI.pInputAssemblyState = &InputAssemblyCI;
+
+
+ VkPipelineTessellationStateCreateInfo TessStateCI = {};
+
+ TessStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
+ TessStateCI.pNext = nullptr;
+ TessStateCI.flags = 0; // reserved for future use
+ PipelineCI.pTessellationState = &TessStateCI;
+
+ if (Desc.PipelineType == PIPELINE_TYPE_MESH)
+ {
+ // Input assembly is not used in the mesh pipeline, so topology may contain any value.
+ // Validation layers may generate a warning if point_list topology is used, so use MAX_ENUM value.
+ InputAssemblyCI.topology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
+
+ // Vertex input state and tessellation state are ignored in a mesh pipeline and should be null.
+ PipelineCI.pVertexInputState = nullptr;
+ PipelineCI.pTessellationState = nullptr;
}
else
{
- const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
- auto& GraphicsPipeline = m_Desc.GraphicsPipeline;
- auto& RPCache = pDeviceVk->GetImplicitRenderPassCache();
+ PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(GraphicsPipeline.PrimitiveTopology, InputAssemblyCI.topology, TessStateCI.patchControlPoints);
+ }
- if (m_pRenderPass == nullptr)
+ VkPipelineViewportStateCreateInfo ViewPortStateCI = {};
+
+ ViewPortStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ ViewPortStateCI.pNext = nullptr;
+ ViewPortStateCI.flags = 0; // reserved for future use
+ ViewPortStateCI.viewportCount =
+ GraphicsPipeline.NumViewports; // Even though we use dynamic viewports, the number of viewports used
+ // by the pipeline is still specified by the viewportCount member (23.5)
+ ViewPortStateCI.pViewports = nullptr; // We will be using dynamic viewport & scissor states
+ ViewPortStateCI.scissorCount = ViewPortStateCI.viewportCount; // the number of scissors must match the number of viewports (23.5)
+ // (why the hell it is in the struct then?)
+ VkRect2D ScissorRect = {};
+ if (GraphicsPipeline.RasterizerDesc.ScissorEnable)
+ {
+ ViewPortStateCI.pScissors = nullptr; // Ignored if the scissor state is dynamic
+ }
+ else
+ {
+ const auto& Props = PhysicalDevice.GetProperties();
+ // There are limitiations on the viewport width and height (23.5), but
+ // it is not clear if there are limitations on the scissor rect width and
+ // height
+ ScissorRect.extent.width = Props.limits.maxViewportDimensions[0];
+ ScissorRect.extent.height = Props.limits.maxViewportDimensions[1];
+ ViewPortStateCI.pScissors = &ScissorRect;
+ }
+ PipelineCI.pViewportState = &ViewPortStateCI;
+
+ VkPipelineRasterizationStateCreateInfo RasterizerStateCI =
+ RasterizerStateDesc_To_VkRasterizationStateCI(GraphicsPipeline.RasterizerDesc);
+ PipelineCI.pRasterizationState = &RasterizerStateCI;
+
+ // Multisample state (24)
+ VkPipelineMultisampleStateCreateInfo MSStateCI = {};
+
+ MSStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ MSStateCI.pNext = nullptr;
+ MSStateCI.flags = 0; // reserved for future use
+ // If subpass uses color and/or depth/stencil attachments, then the rasterizationSamples member of
+ // pMultisampleState must be the same as the sample count for those subpass attachments
+ MSStateCI.rasterizationSamples = static_cast<VkSampleCountFlagBits>(GraphicsPipeline.SmplDesc.Count);
+ MSStateCI.sampleShadingEnable = VK_FALSE;
+ MSStateCI.minSampleShading = 0; // a minimum fraction of sample shading if sampleShadingEnable is set to VK_TRUE.
+ uint32_t SampleMask[] = {GraphicsPipeline.SampleMask, 0}; // Vulkan spec allows up to 64 samples
+ MSStateCI.pSampleMask = SampleMask; // an array of static coverage information that is ANDed with
+ // the coverage information generated during rasterization (25.3)
+ MSStateCI.alphaToCoverageEnable = VK_FALSE; // whether a temporary coverage value is generated based on
+ // the alpha component of the fragment's first color output
+ MSStateCI.alphaToOneEnable = VK_FALSE; // whether the alpha component of the fragment's first color output is replaced with one
+ PipelineCI.pMultisampleState = &MSStateCI;
+
+ VkPipelineDepthStencilStateCreateInfo DepthStencilStateCI =
+ DepthStencilStateDesc_To_VkDepthStencilStateCI(GraphicsPipeline.DepthStencilDesc);
+ PipelineCI.pDepthStencilState = &DepthStencilStateCI;
+
+ const auto& RPDesc = pRenderPass->GetDesc();
+ const auto NumRTAttachments = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex].RenderTargetAttachmentCount;
+ VERIFY_EXPR(GraphicsPipeline.pRenderPass != nullptr || GraphicsPipeline.NumRenderTargets == NumRTAttachments);
+ std::vector<VkPipelineColorBlendAttachmentState> ColorBlendAttachmentStates(NumRTAttachments);
+
+ VkPipelineColorBlendStateCreateInfo BlendStateCI = {};
+
+ BlendStateCI.pAttachments = !ColorBlendAttachmentStates.empty() ? ColorBlendAttachmentStates.data() : nullptr;
+ BlendStateCI.attachmentCount = NumRTAttachments; // must equal the colorAttachmentCount for the subpass
+ // in which this pipeline is used.
+ BlendStateDesc_To_VkBlendStateCI(GraphicsPipeline.BlendDesc, BlendStateCI, ColorBlendAttachmentStates);
+ PipelineCI.pColorBlendState = &BlendStateCI;
+
+
+ VkPipelineDynamicStateCreateInfo DynamicStateCI = {};
+
+ DynamicStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ DynamicStateCI.pNext = nullptr;
+ DynamicStateCI.flags = 0; // reserved for future use
+ std::vector<VkDynamicState> DynamicStates =
{
- RenderPassCache::RenderPassCacheKey Key{
- GraphicsPipeline.NumRenderTargets,
- GraphicsPipeline.SmplDesc.Count,
- GraphicsPipeline.RTVFormats,
- GraphicsPipeline.DSVFormat};
- m_pRenderPass = RPCache.GetRenderPass(Key);
- }
+ VK_DYNAMIC_STATE_VIEWPORT, // pViewports state in VkPipelineViewportStateCreateInfo will be ignored and must be
+ // set dynamically with vkCmdSetViewport before any draw commands. The number of viewports
+ // used by a pipeline is still specified by the viewportCount member of
+ // VkPipelineViewportStateCreateInfo.
- VkGraphicsPipelineCreateInfo PipelineCI = {};
+ VK_DYNAMIC_STATE_BLEND_CONSTANTS, // blendConstants state in VkPipelineColorBlendStateCreateInfo will be ignored
+ // and must be set dynamically with vkCmdSetBlendConstants
- PipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- PipelineCI.pNext = nullptr;
-#ifdef DILIGENT_DEBUG
- PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
-#endif
+ VK_DYNAMIC_STATE_STENCIL_REFERENCE // pecifies that the reference state in VkPipelineDepthStencilStateCreateInfo
+ // for both front and back will be ignored and must be set dynamically
+ // with vkCmdSetStencilReference
+ };
- PipelineCI.stageCount = m_NumShaders;
- PipelineCI.pStages = ShaderStages.data();
- PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout();
+ if (GraphicsPipeline.RasterizerDesc.ScissorEnable)
+ {
+ // pScissors state in VkPipelineViewportStateCreateInfo will be ignored and must be set
+ // dynamically with vkCmdSetScissor before any draw commands. The number of scissor rectangles
+ // used by a pipeline is still specified by the scissorCount member of
+ // VkPipelineViewportStateCreateInfo.
+ DynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
+ }
+ DynamicStateCI.dynamicStateCount = static_cast<uint32_t>(DynamicStates.size());
+ DynamicStateCI.pDynamicStates = DynamicStates.data();
+ PipelineCI.pDynamicState = &DynamicStateCI;
- VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {};
- std::array<VkVertexInputBindingDescription, MAX_LAYOUT_ELEMENTS> BindingDescriptions;
- std::array<VkVertexInputAttributeDescription, MAX_LAYOUT_ELEMENTS> AttributeDescription;
- InputLayoutDesc_To_VkVertexInputStateCI(GraphicsPipeline.InputLayout, VertexInputStateCI, BindingDescriptions, AttributeDescription);
- PipelineCI.pVertexInputState = &VertexInputStateCI;
+ PipelineCI.renderPass = pRenderPass.RawPtr<IRenderPassVk>()->GetVkRenderPass();
+ PipelineCI.subpass = Desc.GraphicsPipeline.SubpassIndex;
+ PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
+ PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from
+ Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, Desc.Name);
+}
- VkPipelineInputAssemblyStateCreateInfo InputAssemblyCI = {};
- InputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
- InputAssemblyCI.pNext = nullptr;
- InputAssemblyCI.flags = 0; // reserved for future use
- InputAssemblyCI.primitiveRestartEnable = VK_FALSE;
- PipelineCI.pInputAssemblyState = &InputAssemblyCI;
+PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDeviceVk,
+ const PipelineStateCreateInfo& CreateInfo) :
+ TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc},
+ m_SRBMemAllocator{GetRawAllocator()}
+{
+ m_ResourceLayoutIndex.fill(-1);
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
- VkPipelineTessellationStateCreateInfo TessStateCI = {};
+ ShaderStages_t ShaderStages;
+ ShaderSPIRVs_t ShaderSPIRVs;
+ ExtractShaders(ShaderStages);
- TessStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
- TessStateCI.pNext = nullptr;
- TessStateCI.flags = 0; // reserved for future use
- PipelineCI.pTessellationState = &TessStateCI;
+ ShaderSPIRVs.resize(ShaderStages.size());
+ for (size_t s = 0; s < ShaderSPIRVs.size(); ++s)
+ {
+ auto* pShaderVk = ValidatedCast<ShaderVkImpl>(ShaderStages[s].second);
+ ShaderSPIRVs[s] = pShaderVk->GetSPIRV();
+ }
- if (m_Desc.PipelineType == PIPELINE_TYPE_MESH)
- {
- // Input assembly is not used in the mesh pipeline, so topology may contain any value.
- // Validation layers may generate a warning if point_list topology is used, so use MAX_ENUM value.
- InputAssemblyCI.topology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
+ // clang-format off
+ static_assert((sizeof(ShaderResourceLayoutVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutVk) is expected to be a multiple of sizeof(void*)");
+ static_assert((sizeof(ShaderResourceCacheVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheVk) is expected to be a multiple of sizeof(void*)");
+ static_assert((sizeof(ShaderVariableManagerVk) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerVk) is expected to be a multiple of sizeof(void*)");
+ // clang-format on
+ const auto MemSize = (sizeof(ShaderResourceLayoutVk) * 2 + sizeof(ShaderResourceCacheVk) + sizeof(ShaderVariableManagerVk)) * GetNumShaderTypes();
+ auto* const pRawMem =
+ ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutVk, ShaderResourceCacheVk, and ShaderVariableManagerVk arrays", MemSize);
- // Vertex input state and tessellation state are ignored in a mesh pipeline and should be null.
- PipelineCI.pVertexInputState = nullptr;
- PipelineCI.pTessellationState = nullptr;
- }
- else
- {
- PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(GraphicsPipeline.PrimitiveTopology, InputAssemblyCI.topology, TessStateCI.patchControlPoints);
- }
+ m_ShaderResourceLayouts = reinterpret_cast<ShaderResourceLayoutVk*>(pRawMem);
+ m_StaticResCaches = reinterpret_cast<ShaderResourceCacheVk*>(m_ShaderResourceLayouts + GetNumShaderTypes() * 2);
+ m_StaticVarsMgrs = reinterpret_cast<ShaderVariableManagerVk*>(m_StaticResCaches + GetNumShaderTypes());
- VkPipelineViewportStateCreateInfo ViewPortStateCI = {};
-
- ViewPortStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
- ViewPortStateCI.pNext = nullptr;
- ViewPortStateCI.flags = 0; // reserved for future use
- ViewPortStateCI.viewportCount =
- GraphicsPipeline.NumViewports; // Even though we use dynamic viewports, the number of viewports used
- // by the pipeline is still specified by the viewportCount member (23.5)
- ViewPortStateCI.pViewports = nullptr; // We will be using dynamic viewport & scissor states
- ViewPortStateCI.scissorCount = ViewPortStateCI.viewportCount; // the number of scissors must match the number of viewports (23.5)
- // (why the hell it is in the struct then?)
- VkRect2D ScissorRect = {};
- if (GraphicsPipeline.RasterizerDesc.ScissorEnable)
- {
- ViewPortStateCI.pScissors = nullptr; // Ignored if the scissor state is dynamic
- }
- else
- {
- const auto& Props = PhysicalDevice.GetProperties();
- // There are limitiations on the viewport width and height (23.5), but
- // it is not clear if there are limitations on the scissor rect width and
- // height
- ScissorRect.extent.width = Props.limits.maxViewportDimensions[0];
- ScissorRect.extent.height = Props.limits.maxViewportDimensions[1];
- ViewPortStateCI.pScissors = &ScissorRect;
- }
- PipelineCI.pViewportState = &ViewPortStateCI;
-
- VkPipelineRasterizationStateCreateInfo RasterizerStateCI =
- RasterizerStateDesc_To_VkRasterizationStateCI(GraphicsPipeline.RasterizerDesc);
- PipelineCI.pRasterizationState = &RasterizerStateCI;
-
- // Multisample state (24)
- VkPipelineMultisampleStateCreateInfo MSStateCI = {};
-
- MSStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- MSStateCI.pNext = nullptr;
- MSStateCI.flags = 0; // reserved for future use
- // If subpass uses color and/or depth/stencil attachments, then the rasterizationSamples member of
- // pMultisampleState must be the same as the sample count for those subpass attachments
- MSStateCI.rasterizationSamples = static_cast<VkSampleCountFlagBits>(GraphicsPipeline.SmplDesc.Count);
- MSStateCI.sampleShadingEnable = VK_FALSE;
- MSStateCI.minSampleShading = 0; // a minimum fraction of sample shading if sampleShadingEnable is set to VK_TRUE.
- uint32_t SampleMask[] = {GraphicsPipeline.SampleMask, 0}; // Vulkan spec allows up to 64 samples
- MSStateCI.pSampleMask = SampleMask; // an array of static coverage information that is ANDed with
- // the coverage information generated during rasterization (25.3)
- MSStateCI.alphaToCoverageEnable = VK_FALSE; // whether a temporary coverage value is generated based on
- // the alpha component of the fragment's first color output
- MSStateCI.alphaToOneEnable = VK_FALSE; // whether the alpha component of the fragment's first color output is replaced with one
- PipelineCI.pMultisampleState = &MSStateCI;
-
- VkPipelineDepthStencilStateCreateInfo DepthStencilStateCI =
- DepthStencilStateDesc_To_VkDepthStencilStateCI(GraphicsPipeline.DepthStencilDesc);
- PipelineCI.pDepthStencilState = &DepthStencilStateCI;
-
- const auto& RPDesc = m_pRenderPass->GetDesc();
- const auto NumRTAttachments = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex].RenderTargetAttachmentCount;
- VERIFY_EXPR(GraphicsPipeline.pRenderPass != nullptr || GraphicsPipeline.NumRenderTargets == NumRTAttachments);
- std::vector<VkPipelineColorBlendAttachmentState> ColorBlendAttachmentStates(NumRTAttachments);
-
- VkPipelineColorBlendStateCreateInfo BlendStateCI = {};
-
- BlendStateCI.pAttachments = !ColorBlendAttachmentStates.empty() ? ColorBlendAttachmentStates.data() : nullptr;
- BlendStateCI.attachmentCount = NumRTAttachments; // must equal the colorAttachmentCount for the subpass
- // in which this pipeline is used.
- BlendStateDesc_To_VkBlendStateCI(GraphicsPipeline.BlendDesc, BlendStateCI, ColorBlendAttachmentStates);
- PipelineCI.pColorBlendState = &BlendStateCI;
-
-
- VkPipelineDynamicStateCreateInfo DynamicStateCI = {};
-
- DynamicStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
- DynamicStateCI.pNext = nullptr;
- DynamicStateCI.flags = 0; // reserved for future use
- std::vector<VkDynamicState> DynamicStates =
- {
- VK_DYNAMIC_STATE_VIEWPORT, // pViewports state in VkPipelineViewportStateCreateInfo will be ignored and must be
- // set dynamically with vkCmdSetViewport before any draw commands. The number of viewports
- // used by a pipeline is still specified by the viewportCount member of
- // VkPipelineViewportStateCreateInfo.
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
+ {
+ new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk{LogicalDevice};
+
+ const auto ShaderType = ShaderStages[s].first;
+ auto& Shaders = ShaderStages[s].second;
+ const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType);
+ m_ResourceLayoutIndex[ShaderTypeInd] = static_cast<Int8>(s);
- VK_DYNAMIC_STATE_BLEND_CONSTANTS, // blendConstants state in VkPipelineColorBlendStateCreateInfo will be ignored
- // and must be set dynamically with vkCmdSetBlendConstants
+ auto* pStaticResLayout = new (m_ShaderResourceLayouts + ShaderStages.size() + s) ShaderResourceLayoutVk{LogicalDevice};
+ auto* pStaticResCache = new (m_StaticResCaches + s) ShaderResourceCacheVk{ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources};
+ pStaticResLayout->InitializeStaticResourceLayout(Shaders, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]);
- VK_DYNAMIC_STATE_STENCIL_REFERENCE // pecifies that the reference state in VkPipelineDepthStencilStateCreateInfo
- // for both front and back will be ignored and must be set dynamically
- // with vkCmdSetStencilReference
- };
+ new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, *pStaticResLayout, GetRawAllocator(), nullptr, 0, *pStaticResCache};
+ }
+ ShaderResourceLayoutVk::Initialize(pDeviceVk, ShaderStages, m_ShaderResourceLayouts, GetRawAllocator(),
+ m_Desc.ResourceLayout, ShaderSPIRVs, m_PipelineLayout,
+ (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0,
+ (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0);
+ m_PipelineLayout.Finalize(LogicalDevice);
- if (GraphicsPipeline.RasterizerDesc.ScissorEnable)
+ if (m_Desc.SRBAllocationGranularity > 1)
+ {
+ std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderVariableDataSizes = {};
+ for (Uint32 s = 0; s < GetNumShaderTypes(); ++s)
{
- // pScissors state in VkPipelineViewportStateCreateInfo will be ignored and must be set
- // dynamically with vkCmdSetScissor before any draw commands. The number of scissor rectangles
- // used by a pipeline is still specified by the scissorCount member of
- // VkPipelineViewportStateCreateInfo.
- DynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
+ const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
+
+ Uint32 UnusedNumVars = 0;
+ ShaderVariableDataSizes[s] = ShaderVariableManagerVk::GetRequiredMemorySize(m_ShaderResourceLayouts[s], AllowedVarTypes, _countof(AllowedVarTypes), UnusedNumVars);
}
- DynamicStateCI.dynamicStateCount = static_cast<uint32_t>(DynamicStates.size());
- DynamicStateCI.pDynamicStates = DynamicStates.data();
- PipelineCI.pDynamicState = &DynamicStateCI;
+ Uint32 NumSets = 0;
+ auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets);
+ auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data());
+
+ m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderTypes(), ShaderVariableDataSizes.data(), 1, &CacheMemorySize);
+ }
- PipelineCI.renderPass = GetRenderPass()->GetVkRenderPass();
- PipelineCI.subpass = m_Desc.GraphicsPipeline.SubpassIndex;
- 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
+ // Create shader modules and initialize shader stages
+ std::vector<VkPipelineShaderStageCreateInfo> VkShaderStages;
+ std::vector<VulkanUtilities::ShaderModuleWrapper> ShaderModules;
+ InitializeShaderStages(LogicalDevice, ShaderStages, ShaderSPIRVs, ShaderModules, VkShaderStages);
- m_Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name);
+ // Create pipeline
+ switch (m_Desc.PipelineType)
+ {
+ // clang-format off
+ case PIPELINE_TYPE_GRAPHICS:
+ case PIPELINE_TYPE_MESH: CreateGraphicsPipeline( pDeviceVk, VkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline, m_pRenderPass); break;
+ case PIPELINE_TYPE_COMPUTE: CreateComputePipeline( pDeviceVk, VkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); break;
+ default: UNEXPECTED("unknown pipeline type");
+ // clang-format on
}
m_HasStaticResources = false;
m_HasNonStaticResources = false;
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderTypes(); ++s)
{
const auto& Layout = m_ShaderResourceLayouts[s];
if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_STATIC) != 0)
@@ -493,21 +517,13 @@ PipelineStateVkImpl::~PipelineStateVkImpl()
m_pDevice->SafeReleaseDeviceObject(std::move(m_Pipeline), m_Desc.CommandQueueMask);
m_PipelineLayout.Release(m_pDevice, m_Desc.CommandQueueMask);
- for (auto& ShaderModule : m_ShaderModules)
- {
- if (ShaderModule != VK_NULL_HANDLE)
- {
- m_pDevice->SafeReleaseDeviceObject(std::move(ShaderModule), m_Desc.CommandQueueMask);
- }
- }
-
auto& RawAllocator = GetRawAllocator();
- for (Uint32 s = 0; s < m_NumShaders * 2; ++s)
+ for (Uint32 s = 0; s < GetNumShaderTypes() * 2; ++s)
{
m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk();
}
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderTypes(); ++s)
{
m_StaticResCaches[s].~ShaderResourceCacheVk();
m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator());
@@ -547,27 +563,27 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const
#ifdef DILIGENT_DEBUG
{
bool IsCompatibleShaders = true;
- if (m_NumShaders != pPSOVk->m_NumShaders)
+ if (GetNumShaderTypes() != pPSOVk->GetNumShaderTypes())
IsCompatibleShaders = false;
if (IsCompatibleShaders)
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderTypes(); ++s)
{
- auto* pShader0 = GetShader<const ShaderVkImpl>(s);
- auto* pShader1 = pPSOVk->GetShader<const ShaderVkImpl>(s);
- if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType)
+ if (GetShaderTypes()[s] != pPSOVk->GetShaderTypes()[s])
{
IsCompatibleShaders = false;
break;
}
- const auto* pRes0 = pShader0->GetShaderResources().get();
+
+ // AZ TODO
+ /*const auto* pRes0 = pShader0->GetShaderResources().get();
const auto* pRes1 = pShader1->GetShaderResources().get();
if (!pRes0->IsCompatibleWith(*pRes1))
{
IsCompatibleShaders = false;
break;
- }
+ }*/
}
}
@@ -621,7 +637,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
auto& ResourceCache = pResBindingVkImpl->GetResourceCache();
#ifdef DILIGENT_DEVELOPMENT
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderTypes(); ++s)
{
m_ShaderResourceLayouts[s].dvpVerifyBindings(ResourceCache);
}
@@ -656,7 +672,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
// Allocate vulkan descriptor set for dynamic resources
DynamicDescrSet = pCtxVkImpl->AllocateDynamicDescriptorSet(DynamicDescriptorSetVkLayout, DynamicDescrSetName);
// Commit all dynamic resource descriptors
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderTypes(); ++s)
{
const auto& Layout = m_ShaderResourceLayouts[s];
if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) != 0)
@@ -673,7 +689,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
void PipelineStateVkImpl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags)
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderTypes(); ++s)
{
auto ShaderType = GetStaticShaderResLayout(s).GetShaderType();
if ((ShaderType & ShaderFlags) != 0)
@@ -717,17 +733,17 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY
void PipelineStateVkImpl::InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderTypes(); ++s)
{
const auto& StaticResLayout = GetStaticShaderResLayout(s);
const auto& StaticResCache = GetStaticResCache(s);
+
#ifdef DILIGENT_DEVELOPMENT
if (!StaticResLayout.dvpVerifyBindings(StaticResCache))
{
- const auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", GetDesc().Name,
"' will not be successfully initialized because not all static resource bindings in shader '",
- pShaderVk->GetDesc().Name,
+ GetShaderTypeLiteralName(GetShaderTypes()[s]),
"' are valid. Please make sure you bind all static resources to PSO before calling InitializeStaticResources() "
"directly or indirectly by passing InitStaticResources=true to CreateShaderResourceBinding() method.");
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
index 53a92a59..75f3bb37 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
@@ -49,8 +49,8 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR
{
m_ResourceLayoutIndex.fill(-1);
- auto* ppShaders = pPSO->GetShaders();
- m_NumShaders = static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaders());
+ auto* pShaderTypes = pPSO->GetShaderTypes();
+ m_NumShaders = static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaderTypes());
auto* pRenderDeviceVkImpl = pPSO->GetDevice();
// This will only allocate memory and initialize descriptor sets in the resource cache
@@ -62,9 +62,7 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR
for (Uint32 s = 0; s < m_NumShaders; ++s)
{
- auto* pShader = ppShaders[s];
- auto ShaderType = pShader->GetDesc().ShaderType;
- auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType);
+ auto ShaderInd = GetShaderTypePipelineIndex(pShaderTypes[s], pPSO->GetDesc().PipelineType);
m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index 4f28af80..1f798eb9 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -103,36 +103,40 @@ ShaderResourceLayoutVk::~ShaderResourceLayoutVk()
GetImmutableSampler(s).~ImmutableSamplerPtrType();
}
-void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
- IMemoryAllocator& Allocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- bool AllocateImmutableSamplers)
+void ShaderResourceLayoutVk::AllocateMemory(IShader* pShader,
+ IMemoryAllocator& Allocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ bool AllocateImmutableSamplers)
{
VERIFY(!m_ResourceBuffer, "Memory has already been initialized");
- VERIFY_EXPR(!m_pResources);
- VERIFY_EXPR(pSrcResources);
+ VERIFY_EXPR(pShader != nullptr);
+ VERIFY_EXPR(m_ShaderType == SHADER_TYPE_UNKNOWN);
- m_pResources = std::move(pSrcResources);
-
- const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
- const auto ShaderType = m_pResources->GetShaderType();
- const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
+ const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+ m_ShaderType = pShader->GetDesc().ShaderType;
// Count the number of resources to allocate all needed memory
- m_pResources->ProcessResources(
- [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) //
- {
- auto VarType = FindShaderVariableType(ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix);
- if (IsAllowedType(VarType, AllowedTypeBits))
+ {
+ auto* pShaderVk = ValidatedCast<ShaderVkImpl>(pShader);
+ auto pResources = pShaderVk->GetShaderResources();
+ const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix();
+ VERIFY_EXPR(pResources->GetShaderType() == m_ShaderType);
+ pResources->ProcessResources(
+ [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) //
{
- // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app
+ auto VarType = FindShaderVariableType(m_ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix);
+ if (IsAllowedType(VarType, AllowedTypeBits))
+ {
+ // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app
- VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds Uint16 maximum representable value");
- ++m_NumResources[VarType];
- }
- } //
- );
+ VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds Uint16 maximum representable value");
+ ++m_NumResources[VarType];
+ }
+ } //
+ );
+ m_IsUsingSeparateSamplers = !pResources->IsUsingCombinedSamplers();
+ }
Uint32 TotalResources = 0;
for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
@@ -148,7 +152,7 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderRes
for (Uint32 s = 0; s < ResourceLayoutDesc.NumStaticSamplers; ++s)
{
const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[s];
- if ((StSamDesc.ShaderStages & ShaderType) != 0)
+ if ((StSamDesc.ShaderStages & m_ShaderType) != 0)
++m_NumImmutableSamplers;
}
}
@@ -169,56 +173,99 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderRes
}
-void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- ShaderResourceCacheVk& StaticResourceCache)
+Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout,
+ const SPIRVShaderResources& Resources,
+ const SPIRVShaderResourceAttribs& SepImg,
+ Uint32 CurrResourceCount,
+ SHADER_RESOURCE_VARIABLE_TYPE ImgVarType)
+{
+ using VkResource = ShaderResourceLayoutVk::VkResource;
+ VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage);
+
+ Uint32 SamplerInd = VkResource::InvalidSamplerInd;
+ if (Resources.IsUsingCombinedSamplers() && SepImg.IsValidSepSamplerAssigned())
+ {
+ const auto& SepSampler = Resources.GetAssignedSepSampler(SepImg);
+ for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd)
+ {
+ const auto& Res = Layout.GetResource(ImgVarType, SamplerInd);
+ if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
+ strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0)
+ {
+ VERIFY(ImgVarType == Res.GetVariableType(),
+ "The type (", GetShaderVariableTypeLiteralName(ImgVarType), ") of separate image variable '", SepImg.Name,
+ "' is not consistent with the type (", GetShaderVariableTypeLiteralName(Res.GetVariableType()),
+ ") of the separate sampler '", SepSampler.Name,
+ "' that is assigned to it. "
+ "This should never happen as when HLSL-style combined texture samplers are used, the type of the sampler "
+ "is derived from the type of the corresponding separate image.");
+ break;
+ }
+ }
+ if (SamplerInd == CurrResourceCount)
+ {
+ LOG_ERROR("Unable to find separate sampler '", SepSampler.Name, "' assigned to separate image '", SepImg.Name, "' in the list of already created resources. This seems to be a bug.");
+ SamplerInd = VkResource::InvalidSamplerInd;
+ }
+ }
+ return SamplerInd;
+}
+
+
+void ShaderResourceLayoutVk::InitializeStaticResourceLayout(IShader* pShader,
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ ShaderResourceCacheVk& StaticResourceCache)
{
const auto AllowedVarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC;
// We do not need immutable samplers in static shader resource layout as they
// are relevant only when the main layout is initialized
constexpr bool AllocateImmutableSamplers = false;
- AllocateMemory(std::move(pSrcResources), LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers);
+ AllocateMemory(pShader, LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers);
std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES> CurrResInd = {};
Uint32 StaticResCacheSize = 0;
- const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1);
- const auto ShaderType = m_pResources->GetShaderType();
- const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
+ const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1);
- m_pResources->ProcessResources(
- [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) //
- {
- auto VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix);
- if (!IsAllowedType(VarType, AllowedTypeBits))
- return;
+ {
+ auto* pShaderVk = ValidatedCast<ShaderVkImpl>(pShader);
+ auto pResources = pShaderVk->GetShaderResources();
+ const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix();
- Int32 SrcImmutableSamplerInd = -1;
- if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
- Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler)
+ pResources->ProcessResources(
+ [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) //
{
- // Only search for the immutable sampler for combined image samplers and separate samplers
- SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix);
- // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app
- }
+ auto VarType = FindShaderVariableType(m_ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix);
+ if (!IsAllowedType(VarType, AllowedTypeBits))
+ return;
- Uint32 Binding = Attribs.Type;
- Uint32 DescriptorSet = 0;
- Uint32 CacheOffset = StaticResCacheSize;
- StaticResCacheSize += Attribs.ArraySize;
+ Int32 SrcImmutableSamplerInd = -1;
+ if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
+ Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler)
+ {
+ // Only search for the immutable sampler for combined image samplers and separate samplers
+ SrcImmutableSamplerInd = FindImmutableSampler(m_ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix);
+ // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app
+ }
- Uint32 SamplerInd = VkResource::InvalidSamplerInd;
- if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage)
- {
- // Separate samplers are enumerated before separate images, so the sampler
- // assigned to this separate image must have already been created.
- SamplerInd = FindAssignedSampler(Attribs, CurrResInd[VarType], VarType);
- }
- ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0);
- } //
- );
+ Uint32 Binding = Attribs.Type;
+ Uint32 DescriptorSet = 0;
+ Uint32 CacheOffset = StaticResCacheSize;
+ StaticResCacheSize += Attribs.ArraySize;
+
+ Uint32 SamplerInd = VkResource::InvalidSamplerInd;
+ if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage)
+ {
+ // Separate samplers are enumerated before separate images, so the sampler
+ // assigned to this separate image must have already been created.
+ SamplerInd = FindAssignedSampler(*this, *pResources, Attribs, CurrResInd[VarType], VarType);
+ }
+ ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0);
+ } //
+ );
+ }
#ifdef DILIGENT_DEBUG
for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
@@ -235,25 +282,24 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons
}
#ifdef DILIGENT_DEVELOPMENT
-void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32 NumShaders,
- const std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- bool VerifyVariables,
- bool VerifyStaticSamplers)
+void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const ShaderStages_t& ShaderStages,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ bool VerifyVariables,
+ bool VerifyStaticSamplers)
{
- auto GetAllowedShadersString = [&](SHADER_TYPE ShaderStages) //
+ auto GetAllowedShadersString = [&](SHADER_TYPE Stages) //
{
std::string ShadersStr;
- while (ShaderStages != SHADER_TYPE_UNKNOWN)
+ while (Stages != SHADER_TYPE_UNKNOWN)
{
- const auto ShaderType = ShaderStages & static_cast<SHADER_TYPE>(~(static_cast<Uint32>(ShaderStages) - 1));
+ const auto ShaderType = Stages & static_cast<SHADER_TYPE>(~(static_cast<Uint32>(Stages) - 1));
const char* ShaderName = nullptr;
- for (Uint32 s = 0; s < NumShaders; ++s)
+
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- const auto& Resources = *pShaderResources[s];
- if ((ShaderStages & Resources.GetShaderType()) != 0)
+ if ((Stages & ShaderStages[s].first) != 0)
{
- ShaderName = Resources.GetShaderName();
+ ShaderName = ShaderStages[s].second->GetDesc().Name;
break;
}
}
@@ -274,7 +320,7 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
ShadersStr.append(")");
- ShaderStages &= ~ShaderType;
+ Stages &= ~ShaderType;
}
return ShadersStr;
};
@@ -291,9 +337,10 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
bool VariableFound = false;
- for (Uint32 s = 0; s < NumShaders && !VariableFound; ++s)
+ for (size_t s = 0; s < ShaderStages.size() && !VariableFound; ++s)
{
- const auto& Resources = *pShaderResources[s];
+ const auto* pShaderVk = ValidatedCast<ShaderVkImpl>(ShaderStages[s].second);
+ const auto& Resources = *pShaderVk->GetShaderResources();
if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0)
{
for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res)
@@ -324,9 +371,10 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
bool SamplerFound = false;
- for (Uint32 s = 0; s < NumShaders && !SamplerFound; ++s)
+ for (size_t s = 0; s < ShaderStages.size() && !SamplerFound; ++s)
{
- const auto& Resources = *pShaderResources[s];
+ const auto* pShaderVk = ValidatedCast<ShaderVkImpl>(ShaderStages[s].second);
+ const auto& Resources = *pShaderVk->GetShaderResources();
if ((StSamDesc.ShaderStages & Resources.GetShaderType()) == 0)
continue;
@@ -363,32 +411,31 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
#endif
-void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice,
- Uint32 NumShaders,
- ShaderResourceLayoutVk Layouts[],
- std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- std::vector<uint32_t> SPIRVs[],
- class PipelineLayout& PipelineLayout,
- bool VerifyVariables,
- bool VerifyStaticSamplers)
+void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice,
+ const ShaderStages_t& ShaderStages,
+ ShaderResourceLayoutVk Layouts[],
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ ShaderSPIRVs_t& SPIRVs,
+ class PipelineLayout& PipelineLayout,
+ bool VerifyVariables,
+ bool VerifyStaticSamplers)
{
#ifdef DILIGENT_DEVELOPMENT
- dvpVerifyResourceLayoutDesc(NumShaders, pShaderResources, ResourceLayoutDesc, VerifyVariables, VerifyStaticSamplers);
+ dvpVerifyResourceLayoutDesc(ShaderStages, ResourceLayoutDesc, VerifyVariables, VerifyStaticSamplers);
#endif
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr;
- const Uint32 NumAllowedTypes = 0;
- const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr;
+ const Uint32 NumAllowedTypes = 0;
+ const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+ constexpr bool AllocateImmutableSamplers = true;
- for (Uint32 s = 0; s < NumShaders; ++s)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- constexpr bool AllocateImmutableSamplers = true;
- Layouts[s].AllocateMemory(std::move(pShaderResources[s]), LayoutDataAllocator, ResourceLayoutDesc, AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers);
+ Layouts[s].AllocateMemory(ShaderStages[s].second, LayoutDataAllocator, ResourceLayoutDesc, AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers);
}
- VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE);
+ //VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE);
std::array<std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES>, MAX_SHADERS_IN_PIPELINE> CurrResInd = {};
std::array<Uint32, MAX_SHADERS_IN_PIPELINE> CurrImmutableSamplerInd = {};
#ifdef DILIGENT_DEBUG
@@ -414,7 +461,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
{
// Separate samplers are enumerated before separate images, so the sampler
// assigned to this separate image must have already been created.
- SamplerInd = ResLayout.FindAssignedSampler(Attribs, CurrResInd[ShaderInd][VarType], VarType);
+ SamplerInd = FindAssignedSampler(ResLayout, Resources, Attribs, CurrResInd[ShaderInd][VarType], VarType);
}
VkSampler vkImmutableSampler = VK_NULL_HANDLE;
@@ -454,42 +501,48 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
};
// 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)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- auto& Layout = Layouts[s];
- const auto& Resources = *Layout.m_pResources;
+ auto& pShader = ShaderStages[s].second;
+ auto& Layout = Layouts[s];
+ auto* pShaderVk = ValidatedCast<ShaderVkImpl>(pShader);
+ auto& Resources = *pShaderVk->GetShaderResources();
for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n)
{
const auto& UB = Resources.GetUB(n);
auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc);
if (IsAllowedType(VarType, AllowedTypeBits))
{
- AddResource(s, Layout, Resources, UB);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, UB);
}
}
}
// Second, process all storage buffers
- for (Uint32 s = 0; s < NumShaders; ++s)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- auto& Layout = Layouts[s];
- const auto& Resources = *Layout.m_pResources;
+ auto& pShader = ShaderStages[s].second;
+ auto& Layout = Layouts[s];
+ auto* pShaderVk = ValidatedCast<ShaderVkImpl>(pShader);
+ auto& Resources = *pShaderVk->GetShaderResources();
for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n)
{
const auto& SB = Resources.GetSB(n);
auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc);
if (IsAllowedType(VarType, AllowedTypeBits))
{
- AddResource(s, Layout, Resources, SB);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SB);
}
}
}
// Finally, process all other resource types
- for (Uint32 s = 0; s < NumShaders; ++s)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- auto& Layout = Layouts[s];
- const auto& Resources = *Layout.m_pResources;
+ auto& pShader = ShaderStages[s].second;
+ auto& Layout = Layouts[s];
+ auto* pShaderVk = ValidatedCast<ShaderVkImpl>(pShader);
+ auto& Resources = *pShaderVk->GetShaderResources();
// clang-format off
Resources.ProcessResources(
[&](const SPIRVShaderResourceAttribs& UB, Uint32)
@@ -505,39 +558,39 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
[&](const SPIRVShaderResourceAttribs& Img, Uint32)
{
VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer);
- AddResource(s, Layout, Resources, Img);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, Img);
},
[&](const SPIRVShaderResourceAttribs& SmplImg, Uint32)
{
VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer);
- AddResource(s, Layout, Resources, SmplImg);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SmplImg);
},
[&](const SPIRVShaderResourceAttribs& AC, Uint32)
{
VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter);
- AddResource(s, Layout, Resources, AC);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, AC);
},
[&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32)
{
VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler);
- AddResource(s, Layout, Resources, SepSmpl);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SepSmpl);
},
[&](const SPIRVShaderResourceAttribs& SepImg, Uint32)
{
VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer);
- AddResource(s, Layout, Resources, SepImg);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SepImg);
},
[&](const SPIRVShaderResourceAttribs& InputAtt, Uint32)
{
VERIFY_EXPR(InputAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment);
- AddResource(s, Layout, Resources, InputAtt);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, InputAtt);
}
);
// clang-format on
}
#ifdef DILIGENT_DEBUG
- for (Uint32 s = 0; s < NumShaders; ++s)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
auto& Layout = Layouts[s];
for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
@@ -551,41 +604,40 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
}
-Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg,
- Uint32 CurrResourceCount,
- SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) const
+ShaderResourceLayoutVk::VkResource::VkResource(const ShaderResourceLayoutVk& _ParentLayout,
+ const SPIRVShaderResourceAttribs& _SpirvAttribs,
+ SHADER_RESOURCE_VARIABLE_TYPE _VariableType,
+ uint32_t _Binding,
+ uint32_t _DescriptorSet,
+ Uint32 _CacheOffset,
+ Uint32 _SamplerInd,
+ bool _ImmutableSamplerAssigned) noexcept :
+ // clang-format off
+ Binding {static_cast<decltype(Binding)>(_Binding) },
+ DescriptorSet {static_cast<decltype(DescriptorSet)>(_DescriptorSet)},
+ CacheOffset {_CacheOffset },
+ SamplerInd {_SamplerInd },
+ VariableType {_VariableType },
+ ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U},
+ SpirvAttribs {_SpirvAttribs },
+ ParentResLayout {_ParentLayout }
+// clang-format on
{
- VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage);
-
- Uint32 SamplerInd = VkResource::InvalidSamplerInd;
- if (m_pResources->IsUsingCombinedSamplers() && SepImg.IsValidSepSamplerAssigned())
- {
- const auto& SepSampler = m_pResources->GetAssignedSepSampler(SepImg);
- for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd)
- {
- const auto& Res = GetResource(ImgVarType, SamplerInd);
- if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
- strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0)
- {
- VERIFY(ImgVarType == Res.GetVariableType(),
- "The type (", GetShaderVariableTypeLiteralName(ImgVarType), ") of separate image variable '", SepImg.Name,
- "' is not consistent with the type (", GetShaderVariableTypeLiteralName(Res.GetVariableType()),
- ") of the separate sampler '", SepSampler.Name,
- "' that is assigned to it. "
- "This should never happen as when HLSL-style combined texture samplers are used, the type of the sampler "
- "is derived from the type of the corresponding separate image.");
- break;
- }
- }
- if (SamplerInd == CurrResourceCount)
- {
- LOG_ERROR("Unable to find separate sampler '", SepSampler.Name, "' assigned to separate image '", SepImg.Name, "' in the list of already created resources. This seems to be a bug.");
- SamplerInd = VkResource::InvalidSamplerInd;
- }
- }
- return SamplerInd;
+ VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits));
+ VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits));
+ VERIFY(_Binding <= std::numeric_limits<decltype(Binding)>::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits<decltype(Binding)>::max());
+ VERIFY(_DescriptorSet <= std::numeric_limits<decltype(DescriptorSet)>::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits<decltype(DescriptorSet)>::max());
+
+ const size_t Size = strlen(SpirvAttribs.Name) + 1;
+ char* NameCopy = ALLOCATE(GetRawAllocator(), "SPIRV Attribs Name", char, Size);
+ std::memcpy(NameCopy, SpirvAttribs.Name, Size);
+ const_cast<SPIRVShaderResourceAttribs&>(SpirvAttribs).Name = NameCopy;
}
+ShaderResourceLayoutVk::VkResource::~VkResource()
+{
+ FREE(GetRawAllocator(), const_cast<char*>(SpirvAttribs.Name));
+}
void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
uint32_t ArrayElement,
@@ -1017,7 +1069,7 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou
{
auto NumStaticResources = m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC];
VERIFY(NumStaticResources == SrcLayout.m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC], "Inconsistent number of static resources");
- VERIFY(SrcLayout.m_pResources->GetShaderType() == m_pResources->GetShaderType(), "Incosistent shader types");
+ VERIFY(SrcLayout.GetShaderType() == GetShaderType(), "Incosistent shader types");
// Static shader resources are stored in one large continuous descriptor set
for (Uint32 r = 0; r < NumStaticResources; ++r)
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
index fb151407..95261295 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
@@ -1511,4 +1511,27 @@ VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags)
}
#undef ASSERT_SAME
+
+VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType)
+{
+ static_assert(SHADER_TYPE_LAST == SHADER_TYPE_MESH, "Please update the switch below to handle the new shader type");
+ VERIFY((ShaderType & (ShaderType - 1)) == 0, "More than one shader type specified");
+ switch (ShaderType)
+ {
+ // clang-format off
+ case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT;
+ case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
+ case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
+ case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT;
+ case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT;
+ case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT;
+ case SHADER_TYPE_AMPLIFICATION: return VK_SHADER_STAGE_TASK_BIT_NV;
+ case SHADER_TYPE_MESH: return VK_SHADER_STAGE_MESH_BIT_NV;
+ // clang-format on
+ default:
+ UNEXPECTED("Unknown shader type");
+ return VK_SHADER_STAGE_VERTEX_BIT;
+ }
+}
+
} // namespace Diligent