summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-03-10 23:26:13 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-03-19 00:38:20 +0000
commit3303d4d49a3f3c41154d05f0c78feb7e64a2c10d (patch)
tree1c898135f730ffd295a52c3c849e8de7fa09c92a /Graphics/GraphicsEngineVulkan
parentD3D12 backend: moved resource binding logic to shader variable manger (diff)
downloadDiligentCore-3303d4d49a3f3c41154d05f0c78feb7e64a2c10d.tar.gz
DiligentCore-3303d4d49a3f3c41154d05f0c78feb7e64a2c10d.zip
Vk backend: moved resource binding logic to variable manager and cache
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineResourceAttribsVk.hpp29
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp11
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp85
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderVariableManagerVk.hpp25
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp7
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp655
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp145
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVariableManagerVk.cpp476
8 files changed, 742 insertions, 691 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineResourceAttribsVk.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineResourceAttribsVk.hpp
index 34a19796..2d026392 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineResourceAttribsVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineResourceAttribsVk.hpp
@@ -162,4 +162,33 @@ public:
}
};
+inline VkDescriptorType DescriptorTypeToVkDescriptorType(DescriptorType Type)
+{
+ static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
+ switch (Type)
+ {
+ // clang-format off
+ case DescriptorType::Sampler: return VK_DESCRIPTOR_TYPE_SAMPLER;
+ case DescriptorType::CombinedImageSampler: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ case DescriptorType::SeparateImage: return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ case DescriptorType::StorageImage: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ case DescriptorType::UniformTexelBuffer: return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+ case DescriptorType::StorageTexelBuffer: return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ case DescriptorType::StorageTexelBuffer_ReadOnly: return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ case DescriptorType::UniformBuffer: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ case DescriptorType::UniformBufferDynamic: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ case DescriptorType::StorageBuffer: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ case DescriptorType::StorageBuffer_ReadOnly: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
+ case DescriptorType::StorageBufferDynamic: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
+ case DescriptorType::StorageBufferDynamic_ReadOnly: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
+ case DescriptorType::InputAttachment: return VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
+ case DescriptorType::AccelerationStructure: return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
+ // clang-format on
+ default:
+ UNEXPECTED("Unknown descriptor type");
+ return VK_DESCRIPTOR_TYPE_MAX_ENUM;
+ }
+}
+
+
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp
index 935367dd..5823f884 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp
@@ -121,17 +121,6 @@ public:
// Copies static resources from the static resource cache to the destination cache
void CopyStaticResources(ShaderResourceCacheVk& ResourceCache) const;
- // Binds object pObj to resource with index ResIndex in m_Desc.Resources and
- // array index ArrayIndex.
- void BindResource(IDeviceObject* pObj,
- Uint32 ArrayIndex,
- Uint32 ResIndex,
- ShaderResourceCacheVk& ResourceCache) const;
-
- bool IsBound(Uint32 ArrayIndex,
- Uint32 ResIndex,
- const ShaderResourceCacheVk& ResourceCache) const;
-
// Commits dynamic resources from ResourceCache to vkDynamicDescriptorSet
void CommitDynamicResources(const ShaderResourceCacheVk& ResourceCache,
VkDescriptorSet vkDynamicDescriptorSet) const;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
index aac66247..7cab3005 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
@@ -61,6 +61,7 @@
#include "BufferVkImpl.hpp"
#include "ShaderResourceCacheCommon.hpp"
#include "PipelineResourceAttribsVk.hpp"
+#include "VulkanUtilities/VulkanLogicalDevice.hpp"
namespace Diligent
{
@@ -90,33 +91,40 @@ public:
static size_t GetRequiredMemorySize(Uint32 NumSets, const Uint32* SetSizes);
void InitializeSets(IMemoryAllocator& MemAllocator, Uint32 NumSets, const Uint32* SetSizes);
- void InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, DescriptorType Type);
+ void InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, DescriptorType Type, bool HasImmutableSampler);
// sizeof(Resource) == 16 (x64, msvc, Release)
struct Resource
{
- // clang-format off
- explicit Resource(DescriptorType _Type) noexcept :
- Type{_Type}
- {}
+ explicit Resource(DescriptorType _Type, bool _HasImmutableSampler) noexcept :
+ Type{_Type},
+ HasImmutableSampler{_HasImmutableSampler}
+ {
+ VERIFY(Type == DescriptorType::CombinedImageSampler || Type == DescriptorType::Sampler || !HasImmutableSampler,
+ "Immutable sampler can only be assigned to a combined image sampler or a separate sampler");
+ }
+ // clang-format off
Resource (const Resource&) = delete;
Resource (Resource&&) = delete;
Resource& operator = (const Resource&) = delete;
Resource& operator = (Resource&&) = delete;
/* 0 */ const DescriptorType Type;
-/*1-7*/ // Unused
+/* 1 */ const bool HasImmutableSampler;
+/*2-7*/ // Unused
/* 8 */ RefCntAutoPtr<IDeviceObject> pObject;
- VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo () const;
- VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo () const;
- VkDescriptorImageInfo GetImageDescriptorWriteInfo (bool IsImmutableSampler) const;
+ VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo() const;
+ VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo() const;
+ VkDescriptorImageInfo GetImageDescriptorWriteInfo () const;
VkBufferView GetBufferViewWriteInfo () const;
VkDescriptorImageInfo GetSamplerDescriptorWriteInfo() const;
VkDescriptorImageInfo GetInputAttachmentDescriptorWriteInfo() const;
VkWriteDescriptorSetAccelerationStructureKHR GetAccelerationStructureWriteInfo() const;
// clang-format on
+
+ bool IsNull() const { return pObject == nullptr; }
};
// sizeof(DescriptorSet) == 48 (x64, msvc, Release)
@@ -135,55 +143,66 @@ public:
DescriptorSet& operator = (DescriptorSet&&) = delete;
// clang-format on
- inline Resource& GetResource(Uint32 CacheOffset)
- {
- VERIFY(CacheOffset < m_NumResources, "Offset ", CacheOffset, " is out of range");
- return m_pResources[CacheOffset];
- }
- inline const Resource& GetResource(Uint32 CacheOffset) const
+ const Resource& GetResource(Uint32 CacheOffset) const
{
VERIFY(CacheOffset < m_NumResources, "Offset ", CacheOffset, " is out of range");
return m_pResources[CacheOffset];
}
- inline Uint32 GetSize() const { return m_NumResources; }
+ Uint32 GetSize() const { return m_NumResources; }
VkDescriptorSet GetVkDescriptorSet() const
{
return m_DescriptorSetAllocation.GetVkDescriptorSet();
}
- void AssignDescriptorSetAllocation(DescriptorSetAllocation&& Allocation)
- {
- VERIFY(m_NumResources > 0, "Descriptor set is empty");
- m_DescriptorSetAllocation = std::move(Allocation);
- }
-
// clang-format off
/* 0 */ const Uint32 m_NumResources = 0;
private:
+ friend ShaderResourceCacheVk;
+ Resource& GetResource(Uint32 CacheOffset)
+ {
+ VERIFY(CacheOffset < m_NumResources, "Offset ", CacheOffset, " is out of range");
+ return m_pResources[CacheOffset];
+ }
+
/* 8 */ Resource* const m_pResources = nullptr;
/*16 */ DescriptorSetAllocation m_DescriptorSetAllocation;
/*48 */ // End of structure
// clang-format on
};
- inline DescriptorSet& GetDescriptorSet(Uint32 Index)
+ const DescriptorSet& GetDescriptorSet(Uint32 Index) const
{
VERIFY_EXPR(Index < m_NumSets);
- return reinterpret_cast<DescriptorSet*>(m_pMemory.get())[Index];
+ return reinterpret_cast<const DescriptorSet*>(m_pMemory.get())[Index];
}
- inline const DescriptorSet& GetDescriptorSet(Uint32 Index) const
+
+ void AssignDescriptorSetAllocation(Uint32 SetIndex, DescriptorSetAllocation&& Allocation)
{
- VERIFY_EXPR(Index < m_NumSets);
- return reinterpret_cast<const DescriptorSet*>(m_pMemory.get())[Index];
+ auto& DescrSet = GetDescriptorSet(SetIndex);
+ VERIFY(DescrSet.GetSize() > 0, "Descriptor set is empty");
+ VERIFY(!DescrSet.m_DescriptorSetAllocation, "Descriptor set alloction has already been initialized");
+ DescrSet.m_DescriptorSetAllocation = std::move(Allocation);
}
- inline Uint32 GetNumDescriptorSets() const { return m_NumSets; }
- inline Uint32 GetNumDynamicBuffers() const { return m_NumDynamicBuffers; }
+ // Sets the resource at the given desriptor set index and offset
+ const Resource& SetResource(const VulkanUtilities::VulkanLogicalDevice* pLogicalDevice,
+ Uint32 SetIndex,
+ Uint32 Offset,
+ Uint32 BindingIndex,
+ Uint32 ArrayIndex,
+ RefCntAutoPtr<IDeviceObject>&& pObject);
- Uint16& GetDynamicBuffersCounter() { return m_NumDynamicBuffers; }
+ const Resource& ResetResource(Uint32 SetIndex,
+ Uint32 Offset)
+ {
+ return SetResource(nullptr, SetIndex, Offset, ~0u, ~0u, RefCntAutoPtr<IDeviceObject>{});
+ }
+
+ Uint32 GetNumDescriptorSets() const { return m_NumSets; }
+ Uint32 GetNumDynamicBuffers() const { return m_NumDynamicBuffers; }
ResourceCacheContentType GetContentType() const { return static_cast<ResourceCacheContentType>(m_ContentType); }
@@ -208,6 +227,12 @@ private:
return reinterpret_cast<const Resource*>(reinterpret_cast<const DescriptorSet*>(m_pMemory.get()) + m_NumSets);
}
+ DescriptorSet& GetDescriptorSet(Uint32 Index)
+ {
+ VERIFY_EXPR(Index < m_NumSets);
+ return reinterpret_cast<DescriptorSet*>(m_pMemory.get())[Index];
+ }
+
std::unique_ptr<void, STDDeleter<void, IMemoryAllocator>> m_pMemory;
Uint16 m_NumSets = 0;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableManagerVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderVariableManagerVk.hpp
index b2980659..06db6075 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableManagerVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableManagerVk.hpp
@@ -93,6 +93,14 @@ public:
ShaderVariableVkImpl* GetVariable(const Char* Name) const;
ShaderVariableVkImpl* GetVariable(Uint32 Index) const;
+ // Binds object pObj to resource with index ResIndex and array index ArrayIndex.
+ void BindResource(IDeviceObject* pObj,
+ Uint32 ArrayIndex,
+ Uint32 ResIndex);
+
+ bool IsBound(Uint32 ArrayIndex,
+ Uint32 ResIndex) const;
+
void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) const;
static size_t GetRequiredMemorySize(const PipelineResourceSignatureVkImpl& Signature,
@@ -183,13 +191,20 @@ public:
return m_ParentManager.GetVariableIndex(*this);
}
- // This method can't be implemented in the header because it depends on PipelineResourceSignatureVkImpl
- virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final;
+ virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final
+ {
+ return m_ParentManager.IsBound(ArrayIndex, m_ResIndex);
+ }
- const PipelineResourceDesc& GetDesc() const { return m_ParentManager.GetResourceDesc(m_ResIndex); }
+ const PipelineResourceDesc& GetDesc() const
+ {
+ return m_ParentManager.GetResourceDesc(m_ResIndex);
+ }
- // This method can't be implemented in the header because it depends on PipelineResourceSignatureVkImpl
- void BindResource(IDeviceObject* pObj, Uint32 ArrayIndex) const;
+ void BindResource(IDeviceObject* pObj, Uint32 ArrayIndex) const
+ {
+ return m_ParentManager.BindResource(pObj, ArrayIndex, m_ResIndex);
+ }
private:
using ResourceAttribs = PipelineResourceAttribsVk;
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index d2885d5f..a9c0a7ad 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -584,15 +584,16 @@ void DeviceContextVkImpl::CommitShaderResources(IShaderResourceBinding* pShaderR
if (pSignature->HasDescriptorSet(PipelineResourceSignatureVkImpl::DESCRIPTOR_SET_ID_STATIC_MUTABLE))
{
VERIFY_EXPR(DSIndex == pSignature->GetDescriptorSetIndex<PipelineResourceSignatureVkImpl::DESCRIPTOR_SET_ID_STATIC_MUTABLE>());
- VERIFY_EXPR(ResourceCache.GetDescriptorSet(DSIndex).GetVkDescriptorSet() != VK_NULL_HANDLE);
- ResInfo.vkSets[DSIndex] = ResourceCache.GetDescriptorSet(DSIndex).GetVkDescriptorSet();
+ const auto& CahedDescrSet = const_cast<const ShaderResourceCacheVk&>(ResourceCache).GetDescriptorSet(DSIndex);
+ VERIFY_EXPR(CahedDescrSet.GetVkDescriptorSet() != VK_NULL_HANDLE);
+ ResInfo.vkSets[DSIndex] = CahedDescrSet.GetVkDescriptorSet();
++DSIndex;
}
if (pSignature->HasDescriptorSet(PipelineResourceSignatureVkImpl::DESCRIPTOR_SET_ID_DYNAMIC))
{
VERIFY_EXPR(DSIndex == pSignature->GetDescriptorSetIndex<PipelineResourceSignatureVkImpl::DESCRIPTOR_SET_ID_DYNAMIC>());
- VERIFY_EXPR(ResourceCache.GetDescriptorSet(DSIndex).GetVkDescriptorSet() == VK_NULL_HANDLE);
+ VERIFY_EXPR(const_cast<const ShaderResourceCacheVk&>(ResourceCache).GetDescriptorSet(DSIndex).GetVkDescriptorSet() == VK_NULL_HANDLE);
const auto vkLayout = pSignature->GetVkDescriptorSetLayout(PipelineResourceSignatureVkImpl::DESCRIPTOR_SET_ID_DYNAMIC);
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp
index 0d082479..e4fce2b8 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp
@@ -32,7 +32,6 @@
#include "RenderDeviceVkImpl.hpp"
#include "SamplerVkImpl.hpp"
#include "TextureViewVkImpl.hpp"
-#include "TopLevelASVkImpl.hpp"
#include "VulkanTypeConversions.hpp"
#include "DynamicLinearAllocator.hpp"
@@ -44,34 +43,6 @@ namespace Diligent
namespace
{
-inline VkDescriptorType GetVkDescriptorType(DescriptorType Type)
-{
- static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
- switch (Type)
- {
- // clang-format off
- case DescriptorType::Sampler: return VK_DESCRIPTOR_TYPE_SAMPLER;
- case DescriptorType::CombinedImageSampler: return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- case DescriptorType::SeparateImage: return VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
- case DescriptorType::StorageImage: return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- case DescriptorType::UniformTexelBuffer: return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
- case DescriptorType::StorageTexelBuffer: return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
- case DescriptorType::StorageTexelBuffer_ReadOnly: return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
- case DescriptorType::UniformBuffer: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- case DescriptorType::UniformBufferDynamic: return VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
- case DescriptorType::StorageBuffer: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- case DescriptorType::StorageBuffer_ReadOnly: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- case DescriptorType::StorageBufferDynamic: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
- case DescriptorType::StorageBufferDynamic_ReadOnly: return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
- case DescriptorType::InputAttachment: return VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
- case DescriptorType::AccelerationStructure: return VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
- // clang-format on
- default:
- UNEXPECTED("Unknown descriptor type");
- return VK_DESCRIPTOR_TYPE_MAX_ENUM;
- }
-}
-
DescriptorType GetDescriptorType(const PipelineResourceDesc& Res)
{
VERIFY((Res.Flags & ~GetValidPipelineResourceFlags(Res.ResourceType)) == 0,
@@ -116,47 +87,6 @@ DescriptorType GetDescriptorType(const PipelineResourceDesc& Res)
}
}
-inline BUFFER_VIEW_TYPE DescriptorTypeToBufferView(DescriptorType Type)
-{
- static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
- switch (Type)
- {
- case DescriptorType::UniformTexelBuffer:
- case DescriptorType::StorageTexelBuffer_ReadOnly:
- case DescriptorType::StorageBuffer_ReadOnly:
- case DescriptorType::StorageBufferDynamic_ReadOnly:
- return BUFFER_VIEW_SHADER_RESOURCE;
-
- case DescriptorType::StorageTexelBuffer:
- case DescriptorType::StorageBuffer:
- case DescriptorType::StorageBufferDynamic:
- return BUFFER_VIEW_UNORDERED_ACCESS;
-
- default:
- UNEXPECTED("Unsupported descriptor type for buffer view");
- return BUFFER_VIEW_UNDEFINED;
- }
-}
-
-inline TEXTURE_VIEW_TYPE DescriptorTypeToTextureView(DescriptorType Type)
-{
- static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
- switch (Type)
- {
- case DescriptorType::StorageImage:
- return TEXTURE_VIEW_UNORDERED_ACCESS;
-
- case DescriptorType::CombinedImageSampler:
- case DescriptorType::SeparateImage:
- case DescriptorType::InputAttachment:
- return TEXTURE_VIEW_SHADER_RESOURCE;
-
- default:
- UNEXPECTED("Unsupported descriptor type for texture view");
- return TEXTURE_VIEW_UNDEFINED;
- }
-}
-
Uint32 FindImmutableSamplerVk(const PipelineResourceDesc& Res,
DescriptorType DescType,
const PipelineResourceSignatureDesc& Desc,
@@ -397,12 +327,13 @@ void PipelineResourceSignatureVkImpl::CreateSetLayouts()
vkSetLayoutBinding.descriptorCount = ResDesc.ArraySize;
vkSetLayoutBinding.stageFlags = ShaderTypesToVkShaderStageFlags(ResDesc.ShaderStages);
vkSetLayoutBinding.pImmutableSamplers = pVkImmutableSamplers;
- vkSetLayoutBinding.descriptorType = GetVkDescriptorType(pAttribs->GetDescriptorType());
+ vkSetLayoutBinding.descriptorType = DescriptorTypeToVkDescriptorType(pAttribs->GetDescriptorType());
if (ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
{
VERIFY(pAttribs->DescrSet == 0, "Static resources must always be allocated in descriptor set 0");
- m_pStaticResCache->InitializeResources(pAttribs->DescrSet, StaticCacheOffset, ResDesc.ArraySize, pAttribs->GetDescriptorType());
+ m_pStaticResCache->InitializeResources(pAttribs->DescrSet, StaticCacheOffset, ResDesc.ArraySize,
+ pAttribs->GetDescriptorType(), pAttribs->IsImmutableSamplerAssigned());
StaticCacheOffset += ResDesc.ArraySize;
}
}
@@ -419,7 +350,7 @@ void PipelineResourceSignatureVkImpl::CreateSetLayouts()
VERIFY_EXPR(m_DynamicUniformBufferCount == CacheGroupSizes[CACHE_GROUP_DYN_UB_STAT_VAR] + CacheGroupSizes[CACHE_GROUP_DYN_UB_DYN_VAR]);
VERIFY_EXPR(m_DynamicStorageBufferCount == CacheGroupSizes[CACHE_GROUP_DYN_SB_STAT_VAR] + CacheGroupSizes[CACHE_GROUP_DYN_SB_DYN_VAR]);
- VERIFY_EXPR(m_pStaticResCache == nullptr || m_pStaticResCache->GetDescriptorSet(0).GetSize() == StaticCacheOffset);
+ VERIFY_EXPR(m_pStaticResCache == nullptr || const_cast<const ShaderResourceCacheVk*>(m_pStaticResCache)->GetDescriptorSet(0).GetSize() == StaticCacheOffset);
VERIFY_EXPR(CacheGroupOffsets[CACHE_GROUP_DYN_UB_STAT_VAR] == CacheGroupSizes[CACHE_GROUP_DYN_UB_STAT_VAR]);
VERIFY_EXPR(CacheGroupOffsets[CACHE_GROUP_DYN_SB_STAT_VAR] == CacheGroupSizes[CACHE_GROUP_DYN_UB_STAT_VAR] + CacheGroupSizes[CACHE_GROUP_DYN_SB_STAT_VAR]);
VERIFY_EXPR(CacheGroupOffsets[CACHE_GROUP_OTHER_STAT_VAR] == CacheGroupSizes[CACHE_GROUP_DYN_UB_STAT_VAR] + CacheGroupSizes[CACHE_GROUP_DYN_SB_STAT_VAR] + CacheGroupSizes[CACHE_GROUP_OTHER_STAT_VAR]);
@@ -583,7 +514,8 @@ void PipelineResourceSignatureVkImpl::InitSRBResourceCache(ShaderResourceCacheVk
{
const auto& ResDesc = GetResourceDesc(r);
const auto& Attr = GetResourceAttribs(r);
- ResourceCache.InitializeResources(Attr.DescrSet, Attr.CacheOffset(CacheType), ResDesc.ArraySize, Attr.GetDescriptorType());
+ ResourceCache.InitializeResources(Attr.DescrSet, Attr.CacheOffset(CacheType), ResDesc.ArraySize,
+ Attr.GetDescriptorType(), Attr.IsImmutableSamplerAssigned());
}
#ifdef DILIGENT_DEBUG
@@ -599,7 +531,7 @@ void PipelineResourceSignatureVkImpl::InitSRBResourceCache(ShaderResourceCacheVk
DescrSetName = _DescrSetName.c_str();
#endif
DescriptorSetAllocation SetAllocation = GetDevice()->AllocateDescriptorSet(~Uint64{0}, vkLayout, DescrSetName);
- ResourceCache.GetDescriptorSet(GetDescriptorSetIndex<DESCRIPTOR_SET_ID_STATIC_MUTABLE>()).AssignDescriptorSetAllocation(std::move(SetAllocation));
+ ResourceCache.AssignDescriptorSetAllocation(GetDescriptorSetIndex<DESCRIPTOR_SET_ID_STATIC_MUTABLE>(), std::move(SetAllocation));
}
}
@@ -613,7 +545,7 @@ void PipelineResourceSignatureVkImpl::CopyStaticResources(ShaderResourceCacheVk&
const auto& SrcResourceCache = *m_pStaticResCache;
const auto StaticSetIdx = GetDescriptorSetIndex<DESCRIPTOR_SET_ID_STATIC_MUTABLE>();
const auto& SrcDescrSet = SrcResourceCache.GetDescriptorSet(StaticSetIdx);
- auto& DstDescrSet = DstResourceCache.GetDescriptorSet(StaticSetIdx);
+ const auto& DstDescrSet = const_cast<const ShaderResourceCacheVk&>(DstResourceCache).GetDescriptorSet(StaticSetIdx);
const auto ResIdxRange = GetResourceIndexRange(SHADER_RESOURCE_VARIABLE_TYPE_STATIC);
const auto SrcCacheType = SrcResourceCache.GetContentType();
const auto DstCacheType = DstResourceCache.GetContentType();
@@ -635,15 +567,17 @@ void PipelineResourceSignatureVkImpl::CopyStaticResources(ShaderResourceCacheVk&
if (!pObject)
LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", GetShaderResourcePrintName(ResDesc, ArrInd), "' in pipeline resource signature '", m_Desc.Name, "'.");
- const auto DstCacheOffset = Attr.CacheOffset(DstCacheType) + ArrInd;
- auto& DstCachedRes = DstDescrSet.GetResource(DstCacheOffset);
+ const auto DstCacheOffset = Attr.CacheOffset(DstCacheType) + ArrInd;
+ const auto& DstCachedRes = DstDescrSet.GetResource(DstCacheOffset);
VERIFY_EXPR(SrcCachedRes.Type == DstCachedRes.Type);
- IDeviceObject* pCachedResource = DstCachedRes.pObject;
+ const IDeviceObject* pCachedResource = DstCachedRes.pObject;
if (pCachedResource != pObject)
{
VERIFY(pCachedResource == nullptr, "Static resource has already been initialized, and the new resource does not match previously assigned resource");
- BindResource(pObject, ArrInd, r, DstResourceCache);
+ DstResourceCache.SetResource(&GetDevice()->GetLogicalDevice(),
+ StaticSetIdx, DstCacheOffset, Attr.BindingIndex, ArrInd,
+ RefCntAutoPtr<IDeviceObject>{SrcCachedRes.pObject});
}
}
}
@@ -732,7 +666,7 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc
WriteDescrSetIt->dstArrayElement = ArrElem;
// descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding.
// The type of the descriptor also controls which array the descriptors are taken from. (13.2.4)
- WriteDescrSetIt->descriptorType = GetVkDescriptorType(DescrType);
+ WriteDescrSetIt->descriptorType = DescriptorTypeToVkDescriptorType(DescrType);
// For every resource type, try to batch as many descriptor updates as we can
static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
@@ -785,7 +719,7 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc
while (ArrElem < ArraySize && DescrImgIt != DescrImgInfoArr.end())
{
const auto& CachedRes = SetResources.GetResource(CacheOffset + ArrElem);
- *DescrImgIt = CachedRes.GetImageDescriptorWriteInfo(Attr.IsImmutableSamplerAssigned());
+ *DescrImgIt = CachedRes.GetImageDescriptorWriteInfo();
++DescrImgIt;
++ArrElem;
}
@@ -863,554 +797,6 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc
LogicalDevice.UpdateDescriptorSets(DescrWriteCount, WriteDescrSetArr.data(), 0, nullptr);
}
-namespace
-{
-
-struct BindResourceHelper
-{
- BindResourceHelper(const PipelineResourceSignatureVkImpl& Signature,
- ShaderResourceCacheVk& ResourceCache,
- Uint32 ResIndex,
- Uint32 ArrayIndex);
-
- void operator()(IDeviceObject* pObj) const;
-
-private:
- void CacheUniformBuffer(IDeviceObject* pBuffer) const;
-
- void CacheStorageBuffer(IDeviceObject* pBufferView) const;
-
- void CacheTexelBuffer(IDeviceObject* pBufferView) const;
-
- void CacheImage(IDeviceObject* pTexView) const;
-
- void CacheSeparateSampler(IDeviceObject* pSampler) const;
-
- void CacheInputAttachment(IDeviceObject* pTexView) const;
-
- void CacheAccelerationStructure(IDeviceObject* pTLAS) const;
-
- template <typename ObjectType, typename TPreUpdateObject>
- bool UpdateCachedResource(RefCntAutoPtr<ObjectType>&& pObject,
- TPreUpdateObject PreUpdateObject) const;
-
- // Updates resource descriptor in the descriptor set
- inline void UpdateDescriptorHandle(const VkDescriptorImageInfo* pImageInfo,
- const VkDescriptorBufferInfo* pBufferInfo,
- const VkBufferView* pTexelBufferView,
- const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo = nullptr) const;
-
-private:
- using ResourceAttribs = PipelineResourceSignatureVkImpl::ResourceAttribs;
- using CachedSet = ShaderResourceCacheVk::DescriptorSet;
-
- const PipelineResourceSignatureVkImpl& m_Signature;
- ShaderResourceCacheVk& m_ResourceCache;
- const Uint32 m_ArrayIndex;
- const ResourceCacheContentType m_CacheType;
- const PipelineResourceDesc& m_ResDesc;
- const ResourceAttribs& m_Attribs;
- CachedSet& m_CachedSet;
- ShaderResourceCacheVk::Resource& m_DstRes;
- const VkDescriptorSet m_vkDescrSet;
-};
-
-BindResourceHelper::BindResourceHelper(const PipelineResourceSignatureVkImpl& Signature,
- ShaderResourceCacheVk& ResourceCache,
- Uint32 ResIndex,
- Uint32 ArrayIndex) :
- m_Signature{Signature},
- m_ResourceCache{ResourceCache},
- m_ArrayIndex{ArrayIndex},
- m_CacheType{ResourceCache.GetContentType()},
- m_ResDesc{Signature.GetResourceDesc(ResIndex)},
- m_Attribs{Signature.GetResourceAttribs(ResIndex)},
- m_CachedSet{ResourceCache.GetDescriptorSet(m_Attribs.DescrSet)},
- m_DstRes{m_CachedSet.GetResource(m_Attribs.CacheOffset(m_CacheType) + ArrayIndex)},
- m_vkDescrSet{m_CachedSet.GetVkDescriptorSet()}
-{
- VERIFY_EXPR(ArrayIndex < m_ResDesc.ArraySize);
- VERIFY(m_DstRes.Type == m_Attribs.GetDescriptorType(), "Inconsistent types");
-
-#ifdef DILIGENT_DEBUG
- if (m_CacheType == ResourceCacheContentType::SRB)
- {
- if (m_ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC || m_ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE)
- {
- VERIFY(m_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 (m_CacheType == ResourceCacheContentType::Signature)
- {
- VERIFY(m_vkDescrSet == VK_NULL_HANDLE, "Static shader resource cache should not have vulkan descriptor set allocation");
- }
- else
- {
- UNEXPECTED("Unexpected shader resource cache content type");
- }
-#endif
-}
-
-void BindResourceHelper::operator()(IDeviceObject* pObj) const
-{
- if (pObj)
- {
- static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
- switch (m_DstRes.Type)
- {
- case DescriptorType::UniformBuffer:
- case DescriptorType::UniformBufferDynamic:
- CacheUniformBuffer(pObj);
- break;
-
- case DescriptorType::StorageBuffer:
- case DescriptorType::StorageBuffer_ReadOnly:
- case DescriptorType::StorageBufferDynamic:
- case DescriptorType::StorageBufferDynamic_ReadOnly:
- CacheStorageBuffer(pObj);
- break;
-
- case DescriptorType::UniformTexelBuffer:
- case DescriptorType::StorageTexelBuffer:
- case DescriptorType::StorageTexelBuffer_ReadOnly:
- CacheTexelBuffer(pObj);
- break;
-
- case DescriptorType::StorageImage:
- case DescriptorType::SeparateImage:
- case DescriptorType::CombinedImageSampler:
- CacheImage(pObj);
- break;
-
- case DescriptorType::Sampler:
- if (!m_Attribs.IsImmutableSamplerAssigned())
- {
- CacheSeparateSampler(pObj);
- }
- else
- {
- // Immutable samplers are permanently bound into the set layout; later binding a sampler
- // into an immutable sampler slot in a descriptor set is not allowed (13.2.1)
- UNEXPECTED("Attempting to assign a sampler to an immutable sampler '", m_ResDesc.Name, '\'');
- }
- break;
-
- case DescriptorType::InputAttachment:
- CacheInputAttachment(pObj);
- break;
-
- case DescriptorType::AccelerationStructure:
- CacheAccelerationStructure(pObj);
- break;
-
- default: UNEXPECTED("Unknown resource type ", static_cast<Uint32>(m_DstRes.Type));
- }
- }
- else
- {
- if (m_DstRes.pObject && m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- {
- LOG_ERROR_MESSAGE("Shader variable '", m_ResDesc.Name, "' is not dynamic but being unbound. This is an error and may cause unpredicted behavior. ",
- "Use another shader resource binding instance or label shader variable as dynamic if you need to bind another resource.");
- }
-
- m_DstRes.pObject.Release();
- }
-}
-
-template <typename ObjectType, typename TPreUpdateObject>
-bool BindResourceHelper::UpdateCachedResource(RefCntAutoPtr<ObjectType>&& pObject,
- TPreUpdateObject PreUpdateObject) const
-{
- if (pObject)
- {
- if (m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && m_DstRes.pObject != nullptr)
- {
- // Do not update resource if one is already bound unless it is dynamic. This may be
- // dangerous as writing descriptors while they are used by the GPU is an undefined behavior
- return false;
- }
-
- PreUpdateObject(m_DstRes.pObject.template RawPtr<const ObjectType>(), pObject.template RawPtr<const ObjectType>());
- m_DstRes.pObject.Attach(pObject.Detach());
- return true;
- }
- else
- {
- return false;
- }
-}
-
-void BindResourceHelper::CacheUniformBuffer(IDeviceObject* pBuffer) const
-{
- VERIFY((m_DstRes.Type == DescriptorType::UniformBuffer ||
- m_DstRes.Type == DescriptorType::UniformBufferDynamic),
- "Uniform buffer resource is expected");
-
- // We cannot use ValidatedCast<> here as the resource can have wrong type
- RefCntAutoPtr<BufferVkImpl> pBufferVk{pBuffer, IID_BufferVk};
-#ifdef DILIGENT_DEVELOPMENT
- VerifyConstantBufferBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ResDesc.Flags, m_ArrayIndex,
- pBuffer, pBufferVk.RawPtr(), m_DstRes.pObject.RawPtr());
-#endif
-
- auto UpdateDynamicBuffersCounter = [this](const BufferVkImpl* pOldBuffer, const BufferVkImpl* pNewBuffer) {
- auto& DynamicBuffersCounter = m_ResourceCache.GetDynamicBuffersCounter();
- if (pOldBuffer != nullptr && pOldBuffer->GetDesc().Usage == USAGE_DYNAMIC)
- {
- VERIFY(DynamicBuffersCounter > 0, "Dynamic buffers counter must be greater than zero when there is at least one dynamic buffer bound in the resource cache");
- --DynamicBuffersCounter;
- }
- if (pNewBuffer != nullptr && pNewBuffer->GetDesc().Usage == USAGE_DYNAMIC)
- {
- ++DynamicBuffersCounter;
- VERIFY(DynamicBuffersCounter <= m_Signature.GetDynamicOffsetCount(), "Dynamic buffers counter exceeded the numer of dynamic offsets in the signature");
- }
- };
- if (UpdateCachedResource(std::move(pBufferVk), UpdateDynamicBuffersCounter))
- {
- // VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER or VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC descriptor type require
- // buffer to be created with VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
-
- // Do not update descriptor for a dynamic uniform buffer. All dynamic resource
- // descriptors are updated at once by CommitDynamicResources() when SRB is committed.
- if (m_vkDescrSet != VK_NULL_HANDLE && m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- {
- VkDescriptorBufferInfo DescrBuffInfo = m_DstRes.GetUniformBufferDescriptorWriteInfo();
- UpdateDescriptorHandle(nullptr, &DescrBuffInfo, nullptr);
- }
- }
-}
-
-void BindResourceHelper::CacheStorageBuffer(IDeviceObject* pBufferView) const
-{
- VERIFY((m_DstRes.Type == DescriptorType::StorageBuffer ||
- m_DstRes.Type == DescriptorType::StorageBuffer_ReadOnly ||
- m_DstRes.Type == DescriptorType::StorageBufferDynamic ||
- m_DstRes.Type == DescriptorType::StorageBufferDynamic_ReadOnly),
- "Storage buffer resource is expected");
-
- RefCntAutoPtr<BufferViewVkImpl> pBufferViewVk{pBufferView, IID_BufferViewVk};
-#ifdef DILIGENT_DEVELOPMENT
- {
- // HLSL buffer SRVs are mapped to storge buffers in GLSL
- const auto RequiredViewType = DescriptorTypeToBufferView(m_DstRes.Type);
- VerifyResourceViewBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex,
- pBufferView, pBufferViewVk.RawPtr(),
- {RequiredViewType}, RESOURCE_DIM_BUFFER,
- false, // IsMultisample
- m_DstRes.pObject.RawPtr());
- 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 '",
- m_ResDesc.Name, "': structured buffer view is expected.");
- }
- }
- }
-#endif
-
- auto UpdateDynamicBuffersCounter = [this](const BufferViewVkImpl* pOldBufferView, const BufferViewVkImpl* pNewBufferView) {
- auto& DynamicBuffersCounter = m_ResourceCache.GetDynamicBuffersCounter();
- if (pOldBufferView != nullptr && pOldBufferView->GetBuffer<const BufferVkImpl>()->GetDesc().Usage == USAGE_DYNAMIC)
- {
- VERIFY(DynamicBuffersCounter > 0, "Dynamic buffers counter must be greater than zero when there is at least one dynamic buffer bound in the resource cache");
- --DynamicBuffersCounter;
- }
- if (pNewBufferView != nullptr && pNewBufferView->GetBuffer<const BufferVkImpl>()->GetDesc().Usage == USAGE_DYNAMIC)
- {
- ++DynamicBuffersCounter;
- VERIFY(DynamicBuffersCounter <= m_Signature.GetDynamicOffsetCount(), "Dynamic buffers counter exceeded the numer of dynamic offsets in the signature");
- }
- };
-
- if (UpdateCachedResource(std::move(pBufferViewVk), UpdateDynamicBuffersCounter))
- {
- // VK_DESCRIPTOR_TYPE_STORAGE_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC descriptor type
- // require buffer to be created with VK_BUFFER_USAGE_STORAGE_BUFFER_BIT (13.2.4)
-
- // Do not update descriptor for a dynamic storage buffer. All dynamic resource
- // descriptors are updated at once by CommitDynamicResources() when SRB is committed.
- if (m_vkDescrSet != VK_NULL_HANDLE && m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- {
- VkDescriptorBufferInfo DescrBuffInfo = m_DstRes.GetStorageBufferDescriptorWriteInfo();
- UpdateDescriptorHandle(nullptr, &DescrBuffInfo, nullptr);
- }
- }
-}
-
-void BindResourceHelper::CacheTexelBuffer(IDeviceObject* pBufferView) const
-{
- VERIFY((m_DstRes.Type == DescriptorType::UniformTexelBuffer ||
- m_DstRes.Type == DescriptorType::StorageTexelBuffer ||
- m_DstRes.Type == DescriptorType::StorageTexelBuffer_ReadOnly),
- "Uniform or storage buffer resource is expected");
-
- RefCntAutoPtr<BufferViewVkImpl> pBufferViewVk{pBufferView, IID_BufferViewVk};
-#ifdef DILIGENT_DEVELOPMENT
- {
- // HLSL buffer SRVs are mapped to storge buffers in GLSL
- const auto RequiredViewType = DescriptorTypeToBufferView(m_DstRes.Type);
- VerifyResourceViewBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex,
- pBufferView, pBufferViewVk.RawPtr(),
- {RequiredViewType}, RESOURCE_DIM_BUFFER,
- false, // IsMultisample
- m_DstRes.pObject.RawPtr());
- 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))
- {
- LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
- m_ResDesc.Name, "': formatted buffer view is expected.");
- }
- }
- }
-#endif
-
- if (UpdateCachedResource(std::move(pBufferViewVk), [](const BufferViewVkImpl* pOldBufferView, const BufferViewVkImpl* pNewBufferView) {}))
- {
- // The following bits must have been set at buffer creation time:
- // * VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER -> VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
- // * VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER -> VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
-
- // Do not update descriptor for a dynamic texel buffer. All dynamic resource descriptors
- // are updated at once by CommitDynamicResources() when SRB is committed.
- if (m_vkDescrSet != VK_NULL_HANDLE && m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- {
- VkBufferView BuffView = m_DstRes.pObject.RawPtr<BufferViewVkImpl>()->GetVkBufferView();
- UpdateDescriptorHandle(nullptr, nullptr, &BuffView);
- }
- }
-}
-
-void BindResourceHelper::CacheImage(IDeviceObject* pTexView) const
-{
- VERIFY((m_DstRes.Type == DescriptorType::StorageImage ||
- m_DstRes.Type == DescriptorType::SeparateImage ||
- m_DstRes.Type == DescriptorType::CombinedImageSampler),
- "Storage image, separate image or sampled image resource is expected");
-
- RefCntAutoPtr<TextureViewVkImpl> pTexViewVk0{pTexView, IID_TextureViewVk};
-#ifdef DILIGENT_DEVELOPMENT
- {
- // HLSL buffer SRVs are mapped to storge buffers in GLSL
- auto RequiredViewType = DescriptorTypeToTextureView(m_DstRes.Type);
- VerifyResourceViewBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex,
- pTexView, pTexViewVk0.RawPtr(),
- {RequiredViewType},
- RESOURCE_DIM_UNDEFINED, // Required resource dimension is not known
- false, // IsMultisample
- m_DstRes.pObject.RawPtr());
- }
-#endif
- if (UpdateCachedResource(std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*) {}))
- {
- // We can do RawPtr here safely since UpdateCachedResource() returned true
- auto* pTexViewVk = m_DstRes.pObject.RawPtr<TextureViewVkImpl>();
-#ifdef DILIGENT_DEVELOPMENT
- if (m_DstRes.Type == DescriptorType::CombinedImageSampler && !m_Attribs.IsImmutableSamplerAssigned())
- {
- if (pTexViewVk->GetSampler() == nullptr)
- {
- LOG_ERROR_MESSAGE("Error binding texture view '", pTexViewVk->GetDesc().Name, "' to variable '",
- GetShaderResourcePrintName(m_ResDesc, m_ArrayIndex), "'. No sampler is assigned to the view");
- }
- }
-#endif
-
- // Do not update descriptor for a dynamic image. All dynamic resource descriptors
- // are updated at once by CommitDynamicResources() when SRB is committed.
- if (m_vkDescrSet != VK_NULL_HANDLE && m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- {
- VkDescriptorImageInfo DescrImgInfo = m_DstRes.GetImageDescriptorWriteInfo(m_Attribs.IsImmutableSamplerAssigned());
- UpdateDescriptorHandle(&DescrImgInfo, nullptr, nullptr);
- }
-
- if (m_Attribs.IsCombinedWithSampler())
- {
- VERIFY(m_DstRes.Type == DescriptorType::SeparateImage,
- "Only separate images can be assigned separate samplers when using HLSL-style combined samplers.");
- VERIFY(!m_Attribs.IsImmutableSamplerAssigned(), "Separate image can't be assigned an immutable sampler.");
-
- const auto& SamplerResDesc = m_Signature.GetResourceDesc(m_Attribs.SamplerInd);
- const auto& SamplerAttribs = m_Signature.GetResourceAttribs(m_Attribs.SamplerInd);
- VERIFY_EXPR(SamplerResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER);
-
- if (!SamplerAttribs.IsImmutableSamplerAssigned())
- {
- auto* pSampler = pTexViewVk->GetSampler();
- if (pSampler != nullptr)
- {
- DEV_CHECK_ERR(SamplerResDesc.ArraySize == 1 || SamplerResDesc.ArraySize == m_ResDesc.ArraySize,
- "Array size (", SamplerResDesc.ArraySize,
- ") of separate sampler variable '",
- SamplerResDesc.Name,
- "' must be one or the same as the array size (", m_ResDesc.ArraySize,
- ") of separate image variable '", m_ResDesc.Name, "' it is assigned to");
-
- BindResourceHelper BindSeparateSamler{
- m_Signature,
- m_ResourceCache,
- m_Attribs.SamplerInd,
- SamplerResDesc.ArraySize == 1 ? 0 : m_ArrayIndex};
- BindSeparateSamler(pSampler);
- }
- else
- {
- LOG_ERROR_MESSAGE("Failed to bind sampler to sampler variable '", SamplerResDesc.Name,
- "' assigned to separate image '", GetShaderResourcePrintName(m_ResDesc, m_ArrayIndex),
- "': no sampler is set in texture view '", pTexViewVk->GetDesc().Name, '\'');
- }
- }
- }
- }
-}
-
-void BindResourceHelper::CacheSeparateSampler(IDeviceObject* pSampler) const
-{
- VERIFY(m_DstRes.Type == DescriptorType::Sampler, "Separate sampler resource is expected");
- VERIFY(!m_Attribs.IsImmutableSamplerAssigned(), "This separate sampler is assigned an immutable sampler");
-
- RefCntAutoPtr<SamplerVkImpl> pSamplerVk{pSampler, IID_Sampler};
-#ifdef DILIGENT_DEVELOPMENT
- if (pSampler != nullptr && pSamplerVk == nullptr)
- {
- LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '",
- GetShaderResourcePrintName(m_ResDesc, m_ArrayIndex), "'. Unexpected object type: sampler is expected");
- }
- if (m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && m_DstRes.pObject != nullptr && m_DstRes.pObject != pSamplerVk)
- {
- auto VarTypeStr = GetShaderVariableTypeLiteralName(m_ResDesc.VarType);
- LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", GetShaderResourcePrintName(m_ResDesc, m_ArrayIndex),
- "'. Attempting to bind another sampler or null is an error and may "
- "cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic.");
- }
-#endif
- if (UpdateCachedResource(std::move(pSamplerVk), [](const SamplerVkImpl*, const SamplerVkImpl*) {}))
- {
- // Do not update descriptor for a dynamic sampler. All dynamic resource descriptors
- // are updated at once by CommitDynamicResources() when SRB is committed.
- if (m_vkDescrSet != VK_NULL_HANDLE && m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- {
- VkDescriptorImageInfo DescrImgInfo = m_DstRes.GetSamplerDescriptorWriteInfo();
- UpdateDescriptorHandle(&DescrImgInfo, nullptr, nullptr);
- }
- }
-}
-
-void BindResourceHelper::CacheInputAttachment(IDeviceObject* pTexView) const
-{
- VERIFY(m_DstRes.Type == DescriptorType::InputAttachment, "Input attachment resource is expected");
- RefCntAutoPtr<TextureViewVkImpl> pTexViewVk0{pTexView, IID_TextureViewVk};
-#ifdef DILIGENT_DEVELOPMENT
- VerifyResourceViewBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex,
- pTexView, pTexViewVk0.RawPtr(),
- {TEXTURE_VIEW_SHADER_RESOURCE},
- RESOURCE_DIM_UNDEFINED,
- false, // IsMultisample
- m_DstRes.pObject.RawPtr());
-#endif
- if (UpdateCachedResource(std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*) {}))
- {
- // Do not update descriptor for a dynamic image. All dynamic resource descriptors
- // are updated at once by CommitDynamicResources() when SRB is committed.
- if (m_vkDescrSet != VK_NULL_HANDLE && m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- {
- VkDescriptorImageInfo DescrImgInfo = m_DstRes.GetInputAttachmentDescriptorWriteInfo();
- UpdateDescriptorHandle(&DescrImgInfo, nullptr, nullptr);
- }
- //
- }
-}
-
-void BindResourceHelper::CacheAccelerationStructure(IDeviceObject* pTLAS) const
-{
- VERIFY(m_DstRes.Type == DescriptorType::AccelerationStructure, "Acceleration Structure resource is expected");
- RefCntAutoPtr<TopLevelASVkImpl> pTLASVk{pTLAS, IID_TopLevelASVk};
-#ifdef DILIGENT_DEVELOPMENT
- VerifyTLASResourceBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex, pTLAS, pTLASVk.RawPtr(), m_DstRes.pObject.RawPtr());
-#endif
- if (UpdateCachedResource(std::move(pTLASVk), [](const TopLevelASVkImpl*, const TopLevelASVkImpl*) {}))
- {
- // Do not update descriptor for a dynamic TLAS. All dynamic resource descriptors
- // are updated at once by CommitDynamicResources() when SRB is committed.
- if (m_vkDescrSet != VK_NULL_HANDLE && m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- {
- VkWriteDescriptorSetAccelerationStructureKHR DescrASInfo = m_DstRes.GetAccelerationStructureWriteInfo();
- UpdateDescriptorHandle(nullptr, nullptr, nullptr, &DescrASInfo);
- }
- //
- }
-}
-
-void BindResourceHelper::UpdateDescriptorHandle(const VkDescriptorImageInfo* pImageInfo,
- const VkDescriptorBufferInfo* pBufferInfo,
- const VkBufferView* pTexelBufferView,
- const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo) const
-{
- VERIFY_EXPR(m_vkDescrSet != VK_NULL_HANDLE);
-
- VkWriteDescriptorSet WriteDescrSet;
- WriteDescrSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- WriteDescrSet.pNext = pAccelStructInfo;
- WriteDescrSet.dstSet = m_vkDescrSet;
- WriteDescrSet.dstBinding = m_Attribs.BindingIndex;
- WriteDescrSet.dstArrayElement = m_ArrayIndex;
- WriteDescrSet.descriptorCount = 1;
- // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding.
- // The type of the descriptor also controls which array the descriptors are taken from. (13.2.4)
- WriteDescrSet.descriptorType = GetVkDescriptorType(m_DstRes.Type);
- WriteDescrSet.pImageInfo = pImageInfo;
- WriteDescrSet.pBufferInfo = pBufferInfo;
- WriteDescrSet.pTexelBufferView = pTexelBufferView;
-
- m_Signature.GetDevice()->GetLogicalDevice().UpdateDescriptorSets(1, &WriteDescrSet, 0, nullptr);
-}
-
-} // namespace
-
-void PipelineResourceSignatureVkImpl::BindResource(IDeviceObject* pObj,
- Uint32 ArrayIndex,
- Uint32 ResIndex,
- ShaderResourceCacheVk& ResourceCache) const
-{
- BindResourceHelper BindHelper{
- *this,
- ResourceCache,
- ResIndex,
- ArrayIndex};
-
- BindHelper(pObj);
-}
-
-bool PipelineResourceSignatureVkImpl::IsBound(Uint32 ArrayIndex,
- Uint32 ResIndex,
- const ShaderResourceCacheVk& ResourceCache) const
-{
- const auto& ResDesc = GetResourceDesc(ResIndex);
- const auto& Attribs = GetResourceAttribs(ResIndex);
- const Uint32 CacheOffset = Attribs.CacheOffset(ResourceCache.GetContentType());
-
- VERIFY_EXPR(ArrayIndex < ResDesc.ArraySize);
-
- if (Attribs.DescrSet < ResourceCache.GetNumDescriptorSets())
- {
- const auto& Set = ResourceCache.GetDescriptorSet(Attribs.DescrSet);
- if (CacheOffset + ArrayIndex < Set.GetSize())
- {
- const auto& CachedRes = Set.GetResource(CacheOffset + ArrayIndex);
- return CachedRes.pObject != nullptr;
- }
- }
-
- return false;
-}
#ifdef DILIGENT_DEVELOPMENT
bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVShaderResourceAttribs& SPIRVAttribs,
@@ -1436,7 +822,8 @@ bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVSh
bool BindingsOK = true;
for (Uint32 ArrIndex = 0; ArrIndex < SPIRVAttribs.ArraySize; ++ArrIndex)
{
- if (!IsBound(ArrIndex, ResIndex, ResourceCache))
+ const auto& Res = DescrSetResources.GetResource(CacheOffset + ArrIndex);
+ if (Res.IsNull())
{
LOG_ERROR_MESSAGE("No resource is bound to variable '", GetShaderResourcePrintName(SPIRVAttribs, ArrIndex),
"' in shader '", ShaderName, "' of PSO '", PSOName, "'");
@@ -1454,7 +841,10 @@ bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVSh
{
if (ArrIndex < SamplerResDesc.ArraySize)
{
- if (!IsBound(ArrIndex, ResAttribs.SamplerInd, ResourceCache))
+ const auto& SamDescrSetResources = ResourceCache.GetDescriptorSet(SamplerAttribs.DescrSet);
+ const auto SamCacheOffset = SamplerAttribs.CacheOffset(CacheType);
+ const auto& Sam = SamDescrSetResources.GetResource(SamCacheOffset + ArrIndex);
+ if (Sam.IsNull())
{
LOG_ERROR_MESSAGE("No sampler is bound to sampler variable '", GetShaderResourcePrintName(SamplerResDesc, ArrIndex),
"' combined with texture '", SPIRVAttribs.Name, "' in shader '", ShaderName, "' of PSO '", PSOName, "'.");
@@ -1464,7 +854,6 @@ bool PipelineResourceSignatureVkImpl::DvpValidateCommittedResource(const SPIRVSh
}
}
- const auto& Res = DescrSetResources.GetResource(CacheOffset + ArrIndex);
switch (ResAttribs.GetDescriptorType())
{
case DescriptorType::UniformBuffer:
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
index c4c40f7c..83058f38 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
@@ -100,12 +100,12 @@ void ShaderResourceCacheVk::InitializeSets(IMemoryAllocator& MemAllocator, Uint3
}
}
-void ShaderResourceCacheVk::InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, DescriptorType Type)
+void ShaderResourceCacheVk::InitializeResources(Uint32 Set, Uint32 Offset, Uint32 ArraySize, DescriptorType Type, bool HasImmutableSampler)
{
auto& DescrSet = GetDescriptorSet(Set);
for (Uint32 res = 0; res < ArraySize; ++res)
{
- new (&DescrSet.GetResource(Offset + res)) Resource{Type};
+ new (&DescrSet.GetResource(Offset + res)) Resource{Type, HasImmutableSampler};
#ifdef DILIGENT_DEBUG
m_DbgInitializedResources[Set][Offset + res] = true;
#endif
@@ -174,6 +174,140 @@ ShaderResourceCacheVk::~ShaderResourceCacheVk()
}
}
+const ShaderResourceCacheVk::Resource& ShaderResourceCacheVk::SetResource(const VulkanUtilities::VulkanLogicalDevice* pLogicalDevice,
+ Uint32 SetIndex,
+ Uint32 Offset,
+ Uint32 BindingIndex,
+ Uint32 ArrayIndex,
+ RefCntAutoPtr<IDeviceObject>&& pObject)
+{
+ auto& DescrSet = GetDescriptorSet(SetIndex);
+ auto& Res = DescrSet.GetResource(Offset);
+
+ const BufferVkImpl* pOldBuffer = nullptr;
+ const BufferVkImpl* pNewBuffer = nullptr;
+ switch (Res.Type)
+ {
+ case DescriptorType::UniformBuffer:
+ VERIFY(!pObject || pObject.RawPtr<const BufferVkImpl>()->GetDesc().Usage != USAGE_DYNAMIC,
+ "Dynamic uniform buffer is being bound to a non-dynamic descriptor. The buffer's dynamic offset will not be properly handled.");
+ break;
+
+ case DescriptorType::UniformBufferDynamic:
+ pOldBuffer = Res.pObject.RawPtr<const BufferVkImpl>();
+ pNewBuffer = pObject.RawPtr<const BufferVkImpl>();
+ break;
+
+ case DescriptorType::StorageBuffer:
+ case DescriptorType::StorageBuffer_ReadOnly:
+ VERIFY(!pObject || pObject.RawPtr<const BufferViewVkImpl>()->GetBuffer<const BufferVkImpl>()->GetDesc().Usage != USAGE_DYNAMIC,
+ "Dynamic storage buffer is being bound to a non-dynamic descriptor. The buffer's dynamic offset will not be properly handled.");
+ break;
+
+ case DescriptorType::StorageBufferDynamic:
+ case DescriptorType::StorageBufferDynamic_ReadOnly:
+ pOldBuffer = Res.pObject ? Res.pObject.RawPtr<const BufferViewVkImpl>()->GetBuffer<const BufferVkImpl>() : nullptr;
+ pNewBuffer = pObject ? pObject.RawPtr<const BufferViewVkImpl>()->GetBuffer<const BufferVkImpl>() : nullptr;
+ break;
+
+ default:
+ // Do nothing
+ break;
+ }
+
+ if (pOldBuffer != nullptr && pOldBuffer->GetDesc().Usage == USAGE_DYNAMIC)
+ {
+ VERIFY(m_NumDynamicBuffers > 0, "Dynamic buffers counter must be greater than zero when there is at least one dynamic buffer bound in the resource cache");
+ --m_NumDynamicBuffers;
+ }
+ if (pNewBuffer != nullptr && pNewBuffer->GetDesc().Usage == USAGE_DYNAMIC)
+ {
+ ++m_NumDynamicBuffers;
+ }
+
+ Res.pObject = std::move(pObject);
+
+ auto vkSet = DescrSet.GetVkDescriptorSet();
+ if (vkSet != VK_NULL_HANDLE && Res.pObject)
+ {
+ VERIFY(pLogicalDevice != nullptr, "Logical device must not be null to write descriptor to a non-null set");
+
+ VkWriteDescriptorSet WriteDescrSet;
+ WriteDescrSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ WriteDescrSet.pNext = nullptr;
+ WriteDescrSet.dstSet = vkSet;
+ WriteDescrSet.dstBinding = BindingIndex;
+ WriteDescrSet.dstArrayElement = ArrayIndex;
+ WriteDescrSet.descriptorCount = 1;
+ // descriptorType must be the same type as that specified in VkDescriptorSetLayoutBinding for dstSet at dstBinding.
+ // The type of the descriptor also controls which array the descriptors are taken from. (13.2.4)
+ WriteDescrSet.descriptorType = DescriptorTypeToVkDescriptorType(Res.Type);
+ WriteDescrSet.pImageInfo = nullptr;
+ WriteDescrSet.pBufferInfo = nullptr;
+ WriteDescrSet.pTexelBufferView = nullptr;
+
+ // Do not zero-initialize!
+ VkDescriptorImageInfo vkDescrImageInfo;
+ VkDescriptorBufferInfo vkDescrBufferInfo;
+ VkBufferView vkDescrBufferView;
+ VkWriteDescriptorSetAccelerationStructureKHR vkDescrAccelStructInfo;
+
+ static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
+ switch (Res.Type)
+ {
+ case DescriptorType::Sampler:
+ vkDescrImageInfo = Res.GetSamplerDescriptorWriteInfo();
+ WriteDescrSet.pImageInfo = &vkDescrImageInfo;
+ break;
+
+ case DescriptorType::CombinedImageSampler:
+ case DescriptorType::SeparateImage:
+ case DescriptorType::StorageImage:
+ vkDescrImageInfo = Res.GetImageDescriptorWriteInfo();
+ WriteDescrSet.pImageInfo = &vkDescrImageInfo;
+ break;
+
+ case DescriptorType::UniformTexelBuffer:
+ case DescriptorType::StorageTexelBuffer:
+ case DescriptorType::StorageTexelBuffer_ReadOnly:
+ vkDescrBufferView = Res.GetBufferViewWriteInfo();
+ WriteDescrSet.pTexelBufferView = &vkDescrBufferView;
+ break;
+
+ case DescriptorType::UniformBuffer:
+ case DescriptorType::UniformBufferDynamic:
+ vkDescrBufferInfo = Res.GetUniformBufferDescriptorWriteInfo();
+ WriteDescrSet.pBufferInfo = &vkDescrBufferInfo;
+ break;
+
+ case DescriptorType::StorageBuffer:
+ case DescriptorType::StorageBuffer_ReadOnly:
+ case DescriptorType::StorageBufferDynamic:
+ case DescriptorType::StorageBufferDynamic_ReadOnly:
+ vkDescrBufferInfo = Res.GetStorageBufferDescriptorWriteInfo();
+ WriteDescrSet.pBufferInfo = &vkDescrBufferInfo;
+ break;
+
+ case DescriptorType::InputAttachment:
+ vkDescrImageInfo = Res.GetInputAttachmentDescriptorWriteInfo();
+ WriteDescrSet.pImageInfo = &vkDescrImageInfo;
+ break;
+
+ case DescriptorType::AccelerationStructure:
+ vkDescrAccelStructInfo = Res.GetAccelerationStructureWriteInfo();
+ WriteDescrSet.pNext = &vkDescrAccelStructInfo;
+ break;
+
+ default:
+ UNEXPECTED("Unexpected descriptor type");
+ }
+
+ pLogicalDevice->UpdateDescriptorSets(1, &WriteDescrSet, 0, nullptr);
+ }
+
+ return Res;
+}
+
static RESOURCE_STATE DescriptorTypeToResourceState(DescriptorType Type)
{
static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
@@ -486,7 +620,7 @@ VkDescriptorBufferInfo ShaderResourceCacheVk::Resource::GetStorageBufferDescript
return DescrBuffInfo;
}
-VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteInfo(bool IsImmutableSampler) const
+VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteInfo() const
{
// clang-format off
VERIFY(Type == DescriptorType::StorageImage ||
@@ -503,9 +637,9 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteIn
VkDescriptorImageInfo DescrImgInfo;
DescrImgInfo.sampler = VK_NULL_HANDLE;
- VERIFY(Type == DescriptorType::CombinedImageSampler || !IsImmutableSampler,
+ VERIFY(Type == DescriptorType::CombinedImageSampler || !HasImmutableSampler,
"Immutable sampler can't be assigned to separarate image or storage image");
- if (Type == DescriptorType::CombinedImageSampler && !IsImmutableSampler)
+ if (Type == DescriptorType::CombinedImageSampler && !HasImmutableSampler)
{
// Immutable samplers are permanently bound into the set layout; later binding a sampler
// into an immutable sampler slot in a descriptor set is not allowed (13.2.1)
@@ -563,6 +697,7 @@ VkBufferView ShaderResourceCacheVk::Resource::GetBufferViewWriteInfo() const
VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetSamplerDescriptorWriteInfo() const
{
VERIFY(Type == DescriptorType::Sampler, "Separate sampler resource is expected");
+ VERIFY(!HasImmutableSampler, "Separate immutable samplers can't be updated");
DEV_CHECK_ERR(pObject != nullptr, "Unable to get separate sampler descriptor write info: cached object is null");
const auto* pSamplerVk = pObject.RawPtr<const SamplerVkImpl>();
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableManagerVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableManagerVk.cpp
index 58b16b90..a159b8b9 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableManagerVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableManagerVk.cpp
@@ -30,6 +30,9 @@
#include "ShaderVariableManagerVk.hpp"
#include "RenderDeviceVkImpl.hpp"
#include "PipelineResourceSignatureVkImpl.hpp"
+#include "SamplerVkImpl.hpp"
+#include "TextureViewVkImpl.hpp"
+#include "TopLevelASVkImpl.hpp"
namespace Diligent
{
@@ -210,14 +213,479 @@ void ShaderVariableVkImpl::SetArray(IDeviceObject* const* ppObjects,
BindResource(ppObjects[Elem], FirstElement + Elem);
}
-bool ShaderVariableVkImpl::IsBound(Uint32 ArrayIndex) const
+
+namespace
+{
+
+inline BUFFER_VIEW_TYPE DescriptorTypeToBufferView(DescriptorType Type)
+{
+ static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
+ switch (Type)
+ {
+ case DescriptorType::UniformTexelBuffer:
+ case DescriptorType::StorageTexelBuffer_ReadOnly:
+ case DescriptorType::StorageBuffer_ReadOnly:
+ case DescriptorType::StorageBufferDynamic_ReadOnly:
+ return BUFFER_VIEW_SHADER_RESOURCE;
+
+ case DescriptorType::StorageTexelBuffer:
+ case DescriptorType::StorageBuffer:
+ case DescriptorType::StorageBufferDynamic:
+ return BUFFER_VIEW_UNORDERED_ACCESS;
+
+ default:
+ UNEXPECTED("Unsupported descriptor type for buffer view");
+ return BUFFER_VIEW_UNDEFINED;
+ }
+}
+
+inline TEXTURE_VIEW_TYPE DescriptorTypeToTextureView(DescriptorType Type)
+{
+ static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
+ switch (Type)
+ {
+ case DescriptorType::StorageImage:
+ return TEXTURE_VIEW_UNORDERED_ACCESS;
+
+ case DescriptorType::CombinedImageSampler:
+ case DescriptorType::SeparateImage:
+ case DescriptorType::InputAttachment:
+ return TEXTURE_VIEW_SHADER_RESOURCE;
+
+ default:
+ UNEXPECTED("Unsupported descriptor type for texture view");
+ return TEXTURE_VIEW_UNDEFINED;
+ }
+}
+
+
+struct BindResourceHelper
+{
+ BindResourceHelper(const PipelineResourceSignatureVkImpl& Signature,
+ ShaderResourceCacheVk& ResourceCache,
+ Uint32 ResIndex,
+ Uint32 ArrayIndex);
+
+ void operator()(IDeviceObject* pObj) const;
+
+private:
+ void CacheUniformBuffer(IDeviceObject* pBuffer) const;
+
+ void CacheStorageBuffer(IDeviceObject* pBufferView) const;
+
+ void CacheTexelBuffer(IDeviceObject* pBufferView) const;
+
+ void CacheImage(IDeviceObject* pTexView) const;
+
+ void CacheSeparateSampler(IDeviceObject* pSampler) const;
+
+ void CacheInputAttachment(IDeviceObject* pTexView) const;
+
+ void CacheAccelerationStructure(IDeviceObject* pTLAS) const;
+
+ template <typename ObjectType>
+ bool UpdateCachedResource(RefCntAutoPtr<ObjectType>&& pObject) const;
+
+ // Updates resource descriptor in the descriptor set
+ inline void UpdateDescriptorHandle(const VkDescriptorImageInfo* pImageInfo,
+ const VkDescriptorBufferInfo* pBufferInfo,
+ const VkBufferView* pTexelBufferView,
+ const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo = nullptr) const;
+
+private:
+ using ResourceAttribs = PipelineResourceSignatureVkImpl::ResourceAttribs;
+ using CachedSet = ShaderResourceCacheVk::DescriptorSet;
+
+ const PipelineResourceSignatureVkImpl& m_Signature;
+ ShaderResourceCacheVk& m_ResourceCache;
+ const Uint32 m_ArrayIndex;
+ const ResourceCacheContentType m_CacheType;
+ const PipelineResourceDesc& m_ResDesc;
+ const ResourceAttribs& m_Attribs;
+ const Uint32 m_DstResCacheOffset;
+ const CachedSet& m_CachedSet;
+ const ShaderResourceCacheVk::Resource& m_DstRes;
+};
+
+BindResourceHelper::BindResourceHelper(const PipelineResourceSignatureVkImpl& Signature,
+ ShaderResourceCacheVk& ResourceCache,
+ Uint32 ResIndex,
+ Uint32 ArrayIndex) :
+ // clang-format off
+ m_Signature {Signature},
+ m_ResourceCache {ResourceCache},
+ m_ArrayIndex {ArrayIndex},
+ m_CacheType {ResourceCache.GetContentType()},
+ m_ResDesc {Signature.GetResourceDesc(ResIndex)},
+ m_Attribs {Signature.GetResourceAttribs(ResIndex)},
+ m_DstResCacheOffset {m_Attribs.CacheOffset(m_CacheType) + ArrayIndex},
+ m_CachedSet {const_cast<const ShaderResourceCacheVk&>(ResourceCache).GetDescriptorSet(m_Attribs.DescrSet)},
+ m_DstRes {m_CachedSet.GetResource(m_DstResCacheOffset)}
+// clang-format on
+{
+ VERIFY_EXPR(ArrayIndex < m_ResDesc.ArraySize);
+ VERIFY(m_DstRes.Type == m_Attribs.GetDescriptorType(), "Inconsistent types");
+
+#ifdef DILIGENT_DEBUG
+ {
+ auto vkDescrSet = m_CachedSet.GetVkDescriptorSet();
+ if (m_CacheType == ResourceCacheContentType::SRB)
+ {
+ if (m_ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC ||
+ m_ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE)
+ {
+ VERIFY(vkDescrSet != VK_NULL_HANDLE, "Static and mutable variables must have a valid Vulkan descriptor set assigned");
+ }
+ else
+ {
+ VERIFY(vkDescrSet == VK_NULL_HANDLE, "Dynamic variables must never have valid Vulkan descriptor set assigned");
+ }
+ }
+ else if (m_CacheType == ResourceCacheContentType::Signature)
+ {
+ VERIFY(vkDescrSet == VK_NULL_HANDLE, "Static shader resource cache should not have Vulkan descriptor set allocation");
+ }
+ else
+ {
+ UNEXPECTED("Unexpected shader resource cache content type");
+ }
+ }
+#endif
+}
+
+void BindResourceHelper::operator()(IDeviceObject* pObj) const
+{
+ if (pObj)
+ {
+ static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
+ switch (m_DstRes.Type)
+ {
+ case DescriptorType::UniformBuffer:
+ case DescriptorType::UniformBufferDynamic:
+ CacheUniformBuffer(pObj);
+ break;
+
+ case DescriptorType::StorageBuffer:
+ case DescriptorType::StorageBuffer_ReadOnly:
+ case DescriptorType::StorageBufferDynamic:
+ case DescriptorType::StorageBufferDynamic_ReadOnly:
+ CacheStorageBuffer(pObj);
+ break;
+
+ case DescriptorType::UniformTexelBuffer:
+ case DescriptorType::StorageTexelBuffer:
+ case DescriptorType::StorageTexelBuffer_ReadOnly:
+ CacheTexelBuffer(pObj);
+ break;
+
+ case DescriptorType::StorageImage:
+ case DescriptorType::SeparateImage:
+ case DescriptorType::CombinedImageSampler:
+ CacheImage(pObj);
+ break;
+
+ case DescriptorType::Sampler:
+ if (!m_Attribs.IsImmutableSamplerAssigned())
+ {
+ CacheSeparateSampler(pObj);
+ }
+ else
+ {
+ // Immutable samplers are permanently bound into the set layout; later binding a sampler
+ // into an immutable sampler slot in a descriptor set is not allowed (13.2.1)
+ UNEXPECTED("Attempting to assign a sampler to an immutable sampler '", m_ResDesc.Name, '\'');
+ }
+ break;
+
+ case DescriptorType::InputAttachment:
+ CacheInputAttachment(pObj);
+ break;
+
+ case DescriptorType::AccelerationStructure:
+ CacheAccelerationStructure(pObj);
+ break;
+
+ default: UNEXPECTED("Unknown resource type ", static_cast<Uint32>(m_DstRes.Type));
+ }
+ }
+ else
+ {
+ if (m_DstRes.pObject && m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
+ {
+ LOG_ERROR_MESSAGE("Shader variable '", m_ResDesc.Name, "' is not dynamic but being unbound. This is an error and may cause unpredicted behavior. ",
+ "Use another shader resource binding instance or label shader variable as dynamic if you need to bind another resource.");
+ }
+
+ m_ResourceCache.ResetResource(m_Attribs.DescrSet, m_DstResCacheOffset);
+ }
+}
+
+template <typename ObjectType>
+bool BindResourceHelper::UpdateCachedResource(RefCntAutoPtr<ObjectType>&& pObject) const
+{
+ if (pObject)
+ {
+ if (m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && m_DstRes.pObject != nullptr)
+ {
+ // Do not update resource if one is already bound unless it is dynamic. This may be
+ // dangerous as writing descriptors while they are used by the GPU is an undefined behavior
+ return false;
+ }
+
+ m_ResourceCache.SetResource(&m_Signature.GetDevice()->GetLogicalDevice(),
+ m_Attribs.DescrSet, m_DstResCacheOffset,
+ m_Attribs.BindingIndex, m_ArrayIndex,
+ std::move(pObject));
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void BindResourceHelper::CacheUniformBuffer(IDeviceObject* pBuffer) const
+{
+ VERIFY((m_DstRes.Type == DescriptorType::UniformBuffer ||
+ m_DstRes.Type == DescriptorType::UniformBufferDynamic),
+ "Uniform buffer resource is expected");
+
+ // We cannot use ValidatedCast<> here as the resource can have wrong type
+ RefCntAutoPtr<BufferVkImpl> pBufferVk{pBuffer, IID_BufferVk};
+#ifdef DILIGENT_DEVELOPMENT
+ VerifyConstantBufferBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ResDesc.Flags, m_ArrayIndex,
+ pBuffer, pBufferVk.RawPtr(), m_DstRes.pObject.RawPtr());
+#endif
+
+ UpdateCachedResource(std::move(pBufferVk));
+}
+
+void BindResourceHelper::CacheStorageBuffer(IDeviceObject* pBufferView) const
+{
+ VERIFY((m_DstRes.Type == DescriptorType::StorageBuffer ||
+ m_DstRes.Type == DescriptorType::StorageBuffer_ReadOnly ||
+ m_DstRes.Type == DescriptorType::StorageBufferDynamic ||
+ m_DstRes.Type == DescriptorType::StorageBufferDynamic_ReadOnly),
+ "Storage buffer resource is expected");
+
+ RefCntAutoPtr<BufferViewVkImpl> pBufferViewVk{pBufferView, IID_BufferViewVk};
+#ifdef DILIGENT_DEVELOPMENT
+ {
+ // HLSL buffer SRVs are mapped to storge buffers in GLSL
+ const auto RequiredViewType = DescriptorTypeToBufferView(m_DstRes.Type);
+ VerifyResourceViewBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex,
+ pBufferView, pBufferViewVk.RawPtr(),
+ {RequiredViewType}, RESOURCE_DIM_BUFFER,
+ false, // IsMultisample
+ m_DstRes.pObject.RawPtr());
+ 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 '",
+ m_ResDesc.Name, "': structured buffer view is expected.");
+ }
+ }
+ }
+#endif
+
+ UpdateCachedResource(std::move(pBufferViewVk));
+}
+
+void BindResourceHelper::CacheTexelBuffer(IDeviceObject* pBufferView) const
{
- return m_ParentManager.m_pSignature->IsBound(ArrayIndex, m_ResIndex, m_ParentManager.m_ResourceCache);
+ VERIFY((m_DstRes.Type == DescriptorType::UniformTexelBuffer ||
+ m_DstRes.Type == DescriptorType::StorageTexelBuffer ||
+ m_DstRes.Type == DescriptorType::StorageTexelBuffer_ReadOnly),
+ "Uniform or storage buffer resource is expected");
+
+ RefCntAutoPtr<BufferViewVkImpl> pBufferViewVk{pBufferView, IID_BufferViewVk};
+#ifdef DILIGENT_DEVELOPMENT
+ {
+ // HLSL buffer SRVs are mapped to storge buffers in GLSL
+ const auto RequiredViewType = DescriptorTypeToBufferView(m_DstRes.Type);
+ VerifyResourceViewBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex,
+ pBufferView, pBufferViewVk.RawPtr(),
+ {RequiredViewType}, RESOURCE_DIM_BUFFER,
+ false, // IsMultisample
+ m_DstRes.pObject.RawPtr());
+ 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))
+ {
+ LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
+ m_ResDesc.Name, "': formatted buffer view is expected.");
+ }
+ }
+ }
+#endif
+
+ UpdateCachedResource(std::move(pBufferViewVk));
+}
+
+void BindResourceHelper::CacheImage(IDeviceObject* pTexView) const
+{
+ VERIFY((m_DstRes.Type == DescriptorType::StorageImage ||
+ m_DstRes.Type == DescriptorType::SeparateImage ||
+ m_DstRes.Type == DescriptorType::CombinedImageSampler),
+ "Storage image, separate image or sampled image resource is expected");
+
+ RefCntAutoPtr<TextureViewVkImpl> pTexViewVk0{pTexView, IID_TextureViewVk};
+#ifdef DILIGENT_DEVELOPMENT
+ {
+ // HLSL buffer SRVs are mapped to storge buffers in GLSL
+ auto RequiredViewType = DescriptorTypeToTextureView(m_DstRes.Type);
+ VerifyResourceViewBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex,
+ pTexView, pTexViewVk0.RawPtr(),
+ {RequiredViewType},
+ RESOURCE_DIM_UNDEFINED, // Required resource dimension is not known
+ false, // IsMultisample
+ m_DstRes.pObject.RawPtr());
+ }
+#endif
+
+ TextureViewVkImpl* pTexViewVk = pTexViewVk0;
+ if (UpdateCachedResource(std::move(pTexViewVk0)))
+ {
+#ifdef DILIGENT_DEVELOPMENT
+ if (m_DstRes.Type == DescriptorType::CombinedImageSampler && !m_Attribs.IsImmutableSamplerAssigned())
+ {
+ if (pTexViewVk->GetSampler() == nullptr)
+ {
+ LOG_ERROR_MESSAGE("Error binding texture view '", pTexViewVk->GetDesc().Name, "' to variable '",
+ GetShaderResourcePrintName(m_ResDesc, m_ArrayIndex), "'. No sampler is assigned to the view");
+ }
+ }
+#endif
+
+ if (m_Attribs.IsCombinedWithSampler())
+ {
+ VERIFY(m_DstRes.Type == DescriptorType::SeparateImage,
+ "Only separate images can be assigned separate samplers when using HLSL-style combined samplers.");
+ VERIFY(!m_Attribs.IsImmutableSamplerAssigned(), "Separate image can't be assigned an immutable sampler.");
+
+ const auto& SamplerResDesc = m_Signature.GetResourceDesc(m_Attribs.SamplerInd);
+ const auto& SamplerAttribs = m_Signature.GetResourceAttribs(m_Attribs.SamplerInd);
+ VERIFY_EXPR(SamplerResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER);
+
+ if (!SamplerAttribs.IsImmutableSamplerAssigned())
+ {
+ auto* pSampler = pTexViewVk->GetSampler();
+ if (pSampler != nullptr)
+ {
+ DEV_CHECK_ERR(SamplerResDesc.ArraySize == 1 || SamplerResDesc.ArraySize == m_ResDesc.ArraySize,
+ "Array size (", SamplerResDesc.ArraySize,
+ ") of separate sampler variable '",
+ SamplerResDesc.Name,
+ "' must be one or the same as the array size (", m_ResDesc.ArraySize,
+ ") of separate image variable '", m_ResDesc.Name, "' it is assigned to");
+
+ BindResourceHelper BindSeparateSamler{
+ m_Signature,
+ m_ResourceCache,
+ m_Attribs.SamplerInd,
+ SamplerResDesc.ArraySize == 1 ? 0 : m_ArrayIndex};
+ BindSeparateSamler(pSampler);
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("Failed to bind sampler to sampler variable '", SamplerResDesc.Name,
+ "' assigned to separate image '", GetShaderResourcePrintName(m_ResDesc, m_ArrayIndex),
+ "': no sampler is set in texture view '", pTexViewVk->GetDesc().Name, '\'');
+ }
+ }
+ }
+ }
}
-void ShaderVariableVkImpl::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex) const
+void BindResourceHelper::CacheSeparateSampler(IDeviceObject* pSampler) const
{
- m_ParentManager.m_pSignature->BindResource(pObj, ArrayIndex, m_ResIndex, m_ParentManager.m_ResourceCache);
+ VERIFY(m_DstRes.Type == DescriptorType::Sampler, "Separate sampler resource is expected");
+ VERIFY(!m_Attribs.IsImmutableSamplerAssigned(), "This separate sampler is assigned an immutable sampler");
+
+ RefCntAutoPtr<SamplerVkImpl> pSamplerVk{pSampler, IID_Sampler};
+#ifdef DILIGENT_DEVELOPMENT
+ if (pSampler != nullptr && pSamplerVk == nullptr)
+ {
+ LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '",
+ GetShaderResourcePrintName(m_ResDesc, m_ArrayIndex), "'. Unexpected object type: sampler is expected");
+ }
+ if (m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && m_DstRes.pObject != nullptr && m_DstRes.pObject != pSamplerVk)
+ {
+ auto VarTypeStr = GetShaderVariableTypeLiteralName(m_ResDesc.VarType);
+ LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", GetShaderResourcePrintName(m_ResDesc, m_ArrayIndex),
+ "'. Attempting to bind another sampler or null is an error and may "
+ "cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic.");
+ }
+#endif
+
+ UpdateCachedResource(std::move(pSamplerVk));
+}
+
+void BindResourceHelper::CacheInputAttachment(IDeviceObject* pTexView) const
+{
+ VERIFY(m_DstRes.Type == DescriptorType::InputAttachment, "Input attachment resource is expected");
+ RefCntAutoPtr<TextureViewVkImpl> pTexViewVk{pTexView, IID_TextureViewVk};
+#ifdef DILIGENT_DEVELOPMENT
+ VerifyResourceViewBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex,
+ pTexView, pTexViewVk.RawPtr(),
+ {TEXTURE_VIEW_SHADER_RESOURCE},
+ RESOURCE_DIM_UNDEFINED,
+ false, // IsMultisample
+ m_DstRes.pObject.RawPtr());
+#endif
+
+ UpdateCachedResource(std::move(pTexViewVk));
+}
+
+void BindResourceHelper::CacheAccelerationStructure(IDeviceObject* pTLAS) const
+{
+ VERIFY(m_DstRes.Type == DescriptorType::AccelerationStructure, "Acceleration Structure resource is expected");
+ RefCntAutoPtr<TopLevelASVkImpl> pTLASVk{pTLAS, IID_TopLevelASVk};
+#ifdef DILIGENT_DEVELOPMENT
+ VerifyTLASResourceBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex, pTLAS, pTLASVk.RawPtr(), m_DstRes.pObject.RawPtr());
+#endif
+
+ UpdateCachedResource(std::move(pTLASVk));
+}
+
+} // namespace
+
+
+void ShaderVariableManagerVk::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex, Uint32 ResIndex)
+{
+ BindResourceHelper BindHelper{
+ *m_pSignature,
+ m_ResourceCache,
+ ResIndex,
+ ArrayIndex};
+
+ BindHelper(pObj);
+}
+
+bool ShaderVariableManagerVk::IsBound(Uint32 ArrayIndex, Uint32 ResIndex) const
+{
+ const auto& ResDesc = GetResourceDesc(ResIndex);
+ const auto& Attribs = GetAttribs(ResIndex);
+ const Uint32 CacheOffset = Attribs.CacheOffset(m_ResourceCache.GetContentType());
+
+ VERIFY_EXPR(ArrayIndex < ResDesc.ArraySize);
+
+ if (Attribs.DescrSet < m_ResourceCache.GetNumDescriptorSets())
+ {
+ const auto& Set = const_cast<const ShaderResourceCacheVk&>(m_ResourceCache).GetDescriptorSet(Attribs.DescrSet);
+ if (CacheOffset + ArrayIndex < Set.GetSize())
+ {
+ const auto& CachedRes = Set.GetResource(CacheOffset + ArrayIndex);
+ return !CachedRes.IsNull();
+ }
+ }
+
+ return false;
}
} // namespace Diligent