summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-05-23 15:43:13 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-05-23 15:43:13 +0000
commit2e3eb1a74d76eb22825d83020aae053c02139b83 (patch)
treec65197280dec2ac1525a618b0f36b21835d891b6 /Graphics/GraphicsEngineVulkan
parentRemoved VulkanResourceBase (diff)
downloadDiligentCore-2e3eb1a74d76eb22825d83020aae053c02139b83.tar.gz
DiligentCore-2e3eb1a74d76eb22825d83020aae053c02139b83.zip
Implemented dynamic descriptor resource descriptors update
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h12
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineLayout.h27
-rw-r--r--Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h4
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h12
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h16
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h11
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/BufferViewVk.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/BufferVk.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/interface/SamplerVk.h2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp9
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp383
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp15
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp8
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp310
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp181
18 files changed, 443 insertions, 557 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h b/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h
index 1cfe3ac0..c6085487 100644
--- a/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/BufferViewVkImpl.h
@@ -51,7 +51,7 @@ public:
virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface );
- virtual VkBufferView GetVkBufferView()override final{return m_BuffView;}
+ virtual VkBufferView GetVkBufferView()const override final{return m_BuffView;}
protected:
diff --git a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h
index b022d3b9..45a21735 100644
--- a/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/BufferVkImpl.h
@@ -88,7 +88,7 @@ public:
}
*/
- VkBuffer GetVkBuffer()override final
+ VkBuffer GetVkBuffer()const override final
{
return m_VulkanBuffer;
}
diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
index 5b9891e7..ea889332 100644
--- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.h
@@ -124,11 +124,17 @@ public:
#if 0
struct DynamicAllocation AllocateDynamicSpace(size_t NumBytes);
-
+#endif
Uint32 GetContextId()const{return m_ContextId;}
-#endif
+
size_t GetNumCommandsInCtx()const { return m_State.NumCommands; }
+ VulkanUtilities::VulkanCommandBuffer& GetCommandBuffer()
+ {
+ EnsureVkCmdBuffer();
+ return m_CommandBuffer;
+ }
+
private:
void CommitRenderPassAndFramebuffer(class PipelineStateVkImpl *pPipelineStateVk);
void CommitVkIndexBuffer(VALUE_TYPE IndexType);
@@ -170,8 +176,8 @@ private:
class ShaderResourceCacheVk *m_pCommittedResourceCache = nullptr;
#if 0
FixedBlockMemoryAllocator m_CmdListAllocator;
- const Uint32 m_ContextId;
#endif
+ const Uint32 m_ContextId;
VulkanUtilities::VulkanCommandBufferPool m_CmdPool;
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h
index 1e82aa2e..7f26427f 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.h
@@ -37,6 +37,7 @@ namespace Diligent
{
class RenderDeviceVkImpl;
+class DeviceContextVkImpl;
/// Implementation of the Diligent::PipelineLayout class
@@ -60,21 +61,6 @@ public:
Uint32& OffsetInCache,
std::vector<uint32_t>& SPIRV);
- // This method should be thread-safe as it does not modify any object state
-
-#if 0
- // This method should be thread-safe as it does not modify any object state
- void (PipelineLayout::*CommitDescriptorHandles)(RenderDeviceVkImpl *pRenderDeviceVk,
- ShaderResourceCacheVk& ResourceCache,
- class CommandContext &Ctx,
- bool IsCompute)const = nullptr;
-
- void (PipelineLayout::*TransitionAndCommitDescriptorHandles)(RenderDeviceVkImpl *pRenderDeviceVk,
- ShaderResourceCacheVk& ResourceCache,
- class CommandContext &Ctx,
- bool IsCompute)const = nullptr;
-#endif
-
Uint32 GetTotalDescriptors(SHADER_VARIABLE_TYPE VarType)const
{
VERIFY_EXPR(VarType >= 0 && VarType < SHADER_VARIABLE_TYPE_NUM_TYPES);
@@ -90,6 +76,17 @@ public:
return m_LayoutMgr.GetHash();
}
+ // Allocates Vulkan descriptor set for dynamic resources and assigns the
+ // set to the resource cache
+ void AllocateDynamicDescriptorSet(RenderDeviceVkImpl* pDevicVkImpl,
+ DeviceContextVkImpl* pCtxVkImpl,
+ ShaderResourceCacheVk& ResourceCache)const;
+
+ // Binds Vulkan descriptor sets to the command buffer in the cmd context
+ void BindDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
+ bool IsCompute,
+ ShaderResourceCacheVk& ResourceCache)const;
+
private:
class DescriptorSetLayoutManager
diff --git a/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h b/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h
index 1756b097..14bcf32e 100644
--- a/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/SamplerVkImpl.h
@@ -45,7 +45,7 @@ public:
virtual void QueryInterface( const Diligent::INTERFACE_ID &IID, IObject **ppInterface )override;
- virtual VkSampler GetVkSampler()override final{return m_VkSampler;}
+ virtual VkSampler GetVkSampler()const override final{return m_VkSampler;}
private:
friend class ShaderVkImpl;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h
index 5f572c93..5dd36dcc 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.h
@@ -68,6 +68,10 @@ public:
bool StaticResourcesInitialized()const{return m_bStaticResourcesInitialized;}
void InitializeStaticResources(const PipelineStateVkImpl *pPSO);
+ // Updates dynamic resource descriptors in the descriptor set, for every layout.
+ // The set is assigned to the resource cache by PipelineLayout::AllocateDynamicDescriptorSet().
+ void CommitDynamicResources();
+
private:
ShaderResourceCacheVk m_ShaderResourceCache;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h
index 02f347bb..b4fe5972 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.h
@@ -88,8 +88,14 @@ public:
struct Resource
{
- const SPIRVShaderResourceAttribs::ResourceType Type;
- RefCntAutoPtr<IDeviceObject> pObject;
+ const SPIRVShaderResourceAttribs::ResourceType Type;
+ RefCntAutoPtr<IDeviceObject> pObject;
+ void* vkDescriptor = nullptr;
+
+ VkDescriptorBufferInfo GetBufferDescriptorWriteInfo () const;
+ VkDescriptorImageInfo GetImageDescriptorWriteInfo (bool IsImmutableSampler)const;
+ VkBufferView GetBufferViewWriteInfo () const;
+ VkDescriptorImageInfo GetSamplerDescriptorWriteInfo() const;
};
class DescriptorSet
@@ -141,7 +147,7 @@ public:
template<bool VerifyOnly>
void TransitionResources(DeviceContextVkImpl *pCtxVkImpl);
-
+
private:
ShaderResourceCacheVk (const ShaderResourceCacheVk&) = delete;
ShaderResourceCacheVk (ShaderResourceCacheVk&&) = delete;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h
index 93dd41b0..5cb2de31 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.h
@@ -226,6 +226,14 @@ public:
BindResource(ppObjects[Elem], FirstElement+Elem, nullptr);
}
+ // Updates dynamic resource descriptors in the descriptor set. The set is assigned
+ // to the resource cache by PipelineLayout::AllocateDynamicDescriptorSet().
+ inline void UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
+ uint32_t ArrayElement,
+ const VkDescriptorImageInfo* pImageInfo,
+ const VkDescriptorBufferInfo* pBufferInfo,
+ const VkBufferView* pTexelBufferView)const;
+
private:
void CacheBuffer(IDeviceObject* pBuffer,
ShaderResourceCacheVk::Resource& DstRes,
@@ -247,12 +255,6 @@ public:
VkDescriptorSet vkDescrSet,
Uint32 ArrayInd);
- inline void UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
- uint32_t ArrayElement,
- const VkDescriptorImageInfo* pImageInfo,
- const VkDescriptorBufferInfo* pBufferInfo,
- const VkBufferView* pTexelBufferView);
-
bool UpdateCachedResource(ShaderResourceCacheVk::Resource& DstRes,
Uint32 ArrayInd,
IDeviceObject* pObject,
@@ -279,6 +281,8 @@ public:
}
void InitializeResourcesInCache();
+
+ void CommitDynamicResources();
private:
void InitVariablesHashMap();
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
index 43e41dd5..8e23f085 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanCommandBuffer.h
@@ -308,6 +308,17 @@ namespace VulkanUtilities
BufferMemoryBarrier(m_VkCmdBuffer, Buffer, srcAccessMask, dstAccessMask, SrcStages, DestStages);
}
+ void BindDescriptorSets(VkPipelineBindPoint pipelineBindPoint,
+ VkPipelineLayout layout,
+ uint32_t firstSet,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet* pDescriptorSets,
+ uint32_t dynamicOffsetCount = 0,
+ const uint32_t* pDynamicOffsets = nullptr)
+ {
+ VERIFY_EXPR(m_VkCmdBuffer != VK_NULL_HANDLE);
+ vkCmdBindDescriptorSets(m_VkCmdBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
+ }
void FlushBarriers();
diff --git a/Graphics/GraphicsEngineVulkan/interface/BufferViewVk.h b/Graphics/GraphicsEngineVulkan/interface/BufferViewVk.h
index eca95c91..646a6c46 100644
--- a/Graphics/GraphicsEngineVulkan/interface/BufferViewVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/BufferViewVk.h
@@ -41,7 +41,7 @@ class IBufferViewVk : public IBufferView
public:
/// Returns Vulkan buffer view object.
- virtual VkBufferView GetVkBufferView() = 0;
+ virtual VkBufferView GetVkBufferView()const = 0;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/interface/BufferVk.h b/Graphics/GraphicsEngineVulkan/interface/BufferVk.h
index 8f2bc4d1..6b3b672d 100644
--- a/Graphics/GraphicsEngineVulkan/interface/BufferVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/BufferVk.h
@@ -42,7 +42,7 @@ class IBufferVk : public IBuffer
public:
/// Returns a vulkan buffer handle
- virtual VkBuffer GetVkBuffer() = 0;
+ virtual VkBuffer GetVkBuffer()const = 0;
/// Sets vulkan access flags
diff --git a/Graphics/GraphicsEngineVulkan/interface/SamplerVk.h b/Graphics/GraphicsEngineVulkan/interface/SamplerVk.h
index a849033d..e7f21cc2 100644
--- a/Graphics/GraphicsEngineVulkan/interface/SamplerVk.h
+++ b/Graphics/GraphicsEngineVulkan/interface/SamplerVk.h
@@ -41,7 +41,7 @@ class ISamplerVk : public ISampler
public:
/// Returns a vulkan sampler object handle
- virtual VkSampler GetVkSampler() = 0;
+ virtual VkSampler GetVkSampler()const = 0;
};
}
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index a6ed69de..f739b794 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -41,8 +41,8 @@ namespace Diligent
//m_pUploadHeap(pDeviceVkImpl->RequestUploadHeap() ),
m_NumCommandsToFlush(bIsDeferred ? std::numeric_limits<decltype(m_NumCommandsToFlush)>::max() : Attribs.NumCommandsToFlushCmdBuffer),
/*m_MipsGenerator(pDeviceVkImpl->GetVkDevice()),
- m_CmdListAllocator(GetRawAllocator(), sizeof(CommandListVkImpl), 64 ),
- m_ContextId(ContextId),*/
+ m_CmdListAllocator(GetRawAllocator(), sizeof(CommandListVkImpl), 64 ),*/
+ m_ContextId(ContextId),
m_CmdPool(pDeviceVkImpl->GetLogicalDevice().GetSharedPtr(), pDeviceVkImpl->GetCmdQueue()->GetQueueFamilyIndex(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
{
#if 0
@@ -189,13 +189,10 @@ namespace Diligent
void DeviceContextVkImpl::TransitionShaderResources(IPipelineState *pPipelineState, IShaderResourceBinding *pShaderResourceBinding)
{
-#if 0
VERIFY_EXPR(pPipelineState != nullptr);
- auto *pCtx = RequestCmdContext();
auto *pPipelineStateVk = ValidatedCast<PipelineStateVkImpl>(pPipelineState);
- pPipelineStateVk->CommitAndTransitionShaderResources(pShaderResourceBinding, *pCtx, false, true);
-#endif
+ pPipelineStateVk->CommitAndTransitionShaderResources(pShaderResourceBinding, this, false, true);
}
void DeviceContextVkImpl::CommitShaderResources(IShaderResourceBinding *pShaderResourceBinding, Uint32 Flags)
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
index f427b7a0..fb74d019 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
@@ -28,6 +28,7 @@
#include "ShaderVkImpl.h"
#include "CommandContext.h"
#include "RenderDeviceVkImpl.h"
+#include "DeviceContextVkImpl.h"
#include "TextureVkImpl.h"
#include "BufferVkImpl.h"
#include "VulkanTypeConversions.h"
@@ -549,369 +550,57 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl *pDeviceVkImpl, Shader
{
ResourceCache.GetDescriptorSet(StaticAndMutSet.SetIndex).AssignDescriptorSetAllocation(std::move(SetAllocation));
}
-
-#if 0
- // Get root table size for every root index
- // m_RootParams keeps root tables sorted by the array index, not the root index
- // Root views are treated as one-descriptor tables
- std::vector<Uint32, STDAllocatorRawMem<Uint32> > CacheTableSizes(m_RootParams.GetNumRootTables() + m_RootParams.GetNumRootViews(), 0, STD_ALLOCATOR_RAW_MEM(Uint32, GetRawAllocator(), "Allocator for vector<Uint32>") );
- for(Uint32 rt = 0; rt < m_RootParams.GetNumRootTables(); ++rt)
- {
- auto &RootParam = m_RootParams.GetRootTable(rt);
- CacheTableSizes[RootParam.GetRootIndex()] = RootParam.GetDescriptorTableSize();
- }
-
- for(Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv)
- {
- auto &RootParam = m_RootParams.GetRootView(rv);
- CacheTableSizes[RootParam.GetRootIndex()] = 1;
- }
- // Initialize resource cache to hold root tables
- ResourceCache.Initialize(CacheMemAllocator, static_cast<Uint32>(CacheTableSizes.size()), CacheTableSizes.data());
-
- // Allocate space in GPU-visible descriptor heap for static and mutable variables only
- Uint32 TotalSrvCbvUavDescriptors =
- m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_STATIC] +
- m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_MUTABLE];
- Uint32 TotalSamplerDescriptors =
- m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_STATIC] +
- m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_MUTABLE];
-
- DescriptorHeapAllocation CbcSrvUavHeapSpace, SamplerHeapSpace;
- if(TotalSrvCbvUavDescriptors)
- CbcSrvUavHeapSpace = pDeviceVkImpl->AllocateGPUDescriptors(Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, TotalSrvCbvUavDescriptors);
- VERIFY_EXPR(TotalSrvCbvUavDescriptors == 0 && CbcSrvUavHeapSpace.IsNull() || CbcSrvUavHeapSpace.GetNumHandles() == TotalSrvCbvUavDescriptors);
-
- if(TotalSamplerDescriptors)
- SamplerHeapSpace = pDeviceVkImpl->AllocateGPUDescriptors(Vk_DESCRIPTOR_HEAP_TYPE_SAMPLER, TotalSamplerDescriptors);
- VERIFY_EXPR(TotalSamplerDescriptors == 0 && SamplerHeapSpace.IsNull() || SamplerHeapSpace.GetNumHandles() == TotalSamplerDescriptors);
-
- // Iterate through all root static/mutable tables and assign start offsets. The tables are tightly packed, so
- // start offset of table N+1 is start offset of table N plus the size of table N.
- // Root tables with dynamic resources as well as root views are not assigned space in GPU-visible allocation
- // (root views are simply not processed)
- Uint32 SrvCbvUavTblStartOffset = 0;
- Uint32 SamplerTblStartOffset = 0;
- for(Uint32 rt = 0; rt < m_RootParams.GetNumRootTables(); ++rt)
- {
- auto &RootParam = m_RootParams.GetRootTable(rt);
- const auto& VkRootParam = static_cast<const Vk_ROOT_PARAMETER&>(RootParam);
- auto &RootTableCache = ResourceCache.GetRootTable(RootParam.GetRootIndex());
-
- SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN;
-#ifdef _DEBUG
- dbgShaderType = ShaderTypeFromShaderVisibility(VkRootParam.ShaderVisibility);
-#endif
- VERIFY_EXPR( VkRootParam.ParameterType == Vk_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE );
-
- auto TableSize = RootParam.GetDescriptorTableSize();
- VERIFY(TableSize > 0, "Unexpected empty descriptor table");
-
- auto HeapType = HeapTypeFromRangeType(VkRootParam.DescriptorTable.pDescriptorRanges[0].RangeType);
-
-#ifdef _DEBUG
- RootTableCache.SetDebugAttribs( TableSize, HeapType, dbgShaderType );
-#endif
-
- // Space for dynamic variables is allocated at every draw call
- if( RootParam.GetShaderVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC )
- {
- if( HeapType == Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV )
- {
- RootTableCache.m_TableStartOffset = SrvCbvUavTblStartOffset;
- SrvCbvUavTblStartOffset += TableSize;
- }
- else
- {
- RootTableCache.m_TableStartOffset = SamplerTblStartOffset;
- SamplerTblStartOffset += TableSize;
- }
- }
- else
- {
- VERIFY_EXPR(RootTableCache.m_TableStartOffset == ShaderResourceCacheVk::InvalidDescriptorOffset);
- }
- }
-
-#ifdef _DEBUG
- for(Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv)
- {
- auto &RootParam = m_RootParams.GetRootView(rv);
- const auto& VkRootParam = static_cast<const Vk_ROOT_PARAMETER&>(RootParam);
- auto &RootTableCache = ResourceCache.GetRootTable(RootParam.GetRootIndex());
- // Root views are not assigned valid table start offset
- VERIFY_EXPR(RootTableCache.m_TableStartOffset == ShaderResourceCacheVk::InvalidDescriptorOffset);
-
- SHADER_TYPE dbgShaderType = ShaderTypeFromShaderVisibility(VkRootParam.ShaderVisibility);
- VERIFY_EXPR(VkRootParam.ParameterType == Vk_ROOT_PARAMETER_TYPE_CBV);
- RootTableCache.SetDebugAttribs( 1, Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, dbgShaderType );
- }
-#endif
-
- VERIFY_EXPR(SrvCbvUavTblStartOffset == TotalSrvCbvUavDescriptors);
- VERIFY_EXPR(SamplerTblStartOffset == TotalSamplerDescriptors);
-
- ResourceCache.SetDescriptorHeapSpace(std::move(CbcSrvUavHeapSpace), std::move(SamplerHeapSpace));'
-#endif
}
-#if 0
-
-
-template<class TOperation>
-__forceinline void PipelineLayout::DescriptorSetLayoutManager::ProcessRootTables(TOperation Operation)const
+void PipelineLayout::AllocateDynamicDescriptorSet(RenderDeviceVkImpl* pDevicVkImpl,
+ DeviceContextVkImpl* pCtxVkImpl,
+ ShaderResourceCacheVk& ResourceCache)const
{
- for(Uint32 rt = 0; rt < m_NumRootTables; ++rt)
+ const auto &DynSet = m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_DYNAMIC);
+ if (DynSet.SetIndex >= 0)
{
- auto &RootTable = GetRootTable(rt);
- auto RootInd = RootTable.GetRootIndex();
- const Vk_ROOT_PARAMETER& VkParam = RootTable;
-
- VERIFY_EXPR(VkParam.ParameterType == Vk_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE);
-
- auto &VkTable = VkParam.DescriptorTable;
- VERIFY(VkTable.NumDescriptorRanges > 0 && RootTable.GetDescriptorTableSize() > 0, "Unexepected empty descriptor table");
- bool IsResourceTable = VkTable.pDescriptorRanges[0].RangeType != Vk_DESCRIPTOR_RANGE_TYPE_SAMPLER;
- Vk_DESCRIPTOR_HEAP_TYPE dbgHeapType = Vk_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;
-#ifdef _DEBUG
- dbgHeapType = IsResourceTable ? Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV : Vk_DESCRIPTOR_HEAP_TYPE_SAMPLER;
-#endif
- Operation(RootInd, RootTable, VkParam, IsResourceTable, dbgHeapType);
+ auto DynamicSetAllocation = pDevicVkImpl->AllocateDynamicDescriptorSet(DynSet.VkLayout, pCtxVkImpl->GetContextId());
+ auto &DynamicSetCache = ResourceCache.GetDescriptorSet(DynSet.SetIndex);
+ DynamicSetCache.AssignDescriptorSetAllocation(std::move(DynamicSetAllocation));
}
}
-template<class TOperation>
-__forceinline void ProcessCachedTableResources(Uint32 RootInd,
- const Vk_ROOT_PARAMETER& VkParam,
- ShaderResourceCacheVk& ResourceCache,
- Vk_DESCRIPTOR_HEAP_TYPE dbgHeapType,
- TOperation Operation)
+void PipelineLayout::BindDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
+ bool IsCompute,
+ ShaderResourceCacheVk& ResourceCache)const
{
- for (UINT r = 0; r < VkParam.DescriptorTable.NumDescriptorRanges; ++r)
+ uint32_t SetCount = 0;
+ std::array<VkDescriptorSet, 2> vkSets = {};
+
+ VERIFY(m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_STATIC).SetIndex == m_LayoutMgr.GetDescriptorSet(SHADER_VARIABLE_TYPE_MUTABLE).SetIndex,
+ "Static and mutable variables are expected to share the same descriptor set");
+ for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_MUTABLE; VarType <= SHADER_VARIABLE_TYPE_DYNAMIC; VarType = static_cast<SHADER_VARIABLE_TYPE>(VarType+1))
{
- const auto &range = VkParam.DescriptorTable.pDescriptorRanges[r];
- for (UINT d = 0; d < range.NumDescriptors; ++d)
+ const auto &Set = m_LayoutMgr.GetDescriptorSet(VarType);
+ if(Set.SetIndex >= 0)
{
- SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN;
-#ifdef _DEBUG
- dbgShaderType = ShaderTypeFromShaderVisibility(VkParam.ShaderVisibility);
- VERIFY(dbgHeapType == HeapTypeFromRangeType(range.RangeType), "Mistmatch between descriptor heap type and descriptor range type");
-#endif
- auto OffsetInCache = range.OffsetInDescriptorsFromTableStart + d;
- auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(OffsetInCache, dbgHeapType, dbgShaderType);
-
- Operation(OffsetInCache, range, Res);
+ SetCount = std::max(SetCount, static_cast<uint32_t>(Set.SetIndex+1));
+ VERIFY_EXPR(vkSets[Set.SetIndex] == VK_NULL_HANDLE);
+ vkSets[Set.SetIndex] = ResourceCache.GetDescriptorSet(Set.SetIndex).GetVkDescriptorSet();
+ VERIFY(vkSets[Set.SetIndex] != VK_NULL_HANDLE, "Descriptor set must not be null");
}
}
-}
-
-
-template<bool PerformResourceTransitions>
-void PipelineLayout::CommitDescriptorHandlesInternal_SMD(RenderDeviceVkImpl *pRenderDeviceVk,
- ShaderResourceCacheVk& ResourceCache,
- CommandContext &Ctx,
- bool IsCompute)const
-{
- auto *pVkDevice = pRenderDeviceVk->GetVkDevice();
-
- Uint32 NumDynamicCbvSrvUavDescriptors = m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_DYNAMIC];
- Uint32 NumDynamicSamplerDescriptors = m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_DYNAMIC];
- VERIFY_EXPR(NumDynamicCbvSrvUavDescriptors > 0 || NumDynamicSamplerDescriptors > 0);
- DescriptorHeapAllocation DynamicCbvSrvUavDescriptors, DynamicSamplerDescriptors;
- if(NumDynamicCbvSrvUavDescriptors)
- DynamicCbvSrvUavDescriptors = Ctx.AllocateDynamicGPUVisibleDescriptor(Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, NumDynamicCbvSrvUavDescriptors);
- if(NumDynamicSamplerDescriptors)
- DynamicSamplerDescriptors = Ctx.AllocateDynamicGPUVisibleDescriptor(Vk_DESCRIPTOR_HEAP_TYPE_SAMPLER, NumDynamicSamplerDescriptors);
-
- CommandContext::ShaderDescriptorHeaps Heaps(ResourceCache.GetSrvCbvUavDescriptorHeap(), ResourceCache.GetSamplerDescriptorHeap());
- if(Heaps.pSamplerHeap == nullptr)
- Heaps.pSamplerHeap = DynamicSamplerDescriptors.GetDescriptorHeap();
-
- if(Heaps.pSrvCbvUavHeap == nullptr)
- Heaps.pSrvCbvUavHeap = DynamicCbvSrvUavDescriptors.GetDescriptorHeap();
-
- if(NumDynamicCbvSrvUavDescriptors)
- VERIFY(DynamicCbvSrvUavDescriptors.GetDescriptorHeap() == Heaps.pSrvCbvUavHeap, "Inconsistent CbvSrvUav descriptor heaps" );
- if(NumDynamicSamplerDescriptors)
- VERIFY(DynamicSamplerDescriptors.GetDescriptorHeap() == Heaps.pSamplerHeap, "Inconsistent Sampler descriptor heaps" );
-
- if(Heaps)
- Ctx.SetDescriptorHeaps(Heaps);
-
- // Offset to the beginning of the current dynamic CBV_SRV_UAV/SAMPLER table from
- // the start of the allocation
- Uint32 DynamicCbvSrvUavTblOffset = 0;
- Uint32 DynamicSamplerTblOffset = 0;
-
- m_RootParams.ProcessRootTables(
- [&](Uint32 RootInd, const RootParameter &RootTable, const Vk_ROOT_PARAMETER& VkParam, bool IsResourceTable, Vk_DESCRIPTOR_HEAP_TYPE dbgHeapType )
- {
- Vk_GPU_DESCRIPTOR_HANDLE RootTableGPUDescriptorHandle;
- bool IsDynamicTable = RootTable.GetShaderVariableType() == SHADER_VARIABLE_TYPE_DYNAMIC;
- if (IsDynamicTable)
- {
- if( IsResourceTable )
- RootTableGPUDescriptorHandle = DynamicCbvSrvUavDescriptors.GetGpuHandle(DynamicCbvSrvUavTblOffset);
- else
- RootTableGPUDescriptorHandle = DynamicSamplerDescriptors.GetGpuHandle(DynamicSamplerTblOffset);
- }
- else
- {
- RootTableGPUDescriptorHandle = IsResourceTable ?
- ResourceCache.GetShaderVisibleTableGPUDescriptorHandle<Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(RootInd) :
- ResourceCache.GetShaderVisibleTableGPUDescriptorHandle<Vk_DESCRIPTOR_HEAP_TYPE_SAMPLER>(RootInd);
- VERIFY(RootTableGPUDescriptorHandle.ptr != 0, "Unexpected null GPU descriptor handle");
- }
-
- if(IsCompute)
- Ctx.GetCommandList()->SetComputeRootDescriptorTable(RootInd, RootTableGPUDescriptorHandle);
- else
- Ctx.GetCommandList()->SetGraphicsRootDescriptorTable(RootInd, RootTableGPUDescriptorHandle);
-
- ProcessCachedTableResources(RootInd, VkParam, ResourceCache, dbgHeapType,
- [&](UINT OffsetInCache, const Vk_DESCRIPTOR_RANGE &range, ShaderResourceCacheVk::Resource &Res)
- {
- if(PerformResourceTransitions)
- {
- TransitionResource(Ctx, Res, range.RangeType);
- }
-#ifdef _DEBUG
- else
- {
- DbgVerifyResourceState(Res, range.RangeType);
- }
-#endif
-
- if(IsDynamicTable)
- {
- if (IsResourceTable)
- {
- if( Res.CPUDescriptorHandle.ptr == 0 )
- LOG_ERROR_MESSAGE("No valid CbvSrvUav descriptor handle found for root parameter ", RootInd, ", descriptor slot ", OffsetInCache);
-
- VERIFY( DynamicCbvSrvUavTblOffset < NumDynamicCbvSrvUavDescriptors, "Not enough space in the descriptor heap allocation");
-
- pVkDevice->CopyDescriptorsSimple(1, DynamicCbvSrvUavDescriptors.GetCpuHandle(DynamicCbvSrvUavTblOffset), Res.CPUDescriptorHandle, Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
- ++DynamicCbvSrvUavTblOffset;
- }
- else
- {
- if( Res.CPUDescriptorHandle.ptr == 0 )
- LOG_ERROR_MESSAGE("No valid sampler descriptor handle found for root parameter ", RootInd, ", descriptor slot ", OffsetInCache);
-
- VERIFY( DynamicSamplerTblOffset < NumDynamicSamplerDescriptors, "Not enough space in the descriptor heap allocation");
-
- pVkDevice->CopyDescriptorsSimple(1, DynamicSamplerDescriptors.GetCpuHandle(DynamicSamplerTblOffset), Res.CPUDescriptorHandle, Vk_DESCRIPTOR_HEAP_TYPE_SAMPLER);
- ++DynamicSamplerTblOffset;
- }
- }
- }
- );
- }
- );
-
- VERIFY_EXPR( DynamicCbvSrvUavTblOffset == NumDynamicCbvSrvUavDescriptors );
- VERIFY_EXPR( DynamicSamplerTblOffset == NumDynamicSamplerDescriptors );
-}
-
-template<bool PerformResourceTransitions>
-void PipelineLayout::CommitDescriptorHandlesInternal_SM(RenderDeviceVkImpl *pRenderDeviceVk,
- ShaderResourceCacheVk& ResourceCache,
- CommandContext &Ctx,
- bool IsCompute)const
-{
- VERIFY_EXPR(m_TotalSrvCbvUavSlots[SHADER_VARIABLE_TYPE_DYNAMIC] == 0 && m_TotalSamplerSlots[SHADER_VARIABLE_TYPE_DYNAMIC] == 0);
-
- CommandContext::ShaderDescriptorHeaps Heaps(ResourceCache.GetSrvCbvUavDescriptorHeap(), ResourceCache.GetSamplerDescriptorHeap());
- if(Heaps)
- Ctx.SetDescriptorHeaps(Heaps);
-
- m_RootParams.ProcessRootTables(
- [&](Uint32 RootInd, const RootParameter &RootTable, const Vk_ROOT_PARAMETER& VkParam, bool IsResourceTable, Vk_DESCRIPTOR_HEAP_TYPE dbgHeapType )
- {
- VERIFY(RootTable.GetShaderVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC, "Unexpected dynamic resource");
-
- Vk_GPU_DESCRIPTOR_HANDLE RootTableGPUDescriptorHandle = IsResourceTable ?
- ResourceCache.GetShaderVisibleTableGPUDescriptorHandle<Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV>(RootInd) :
- ResourceCache.GetShaderVisibleTableGPUDescriptorHandle<Vk_DESCRIPTOR_HEAP_TYPE_SAMPLER>(RootInd);
- VERIFY(RootTableGPUDescriptorHandle.ptr != 0, "Unexpected null GPU descriptor handle");
-
- if(IsCompute)
- Ctx.GetCommandList()->SetComputeRootDescriptorTable(RootInd, RootTableGPUDescriptorHandle);
- else
- Ctx.GetCommandList()->SetGraphicsRootDescriptorTable(RootInd, RootTableGPUDescriptorHandle);
-
- if(PerformResourceTransitions)
- {
- ProcessCachedTableResources(RootInd, VkParam, ResourceCache, dbgHeapType,
- [&](UINT OffsetInCache, const Vk_DESCRIPTOR_RANGE &range, ShaderResourceCacheVk::Resource &Res)
- {
- TransitionResource(Ctx, Res, range.RangeType);
- }
- );
- }
#ifdef _DEBUG
- else
- {
- ProcessCachedTableResources(RootInd, VkParam, ResourceCache, dbgHeapType,
- [&](UINT OffsetInCache, const Vk_DESCRIPTOR_RANGE &range, ShaderResourceCacheVk::Resource &Res)
- {
- DbgVerifyResourceState(Res, range.RangeType);
- }
- );
- }
+ for (uint32_t i = 0; i < SetCount; ++i)
+ VERIFY(vkSets[i] != VK_NULL_HANDLE, "Descriptor set must not be null");
#endif
- }
- );
-}
-
-void PipelineLayout::TransitionResources(ShaderResourceCacheVk& ResourceCache,
- class CommandContext &Ctx)const
-{
- m_RootParams.ProcessRootTables(
- [&](Uint32 RootInd, const RootParameter &RootTable, const Vk_ROOT_PARAMETER& VkParam, bool IsResourceTable, Vk_DESCRIPTOR_HEAP_TYPE dbgHeapType )
- {
- ProcessCachedTableResources(RootInd, VkParam, ResourceCache, dbgHeapType,
- [&](UINT OffsetInCache, const Vk_DESCRIPTOR_RANGE &range, ShaderResourceCacheVk::Resource &Res)
- {
- TransitionResource(Ctx, Res, range.RangeType);
- }
- );
- }
- );
+ auto& CmdBuffer = pCtxVkImpl->GetCommandBuffer();
+ // vkCmdBindDescriptorSets causes the sets numbered [firstSet .. firstSet+descriptorSetCount-1] to use the
+ // bindings stored in pDescriptorSets[0 .. descriptorSetCount-1] for subsequent rendering commands
+ // (either compute or graphics, according to the pipelineBindPoint). Any bindings that were previously
+ // applied via these sets are no longer valid (13.2.5)
+ CmdBuffer.BindDescriptorSets(IsCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS,
+ m_LayoutMgr.GetVkPipelineLayout(),
+ 0, // First set
+ SetCount,
+ vkSets.data());
}
-
-void PipelineLayout::CommitRootViews(ShaderResourceCacheVk& ResourceCache,
- CommandContext &Ctx,
- bool IsCompute,
- Uint32 ContextId)const
-{
- for(Uint32 rv = 0; rv < m_RootParams.GetNumRootViews(); ++rv)
- {
- auto &RootView = m_RootParams.GetRootView(rv);
- auto RootInd = RootView.GetRootIndex();
-
- SHADER_TYPE dbgShaderType = SHADER_TYPE_UNKNOWN;
-#ifdef _DEBUG
- auto &Param = static_cast<const Vk_ROOT_PARAMETER&>( RootView );
- VERIFY_EXPR(Param.ParameterType == Vk_ROOT_PARAMETER_TYPE_CBV);
- dbgShaderType = ShaderTypeFromShaderVisibility(Param.ShaderVisibility);
-#endif
-
- auto& Res = ResourceCache.GetRootTable(RootInd).GetResource(0, Vk_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, dbgShaderType);
- auto *pBuffToTransition = Res.pObject.RawPtr<BufferVkImpl>();
- if( !pBuffToTransition->CheckAllStates(Vk_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER) )
- Ctx.TransitionResource(pBuffToTransition, Vk_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
-
- Vk_GPU_VIRTUAL_ADDRESS CBVAddress = pBuffToTransition->GetGPUAddress(ContextId);
- if(IsCompute)
- Ctx.GetCommandList()->SetComputeRootConstantBufferView(RootInd, CBVAddress);
- else
- Ctx.GetCommandList()->SetGraphicsRootConstantBufferView(RootInd, CBVAddress);
- }
-}
-#endif
}
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index c0627d78..f9075de9 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -27,6 +27,7 @@
#include "ShaderVkImpl.h"
#include "VulkanTypeConversions.h"
#include "RenderDeviceVkImpl.h"
+#include "DeviceContextVkImpl.h"
#include "ShaderResourceBindingVkImpl.h"
#include "CommandContext.h"
#include "EngineMemory.h"
@@ -532,7 +533,6 @@ ShaderResourceCacheVk* PipelineStateVkImpl::CommitAndTransitionShaderResources(I
pResBindingVkImpl->dbgVerifyResourceBindings(this);
#endif
- //auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>( GetDevice() );
auto &ResourceCache = pResBindingVkImpl->GetResourceCache();
if(CommitResources)
@@ -545,11 +545,14 @@ ShaderResourceCacheVk* PipelineStateVkImpl::CommitAndTransitionShaderResources(I
ResourceCache.TransitionResources<true>(pCtxVkImpl);
#endif
}
-
- //if(m_Desc.IsComputePipeline)
- // Ctx.AsComputeContext().SetRootSignature( GetVkRootSignature() );
- //else
- // Ctx.AsGraphicsContext().SetRootSignature( GetVkRootSignature() );
+
+ auto *pDeviceVkImpl = ValidatedCast<RenderDeviceVkImpl>(GetDevice());
+ // Allocate vulkan descriptor set for dynamic resources
+ m_PipelineLayout.AllocateDynamicDescriptorSet(pDeviceVkImpl, pCtxVkImpl, ResourceCache);
+ // Commit all dynamic resource descriptors
+ pResBindingVkImpl->CommitDynamicResources();
+ // Bind descriptor sets
+ m_PipelineLayout.BindDescriptorSets(pCtxVkImpl, m_Desc.IsComputePipeline, ResourceCache);
}
else
{
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
index 29ba4f4f..b320d5ba 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
@@ -143,4 +143,12 @@ void ShaderResourceBindingVkImpl::InitializeStaticResources(const PipelineStateV
m_bStaticResourcesInitialized = true;
}
+void ShaderResourceBindingVkImpl::CommitDynamicResources()
+{
+ for (Uint32 s=0; s < m_NumShaders; ++s)
+ {
+ m_pResourceLayouts[s].CommitDynamicResources();
+ }
+}
+
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
index dbf1db5f..83dd4a71 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
@@ -29,150 +29,228 @@
#include "BufferViewVkImpl.h"
#include "TextureViewVkImpl.h"
#include "TextureVkImpl.h"
+#include "SamplerVkImpl.h"
namespace Diligent
{
- void ShaderResourceCacheVk::InitializeSets(IMemoryAllocator &MemAllocator, Uint32 NumSets, Uint32 SetSizes[])
+
+void ShaderResourceCacheVk::InitializeSets(IMemoryAllocator &MemAllocator, Uint32 NumSets, Uint32 SetSizes[])
+{
+ // Memory layout:
+ // ______________________________________________________________
+ // m_pMemory | m_pResources, m_NumResources == m |
+ // | | |
+ // V | V
+ // | DescriptorSet[0] | .... | DescriptorSet[Ns-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] |
+ // | A \
+ // | | \
+ // |__________________________________________________| \RefCntAutoPtr
+ // m_pResources, m_NumResources == n \_________
+ // | Object |
+ // ---------
+ //
+ // Ns = m_NumSets
+
+ VERIFY(m_pAllocator == nullptr && m_pMemory == nullptr, "Cache already initialized");
+ m_pAllocator = &MemAllocator;
+ m_NumSets = NumSets;
+ m_TotalResources = 0;
+ for(Uint32 t=0; t < NumSets; ++t)
+ m_TotalResources += SetSizes[t];
+ auto MemorySize = NumSets * sizeof(DescriptorSet) + m_TotalResources * sizeof(Resource);
+ if(MemorySize > 0)
{
- // Memory layout:
- // ______________________________________________________________
- // m_pMemory | m_pResources, m_NumResources == m |
- // | | |
- // V | V
- // | DescriptorSet[0] | .... | DescriptorSet[Ns-1] | Res[0] | ... | Res[n-1] | .... | Res[0] | ... | Res[m-1] |
- // | A \
- // | | \
- // |__________________________________________________| \RefCntAutoPtr
- // m_pResources, m_NumResources == n \_________
- // | Object |
- // ---------
- //
- // Ns = m_NumSets
-
- VERIFY(m_pAllocator == nullptr && m_pMemory == nullptr, "Cache already initialized");
- m_pAllocator = &MemAllocator;
- m_NumSets = NumSets;
- m_TotalResources = 0;
- for(Uint32 t=0; t < NumSets; ++t)
- m_TotalResources += SetSizes[t];
- auto MemorySize = NumSets * sizeof(DescriptorSet) + m_TotalResources * sizeof(Resource);
- if(MemorySize > 0)
+ m_pMemory = ALLOCATE( *m_pAllocator, "Memory for shader resource cache data", MemorySize);
+ auto *pSets = reinterpret_cast<DescriptorSet*>(m_pMemory);
+ auto *pCurrResPtr = reinterpret_cast<Resource*>(pSets + m_NumSets);
+ for (Uint32 t = 0; t < NumSets; ++t)
{
- m_pMemory = ALLOCATE( *m_pAllocator, "Memory for shader resource cache data", MemorySize);
- auto *pSets = reinterpret_cast<DescriptorSet*>(m_pMemory);
- auto *pCurrResPtr = reinterpret_cast<Resource*>(pSets + m_NumSets);
- for (Uint32 t = 0; t < NumSets; ++t)
- {
- new(&GetDescriptorSet(t)) DescriptorSet(SetSizes[t], SetSizes[t] > 0 ? pCurrResPtr : nullptr);
- pCurrResPtr += SetSizes[t];
- }
- VERIFY_EXPR((char*)pCurrResPtr == (char*)m_pMemory + MemorySize);
+ new(&GetDescriptorSet(t)) DescriptorSet(SetSizes[t], SetSizes[t] > 0 ? pCurrResPtr : nullptr);
+ pCurrResPtr += SetSizes[t];
}
+ VERIFY_EXPR((char*)pCurrResPtr == (char*)m_pMemory + MemorySize);
}
+}
- void ShaderResourceCacheVk::InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, SPIRVShaderResourceAttribs::ResourceType Type)
- {
- auto &DescrSet = GetDescriptorSet(Set);
- for (Uint32 res = 0; res < ArraySize; ++res)
- new(&DescrSet.GetResource(Offset + res)) Resource{Type};
- }
+void ShaderResourceCacheVk::InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, SPIRVShaderResourceAttribs::ResourceType Type)
+{
+ auto &DescrSet = GetDescriptorSet(Set);
+ for (Uint32 res = 0; res < ArraySize; ++res)
+ new(&DescrSet.GetResource(Offset + res)) Resource{Type};
+}
- ShaderResourceCacheVk::~ShaderResourceCacheVk()
+ShaderResourceCacheVk::~ShaderResourceCacheVk()
+{
+ if (m_pMemory)
{
- if (m_pMemory)
- {
- auto *pResources = reinterpret_cast<Resource*>( reinterpret_cast<DescriptorSet*>(m_pMemory) + m_NumSets);
- for(Uint32 res=0; res < m_TotalResources; ++res)
- pResources[res].~Resource();
- for (Uint32 t = 0; t < m_NumSets; ++t)
- GetDescriptorSet(t).~DescriptorSet();
+ auto *pResources = reinterpret_cast<Resource*>( reinterpret_cast<DescriptorSet*>(m_pMemory) + m_NumSets);
+ for(Uint32 res=0; res < m_TotalResources; ++res)
+ pResources[res].~Resource();
+ for (Uint32 t = 0; t < m_NumSets; ++t)
+ GetDescriptorSet(t).~DescriptorSet();
- m_pAllocator->Free(m_pMemory);
- }
+ m_pAllocator->Free(m_pMemory);
}
+}
- template<bool VerifyOnly>
- void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl *pCtxVkImpl)
+template<bool VerifyOnly>
+void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl *pCtxVkImpl)
+{
+ auto *pResources = reinterpret_cast<Resource*>(reinterpret_cast<DescriptorSet*>(m_pMemory) + m_NumSets);
+ for (Uint32 res = 0; res < m_TotalResources; ++res)
{
- auto *pResources = reinterpret_cast<Resource*>(reinterpret_cast<DescriptorSet*>(m_pMemory) + m_NumSets);
- for (Uint32 res = 0; res < m_TotalResources; ++res)
+ auto &Res = pResources[res];
+ switch (Res.Type)
{
- auto &Res = pResources[res];
- switch (Res.Type)
+ case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
+ case SPIRVShaderResourceAttribs::ResourceType::StorageBuffer:
{
- case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
- case SPIRVShaderResourceAttribs::ResourceType::StorageBuffer:
- {
- auto *pBufferVk = Res.pObject.RawPtr<BufferVkImpl>();
- VkAccessFlags RequiredAccessFlags =
- Res.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer ?
- VK_ACCESS_UNIFORM_READ_BIT :
- (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
- if(pBufferVk->GetAccessFlags() != RequiredAccessFlags)
- {
- if(VerifyOnly)
- LOG_ERROR_MESSAGE("Buffer \"", pBufferVk->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?");
- else
- pCtxVkImpl->BufferMemoryBarrier(*pBufferVk, RequiredAccessFlags);
- }
- }
- break;
-
- case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer:
- case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer:
- {
- auto *pBuffViewVk = Res.pObject.RawPtr<BufferViewVkImpl>();
- auto *pBufferVk = ValidatedCast<BufferVkImpl>(pBuffViewVk->GetBuffer());
- VkAccessFlags RequiredAccessFlags =
- Res.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer ?
- VK_ACCESS_SHADER_READ_BIT :
+ auto *pBufferVk = Res.pObject.RawPtr<BufferVkImpl>();
+ VkAccessFlags RequiredAccessFlags =
+ Res.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer ?
+ VK_ACCESS_UNIFORM_READ_BIT :
(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
- if (pBufferVk->GetAccessFlags() != RequiredAccessFlags)
- {
- if (VerifyOnly)
- LOG_ERROR_MESSAGE("Buffer \"", pBufferVk->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?");
- else
- pCtxVkImpl->BufferMemoryBarrier(*pBufferVk, RequiredAccessFlags);
- }
- }
- break;
-
- case SPIRVShaderResourceAttribs::ResourceType::SeparateImage:
- case SPIRVShaderResourceAttribs::ResourceType::SampledImage:
- case SPIRVShaderResourceAttribs::ResourceType::StorageImage:
+ if(pBufferVk->GetAccessFlags() != RequiredAccessFlags)
{
- auto *pTextureViewVk = Res.pObject.RawPtr<TextureViewVkImpl>();
- auto *pTextureVk = ValidatedCast<TextureVkImpl>(pTextureViewVk->GetTexture());
- VkImageLayout RequiredLayout =
- Res.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ?
- VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- if(pTextureVk->GetLayout() != RequiredLayout)
- {
- if (VerifyOnly)
- LOG_ERROR_MESSAGE("Texture \"", pTextureVk->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?");
- else
- pCtxVkImpl->TransitionImageLayout(*pTextureVk, RequiredLayout);
- }
+ if(VerifyOnly)
+ LOG_ERROR_MESSAGE("Buffer \"", pBufferVk->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?");
+ else
+ pCtxVkImpl->BufferMemoryBarrier(*pBufferVk, RequiredAccessFlags);
}
- break;
+ }
+ break;
- case SPIRVShaderResourceAttribs::ResourceType::AtomicCounter:
+ case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer:
+ case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer:
+ {
+ auto *pBuffViewVk = Res.pObject.RawPtr<BufferViewVkImpl>();
+ auto *pBufferVk = ValidatedCast<BufferVkImpl>(pBuffViewVk->GetBuffer());
+ VkAccessFlags RequiredAccessFlags =
+ Res.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer ?
+ VK_ACCESS_SHADER_READ_BIT :
+ (VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
+ if (pBufferVk->GetAccessFlags() != RequiredAccessFlags)
{
- // Nothing to do with atomic counters
+ if (VerifyOnly)
+ LOG_ERROR_MESSAGE("Buffer \"", pBufferVk->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?");
+ else
+ pCtxVkImpl->BufferMemoryBarrier(*pBufferVk, RequiredAccessFlags);
}
- break;
+ }
+ break;
- case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler:
+ case SPIRVShaderResourceAttribs::ResourceType::SeparateImage:
+ case SPIRVShaderResourceAttribs::ResourceType::SampledImage:
+ case SPIRVShaderResourceAttribs::ResourceType::StorageImage:
+ {
+ auto *pTextureViewVk = Res.pObject.RawPtr<TextureViewVkImpl>();
+ auto *pTextureVk = ValidatedCast<TextureVkImpl>(pTextureViewVk->GetTexture());
+ VkImageLayout RequiredLayout =
+ Res.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ?
+ VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ if(pTextureVk->GetLayout() != RequiredLayout)
{
- // Nothing to do with samplers
+ if (VerifyOnly)
+ LOG_ERROR_MESSAGE("Texture \"", pTextureVk->GetDesc().Name, "\" is not in correct state. Did you forget to call TransitionShaderResources() or specify COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES flag in a call to CommitShaderResources()?");
+ else
+ pCtxVkImpl->TransitionImageLayout(*pTextureVk, RequiredLayout);
}
- break;
+ }
+ break;
- default: UNEXPECTED("Unexpected resource type");
+ case SPIRVShaderResourceAttribs::ResourceType::AtomicCounter:
+ {
+ // Nothing to do with atomic counters
+ }
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler:
+ {
+ // Nothing to do with samplers
}
+ break;
+
+ default: UNEXPECTED("Unexpected resource type");
}
}
+}
+
+template void ShaderResourceCacheVk::TransitionResources<false>(DeviceContextVkImpl *pCtxVkImpl);
+template void ShaderResourceCacheVk::TransitionResources<true>(DeviceContextVkImpl *pCtxVkImpl);
+
+
+VkDescriptorBufferInfo ShaderResourceCacheVk::Resource::GetBufferDescriptorWriteInfo()const
+{
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer ||
+ Type == SPIRVShaderResourceAttribs::ResourceType::StorageBuffer,
+ "Uniform or storage buffer resource is expected");
+
+ auto* pBuffVk = pObject.RawPtr<const BufferVkImpl>();
+
+ VkDescriptorBufferInfo DescrBuffInfo;
+ DescrBuffInfo.buffer = pBuffVk->GetVkBuffer();
+ DescrBuffInfo.offset = 0;
+ DescrBuffInfo.range = pBuffVk->GetDesc().uiSizeInBytes;
+ return DescrBuffInfo;
+}
+
+VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteInfo(bool IsImmutableSampler)const
+{
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ||
+ Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage ||
+ Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage,
+ "Storage image, separate image or sampled image resource is expected");
+
+ auto* pTexViewVk = pObject.RawPtr<const TextureViewVkImpl>();
+
+ VkDescriptorImageInfo DescrImgInfo;
+ DescrImgInfo.sampler = VK_NULL_HANDLE;
+ if (Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !IsImmutableSampler)
+ {
+ auto *pSamplerVk = ValidatedCast<const SamplerVkImpl>(pTexViewVk->GetSampler());
+ if (pSamplerVk != nullptr)
+ {
+ DescrImgInfo.sampler = pSamplerVk->GetVkSampler();
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("No sampler assigned to texture view \"", pTexViewVk->GetDesc().Name, "\"");
+ }
+ }
+ DescrImgInfo.imageView = pTexViewVk->GetVulkanImageView();
+
+ // If descriptorType is VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, for each descriptor that will be accessed
+ // via load or store operations the imageLayout member for corresponding elements of pImageInfo
+ // must be VK_IMAGE_LAYOUT_GENERAL (13.2.4)
+ DescrImgInfo.imageLayout =
+ (Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage) ?
+ VK_IMAGE_LAYOUT_GENERAL :
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+
+ return DescrImgInfo;
+}
+
+VkBufferView ShaderResourceCacheVk::Resource::GetBufferViewWriteInfo()const
+{
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer ||
+ Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer,
+ "Uniform or storage buffer resource is expected");
+
+ auto* pBuffViewVk = pObject.RawPtr<const BufferViewVkImpl>();
+ return pBuffViewVk->GetVkBufferView();
+}
+
+VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetSamplerDescriptorWriteInfo()const
+{
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected");
+
+ auto* pSamplerVk = pObject.RawPtr<const SamplerVkImpl>();
+ VkDescriptorImageInfo DescrImgInfo;
+ DescrImgInfo.sampler = pSamplerVk->GetVkSampler();
+ DescrImgInfo.imageView = VK_NULL_HANDLE;
+ DescrImgInfo.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ return DescrImgInfo;
+}
+
- template void ShaderResourceCacheVk::TransitionResources<false>(DeviceContextVkImpl *pCtxVkImpl);
- template void ShaderResourceCacheVk::TransitionResources<true>(DeviceContextVkImpl *pCtxVkImpl);
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index 98651f09..1b273233 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -309,9 +309,9 @@ void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet
uint32_t ArrayElement,
const VkDescriptorImageInfo* pImageInfo,
const VkDescriptorBufferInfo* pBufferInfo,
- const VkBufferView* pTexelBufferView)
+ const VkBufferView* pTexelBufferView)const
{
- VERIFY(SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC, "Dynamic resource descriptors must be updated by CommitShaderResources()");
+ VERIFY_EXPR(vkDescrSet != VK_NULL_HANDLE);
VkWriteDescriptorSet WriteDescrSet;
WriteDescrSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
@@ -344,7 +344,7 @@ bool ShaderResourceLayoutVk::VkResource::UpdateCachedResource(ShaderResourceCach
if (DstRes.pObject != pResource)
{
auto VarTypeStr = GetShaderVariableTypeLiteralName(SpirvAttribs.VarType);
- LOG_ERROR_MESSAGE("Non-null resource is already bound to ", VarTypeStr, " shader variable \"", SpirvAttribs.GetPrintName(ArrayInd), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempring to bind another resource is an error and will be ignored. Use another shader resource binding instance or label shader variable as dynamic.");
+ LOG_ERROR_MESSAGE("Non-null resource is already bound to ", VarTypeStr, " shader variable \"", SpirvAttribs.GetPrintName(ArrayInd), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempring to bind another resource is an error and will be ignored. Use another shader resource binding instance or label the variable as dynamic.");
}
// Do not update resource if one is already bound unless it is dynamic. This may be
@@ -373,24 +373,24 @@ void ShaderResourceLayoutVk::VkResource::CacheBuffer(IDeviceObject*
if( UpdateCachedResource(DstRes, ArrayInd, pBuffer, IID_BufferVk, "buffer") )
{
+#ifdef VERIFY_SHADER_BINDINGS
auto* pBuffVk = DstRes.pObject.RawPtr<BufferVkImpl>(); // Use final type
const auto IsUniformBuffer = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer;
const auto ExpectedBindFlag = IsUniformBuffer ? BIND_UNIFORM_BUFFER : BIND_UNORDERED_ACCESS;
- if( pBuffVk->GetDesc().BindFlags & ExpectedBindFlag)
+ if( (pBuffVk->GetDesc().BindFlags & ExpectedBindFlag) == 0)
{
- if(vkDescrSet != VK_NULL_HANDLE)
- {
- VkDescriptorBufferInfo DescrBuffInfo;
- DescrBuffInfo.buffer = pBuffVk->GetVkBuffer();
- DescrBuffInfo.offset = 0;
- DescrBuffInfo.range = pBuffVk->GetDesc().uiSizeInBytes;
- UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, &DescrBuffInfo, nullptr);
- }
+ LOG_RESOURCE_BINDING_ERROR("buffer", pBuffer, SpirvAttribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "Buffer was not created with ", (IsUniformBuffer ? "BIND_UNIFORM_BUFFER" : "BIND_UNORDERED_ACCESS"), " flag.")
+ DstRes.pObject.Release();
+ return;
}
- else
+#endif
+
+ // Do not update descriptor for a dynamic uniform/storage buffer. All dynamic resource
+ // descriptors are updated at once by CommitDynamicResources() when SRB is committed.
+ if(vkDescrSet != VK_NULL_HANDLE && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC)
{
- LOG_RESOURCE_BINDING_ERROR("buffer", pBuffer, SpirvAttribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "Buffer was not created with BIND_UNIFORM_BUFFER flag.")
- DstRes.pObject.Release();
+ VkDescriptorBufferInfo DescrBuffInfo = DstRes.GetBufferDescriptorWriteInfo();
+ UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, &DescrBuffInfo, nullptr);
}
}
}
@@ -425,7 +425,9 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
}
#endif
- if (vkDescrSet != VK_NULL_HANDLE)
+ // Do not update descriptor for a dynamic texel buffer. All dynamic resource descriptors
+ // are updated at once by CommitDynamicResources() when SRB is committed.
+ if (vkDescrSet != VK_NULL_HANDLE && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC)
{
VkBufferView BuffView = pBuffViewVk->GetVkBufferView();
UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, nullptr, &BuffView);
@@ -445,10 +447,9 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
if (UpdateCachedResource(DstRes, ArrayInd, pTexView, IID_TextureViewVk, "texture view") )
{
+#ifdef VERIFY_SHADER_BINDINGS
auto* pTexViewVk = DstRes.pObject.RawPtr<TextureViewVkImpl>();
const bool IsStorageImage = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage;
-
-#ifdef VERIFY_SHADER_BINDINGS
const auto& ViewDesc = pTexViewVk->GetDesc();
const auto ViewType = ViewDesc.ViewType;
const auto dbgExpectedViewType = IsStorageImage ? TEXTURE_VIEW_UNORDERED_ACCESS : TEXTURE_VIEW_SHADER_RESOURCE;
@@ -461,29 +462,21 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
DstRes.pObject.Release();
return;
}
-#endif
- if (vkDescrSet != VK_NULL_HANDLE)
+ if (SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && SpirvAttribs.StaticSamplerInd < 0)
{
- VkDescriptorImageInfo DescrImgInfo;
- DescrImgInfo.sampler = VK_NULL_HANDLE;
- if(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && SpirvAttribs.StaticSamplerInd < 0)
+ if(pTexViewVk->GetSampler() == nullptr)
{
- auto *pSamplerVk = ValidatedCast<ISamplerVk>(pTexViewVk->GetSampler());
- if(pSamplerVk != nullptr)
- {
- DescrImgInfo.sampler = pSamplerVk->GetVkSampler();
- }
- else
- {
- LOG_RESOURCE_BINDING_ERROR("resource", pTexView, SpirvAttribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "No sampler assigned to texture view.")
- }
+ LOG_RESOURCE_BINDING_ERROR("resource", pTexView, SpirvAttribs.GetPrintName(ArrayInd), ParentResLayout.GetShaderName(), "No sampler assigned to texture view.");
}
- DescrImgInfo.imageView = pTexViewVk->GetVulkanImageView();
- // If descriptorType is VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, for each descriptor that will be accessed
- // via load or store operations the imageLayout member for corresponding elements of pImageInfo
- // must be VK_IMAGE_LAYOUT_GENERAL (13.2.4)
- DescrImgInfo.imageLayout = IsStorageImage ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ }
+#endif
+
+ // Do not update descriptor for a dynamic image. All dynamic resource descriptors
+ // are updated at once by CommitDynamicResources() when SRB is committed.
+ if (vkDescrSet != VK_NULL_HANDLE && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC)
+ {
+ VkDescriptorImageInfo DescrImgInfo = DstRes.GetImageDescriptorWriteInfo(SpirvAttribs.StaticSamplerInd >= 0);
UpdateDescriptorHandle(vkDescrSet, ArrayInd, &DescrImgInfo, nullptr, nullptr);
}
}
@@ -498,13 +491,11 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject*
if (UpdateCachedResource(DstRes, ArrayInd, pSampler, IID_Sampler, "sampler"))
{
- auto* pSamplerVk = DstRes.pObject.RawPtr<SamplerVkImpl>();
- if (vkDescrSet != VK_NULL_HANDLE)
+ // Do not update descriptor for a dynamic sampler. All dynamic resource descriptors
+ // are updated at once by CommitDynamicResources() when SRB is committed.
+ if (vkDescrSet != VK_NULL_HANDLE && SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC)
{
- VkDescriptorImageInfo DescrImgInfo;
- DescrImgInfo.sampler = pSamplerVk->GetVkSampler();
- DescrImgInfo.imageView = VK_NULL_HANDLE;
- DescrImgInfo.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ VkDescriptorImageInfo DescrImgInfo = DstRes.GetSamplerDescriptorWriteInfo();
UpdateDescriptorHandle(vkDescrSet, ArrayInd, &DescrImgInfo, nullptr, nullptr);
}
}
@@ -523,9 +514,11 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject *pObj, Uint3
#ifdef _DEBUG
if (pResourceCache->DbgGetContentType() == ShaderResourceCacheVk::DbgCacheContentType::SRBResources)
{
- VERIFY(SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_DYNAMIC && vkDescrSet == VK_NULL_HANDLE ||
- SpirvAttribs.VarType != SHADER_VARIABLE_TYPE_DYNAMIC && vkDescrSet != VK_NULL_HANDLE,
- "Static and mutable variables and only them are expected to have valid descriptor set assigned");
+ if(SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_STATIC || SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_MUTABLE)
+ {
+ VERIFY(vkDescrSet != VK_NULL_HANDLE, "Static and mutable variables must have valid vulkan descriptor set assigned");
+ // Dynamic variables do not have vulkan descriptor set only until they are assigned one the first time
+ }
}
else if (pResourceCache->DbgGetContentType() == ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources)
{
@@ -757,9 +750,13 @@ void ShaderResourceLayoutVk::dbgVerifyBindings()const
if(dbgCacheContentType == ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources)
VERIFY(vkDescSet == VK_NULL_HANDLE, "Static resource cache should never have vulkan descriptor set");
else if (dbgCacheContentType == ShaderResourceCacheVk::DbgCacheContentType::SRBResources)
- VERIFY(VarType == SHADER_VARIABLE_TYPE_DYNAMIC && vkDescSet == VK_NULL_HANDLE ||
- VarType != SHADER_VARIABLE_TYPE_DYNAMIC && vkDescSet != VK_NULL_HANDLE,
- "Static and mutable resources (and only them) must have non-null vulkan descriptor set assigned");
+ {
+ if (VarType == SHADER_VARIABLE_TYPE_STATIC || VarType == SHADER_VARIABLE_TYPE_MUTABLE)
+ {
+ VERIFY(vkDescSet != VK_NULL_HANDLE, "Static and mutable variables must have valid vulkan descriptor set assigned");
+ // Dynamic variables do not have vulkan descriptor set only until they are assigned one the first time
+ }
+ }
else
UNEXPECTED("Unexpected cache content type");
#endif
@@ -812,4 +809,90 @@ void ShaderResourceLayoutVk::InitializeResourcesInCache()
}
}
+void ShaderResourceLayoutVk::CommitDynamicResources()
+{
+ VERIFY_EXPR(m_pResourceCache);
+ Uint32 NumDynamicResources = m_NumResources[SHADER_VARIABLE_TYPE_DYNAMIC];
+ if(NumDynamicResources == 0)
+ return;
+
+#if 0
+#ifdef _DEBUG
+ static constexpr size_t ImgUpdateBatchSize = 4;
+ static constexpr size_t BuffUpdateBatchSize = 2;
+ static constexpr size_t TexelBuffUpdateBatchSize = 2;
+#else
+ static constexpr size_t ImgUpdateBatchSize = 128;
+ static constexpr size_t BuffUpdateBatchSize = 64;
+ static constexpr size_t TexelBuffUpdateBatchSize = 32;
+#endif
+
+ std::array<VkDescriptorImageInfo, ImgUpdateBatchSize> ImgInfo;
+ std::array<VkDescriptorBufferInfo, BuffUpdateBatchSize> BuffInfo;
+ std::array<VkBufferView, BuffUpdateBatchSize> TexelBuffInfo;
+#endif
+
+ for(Uint32 r=0; r < NumDynamicResources; ++r)
+ {
+ const auto& Res = GetResource(SHADER_VARIABLE_TYPE_DYNAMIC, r);
+ VERIFY_EXPR(Res.SpirvAttribs.VarType == SHADER_VARIABLE_TYPE_DYNAMIC);
+ auto& SetResources = m_pResourceCache->GetDescriptorSet(Res.DescriptorSet);
+ auto vkSet = SetResources.GetVkDescriptorSet();
+ VERIFY(vkSet != VK_NULL_HANDLE, "Vulkan descriptor set must not be null");
+ switch(Res.SpirvAttribs.Type)
+ {
+ case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
+ case SPIRVShaderResourceAttribs::ResourceType::StorageBuffer:
+ for (Uint32 i = 0; i < Res.SpirvAttribs.ArraySize; ++i)
+ {
+ auto CachedRes = SetResources.GetResource(Res.CacheOffset + i);
+ VkDescriptorBufferInfo DescrBuffInfo = CachedRes.GetBufferDescriptorWriteInfo();
+ Res.UpdateDescriptorHandle(vkSet, i, nullptr, &DescrBuffInfo, nullptr);
+ }
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer:
+ case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer:
+ for (Uint32 i = 0; i < Res.SpirvAttribs.ArraySize; ++i)
+ {
+ auto CachedRes = SetResources.GetResource(Res.CacheOffset + i);
+ VkBufferView BuffView = CachedRes.GetBufferViewWriteInfo();
+ Res.UpdateDescriptorHandle(vkSet, i, nullptr, nullptr, &BuffView);
+ }
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::SeparateImage:
+ case SPIRVShaderResourceAttribs::ResourceType::StorageImage:
+ case SPIRVShaderResourceAttribs::ResourceType::SampledImage:
+ for (Uint32 i = 0; i < Res.SpirvAttribs.ArraySize; ++i)
+ {
+ auto CachedRes = SetResources.GetResource(Res.CacheOffset + i);
+ VkDescriptorImageInfo DescrImgInfo = CachedRes.GetImageDescriptorWriteInfo(Res.SpirvAttribs.StaticSamplerInd >= 0);
+ Res.UpdateDescriptorHandle(vkSet, i, &DescrImgInfo, nullptr, nullptr);
+ }
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::AtomicCounter:
+ // Do nothing
+ break;
+
+
+ case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler:
+ for (Uint32 i = 0; i < Res.SpirvAttribs.ArraySize; ++i)
+ {
+ if(Res.SpirvAttribs.StaticSamplerInd < 0)
+ {
+ auto CachedRes = SetResources.GetResource(Res.CacheOffset + i);
+ VkDescriptorImageInfo DescrImgInfo = CachedRes.GetSamplerDescriptorWriteInfo();
+ Res.UpdateDescriptorHandle(vkSet, i, &DescrImgInfo, nullptr, nullptr);
+ }
+ }
+ break;
+
+ default:
+ UNEXPECTED("Unexpected resource type");
+ }
+ }
+}
+
}