summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-10-21 22:15:55 +0000
committerazhirnov <zh1dron@gmail.com>2020-10-25 10:50:53 +0000
commit42217cc1ec7f81c028dcc5c1f845a2fc3b3da497 (patch)
tree2efcb7c0fdeae582ecb5c8d13c7bedd593ab9a3c /Graphics/GraphicsEngineVulkan
parentFixed Mac/iOS build (diff)
parentUpdated Metal testing environment (diff)
downloadDiligentCore-42217cc1ec7f81c028dcc5c1f845a2fc3b3da497.tar.gz
DiligentCore-42217cc1ec7f81c028dcc5c1f845a2fc3b3da497.zip
Merge branch 'master' into ray_tracing
# Conflicts: # Graphics/GraphicsEngine/interface/PipelineState.h # Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp # Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp # Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp35
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp10
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp68
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp24
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp3
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp6
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp68
-rw-r--r--Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp22
-rw-r--r--Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp18
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp30
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp678
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp19
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp91
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp314
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp29
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp6
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp29
19 files changed, 821 insertions, 633 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
index d1732211..d4f2fc36 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
@@ -57,7 +57,8 @@ class PipelineStateVkImpl final : public PipelineStateBase<IPipelineStateVk, Ren
public:
using TPipelineStateBase = PipelineStateBase<IPipelineStateVk, RenderDeviceVkImpl>;
- PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const PipelineStateCreateInfo& CreateInfo);
+ PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const GraphicsPipelineStateCreateInfo& CreateInfo);
+ PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const ComputePipelineStateCreateInfo& CreateInfo);
~PipelineStateVkImpl();
virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final;
@@ -104,7 +105,7 @@ public:
const ShaderResourceLayoutVk& GetShaderResLayout(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
return m_ShaderResourceLayouts[ShaderInd];
}
@@ -125,33 +126,43 @@ public:
void InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const;
private:
+ using TShaderStages = ShaderResourceLayoutVk::TShaderStages;
+
+ template <typename PSOCreateInfoType>
+ void InitInternalObjects(const PSOCreateInfoType& CreateInfo,
+ std::vector<VkPipelineShaderStageCreateInfo>& vkShaderStages,
+ std::vector<VulkanUtilities::ShaderModuleWrapper>& ShaderModules);
+
+ void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
+ TShaderStages& ShaderStages);
+
+ void Destruct();
+
const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
- return m_ShaderResourceLayouts[m_NumShaders + ShaderInd];
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
+ return m_ShaderResourceLayouts[GetNumShaderStages() + ShaderInd];
}
const ShaderResourceCacheVk& GetStaticResCache(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
return m_StaticResCaches[ShaderInd];
}
- ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const
+ const ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
return m_StaticVarsMgrs[ShaderInd];
}
- ShaderResourceLayoutVk* m_ShaderResourceLayouts = nullptr;
- ShaderResourceCacheVk* m_StaticResCaches = nullptr;
- ShaderVariableManagerVk* m_StaticVarsMgrs = nullptr;
+ ShaderResourceLayoutVk* m_ShaderResourceLayouts = nullptr; // [m_NumShaderStages * 2]
+ ShaderResourceCacheVk* m_StaticResCaches = nullptr; // [m_NumShaderStages]
+ ShaderVariableManagerVk* m_StaticVarsMgrs = nullptr; // [m_NumShaderStages]
// 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;
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
index 94b91cae..d85e9ff3 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
@@ -72,8 +72,11 @@ public:
virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final;
- /// Implementation of IRenderDevice::CreatePipelineState() in Vulkan backend.
- virtual void DILIGENT_CALL_TYPE CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final;
+ /// Implementation of IRenderDevice::CreateGraphicsPipelineState() in Vulkan backend.
+ virtual void DILIGENT_CALL_TYPE CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final;
+
+ /// Implementation of IRenderDevice::CreateComputePipelineState() in Vulkan backend.
+ virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final;
/// Implementation of IRenderDevice::CreateBuffer() in Vulkan backend.
virtual void DILIGENT_CALL_TYPE CreateBuffer(const BufferDesc& BuffDesc,
@@ -192,6 +195,9 @@ public:
IDXCompiler* GetDxCompiler() const { return m_pDxCompiler.get(); }
private:
+ template <typename PSOCreateInfoType>
+ void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState);
+
virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final;
// Submits command buffer for execution to the command queue
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
index 026bb9da..00f2c33a 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
@@ -76,6 +76,8 @@ public:
bool StaticResourcesInitialized() const { return m_bStaticResourcesInitialized; }
private:
+ void Destruct();
+
ShaderResourceCacheVk m_ShaderResourceCache;
ShaderVariableManagerVk* m_pShaderVarMgrs = nullptr;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
index a5278cb7..7d77ff48 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
@@ -75,7 +75,7 @@ public:
};
// clang-format off
- ShaderResourceCacheVk(DbgCacheContentType dbgContentType)
+ ShaderResourceCacheVk(DbgCacheContentType dbgContentType) noexcept
#ifdef DILIGENT_DEBUG
: m_DbgContentType{dbgContentType}
#endif
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
index a6d20641..9452a390 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
@@ -110,12 +110,25 @@
namespace Diligent
{
+class ShaderVkImpl;
+
/// Diligent::ShaderResourceLayoutVk class
// sizeof(ShaderResourceLayoutVk)==56 (MS compiler, x64)
class ShaderResourceLayoutVk
{
public:
- ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) :
+ struct ShaderStageInfo
+ {
+ ShaderStageInfo(SHADER_TYPE _Type,
+ const ShaderVkImpl* _pShader);
+
+ const SHADER_TYPE Type;
+ const ShaderVkImpl* const pShader;
+ std::vector<uint32_t> SPIRV;
+ };
+ using TShaderStages = std::vector<ShaderStageInfo>;
+
+ ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) noexcept :
m_LogicalDevice{LogicalDevice}
{
}
@@ -131,23 +144,21 @@ 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(const ShaderVkImpl* 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,
+ TShaderStages& ShaderStages,
+ ShaderResourceLayoutVk Layouts[],
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ class PipelineLayout& PipelineLayout,
+ bool VerifyVariables,
+ bool VerifyImmutableSamplers);
// sizeof(VkResource) == 24 (x64)
struct VkResource
@@ -279,11 +290,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 TShaderStages& ShaderStages,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ bool VerifyVariables,
+ bool VerifyImmutableSamplers);
#endif
Uint32 GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
@@ -308,6 +318,8 @@ public:
return m_pResources->GetShaderType();
}
+ const SPIRVShaderResources& GetResources() const { return *m_pResources; }
+
const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const
{
VERIFY_EXPR(r < m_NumResources[VarType]);
@@ -346,16 +358,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(const ShaderVkImpl* 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
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp
index 9039e04e..27689c1e 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp
@@ -73,21 +73,25 @@ class ShaderVariableVkImpl;
class ShaderVariableManagerVk
{
public:
- ShaderVariableManagerVk(IObject& Owner,
- const ShaderResourceLayoutVk& SrcLayout,
- IMemoryAllocator& Allocator,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheVk& ResourceCache);
+ ShaderVariableManagerVk(IObject& Owner,
+ ShaderResourceCacheVk& ResourceCache) noexcept :
+ m_Owner{Owner},
+ m_ResourceCache{ResourceCache}
+ {}
+
+ void Initialize(const ShaderResourceLayoutVk& SrcLayout,
+ IMemoryAllocator& Allocator,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes);
~ShaderVariableManagerVk();
void DestroyVariables(IMemoryAllocator& Allocator);
- ShaderVariableVkImpl* GetVariable(const Char* Name);
- ShaderVariableVkImpl* GetVariable(Uint32 Index);
+ ShaderVariableVkImpl* GetVariable(const Char* Name) const;
+ ShaderVariableVkImpl* GetVariable(Uint32 Index) const;
- void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags);
+ void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) const;
static size_t GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout,
const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
@@ -115,7 +119,7 @@ private:
Uint32 m_NumVariables = 0;
#ifdef DILIGENT_DEBUG
- IMemoryAllocator& m_DbgAllocator;
+ IMemoryAllocator* m_pDbgAllocator = nullptr;
#endif
};
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
index 51083968..e88c93d2 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
@@ -83,6 +83,9 @@ ATTACHMENT_STORE_OP VkAttachmentStoreOpToAttachmentStoreOp(VkAttachmentStoreOp V
VkPipelineStageFlags PipelineStageFlagsToVkPipelineStageFlags(PIPELINE_STAGE_FLAGS PipelineStageFlags);
VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags);
+
+VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType);
+
VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureFlags(RAYTRACING_BUILD_AS_FLAGS Flags);
VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags);
VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INSTANCE_FLAGS Flags);
diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
index 7085765c..6b29af25 100644
--- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
@@ -59,8 +59,8 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
{
ValidateBufferInitData(BuffDesc, pBuffData);
- if (m_Desc.Usage == USAGE_STATIC)
- VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers");
+ if (m_Desc.Usage == USAGE_IMMUTABLE)
+ VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for immutable buffers");
if (m_Desc.Usage == USAGE_DYNAMIC)
VERIFY(pBuffData == nullptr || pBuffData->pData == nullptr, "Initial data must be null for dynamic buffers");
@@ -218,7 +218,7 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
VkMemoryPropertyFlags vkMemoryFlags = 0;
switch (m_Desc.Usage)
{
- case USAGE_STATIC:
+ case USAGE_IMMUTABLE:
case USAGE_DEFAULT:
case USAGE_DYNAMIC: // Dynamic buffer with SRV or UAV bind flag
vkMemoryFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index ba36ff7c..99050318 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -260,39 +260,49 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
else
{
const auto& OldPSODesc = m_pPipelineState->GetDesc();
- // Commit all graphics states when switching from compute pipeline
+ // Commit all graphics states when switching from non-graphics pipeline
// This is necessary because if the command list had been flushed
// and the first PSO set on the command list was a compute pipeline,
// the states would otherwise never be committed (since m_pPipelineState != nullptr)
- CommitStates = OldPSODesc.IsComputePipeline();
+ CommitStates = !OldPSODesc.IsAnyGraphicsPipeline();
// We also need to update scissor rect if ScissorEnable state was disabled in previous pipeline
- CommitScissor = !OldPSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable;
+ if (OldPSODesc.IsAnyGraphicsPipeline())
+ CommitScissor = !m_pPipelineState->GetGraphicsPipelineDesc().RasterizerDesc.ScissorEnable;
}
TDeviceContextBase::SetPipelineState(pPipelineStateVk, 0 /*Dummy*/);
EnsureVkCmdBuffer();
- if (PSODesc.IsComputePipeline())
- {
- auto vkPipeline = pPipelineStateVk->GetVkPipeline();
- m_CommandBuffer.BindComputePipeline(vkPipeline);
- }
- else
- {
- auto vkPipeline = pPipelineStateVk->GetVkPipeline();
- m_CommandBuffer.BindGraphicsPipeline(vkPipeline);
+ auto vkPipeline = pPipelineStateVk->GetVkPipeline();
- if (CommitStates)
+ switch (PSODesc.PipelineType)
+ {
+ case PIPELINE_TYPE_GRAPHICS:
+ case PIPELINE_TYPE_MESH:
{
- m_CommandBuffer.SetStencilReference(m_StencilRef);
- m_CommandBuffer.SetBlendConstants(m_BlendFactors);
- CommitViewports();
- }
+ auto& GraphicsPipeline = pPipelineStateVk->GetGraphicsPipelineDesc();
+ m_CommandBuffer.BindGraphicsPipeline(vkPipeline);
+
+ if (CommitStates)
+ {
+ m_CommandBuffer.SetStencilReference(m_StencilRef);
+ m_CommandBuffer.SetBlendConstants(m_BlendFactors);
+ CommitViewports();
+ }
- if (PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable && (CommitStates || CommitScissor))
+ if (GraphicsPipeline.RasterizerDesc.ScissorEnable && (CommitStates || CommitScissor))
+ {
+ CommitScissorRects();
+ }
+ break;
+ }
+ case PIPELINE_TYPE_COMPUTE:
{
- CommitScissorRects();
+ m_CommandBuffer.BindComputePipeline(vkPipeline);
+ break;
}
+ default:
+ UNEXPECTED("unknown pipeline type");
}
m_DescrSetBindInfo.Reset();
@@ -384,8 +394,11 @@ void DeviceContextVkImpl::CommitVkVertexBuffers()
void DeviceContextVkImpl::DvpLogRenderPass_PSOMismatch()
{
+ const auto& Desc = m_pPipelineState->GetDesc();
+ const auto& GrPipeline = m_pPipelineState->GetGraphicsPipelineDesc();
+
std::stringstream ss;
- ss << "Active render pass is incomaptible with PSO '" << m_pPipelineState->GetDesc().Name
+ ss << "Active render pass is incomaptible with PSO '" << Desc.Name
<< "'. This indicates the mismatch between the number and/or format of bound render "
"targets and/or depth stencil buffer and the PSO. Vulkand requires exact match.\n"
" Bound render targets ("
@@ -414,7 +427,6 @@ void DeviceContextVkImpl::DvpLogRenderPass_PSOMismatch()
ss << "<Not set>";
ss << "; Sample count: " << SampleCount;
- const auto& GrPipeline = m_pPipelineState->GetDesc().GraphicsPipeline;
ss << "\n PSO: render targets (" << Uint32{GrPipeline.NumRenderTargets} << "): ";
for (Uint32 rt = 0; rt < GrPipeline.NumRenderTargets; ++rt)
ss << ' ' << GetTextureFormatAttribs(GrPipeline.RTVFormats[rt]).Name;
@@ -475,7 +487,7 @@ void DeviceContextVkImpl::PrepareForDraw(DRAW_FLAGS Flags)
# endif
#endif
- if (m_pPipelineState->GetDesc().GraphicsPipeline.pRenderPass == nullptr)
+ if (m_pPipelineState->GetGraphicsPipelineDesc().pRenderPass == nullptr)
{
#ifdef DILIGENT_DEVELOPMENT
if (m_pPipelineState->GetRenderPass()->GetVkRenderPass() != m_vkRenderPass)
@@ -1129,7 +1141,7 @@ void DeviceContextVkImpl::SetViewports(Uint32 NumViewports, const Viewport* pVie
void DeviceContextVkImpl::CommitScissorRects()
{
- VERIFY(m_pPipelineState && m_pPipelineState->GetDesc().GraphicsPipeline.RasterizerDesc.ScissorEnable, "Scissor test must be enabled in the graphics pipeline");
+ VERIFY(m_pPipelineState && m_pPipelineState->GetGraphicsPipelineDesc().RasterizerDesc.ScissorEnable, "Scissor test must be enabled in the graphics pipeline");
if (m_NumScissorRects == 0)
return; // Scissors have not been set in the context yet
@@ -1155,14 +1167,10 @@ void DeviceContextVkImpl::SetScissorRects(Uint32 NumRects, const Rect* pRects, U
// Only commit scissor rects if scissor test is enabled in the rasterizer state.
// If scissor is currently disabled, or no PSO is bound, scissor rects will be committed by
// the SetPipelineState() when a PSO with enabled scissor test is set.
- if (m_pPipelineState)
+ if (m_pPipelineState && m_pPipelineState->GetDesc().IsAnyGraphicsPipeline() && m_pPipelineState->GetGraphicsPipelineDesc().RasterizerDesc.ScissorEnable)
{
- const auto& PSODesc = m_pPipelineState->GetDesc();
- if (PSODesc.IsAnyGraphicsPipeline() && PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable)
- {
- VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects");
- CommitScissorRects();
- }
+ VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects");
+ CommitScissorRects();
}
}
diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
index 7a7d8a07..d37655a5 100644
--- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
@@ -238,7 +238,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height
};
- const auto& DeiceExtFeatures = PhysicalDevice->GetExtFeatures();
+ const auto& DeviceExtFeatures = PhysicalDevice->GetExtFeatures();
#define ENABLE_FEATURE(IsFeatureSupported, Feature, FeatureName) \
do \
@@ -248,32 +248,32 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
} while (false)
- auto MeshShaderFeats = DeiceExtFeatures.MeshShader;
+ auto MeshShaderFeats = DeviceExtFeatures.MeshShader;
ENABLE_FEATURE(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are");
- auto ShaderFloat16Int8 = DeiceExtFeatures.ShaderFloat16Int8;
+ auto ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8;
// clang-format off
ENABLE_FEATURE(ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are");
ENABLE_FEATURE(ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are");
// clang-format on
- auto Storage16BitFeats = DeiceExtFeatures.Storage16Bit;
+ auto Storage16BitFeats = DeviceExtFeatures.Storage16Bit;
// clang-format off
ENABLE_FEATURE(Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is");
ENABLE_FEATURE(Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is");
ENABLE_FEATURE(Storage16BitFeats.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are");
// clang-format on
- auto Storage8BitFeats = DeiceExtFeatures.Storage8Bit;
+ auto Storage8BitFeats = DeviceExtFeatures.Storage8Bit;
// clang-format off
ENABLE_FEATURE(Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is");
ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is");
// clang-format on
- auto RayTracingFeats = DeiceExtFeatures.RayTracing;
- auto BufferDeviceAddressFeats = DeiceExtFeatures.BufferDeviceAddress;
- auto DescriptorIndexingFeats = DeiceExtFeatures.DescriptorIndexing;
- ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeiceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is");
+ auto RayTracingFeats = DeviceExtFeatures.RayTracing;
+ auto BufferDeviceAddressFeats = DeviceExtFeatures.BufferDeviceAddress;
+ auto DescriptorIndexingFeats = DeviceExtFeatures.DescriptorIndexing;
+ ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is");
#undef FeatureSupport
@@ -396,7 +396,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
// Ray tracing
if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED)
{
- if (DeiceExtFeatures.RayTracingNV)
+ if (DeviceExtFeatures.RayTracingNV)
{
DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
DeviceExtensions.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME);
@@ -429,7 +429,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
}
#if defined(_MSC_VER) && defined(_WIN64)
- static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
+ static_assert(sizeof(DeviceFeatures) == 32, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
#endif
DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data();
diff --git a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
index 5110c873..e7ab95b1 100644
--- a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
@@ -154,23 +154,23 @@ std::array<RefCntAutoPtr<IPipelineState>, 4> GenerateMipsVkHelper::CreatePSOs(TE
m_DeviceVkImpl.CreateShader(CSCreateInfo, &pCS);
- PipelineStateCreateInfo PSOCreateInfo;
- PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc;
+ ComputePipelineStateCreateInfo PSOCreateInfo;
+ PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc;
- PSODesc.PipelineType = PIPELINE_TYPE_COMPUTE;
- PSODesc.Name = name.c_str();
- PSODesc.ComputePipeline.pCS = pCS;
+ PSODesc.PipelineType = PIPELINE_TYPE_COMPUTE;
+ PSODesc.Name = name.c_str();
+ PSOCreateInfo.pCS = pCS;
PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC;
ShaderResourceVariableDesc VarDesc{SHADER_TYPE_COMPUTE, "CB", SHADER_RESOURCE_VARIABLE_TYPE_STATIC};
PSODesc.ResourceLayout.Variables = &VarDesc;
PSODesc.ResourceLayout.NumVariables = 1;
- const StaticSamplerDesc StaticSampler(SHADER_TYPE_COMPUTE, "SrcMip", Sam_LinearClamp);
- PSODesc.ResourceLayout.StaticSamplers = &StaticSampler;
- PSODesc.ResourceLayout.NumStaticSamplers = 1;
+ const ImmutableSamplerDesc ImtblSampler{SHADER_TYPE_COMPUTE, "SrcMip", Sam_LinearClamp};
+ PSODesc.ResourceLayout.ImmutableSamplers = &ImtblSampler;
+ PSODesc.ResourceLayout.NumImmutableSamplers = 1;
- m_DeviceVkImpl.CreatePipelineState(PSOCreateInfo, &PSOs[NonPowOfTwo]);
+ m_DeviceVkImpl.CreateComputePipelineState(PSOCreateInfo, &PSOs[NonPowOfTwo]);
PSOs[NonPowOfTwo]->GetStaticVariableByName(SHADER_TYPE_COMPUTE, "CB")->Set(m_ConstantsCB);
}
#endif
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
index b7d2b1f4..b221659a 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
@@ -40,34 +40,6 @@
namespace Diligent
{
-
-static VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType)
-{
- static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "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;
- case SHADER_TYPE_RAY_GEN: return VK_SHADER_STAGE_RAYGEN_BIT_KHR;
- case SHADER_TYPE_RAY_MISS: return VK_SHADER_STAGE_MISS_BIT_KHR;
- case SHADER_TYPE_RAY_CLOSEST_HIT: return VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
- case SHADER_TYPE_RAY_ANY_HIT: return VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
- case SHADER_TYPE_RAY_INTERSECTION: return VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
- case SHADER_TYPE_CALLABLE: return VK_SHADER_STAGE_CALLABLE_BIT_KHR;
- // clang-format on
- default:
- UNEXPECTED("Unknown shader type");
- return VK_SHADER_STAGE_VERTEX_BIT;
- }
-}
-
class ResourceTypeToVkDescriptorType
{
public:
@@ -241,7 +213,7 @@ bool PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::operator==
if ((B0.pImmutableSamplers != nullptr && B1.pImmutableSamplers == nullptr) ||
(B0.pImmutableSamplers == nullptr && B1.pImmutableSamplers != nullptr))
return false;
- // Static samplers themselves should not affect compatibility
+ // Immutable samplers themselves should not affect compatibility
// clang-format on
}
return true;
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 5c165e32..83512870 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -129,346 +129,324 @@ 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 InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
+ ShaderResourceLayoutVk::TShaderStages& ShaderStages,
+ std::vector<VulkanUtilities::ShaderModuleWrapper>& vkShaderModules,
+ std::vector<VkPipelineShaderStageCreateInfo>& vkPipelineShaderStages)
{
- m_ResourceLayoutIndex.fill(-1);
-
- const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
-
- // Initialize shader resource layouts
- auto& ShaderResLayoutAllocator = GetRawAllocator();
-
- std::array<std::shared_ptr<const SPIRVShaderResources>, MAX_SHADERS_IN_PIPELINE> ShaderResources;
- std::array<std::vector<uint32_t>, MAX_SHADERS_IN_PIPELINE> ShaderSPIRVs;
-
- m_ShaderResourceLayouts = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", ShaderResourceLayoutVk, m_NumShaders * 2);
- m_StaticResCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheVk", ShaderResourceCacheVk, m_NumShaders);
- m_StaticVarsMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders);
-
- for (Uint32 s = 0; s < m_NumShaders; ++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], ShaderResLayoutAllocator, 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);
-
- if (m_Desc.SRBAllocationGranularity > 1)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- 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};
+ auto& StageInfo = ShaderStages[s];
- 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());
+ VkPipelineShaderStageCreateInfo StageCI = {};
- 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(StageInfo.Type);
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
- {
- 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();
- }
+ if (!StripReflection(StageInfo.SPIRV))
+ LOG_ERROR("Failed to strip reflection information from shader '", StageInfo.pShader->GetDesc().Name, "'. This may indicate a problem with the byte code.");
+
+ ShaderModuleCI.codeSize = StageInfo.SPIRV.size() * sizeof(uint32_t);
+ ShaderModuleCI.pCode = StageInfo.SPIRV.data();
- m_ShaderModules[s] = LogicalDevice.CreateShaderModule(ShaderModuleCI, pShaderVk->GetDesc().Name);
+ vkShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, StageInfo.pShader->GetDesc().Name));
- StageCI.module = m_ShaderModules[s];
- StageCI.pName = pShaderVk->GetEntryPoint();
+ StageCI.module = vkShaderModules.back();
+ StageCI.pName = StageInfo.pShader->GetEntryPoint();
StageCI.pSpecializationInfo = nullptr;
+
+ vkPipelineShaderStages.push_back(StageCI);
}
- // Create pipeline
- if (m_Desc.IsComputePipeline())
- {
- auto& ComputePipeline = m_Desc.ComputePipeline;
+ VERIFY_EXPR(vkShaderModules.size() == vkPipelineShaderStages.size());
+}
- if (ComputePipeline.pCS == nullptr)
- LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc");
- VkComputePipelineCreateInfo PipelineCI = {};
+static void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages,
+ const PipelineLayout& Layout,
+ const PipelineStateDesc& PSODesc,
+ VulkanUtilities::PipelineWrapper& Pipeline)
+{
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+
+ VkComputePipelineCreateInfo PipelineCI = {};
- PipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
- PipelineCI.pNext = nullptr;
+ PipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_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.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
- PipelineCI.stage = ShaderStages[0];
- PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout();
+ PipelineCI.stage = Stages[0];
+ PipelineCI.layout = Layout.GetVkPipelineLayout();
- m_Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name);
- }
- else
- {
- const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
- auto& GraphicsPipeline = m_Desc.GraphicsPipeline;
- auto& RPCache = pDeviceVk->GetImplicitRenderPassCache();
+ Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name);
+}
- if (m_pRenderPass == nullptr)
- {
- RenderPassCache::RenderPassCacheKey Key{
- GraphicsPipeline.NumRenderTargets,
- GraphicsPipeline.SmplDesc.Count,
- GraphicsPipeline.RTVFormats,
- GraphicsPipeline.DSVFormat};
- m_pRenderPass = RPCache.GetRenderPass(Key);
- }
- VkGraphicsPipelineCreateInfo PipelineCI = {};
+static void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages,
+ const PipelineLayout& Layout,
+ const PipelineStateDesc& PSODesc,
+ const GraphicsPipelineDesc& GraphicsPipeline,
+ VulkanUtilities::PipelineWrapper& Pipeline,
+ RefCntAutoPtr<IRenderPass>& pRenderPass)
+{
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+ const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
+ 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_GRAPHICS_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.stageCount = m_NumShaders;
- PipelineCI.pStages = ShaderStages.data();
- PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout();
+ PipelineCI.stageCount = static_cast<Uint32>(Stages.size());
+ PipelineCI.pStages = Stages.data();
+ PipelineCI.layout = Layout.GetVkPipelineLayout();
- VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {};
+ 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;
+ 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;
- VkPipelineInputAssemblyStateCreateInfo InputAssemblyCI = {};
+ 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;
+ 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 = {};
+ 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;
+ TessStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
+ TessStateCI.pNext = nullptr;
+ TessStateCI.flags = 0; // reserved for future use
+ PipelineCI.pTessellationState = &TessStateCI;
- 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;
+ if (PSODesc.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
- {
- PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(GraphicsPipeline.PrimitiveTopology, InputAssemblyCI.topology, TessStateCI.patchControlPoints);
- }
+ // 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);
+ }
- 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
+ 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 =
{
- 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.
+ 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.
+
+ VK_DYNAMIC_STATE_BLEND_CONSTANTS, // blendConstants state in VkPipelineColorBlendStateCreateInfo will be ignored
+ // and must be set dynamically with vkCmdSetBlendConstants
+
+ 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
+ };
+
+ 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;
- VK_DYNAMIC_STATE_BLEND_CONSTANTS, // blendConstants state in VkPipelineColorBlendStateCreateInfo will be ignored
- // and must be set dynamically with vkCmdSetBlendConstants
- 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.renderPass = pRenderPass.RawPtr<IRenderPassVk>()->GetVkRenderPass();
+ PipelineCI.subpass = 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
- if (GraphicsPipeline.RasterizerDesc.ScissorEnable)
+ Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name);
+}
+
+void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
+ TShaderStages& ShaderStages)
+{
+ auto* const pDeviceVk = GetDevice();
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
+ {
+ auto& StageInfo = ShaderStages[s];
+ const auto ShaderType = StageInfo.Type;
+ const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType);
+
+ m_ResourceLayoutIndex[ShaderTypeInd] = static_cast<Int8>(s);
+
+ auto& StaticResLayout = m_ShaderResourceLayouts[GetNumShaderStages() + s];
+ StaticResLayout.InitializeStaticResourceLayout(StageInfo.pShader, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]);
+
+ m_StaticVarsMgrs[s].Initialize(StaticResLayout, GetRawAllocator(), nullptr, 0);
+ }
+ ShaderResourceLayoutVk::Initialize(pDeviceVk, ShaderStages, m_ShaderResourceLayouts, GetRawAllocator(),
+ m_Desc.ResourceLayout, m_PipelineLayout,
+ (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0,
+ (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS) == 0);
+ m_PipelineLayout.Finalize(LogicalDevice);
+
+ if (m_Desc.SRBAllocationGranularity > 1)
+ {
+ std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderVariableDataSizes = {};
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++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);
- }
- DynamicStateCI.dynamicStateCount = static_cast<uint32_t>(DynamicStates.size());
- DynamicStateCI.pDynamicStates = DynamicStates.data();
- PipelineCI.pDynamicState = &DynamicStateCI;
+ 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);
+ }
- 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
+ Uint32 NumSets = 0;
+ auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets);
+ auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data());
- m_Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name);
+ m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderVariableDataSizes.data(), 1, &CacheMemorySize);
}
m_HasStaticResources = false;
m_HasNonStaticResources = false;
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
const auto& Layout = m_ShaderResourceLayouts[s];
if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_STATIC) != 0)
@@ -482,34 +460,137 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun
m_ShaderResourceLayoutHash = m_PipelineLayout.GetHash();
}
+template <typename PSOCreateInfoType>
+void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& CreateInfo,
+ std::vector<VkPipelineShaderStageCreateInfo>& vkShaderStages,
+ std::vector<VulkanUtilities::ShaderModuleWrapper>& ShaderModules)
+{
+ m_ResourceLayoutIndex.fill(-1);
+
+ TShaderStages ShaderStages;
+ ExtractShaders<ShaderVkImpl>(CreateInfo, ShaderStages);
+
+ LinearAllocator MemPool{GetRawAllocator()};
+
+ const auto NumShaderStages = GetNumShaderStages();
+ VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size());
+
+ MemPool.AddSpace<ShaderResourceCacheVk>(NumShaderStages);
+ MemPool.AddSpace<ShaderResourceLayoutVk>(NumShaderStages * 2);
+ MemPool.AddSpace<ShaderVariableManagerVk>(NumShaderStages);
+
+ ReserveSpaceForPipelineDesc(CreateInfo, MemPool);
+
+ MemPool.Reserve();
+
+ const auto& LogicalDevice = GetDevice()->GetLogicalDevice();
+
+ m_StaticResCaches = MemPool.ConstructArray<ShaderResourceCacheVk>(NumShaderStages, ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources);
+
+ // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct().
+ auto* Ptr = MemPool.ReleaseOwnership();
+ VERIFY_EXPR(Ptr == m_StaticResCaches);
+ (void)Ptr;
+
+ m_ShaderResourceLayouts = MemPool.ConstructArray<ShaderResourceLayoutVk>(NumShaderStages * 2, LogicalDevice);
+
+ m_StaticVarsMgrs = MemPool.Allocate<ShaderVariableManagerVk>(NumShaderStages);
+ for (Uint32 s = 0; s < NumShaderStages; ++s)
+ new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]};
+
+ InitializePipelineDesc(CreateInfo, MemPool);
+
+ // It is important to construct all objects before initializing them because if an exception is thrown,
+ // destructors will be called for all objects
+
+ InitResourceLayouts(CreateInfo, ShaderStages);
+
+ // Create shader modules and initialize shader stages
+ InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages);
+}
+
+PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDeviceVk,
+ const GraphicsPipelineStateCreateInfo& CreateInfo) :
+ TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc},
+ m_SRBMemAllocator{GetRawAllocator()}
+{
+ try
+ {
+ std::vector<VkPipelineShaderStageCreateInfo> vkShaderStages;
+ std::vector<VulkanUtilities::ShaderModuleWrapper> ShaderModules;
+
+ InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules);
+
+ CreateGraphicsPipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass);
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
+ }
+}
+
+
+PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDeviceVk,
+ const ComputePipelineStateCreateInfo& CreateInfo) :
+ TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc},
+ m_SRBMemAllocator{GetRawAllocator()}
+{
+ try
+ {
+ std::vector<VkPipelineShaderStageCreateInfo> vkShaderStages;
+ std::vector<VulkanUtilities::ShaderModuleWrapper> ShaderModules;
+
+ InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules);
+
+ CreateComputePipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline);
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
+ }
+}
+
+
PipelineStateVkImpl::~PipelineStateVkImpl()
{
+ Destruct();
+}
+
+void PipelineStateVkImpl::Destruct()
+{
m_pDevice->SafeReleaseDeviceObject(std::move(m_Pipeline), m_Desc.CommandQueueMask);
m_PipelineLayout.Release(m_pDevice, m_Desc.CommandQueueMask);
- for (auto& ShaderModule : m_ShaderModules)
+ auto& RawAllocator = GetRawAllocator();
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
- if (ShaderModule != VK_NULL_HANDLE)
+ if (m_StaticVarsMgrs != nullptr)
{
- m_pDevice->SafeReleaseDeviceObject(std::move(ShaderModule), m_Desc.CommandQueueMask);
+ m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator());
+ m_StaticVarsMgrs[s].~ShaderVariableManagerVk();
}
- }
- auto& RawAllocator = GetRawAllocator();
- for (Uint32 s = 0; s < m_NumShaders * 2; ++s)
- {
- m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk();
+ if (m_ShaderResourceLayouts != nullptr)
+ {
+ m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk();
+ m_ShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutVk();
+ }
+
+ if (m_StaticResCaches != nullptr)
+ {
+ m_StaticResCaches[s].~ShaderResourceCacheVk();
+ }
}
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ // All internal objects are allocted in contiguous chunks of memory.
+ if (void* pRawMem = m_StaticResCaches)
{
- m_StaticResCaches[s].~ShaderResourceCacheVk();
- m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator());
- m_StaticVarsMgrs[s].~ShaderVariableManagerVk();
+ RawAllocator.Free(pRawMem);
}
- RawAllocator.Free(m_ShaderResourceLayouts);
- RawAllocator.Free(m_StaticResCaches);
- RawAllocator.Free(m_StaticVarsMgrs);
}
IMPLEMENT_QUERY_INTERFACE(PipelineStateVkImpl, IID_PipelineStateVk, TPipelineStateBase)
@@ -540,23 +621,22 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const
#ifdef DILIGENT_DEBUG
{
bool IsCompatibleShaders = true;
- if (m_NumShaders != pPSOVk->m_NumShaders)
+ if (GetNumShaderStages() != pPSOVk->GetNumShaderStages())
IsCompatibleShaders = false;
if (IsCompatibleShaders)
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
- auto* pShader0 = GetShader<const ShaderVkImpl>(s);
- auto* pShader1 = pPSOVk->GetShader<const ShaderVkImpl>(s);
- if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType)
+ if (GetShaderStageType(s) != pPSOVk->GetShaderStageType(s))
{
IsCompatibleShaders = false;
break;
}
- const auto* pRes0 = pShader0->GetShaderResources().get();
- const auto* pRes1 = pShader1->GetShaderResources().get();
- if (!pRes0->IsCompatibleWith(*pRes1))
+
+ const auto& Res0 = GetShaderResLayout(s).GetResources();
+ const auto& Res1 = pPSOVk->GetShaderResLayout(s).GetResources();
+ if (!Res0.IsCompatibleWith(Res1))
{
IsCompatibleShaders = false;
break;
@@ -614,7 +694,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 < GetNumShaderStages(); ++s)
{
m_ShaderResourceLayouts[s].dvpVerifyBindings(ResourceCache);
}
@@ -649,7 +729,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 < GetNumShaderStages(); ++s)
{
const auto& Layout = m_ShaderResourceLayouts[s];
if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) != 0)
@@ -666,7 +746,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 < GetNumShaderStages(); ++s)
{
auto ShaderType = GetStaticShaderResLayout(s).GetShaderType();
if ((ShaderType & ShaderFlags) != 0)
@@ -703,24 +783,24 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY
if (LayoutInd < 0)
return nullptr;
- auto& StaticVarMgr = GetStaticVarMgr(LayoutInd);
+ const auto& StaticVarMgr = GetStaticVarMgr(LayoutInd);
return StaticVarMgr.GetVariable(Index);
}
void PipelineStateVkImpl::InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++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(GetShaderStageType(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/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index 6e5ec710..cdcac036 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -106,6 +106,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
//{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors},
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors},
},
EngineCI.MainDescriptorPoolSize.MaxDescriptorSets,
true
@@ -126,6 +127,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
//{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors},
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors},
},
EngineCI.DynamicDescriptorPoolSize.MaxDescriptorSets,
false // Pools can only be reset
@@ -217,6 +219,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
// The following features are always enabled
Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED;
+ Features.ShaderResourceQueries = DEVICE_FEATURE_STATE_ENABLED;
Features.IndirectRendering = DEVICE_FEATURE_STATE_ENABLED;
Features.MultithreadedResourceCreation = DEVICE_FEATURE_STATE_ENABLED;
Features.ComputeShaders = DEVICE_FEATURE_STATE_ENABLED;
@@ -226,7 +229,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
Features.DurationQueries = DEVICE_FEATURE_STATE_ENABLED;
#if defined(_MSC_VER) && defined(_WIN64)
- static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary).");
+ static_assert(sizeof(DeviceFeatures) == 32, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary).");
#endif
const auto& vkDeviceLimits = m_PhysicalDevice->GetProperties().limits;
@@ -545,7 +548,8 @@ void RenderDeviceVkImpl::TestTextureFormat(TEXTURE_FORMAT TexFormat)
IMPLEMENT_QUERY_INTERFACE(RenderDeviceVkImpl, IID_RenderDeviceVk, TRenderDeviceBase)
-void RenderDeviceVkImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+template <typename PSOCreateInfoType>
+void RenderDeviceVkImpl::CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState)
{
CreateDeviceObject(
"Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState,
@@ -558,6 +562,17 @@ void RenderDeviceVkImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOC
);
}
+void RenderDeviceVkImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState);
+}
+
+
+void RenderDeviceVkImpl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState);
+}
+
void RenderDeviceVkImpl::CreateBufferFromVulkanResource(VkBuffer vkBuffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
index 6e6c142f..3e4a65cf 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
@@ -30,6 +30,7 @@
#include "PipelineStateVkImpl.hpp"
#include "ShaderVkImpl.hpp"
#include "RenderDeviceVkImpl.hpp"
+#include "LinearAllocator.hpp"
namespace Diligent
{
@@ -47,55 +48,79 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR
m_ShaderResourceCache{ShaderResourceCacheVk::DbgCacheContentType::SRBResources}
// clang-format on
{
- m_ResourceLayoutIndex.fill(-1);
+ try
+ {
+ m_ResourceLayoutIndex.fill(-1);
- auto* ppShaders = pPSO->GetShaders();
- m_NumShaders = static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaders());
+ m_NumShaders = static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaderStages());
- auto* pRenderDeviceVkImpl = pPSO->GetDevice();
- // This will only allocate memory and initialize descriptor sets in the resource cache
- // Resources will be initialized by InitializeResourceMemoryInCache()
- auto& ResourceCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0);
- pPSO->GetPipelineLayout().InitResourceCache(pRenderDeviceVkImpl, m_ShaderResourceCache, ResourceCacheDataAllocator, pPSO->GetDesc().Name);
+ LinearAllocator MemPool{GetRawAllocator()};
+ MemPool.AddSpace<ShaderVariableManagerVk>(m_NumShaders);
+ MemPool.Reserve();
+ m_pShaderVarMgrs = MemPool.ConstructArray<ShaderVariableManagerVk>(m_NumShaders, std::ref(*this), std::ref(m_ShaderResourceCache));
- m_pShaderVarMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders);
+ // The memory is now owned by ShaderResourceBindingVkImpl and will be freed by Destruct().
+ auto* Ptr = MemPool.ReleaseOwnership();
+ VERIFY_EXPR(Ptr == m_pShaderVarMgrs);
+ (void)Ptr;
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- auto* pShader = ppShaders[s];
- auto ShaderType = pShader->GetDesc().ShaderType;
- auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType);
+ // It is important to construct all objects before initializing them because if an exception is thrown,
+ // destructors will be called for all objects
- m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
+ auto* pRenderDeviceVkImpl = pPSO->GetDevice();
+ // This will only allocate memory and initialize descriptor sets in the resource cache
+ // Resources will be initialized by InitializeResourceMemoryInCache()
+ auto& ResourceCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0);
+ pPSO->GetPipelineLayout().InitResourceCache(pRenderDeviceVkImpl, m_ShaderResourceCache, ResourceCacheDataAllocator, pPSO->GetDesc().Name);
- auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ auto ShaderInd = GetShaderTypePipelineIndex(pPSO->GetShaderStageType(s), pPSO->GetDesc().PipelineType);
- const auto& SrcLayout = pPSO->GetShaderResLayout(s);
- // Use source layout to initialize resource memory in the cache
- SrcLayout.InitializeResourceMemoryInCache(m_ShaderResourceCache);
+ m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
- // Create shader variable manager in place
- // Initialize vars manager to reference mutable and dynamic variables
- // Note that the cache has space for all variable types
- const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
- new (m_pShaderVarMgrs + s) ShaderVariableManagerVk{*this, SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes), m_ShaderResourceCache};
- }
+ auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
+
+ const auto& SrcLayout = pPSO->GetShaderResLayout(s);
+ // Use source layout to initialize resource memory in the cache
+ SrcLayout.InitializeResourceMemoryInCache(m_ShaderResourceCache);
+
+ // Create shader variable manager in place
+ // Initialize vars manager to reference mutable and dynamic variables
+ // Note that the cache has space for all variable types
+ const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
+ m_pShaderVarMgrs[s].Initialize(SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes));
+ }
#ifdef DILIGENT_DEBUG
- m_ShaderResourceCache.DbgVerifyResourceInitialization();
+ m_ShaderResourceCache.DbgVerifyResourceInitialization();
#endif
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
+ }
}
ShaderResourceBindingVkImpl::~ShaderResourceBindingVkImpl()
{
- PipelineStateVkImpl* pPSO = ValidatedCast<PipelineStateVkImpl>(m_pPSO);
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ Destruct();
+}
+
+void ShaderResourceBindingVkImpl::Destruct()
+{
+ if (m_pShaderVarMgrs != nullptr)
{
- auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
- m_pShaderVarMgrs[s].DestroyVariables(VarDataAllocator);
- m_pShaderVarMgrs[s].~ShaderVariableManagerVk();
- }
+ auto& SRBMemAllocator = m_pPSO->GetSRBMemoryAllocator();
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s);
+ m_pShaderVarMgrs[s].DestroyVariables(VarDataAllocator);
+ m_pShaderVarMgrs[s].~ShaderVariableManagerVk();
+ }
- GetRawAllocator().Free(m_pShaderVarMgrs);
+ GetRawAllocator().Free(m_pShaderVarMgrs);
+ }
}
IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingVkImpl, IID_ShaderResourceBindingVk, TBase)
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index 4f28af80..e73ee9aa 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -63,10 +63,10 @@ static Int32 FindImmutableSampler(SHADER_TYPE ShaderType,
return -1;
}
- for (Uint32 s = 0; s < ResourceLayoutDesc.NumStaticSamplers; ++s)
+ for (Uint32 s = 0; s < ResourceLayoutDesc.NumImmutableSamplers; ++s)
{
- const auto& StSam = ResourceLayoutDesc.StaticSamplers[s];
- if (((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(Attribs.Name, StSam.SamplerOrTextureName, SamplerSuffix))
+ const auto& ImtblSam = ResourceLayoutDesc.ImmutableSamplers[s];
+ if (((ImtblSam.ShaderStages & ShaderType) != 0) && StreqSuff(Attribs.Name, ImtblSam.SamplerOrTextureName, SamplerSuffix))
return s;
}
@@ -93,6 +93,14 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE
}
}
+ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE _Type,
+ const ShaderVkImpl* _pShader) :
+ Type{_Type},
+ pShader{_pShader},
+ SPIRV{pShader->GetSPIRV()}
+{
+}
+
ShaderResourceLayoutVk::~ShaderResourceLayoutVk()
{
@@ -103,36 +111,37 @@ 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(const ShaderVkImpl* 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);
+ m_pResources = pShader->GetShaderResources();
- m_pResources = std::move(pSrcResources);
-
- const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
- const auto ShaderType = m_pResources->GetShaderType();
- const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
+ const auto ShaderType = pShader->GetDesc().ShaderType;
+ VERIFY_EXPR(m_pResources->GetShaderType() == 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))
+ {
+ const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+ const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
+ m_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(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];
+ }
+ } //
+ );
+ }
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))
@@ -145,10 +154,10 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderRes
m_NumImmutableSamplers = 0;
if (AllocateImmutableSamplers)
{
- for (Uint32 s = 0; s < ResourceLayoutDesc.NumStaticSamplers; ++s)
+ for (Uint32 s = 0; s < ResourceLayoutDesc.NumImmutableSamplers; ++s)
{
- const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[s];
- if ((StSamDesc.ShaderStages & ShaderType) != 0)
+ const auto& ImtblSamDesc = ResourceLayoutDesc.ImmutableSamplers[s];
+ if ((ImtblSamDesc.ShaderStages & ShaderType) != 0)
++m_NumImmutableSamplers;
}
}
@@ -169,24 +178,63 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderRes
}
-void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- ShaderResourceCacheVk& StaticResourceCache)
+static 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(const ShaderVkImpl* 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 auto ShaderType = pShader->GetDesc().ShaderType;
m_pResources->ProcessResources(
[&](const SPIRVShaderResourceAttribs& Attribs, Uint32) //
@@ -214,7 +262,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons
{
// 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);
+ SamplerInd = FindAssignedSampler(*this, *m_pResources, Attribs, CurrResInd[VarType], VarType);
}
::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0);
} //
@@ -235,25 +283,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 TShaderStages& ShaderStages,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ bool VerifyVariables,
+ bool VerifyImmutableSamplers)
{
- 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 (const auto& StageInfo : ShaderStages)
{
- const auto& Resources = *pShaderResources[s];
- if ((ShaderStages & Resources.GetShaderType()) != 0)
+ if ((Stages & StageInfo.Type) != 0)
{
- ShaderName = Resources.GetShaderName();
+ ShaderName = StageInfo.pShader->GetDesc().Name;
break;
}
}
@@ -274,7 +321,7 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
ShadersStr.append(")");
- ShaderStages &= ~ShaderType;
+ Stages &= ~ShaderType;
}
return ShadersStr;
};
@@ -291,9 +338,9 @@ 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& Resources = *ShaderStages[s].pShader->GetShaderResources();
if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0)
{
for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res)
@@ -312,83 +359,82 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
}
- if (VerifyStaticSamplers)
+ if (VerifyImmutableSamplers)
{
- for (Uint32 sam = 0; sam < ResourceLayoutDesc.NumStaticSamplers; ++sam)
+ for (Uint32 sam = 0; sam < ResourceLayoutDesc.NumImmutableSamplers; ++sam)
{
- const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[sam];
- if (StSamDesc.ShaderStages == SHADER_TYPE_UNKNOWN)
+ const auto& ImtblSamDesc = ResourceLayoutDesc.ImmutableSamplers[sam];
+ if (ImtblSamDesc.ShaderStages == SHADER_TYPE_UNKNOWN)
{
- LOG_WARNING_MESSAGE("No allowed shader stages are specified for static sampler '", StSamDesc.SamplerOrTextureName, "'.");
+ LOG_WARNING_MESSAGE("No allowed shader stages are specified for immutable sampler '", ImtblSamDesc.SamplerOrTextureName, "'.");
continue;
}
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];
- if ((StSamDesc.ShaderStages & Resources.GetShaderType()) == 0)
+ const auto& Resources = *ShaderStages[s].pShader->GetShaderResources();
+ if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0)
continue;
// Irrespective of whether HLSL-style combined image samplers are used,
- // a static sampler can be assigned to GLSL sampled image (i.e. sampler2D g_tex)
+ // an immutable sampler can be assigned to a GLSL sampled image (i.e. sampler2D g_tex)
for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i)
{
const auto& SmplImg = Resources.GetSmpldImg(i);
- SamplerFound = (strcmp(SmplImg.Name, StSamDesc.SamplerOrTextureName) == 0);
+ SamplerFound = (strcmp(SmplImg.Name, ImtblSamDesc.SamplerOrTextureName) == 0);
}
if (!SamplerFound)
{
- // Check if static sampler is assigned to a separate sampler.
+ // Check if an immutable sampler is assigned to a separate sampler.
// In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler".
// Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "".
const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix();
for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i)
{
const auto& SepSmpl = Resources.GetSepSmplr(i);
- SamplerFound = StreqSuff(SepSmpl.Name, StSamDesc.SamplerOrTextureName, CombinedSamplerSuffix);
+ SamplerFound = StreqSuff(SepSmpl.Name, ImtblSamDesc.SamplerOrTextureName, CombinedSamplerSuffix);
}
}
}
if (!SamplerFound)
{
- LOG_WARNING_MESSAGE("Static sampler '", StSamDesc.SamplerOrTextureName,
+ LOG_WARNING_MESSAGE("Immutable sampler '", ImtblSamDesc.SamplerOrTextureName,
"' is not found in any of the designated shader stages: ",
- GetAllowedShadersString(StSamDesc.ShaderStages));
+ GetAllowedShadersString(ImtblSamDesc.ShaderStages));
}
}
}
}
#endif
-void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice,
- Uint32 NumShaders,
- ShaderResourceLayoutVk Layouts[],
- std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- std::vector<uint32_t> SPIRVs[],
- class PipelineLayout& PipelineLayout,
- bool VerifyVariables,
- bool VerifyStaticSamplers)
+void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice,
+ TShaderStages& ShaderStages,
+ ShaderResourceLayoutVk Layouts[],
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ class PipelineLayout& PipelineLayout,
+ bool VerifyVariables,
+ bool VerifyImmutableSamplers)
{
#ifdef DILIGENT_DEVELOPMENT
- dvpVerifyResourceLayoutDesc(NumShaders, pShaderResources, ResourceLayoutDesc, VerifyVariables, VerifyStaticSamplers);
+ dvpVerifyResourceLayoutDesc(ShaderStages, ResourceLayoutDesc, VerifyVariables, VerifyImmutableSamplers);
#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].pShader, 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 +460,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;
@@ -427,13 +473,13 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
{
auto& ImmutableSampler = ResLayout.GetImmutableSampler(CurrImmutableSamplerInd[ShaderInd]++);
VERIFY(!ImmutableSampler, "Immutable sampler has already been initialized!");
- const auto& ImmutableSamplerDesc = ResourceLayoutDesc.StaticSamplers[SrcImmutableSamplerInd].Desc;
+ const auto& ImmutableSamplerDesc = ResourceLayoutDesc.ImmutableSamplers[SrcImmutableSamplerInd].Desc;
pRenderDevice->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler);
vkImmutableSampler = ImmutableSampler.RawPtr<SamplerVkImpl>()->GetVkSampler();
}
}
- auto& ShaderSPIRV = SPIRVs[ShaderInd];
+ auto& ShaderSPIRV = ShaderStages[ShaderInd].SPIRV;
PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset, ShaderSPIRV);
VERIFY(DescriptorSet <= std::numeric_limits<decltype(VkResource::DescriptorSet)>::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value");
VERIFY(Binding <= std::numeric_limits<decltype(VkResource::Binding)>::max(), "Binding (", Binding, ") excceeds maximum representable value");
@@ -454,42 +500,43 @@ 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& Layout = Layouts[s];
+ auto* pShaderVk = ShaderStages[s].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& Layout = Layouts[s];
+ auto& Resources = *ShaderStages[s].pShader->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& Layout = Layouts[s];
+ auto& Resources = *ShaderStages[s].pShader->GetShaderResources();
// clang-format off
Resources.ProcessResources(
[&](const SPIRVShaderResourceAttribs& UB, Uint32)
@@ -505,39 +552,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))
@@ -550,43 +597,6 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
#endif
}
-
-Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg,
- Uint32 CurrResourceCount,
- SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) const
-{
- 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;
-}
-
-
void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
uint32_t ArrayElement,
const VkDescriptorImageInfo* pImageInfo,
@@ -692,6 +702,16 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject*
// HLSL buffer SRVs are mapped to storge buffers in GLSL
auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? BUFFER_VIEW_SHADER_RESOURCE : BUFFER_VIEW_UNORDERED_ACCESS;
VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
+ if (pBufferViewVk != nullptr)
+ {
+ const auto& ViewDesc = pBufferViewVk->GetDesc();
+ const auto& BuffDesc = pBufferViewVk->GetBuffer()->GetDesc();
+ if (BuffDesc.Mode != BUFFER_MODE_STRUCTURED && BuffDesc.Mode != BUFFER_MODE_RAW)
+ {
+ LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
+ SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected.");
+ }
+ }
}
#endif
@@ -738,6 +758,16 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
// HLSL buffer SRVs are mapped to storge buffers in GLSL
auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer ? BUFFER_VIEW_UNORDERED_ACCESS : BUFFER_VIEW_SHADER_RESOURCE;
VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
+ if (pBufferViewVk != nullptr)
+ {
+ const auto& ViewDesc = pBufferViewVk->GetDesc();
+ const auto& BuffDesc = pBufferViewVk->GetBuffer()->GetDesc();
+ if (!((BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED) || BuffDesc.Mode == BUFFER_MODE_RAW))
+ {
+ LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
+ SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': formatted buffer view is expected.");
+ }
+ }
}
#endif
@@ -1017,7 +1047,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/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
index 82d26b44..7e06bd69 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
@@ -65,20 +65,15 @@ size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayout
}
// Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes
-ShaderVariableManagerVk::ShaderVariableManagerVk(IObject& Owner,
- const ShaderResourceLayoutVk& SrcLayout,
- IMemoryAllocator& Allocator,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheVk& ResourceCache) :
- // clang-format off
- m_Owner {Owner },
- m_ResourceCache{ResourceCache}
+void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& SrcLayout,
+ IMemoryAllocator& Allocator,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes)
+{
#ifdef DILIGENT_DEBUG
- , m_DbgAllocator {Allocator}
+ m_pDbgAllocator = &Allocator;
#endif
-// clang-format on
-{
+
const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
VERIFY_EXPR(m_NumVariables == 0);
auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables);
@@ -119,10 +114,10 @@ ShaderVariableManagerVk::~ShaderVariableManagerVk()
void ShaderVariableManagerVk::DestroyVariables(IMemoryAllocator& Allocator)
{
- VERIFY(&m_DbgAllocator == &Allocator, "Incosistent alloctor");
-
if (m_pVariables != nullptr)
{
+ VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor");
+
for (Uint32 v = 0; v < m_NumVariables; ++v)
m_pVariables[v].~ShaderVariableVkImpl();
Allocator.Free(m_pVariables);
@@ -130,7 +125,7 @@ void ShaderVariableManagerVk::DestroyVariables(IMemoryAllocator& Allocator)
}
}
-ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name)
+ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) const
{
ShaderVariableVkImpl* pVar = nullptr;
for (Uint32 v = 0; v < m_NumVariables; ++v)
@@ -147,7 +142,7 @@ ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name)
}
-ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(Uint32 Index)
+ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(Uint32 Index) const
{
if (Index >= m_NumVariables)
{
@@ -178,7 +173,7 @@ Uint32 ShaderVariableManagerVk::GetVariableIndex(const ShaderVariableVkImpl& Var
}
}
-void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags)
+void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) const
{
if (!pResourceMapping)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index 313de089..488e4bf6 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -54,13 +54,13 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters,
}
// clang-format on
{
- if (m_Desc.Usage == USAGE_STATIC && (pInitData == nullptr || pInitData->pSubResources == nullptr))
- LOG_ERROR_AND_THROW("Static textures must be initialized with data at creation time: pInitData can't be null");
+ if (m_Desc.Usage == USAGE_IMMUTABLE && (pInitData == nullptr || pInitData->pSubResources == nullptr))
+ LOG_ERROR_AND_THROW("Immutable textures must be initialized with data at creation time: pInitData can't be null");
const auto& FmtAttribs = GetTextureFormatAttribs(m_Desc.Format);
const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
- if (m_Desc.Usage == USAGE_STATIC || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC)
+ if (m_Desc.Usage == USAGE_IMMUTABLE || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC)
{
VkImageCreateInfo ImageCI = {};
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
index fa03bca6..6358174c 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
@@ -1528,6 +1528,35 @@ VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags)
}
#undef ASSERT_SAME
+
+VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType)
+{
+ static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type");
+ VERIFY(IsPowerOfTwo(Uint32{ShaderType}), "More than one shader type is 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;
+ case SHADER_TYPE_RAY_GEN: return VK_SHADER_STAGE_RAYGEN_BIT_KHR;
+ case SHADER_TYPE_RAY_MISS: return VK_SHADER_STAGE_MISS_BIT_KHR;
+ case SHADER_TYPE_RAY_CLOSEST_HIT: return VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
+ case SHADER_TYPE_RAY_ANY_HIT: return VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
+ case SHADER_TYPE_RAY_INTERSECTION: return VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
+ case SHADER_TYPE_CALLABLE: return VK_SHADER_STAGE_CALLABLE_BIT_KHR;
+ // clang-format on
+ default:
+ UNEXPECTED("Unknown shader type");
+ return VK_SHADER_STAGE_VERTEX_BIT;
+ }
+}
+
VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureFlags(RAYTRACING_BUILD_AS_FLAGS Flags)
{
static_assert(RAYTRACING_BUILD_AS_FLAGS_LAST == RAYTRACING_BUILD_AS_LOW_MEMORY,