summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorassiduous <assiduous@diligentgraphics.com>2021-01-23 04:46:14 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-01-23 04:46:14 +0000
commit9eca06a41fa72a8158784ad5116c717076634e40 (patch)
tree243933cedcf15607bf2d2a976cd7eb2e8e548da7 /Graphics/GraphicsEngineVulkan
parentPipelineState.h: updated comments (diff)
parentimprovements and optimizations for resource signature (diff)
downloadDiligentCore-9eca06a41fa72a8158784ad5116c717076634e40.tar.gz
DiligentCore-9eca06a41fa72a8158784ad5116c717076634e40.zip
Merge branch 'azhirnov-res_layout' into resource_signature
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp7
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp33
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp87
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp1
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp4
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp67
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp37
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp64
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp370
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp19
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp76
13 files changed, 446 insertions, 323 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
index b5797361..358cd3bc 100644
--- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp
@@ -479,9 +479,6 @@ private:
// Graphics/mesh, compute, ray tracing
static constexpr Uint32 NUM_PIPELINE_BIND_POINTS = 3;
- // Static/mutable and dynamic descriptor sets
- static constexpr Uint32 MAX_DESCR_SET_PER_SIGNATURE = 2;
-
struct DescriptorSetBindInfo
{
using ShaderResourceArray = std::array<RefCntAutoPtr<ShaderResourceBindingVkImpl>, MAX_RESOURCE_SIGNATURES>;
@@ -491,7 +488,7 @@ private:
ShaderResourceArray Resources;
VkDescSetArray vkSets = {};
BoolArray PendingVkSet = {}; // 'true' if new descriptor set must be bound
- BoolArray PendingDynamicDescriptors = {}; // 'true' if dynamic descriptor set must be bound
+ BoolArray PendingDynamicDescriptors = {}; // 'true' if dynamic descriptor set must be bound // AZ TODO: remove ?
BoolArray DynamicBuffersPresent = {};
DescriptorSetBindInfo()
@@ -522,7 +519,7 @@ private:
/// Descriptor set binding information for each pipeline type (graphics/mesh, compute, ray tracing)
std::array<DescriptorSetBindInfo, NUM_PIPELINE_BIND_POINTS> m_DescrSetBindInfo;
- /// AZ TODO: comment
+ /// Memory to store dynamic buffer offsets for descriptor sets.
std::vector<Uint32> m_DynamicBufferOffsets;
/// Render pass that matches currently bound render targets.
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp
index 0e35f1ae..d1e8fb38 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayoutVk.hpp
@@ -54,8 +54,7 @@ public:
VkPipelineLayout GetVkPipelineLayout() const { return m_VkPipelineLayout; }
Uint32 GetSignatureCount() const { return m_SignatureCount; }
- Uint32 GetDescriptorSetCount() const { return m_DescrSetCount; }
- Uint32 GetDynamicOffsetCount() const { return m_DynamicOffsetCount; }
+ //Uint32 GetDescriptorSetCount() const { return m_DescrSetCount; }
PipelineResourceSignatureVkImpl* GetSignature(Uint32 index) const
{
@@ -70,13 +69,6 @@ public:
return Index < m_SignatureCount ? m_FirstDescrSetIndex[Index] : ~0u;
}
- // Returns the index of the first dynamic buffer used by the given resource signature
- Uint32 GetFirstDynamicBufferIndex(const IPipelineResourceSignature* pPRS) const
- {
- Uint32 Index = pPRS->GetDesc().BindingIndex;
- return Index < m_SignatureCount ? m_FirstDynBuffIndex[Index] : 0;
- }
-
struct ResourceInfo
{
SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN;
@@ -86,30 +78,23 @@ public:
bool GetResourceInfo(const char* Name, SHADER_TYPE Stage, ResourceInfo& Info) const;
private:
+ using SignatureArray = std::array<RefCntAutoPtr<PipelineResourceSignatureVkImpl>, MAX_RESOURCE_SIGNATURES>;
+ using FirstDescrSetIndexArrayType = std::array<Uint8, MAX_RESOURCE_SIGNATURES>;
+
VulkanUtilities::PipelineLayoutWrapper m_VkPipelineLayout;
- // The total number of dynamic offsets in this pipeline layout
- Uint32 m_DynamicOffsetCount = 0;
+ // Index of the first descriptor set, for every resource signature
+ FirstDescrSetIndexArrayType m_FirstDescrSetIndex = {};
// The number of resource signatures used by this pipeline layout
// (Maximum is MAX_RESOURCE_SIGNATURES)
- Uint16 m_SignatureCount = 0;
+ Uint8 m_SignatureCount = 0;
// The total number of descriptor sets used by this pipeline layout.
// (Maximum is MAX_RESOURCE_SIGNATURES * 2)
- Uint16 m_DescrSetCount = 0;
-
- using SignatureArrayType = std::array<RefCntAutoPtr<PipelineResourceSignatureVkImpl>, MAX_RESOURCE_SIGNATURES>;
- using FirstDescrSetIndexArrayType = std::array<Uint8, MAX_RESOURCE_SIGNATURES>;
- using FirstDynBuffIndexArrayType = std::array<Uint16, MAX_RESOURCE_SIGNATURES>;
-
- SignatureArrayType m_Signatures;
-
- // Index of the first descriptor set, for every resource signature
- FirstDescrSetIndexArrayType m_FirstDescrSetIndex = {};
+ Uint8 m_DescrSetCount = 0;
- // Index of the first dynamic buffer, for every resource signature
- FirstDynBuffIndexArrayType m_FirstDynBuffIndex = {};
+ SignatureArray m_Signatures;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp
index c5897f86..87bc319a 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineResourceSignatureVkImpl.hpp
@@ -51,7 +51,6 @@ enum class DescriptorType : Uint8
CombinedImageSampler,
SeparateImage,
StorageImage,
- StorageImage_ReadOnly,
UniformTexelBuffer,
StorageTexelBuffer,
StorageTexelBuffer_ReadOnly,
@@ -82,26 +81,57 @@ public:
bool bIsDeviceInternal = false);
~PipelineResourceSignatureVkImpl();
- Uint32 GetDynamicBufferCount() const { return m_DynamicBufferCount; }
- Uint8 GetNumShaderStages() const { return m_NumShaders; }
+ Uint32 GetDynamicOffsetCount() const { return m_DynamicUniformBufferCount + m_DynamicStorageBufferCount; }
+ Uint32 GetDynamicUniformBufferCount() const { return m_DynamicUniformBufferCount; }
+ Uint32 GetDynamicStorageBufferCount() const { return m_DynamicStorageBufferCount; }
+ Uint32 GetNumDescriptorSets() const;
+
+ Uint32 GetNumShaderStages() const { return m_NumShaders; }
SHADER_TYPE GetShaderStageType(Uint32 StageIndex) const;
- Uint32 GetTotalResourceCount() const { return m_Desc.NumResources; }
- Uint32 GetNumDescriptorSets() const;
- static constexpr Uint32 InvalidSamplerInd = ~0u;
+ static constexpr Uint32 InvalidSamplerInd = (1u << 16) - 1;
+ enum class CacheContentType
+ {
+ Signature = 0, // only static resources
+ SRB = 1 // in SRB
+ };
+
+ // sizeof(ResourceAttribs) == 16, x64
struct ResourceAttribs
{
- DescriptorType Type;
- Uint32 CacheOffset; // for ShaderResourceCacheVk
- Uint16 BindingIndex;
- Uint8 DescrSet : 1;
- Uint8 ImmutableSamplerAssigned : 1;
- Uint32 SamplerInd;
-
- ResourceAttribs() :
- CacheOffset{~0u}, BindingIndex{0xFFFF}, DescrSet{0}, SamplerInd{InvalidSamplerInd}, ImmutableSamplerAssigned{0}
- {}
+ private:
+ static constexpr Uint32 _DescrTypeBits = 4;
+ static constexpr Uint32 _DescrSetBits = 1;
+ static constexpr Uint32 _BindingIndexBits = 16;
+ static constexpr Uint32 _SamplerIndBits = 16;
+ static constexpr Uint32 _SamplerAssignedBits = 1;
+ static constexpr Uint32 _BitsSumm = ((sizeof(Uint32) * 8 * 2) + _DescrTypeBits + _DescrSetBits + _BindingIndexBits + _SamplerIndBits + _SamplerAssignedBits + 31) & ~31;
+
+ static_assert((1u << _DescrTypeBits) >= static_cast<Uint32>(DescriptorType::Count), "not enought bits to store DescriptorType values");
+ static_assert((1u << _SamplerIndBits) - 1 == InvalidSamplerInd, "InvalidSamplerInd is incorrect");
+ static_assert((1u << _DescrSetBits) == MAX_DESCR_SET_PER_SIGNATURE, "not enoght bits to store descriptor set index");
+ static_assert((1u << _BindingIndexBits) >= MAX_RESOURCES_IN_SIGNATURE, "not enoght bits to store resource binding index");
+
+ public:
+ // clang-format off
+ Uint32 BindingIndex : _BindingIndexBits;
+ Uint32 SamplerInd : _SamplerIndBits; // index in m_Desc.Resources and m_pResourceAttribs
+ Uint32 DescrType : _DescrTypeBits;
+ Uint32 DescrSet : _DescrSetBits;
+ Uint32 ImtblSamplerAssigned : _SamplerAssignedBits;
+ Uint32 CacheOffsets[2]; // static and static/mutable/dynamic offsets for ShaderResourceCacheVk
+
+ ResourceAttribs()
+ {
+ static_assert(_BitsSumm == sizeof(ResourceAttribs) * 8, "fields is not properly packed");
+ }
+
+ Uint32 CacheOffset(CacheContentType CacheType) const { return CacheOffsets[static_cast<Uint32>(CacheType)]; }
+
+ DescriptorType Type() const { return static_cast<DescriptorType>(DescrType); }
+ bool IsImmutableSamplerAssigned() const { return ImtblSamplerAssigned; }
+ // clang-format on
};
const ResourceAttribs& GetAttribs(Uint32 ResIndex) const
@@ -172,15 +202,24 @@ public:
}
private:
+ using ImmutableSamplerPtrType = RefCntAutoPtr<ISampler>;
+ using CacheOffsetsType = std::array<Uint32, 3 * MAX_DESCR_SET_PER_SIGNATURE>; // [dynamic uniform buffers, dynamic storage buffers, other] * [descriptor sets] includes ArraySize
+ using BindingCountType = std::array<Uint32, 3 * MAX_DESCR_SET_PER_SIGNATURE>; // [dynamic uniform buffers, dynamic storage buffers, other] * [descriptor sets] without ArraySize
+
void Destruct();
void ReserveSpaceForStaticVarsMgrs(const PipelineResourceSignatureDesc& Desc,
- FixedLinearAllocator& MemPool,
Int8& StaticVarStageCount,
Uint32& StaticVarCount,
- Uint8 DSMapping[2]);
+ CacheOffsetsType& CacheSizes,
+ BindingCountType& BindingCount,
+ Uint8 DSMapping[MAX_DESCR_SET_PER_SIGNATURE]);
+
+ void CreateLayout(const CacheOffsetsType& CacheSizes,
+ const BindingCountType& BindingCount,
+ const Uint8 DSMapping[MAX_DESCR_SET_PER_SIGNATURE]);
- void CreateLayout(Uint32 StaticVarCount, const Uint8 DSMapping[2]);
+ size_t CalculateHash() const;
Uint32 FindAssignedSampler(const PipelineResourceDesc& SepImg) const;
@@ -188,21 +227,21 @@ private:
Uint32 GetStaticDescrSetIndex() const;
Uint32 GetDynamicDescrSetIndex() const;
- using ImmutableSamplerPtrType = RefCntAutoPtr<ISampler>;
-
private:
- VulkanUtilities::DescriptorSetLayoutWrapper m_VkDescSetLayouts[2];
+ VulkanUtilities::DescriptorSetLayoutWrapper m_VkDescSetLayouts[MAX_DESCR_SET_PER_SIGNATURE];
ResourceAttribs* m_pResourceAttribs = nullptr; // [m_Desc.NumResources]
SHADER_TYPE m_ShaderStages = SHADER_TYPE_UNKNOWN;
- Uint32 m_DynamicBufferCount : 29; // buffers with dynamic offsets
- Uint32 m_NumShaders : 3;
+ Uint16 m_DynamicUniformBufferCount = 0;
+ Uint16 m_DynamicStorageBufferCount = 0;
std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_StaticVarIndex = {-1, -1, -1, -1, -1, -1};
static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above");
+ Uint8 m_NumShaders = 0;
+
ShaderResourceCacheVk* m_pResourceCache = nullptr;
ShaderVariableManagerVk* m_StaticVarsMgrs = nullptr; // [m_NumShaders]
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
index 0c0b07b8..438b09e9 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
@@ -38,6 +38,7 @@
#include "ShaderVariableVk.hpp"
#include "FixedBlockMemoryAllocator.hpp"
#include "SRBMemoryAllocator.hpp"
+#include "PipelineLayoutVk.hpp"
#include "VulkanUtilities/VulkanObjectWrappers.hpp"
#include "VulkanUtilities/VulkanCommandBuffer.hpp"
#include "RenderDeviceVkImpl.hpp"
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
index d67e33d2..baa3b786 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
@@ -49,6 +49,7 @@
#include "RenderPassCache.hpp"
#include "CommandPoolManager.hpp"
#include "DXCompiler.hpp"
+#include "PipelineResourceSignatureVkImpl.hpp"
namespace Diligent
{
@@ -232,7 +233,8 @@ public:
return m_Properties;
}
- IPipelineResourceSignature* GetEmptySignature() const { return m_pEmptySignature.RawPtr<IPipelineResourceSignature>(); }
+ IPipelineResourceSignature* GetEmptySignature() const { return m_pEmptySignature.RawPtr<IPipelineResourceSignature>(); }
+ PipelineResourceSignatureVkImpl* GetEmptySignatureVk() const { return m_pEmptySignature.RawPtr<PipelineResourceSignatureVkImpl>(); }
private:
template <typename PSOCreateInfoType>
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
index 949bf29f..db5510d6 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
@@ -68,21 +68,16 @@ class DeviceContextVkImpl;
class ShaderResourceCacheVk
{
public:
- // This enum is used for debug purposes only
- enum DbgCacheContentType
- {
- StaticShaderResources,
- SRBResources
- };
+ using CacheContentType = PipelineResourceSignatureVkImpl::CacheContentType;
- // clang-format off
- explicit ShaderResourceCacheVk(DbgCacheContentType dbgContentType) noexcept
-#ifdef DILIGENT_DEBUG
- : m_DbgContentType{dbgContentType}
-#endif
+ explicit ShaderResourceCacheVk(CacheContentType ContentType) noexcept :
+ m_TotalResources{0},
+ m_ContentType{static_cast<Uint32>(ContentType)}
{
+ VERIFY_EXPR(GetContentType() == ContentType);
}
+ // clang-format off
ShaderResourceCacheVk (const ShaderResourceCacheVk&) = delete;
ShaderResourceCacheVk (ShaderResourceCacheVk&&) = delete;
ShaderResourceCacheVk& operator = (const ShaderResourceCacheVk&) = delete;
@@ -189,11 +184,12 @@ public:
Uint16& GetDynamicBuffersCounter() { return m_NumDynamicBuffers; }
+ CacheContentType GetContentType() const { return static_cast<CacheContentType>(m_ContentType); }
+
#ifdef DILIGENT_DEBUG
// Only for debug purposes: indicates what types of resources are stored in the cache
- DbgCacheContentType DbgGetContentType() const { return m_DbgContentType; }
- void DbgVerifyResourceInitialization() const;
- void DbgVerifyDynamicBuffersCounter() const;
+ void DbgVerifyResourceInitialization() const;
+ void DbgVerifyDynamicBuffersCounter() const;
#endif
template <bool VerifyOnly>
@@ -215,14 +211,15 @@ private:
void* m_pMemory = nullptr;
Uint16 m_NumSets = 0;
- // Total number of dynamic buffers bound in the resource cache regardless of the variable type.
- // This variable is not equal to dynamic offsets count, it just a indicator that dynamic descriptor has dynamic buffers.
+ // Total number of dynamic buffers (that was created with USAGE_DYNAMIC) bound in the resource cache regardless of the variable type.
+ // This variable is not equal to dynamic offsets count.
Uint16 m_NumDynamicBuffers = 0;
- Uint32 m_TotalResources = 0;
+ Uint32 m_TotalResources : 31;
+
+ // Indicates what types of resources are stored in the cache
+ const Uint32 m_ContentType : 1;
#ifdef DILIGENT_DEBUG
- // Only for debug purposes: indicates what types of resources are stored in the cache
- const DbgCacheContentType m_DbgContentType;
// Debug array that stores flags indicating if resources in the cache have been initialized
std::vector<std::vector<bool>> m_DbgInitializedResources;
#endif
@@ -245,26 +242,50 @@ __forceinline Uint32 ShaderResourceCacheVk::GetDynamicBufferOffsets(Uint32
for (Uint32 set = 0; set < m_NumSets; ++set)
{
const auto& DescrSet = GetDescriptorSet(set);
+ Uint32 res = 0;
- // AZ TODO: optimize
- for (Uint32 res = 0; res < DescrSet.GetSize(); ++res)
+ while (res < DescrSet.GetSize())
{
const auto& Res = DescrSet.GetResource(res);
-
if (Res.Type == DescriptorType::UniformBufferDynamic)
{
const auto* pBufferVk = Res.pObject.RawPtr<const BufferVkImpl>();
auto Offset = pBufferVk != nullptr ? pBufferVk->GetDynamicOffset(CtxId, pCtxVkImpl) : 0;
Offsets[OffsetInd++] = Offset;
+ ++res;
}
- if (Res.Type == DescriptorType::StorageBufferDynamic || Res.Type == DescriptorType::StorageBufferDynamic_ReadOnly)
+ else
+ break;
+ }
+
+ while (res < DescrSet.GetSize())
+ {
+ const auto& Res = DescrSet.GetResource(res);
+ if (Res.Type == DescriptorType::StorageBufferDynamic ||
+ Res.Type == DescriptorType::StorageBufferDynamic_ReadOnly)
{
const auto* pBufferVkView = Res.pObject.RawPtr<const BufferViewVkImpl>();
const auto* pBufferVk = pBufferVkView != nullptr ? pBufferVkView->GetBufferVk() : 0;
auto Offset = pBufferVk != nullptr ? pBufferVk->GetDynamicOffset(CtxId, pCtxVkImpl) : 0;
Offsets[OffsetInd++] = Offset;
+ ++res;
}
+ else
+ break;
+ }
+
+#ifdef DILIGENT_DEBUG
+ for (; res < DescrSet.GetSize(); ++res)
+ {
+ const auto& Res = DescrSet.GetResource(res);
+ // clang-format off
+ VERIFY(Res.Type != DescriptorType::UniformBufferDynamic &&
+ Res.Type != DescriptorType::StorageBufferDynamic &&
+ Res.Type != DescriptorType::StorageBufferDynamic_ReadOnly,
+ "All uniform and storage buffers are expected to go first in the beginning of each descriptor set");
+ // clang-format on
}
+#endif
}
return OffsetInd;
}
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 603ce2b6..ad6be668 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -348,7 +348,7 @@ static VkPipelineBindPoint PipelineTypeToVkBindPoint(PIPELINE_TYPE Type)
return vkBindPoints[Uint32{Type}];
}
-void DeviceContextVkImpl::BindShaderResources(PipelineStateVkImpl* pPipelineStateVk)
+__forceinline void DeviceContextVkImpl::BindShaderResources(PipelineStateVkImpl* pPipelineStateVk)
{
VERIFY_EXPR(pPipelineStateVk != nullptr);
@@ -366,36 +366,37 @@ void DeviceContextVkImpl::BindShaderResources(PipelineStateVkImpl* pPipelineStat
// (14.2.2. Pipeline Layouts, clause 'Pipeline Layout Compatibility')
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#descriptorsets-compatibility
- // AZ TODO: do we need to unbind incompatible descriptor sets here or
- // should the user handle this?
+#ifdef DILIGENT_DEBUG
// unbind incompatible descriptor sets
for (Uint32 i = 0; i < SignCount; ++i)
{
- auto* LayoutSign = Layout.GetSignature(i);
+ const auto* LayoutSign = Layout.GetSignature(i);
+ const auto* ResSign = Resources[i] != nullptr ? Resources[i]->GetSignature() : ValidatedCast<RenderDeviceVkImpl>(GetDevice())->GetEmptySignatureVk();
+
VERIFY_EXPR(LayoutSign != nullptr);
+ VERIFY_EXPR(ResSign != nullptr);
- if (Resources[i] != nullptr && LayoutSign->IsIncompatibleWith(*Resources[i]->GetSignature()))
+ if (LayoutSign->IsIncompatibleWith(*ResSign))
{
- Resources[i] = nullptr;
- CompatSignCount = std::min(CompatSignCount, i + 1);
+ CompatSignCount = i;
+ break;
}
}
// reset unused states
for (Uint32 i = CompatSignCount; i < MAX_RESOURCE_SIGNATURES; ++i)
{
- Resources[i] = nullptr;
-
- BindInfo.PendingVkSet[i] = false; // AZ TODO: can be optimized
+ BindInfo.PendingVkSet[i] = false;
BindInfo.PendingDynamicDescriptors[i] = false;
BindInfo.DynamicBuffersPresent[i] = false;
-#ifdef DILIGENT_DEBUG
+ Resources[i] = nullptr;
+
BindInfo.vkSets[i * MAX_DESCR_SET_PER_SIGNATURE + 0] = VK_NULL_HANDLE;
BindInfo.vkSets[i * MAX_DESCR_SET_PER_SIGNATURE + 1] = VK_NULL_HANDLE;
-#endif
}
+#endif
}
void DeviceContextVkImpl::BindDescriptorSetsWithDynamicOffsets(DescriptorSetBindInfo& BindInfo)
@@ -425,12 +426,12 @@ void DeviceContextVkImpl::BindDescriptorSetsWithDynamicOffsets(DescriptorSetBind
for (Uint32 s = 0; s < DSCount; ++s)
VERIFY_EXPR(BindInfo.vkSets[DSOffset + s] != VK_NULL_HANDLE);
#endif
- if (pSignature->GetDynamicBufferCount() > 0)
+ if (pSignature->GetDynamicOffsetCount() > 0)
{
- Offsets.resize(pSignature->GetDynamicBufferCount());
+ Offsets.resize(pSignature->GetDynamicOffsetCount());
auto NumOffsetsWritten = ResourceCache.GetDynamicBufferOffsets(m_ContextId, this, Offsets);
- VERIFY_EXPR(NumOffsetsWritten == pSignature->GetDynamicBufferCount());
+ VERIFY_EXPR(NumOffsetsWritten == pSignature->GetDynamicOffsetCount());
// Note that there is one global dynamic buffer from which all dynamic resources are suballocated in Vulkan back-end,
// and this buffer is not resizable, so the buffer handle can never change.
@@ -517,7 +518,7 @@ void DeviceContextVkImpl::TransitionShaderResources(IPipelineState*, IShaderReso
if (pShaderResourceBinding == nullptr)
{
- LOG_ERROR_MESSAGE("AZ TODO");
+ LOG_ERROR_MESSAGE("pShaderResourceBinding must not be null");
return;
}
#endif
@@ -525,6 +526,7 @@ void DeviceContextVkImpl::TransitionShaderResources(IPipelineState*, IShaderReso
auto* pResBindingVkImpl = ValidatedCast<ShaderResourceBindingVkImpl>(pShaderResourceBinding);
auto& ResourceCache = pResBindingVkImpl->GetResourceCache();
+ // AZ TODO: exclude stages that is not supported by pipeline
ResourceCache.TransitionResources<false>(this);
}
@@ -542,6 +544,7 @@ void DeviceContextVkImpl::CommitShaderResources(IShaderResourceBinding* pShaderR
if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION)
{
+ // AZ TODO: exclude stages that is not supported by pipeline
ResourceCache.TransitionResources<false>(this);
}
#ifdef DILIGENT_DEVELOPMENT
@@ -592,7 +595,7 @@ void DeviceContextVkImpl::CommitShaderResources(IShaderResourceBinding* pShaderR
++DSIndex;
}
- if (pSignature->GetDynamicBufferCount() > 0)
+ if (pSignature->GetDynamicOffsetCount() > 0)
BindInfo.PendingDynamicDescriptors[Index] = true;
VERIFY_EXPR(DSIndex == DSCount);
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp
index 5f2a525c..c4cefb88 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayoutVk.cpp
@@ -40,7 +40,6 @@ namespace Diligent
PipelineLayoutVk::PipelineLayoutVk()
{
m_FirstDescrSetIndex.fill(std::numeric_limits<FirstDescrSetIndexArrayType::value_type>::max());
- m_FirstDynBuffIndex.fill(std::numeric_limits<FirstDynBuffIndexArrayType::value_type>::max());
}
PipelineLayoutVk::~PipelineLayoutVk()
@@ -58,7 +57,7 @@ void PipelineLayoutVk::Release(RenderDeviceVkImpl* pDeviceVk, Uint64 CommandQueu
void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSignature** ppSignatures, Uint32 SignatureCount)
{
- VERIFY(m_DynamicOffsetCount == 0 && m_SignatureCount == 0 && m_DescrSetCount == 0,
+ VERIFY(m_SignatureCount == 0 && m_DescrSetCount == 0,
"This pipeline layout is already initialized");
for (Uint32 i = 0; i < SignatureCount; ++i)
@@ -66,7 +65,7 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSi
auto* pSignature = ValidatedCast<PipelineResourceSignatureVkImpl>(ppSignatures[i]);
VERIFY(pSignature != nullptr, "Pipeline resource signature at index ", i, " is null. This error should've been caught by ValidatePipelineResourceSignatures.");
- const Uint32 Index = pSignature->GetDesc().BindingIndex;
+ const Uint8 Index = pSignature->GetDesc().BindingIndex;
VERIFY(Index < m_Signatures.size(),
"Pipeline resource signature specifies binding index ", Uint32{Index}, " that exceeds the limit (", m_Signatures.size() - 1,
@@ -77,7 +76,7 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSi
" conflicts with another resource signature '", m_Signatures[Index]->GetDesc().Name,
"' that uses the same index. This error should've been caught by ValidatePipelineResourceSignatureDesc.");
- m_SignatureCount = std::max(m_SignatureCount, static_cast<Uint16>(Index + 1));
+ m_SignatureCount = std::max<Uint8>(m_SignatureCount, Index + 1);
m_Signatures[Index] = pSignature;
}
@@ -89,11 +88,9 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSi
m_Signatures[i] = pEmptySign;
}
- std::array<VkDescriptorSetLayout, MAX_RESOURCE_SIGNATURES * 2> DescSetLayouts;
-
- Uint32 DescSetLayoutCount = 0;
- Uint32 DynamicOffsetCount = 0;
+ std::array<VkDescriptorSetLayout, MAX_RESOURCE_SIGNATURES * MAX_DESCR_SET_PER_SIGNATURE> DescSetLayouts;
+ Uint32 DescSetLayoutCount = 0;
Uint32 DynamicUniformBufferCount = 0;
Uint32 DynamicStorageBufferCount = 0;
@@ -106,46 +103,17 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSi
"Descriptor set layout count (", DescSetLayoutCount, ") exceeds the maximum representable value");
m_FirstDescrSetIndex[i] = static_cast<FirstDescrSetIndexArrayType::value_type>(DescSetLayoutCount);
- VERIFY(DescSetLayoutCount <= std::numeric_limits<FirstDynBuffIndexArrayType::value_type>::max(),
- "Dynamic buffer count (", DynamicOffsetCount, ") exceeds the maximum representable value");
- m_FirstDynBuffIndex[i] = static_cast<FirstDynBuffIndexArrayType::value_type>(DynamicOffsetCount);
-
auto StaticDSLayout = pSignature->GetStaticVkDescriptorSetLayout();
auto DynamicDSLayout = pSignature->GetDynamicVkDescriptorSetLayout();
if (StaticDSLayout != VK_NULL_HANDLE) DescSetLayouts[DescSetLayoutCount++] = StaticDSLayout;
if (DynamicDSLayout != VK_NULL_HANDLE) DescSetLayouts[DescSetLayoutCount++] = DynamicDSLayout;
- DynamicOffsetCount += pSignature->GetDynamicBufferCount();
-
- for (Uint32 r = 0, ResCount = pSignature->GetTotalResourceCount(); r < ResCount; ++r)
- {
- const auto& Attr = pSignature->GetAttribs(r);
-
- if (Attr.Type == DescriptorType::UniformBufferDynamic)
- {
- ++DynamicUniformBufferCount;
- }
- else if (Attr.Type == DescriptorType::StorageBufferDynamic ||
- Attr.Type == DescriptorType::StorageBufferDynamic_ReadOnly)
- {
- ++DynamicStorageBufferCount;
- }
- }
+ DynamicUniformBufferCount += pSignature->GetDynamicUniformBufferCount();
+ DynamicStorageBufferCount += pSignature->GetDynamicStorageBufferCount();
}
VERIFY_EXPR(DescSetLayoutCount <= MAX_RESOURCE_SIGNATURES * 2);
- VkPipelineLayoutCreateInfo PipelineLayoutCI = {};
-
- PipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
- PipelineLayoutCI.pNext = nullptr;
- PipelineLayoutCI.flags = 0; // reserved for future use
- PipelineLayoutCI.setLayoutCount = DescSetLayoutCount;
- PipelineLayoutCI.pSetLayouts = DescSetLayoutCount ? DescSetLayouts.data() : nullptr;
- PipelineLayoutCI.pushConstantRangeCount = 0;
- PipelineLayoutCI.pPushConstantRanges = nullptr;
- m_VkPipelineLayout = pDeviceVk->GetLogicalDevice().CreatePipelineLayout(PipelineLayoutCI);
-
const auto& Limits = pDeviceVk->GetPhysicalDevice().GetProperties().limits;
if (DescSetLayoutCount > Limits.maxBoundDescriptorSets)
{
@@ -167,8 +135,19 @@ void PipelineLayoutVk::Create(RenderDeviceVkImpl* pDeviceVk, IPipelineResourceSi
VERIFY(m_DescrSetCount <= std::numeric_limits<decltype(m_DescrSetCount)>::max(),
"Descriptor set count (", DescSetLayoutCount, ") exceeds the maximum representable value");
- m_DescrSetCount = static_cast<decltype(m_DescrSetCount)>(DescSetLayoutCount);
- m_DynamicOffsetCount = DynamicOffsetCount;
+
+ VkPipelineLayoutCreateInfo PipelineLayoutCI = {};
+
+ PipelineLayoutCI.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ PipelineLayoutCI.pNext = nullptr;
+ PipelineLayoutCI.flags = 0; // reserved for future use
+ PipelineLayoutCI.setLayoutCount = DescSetLayoutCount;
+ PipelineLayoutCI.pSetLayouts = DescSetLayoutCount ? DescSetLayouts.data() : nullptr;
+ PipelineLayoutCI.pushConstantRangeCount = 0;
+ PipelineLayoutCI.pPushConstantRanges = nullptr;
+ m_VkPipelineLayout = pDeviceVk->GetLogicalDevice().CreatePipelineLayout(PipelineLayoutCI);
+
+ m_DescrSetCount = static_cast<Uint8>(DescSetLayoutCount);
}
size_t PipelineLayoutVk::GetHash() const
@@ -185,7 +164,6 @@ size_t PipelineLayoutVk::GetHash() const
bool PipelineLayoutVk::GetResourceInfo(const char* Name, SHADER_TYPE Stage, ResourceInfo& Info) const
{
- // AZ TODO: optimize
for (Uint32 i = 0, DSCount = GetSignatureCount(); i < DSCount; ++i)
{
auto* pSignature = GetSignature(i);
@@ -200,7 +178,7 @@ bool PipelineLayoutVk::GetResourceInfo(const char* Name, SHADER_TYPE Stage, Reso
{
Info.Type = Res.ResourceType;
Info.BindingIndex = static_cast<Uint16>(Attr.BindingIndex);
- Info.DescrSetIndex = m_FirstDescrSetIndex[i] + Attr.DescrSet;
+ Info.DescrSetIndex = m_FirstDescrSetIndex[i] + static_cast<Uint16>(Attr.DescrSet);
return true;
}
}
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp
index 2bcafcf1..60631b9f 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineResourceSignatureVkImpl.cpp
@@ -40,9 +40,51 @@ namespace Diligent
{
namespace
{
+
+bool operator==(const PipelineResourceDesc& lhs, const PipelineResourceDesc& rhs)
+{
+ // clang-format off
+ return lhs.ShaderStages == rhs.ShaderStages &&
+ lhs.ArraySize == rhs.ArraySize &&
+ lhs.ResourceType == rhs.ResourceType &&
+ lhs.VarType == rhs.VarType &&
+ lhs.Flags == lhs.Flags;
+ // clang-format on
+}
+
+bool operator==(const PipelineResourceSignatureVkImpl::ResourceAttribs& lhs,
+ const PipelineResourceSignatureVkImpl::ResourceAttribs& rhs)
+{
+ // clang-format off
+ return lhs.DescrType == rhs.DescrType &&
+ lhs.BindingIndex == rhs.BindingIndex &&
+ lhs.DescrSet == rhs.DescrSet &&
+ //lhs.CacheOffset== rhs.CacheOffset &&
+ //lhs.SamplerInd == rhs.SamplerInd &&
+ lhs.ImtblSamplerAssigned == rhs.ImtblSamplerAssigned;
+ // clang-format on
+}
+
+__forceinline Uint32 ResourceToCacheOffsetIndex(const PipelineResourceDesc& Res)
+{
+ const Uint32 SetIdx = (Res.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? 1 : 0) * 3;
+ const bool WithDynamicOffset = !(Res.Flags & PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS);
+ const bool UseTexelBuffer = (Res.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER);
+
+ if (WithDynamicOffset && !UseTexelBuffer)
+ {
+ if (Res.ResourceType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER)
+ return SetIdx;
+
+ if (Res.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV || Res.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV)
+ return SetIdx + 1;
+ }
+ return SetIdx + 2;
+}
+
VkDescriptorType GetVkDescriptorType(DescriptorType Type)
{
- static_assert(static_cast<Uint32>(DescriptorType::Count) == 16, "Please update the switch below to handle the new descriptor 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
@@ -50,7 +92,6 @@ VkDescriptorType GetVkDescriptorType(DescriptorType Type)
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::StorageImage_ReadOnly: 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;
@@ -120,7 +161,7 @@ DescriptorType GetDescriptorType(const PipelineResourceDesc& Res)
BUFFER_VIEW_TYPE DescriptorTypeToBufferView(DescriptorType Type)
{
- static_assert(static_cast<Uint32>(DescriptorType::Count) == 16, "Please update the switch below to handle the new descriptor 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
@@ -140,14 +181,13 @@ BUFFER_VIEW_TYPE DescriptorTypeToBufferView(DescriptorType Type)
TEXTURE_VIEW_TYPE DescriptorTypeToTextureView(DescriptorType Type)
{
- static_assert(static_cast<Uint32>(DescriptorType::Count) == 16, "Please update the switch below to handle the new descriptor 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::StorageImage: return TEXTURE_VIEW_UNORDERED_ACCESS;
case DescriptorType::CombinedImageSampler:
case DescriptorType::SeparateImage:
- case DescriptorType::StorageImage_ReadOnly:
case DescriptorType::InputAttachment: return TEXTURE_VIEW_SHADER_RESOURCE;
// clang-format on
default:
@@ -193,7 +233,7 @@ Int32 FindImmutableSampler(const PipelineResourceDesc& Res,
RESOURCE_STATE DescriptorTypeToResourceState(DescriptorType Type)
{
- static_assert(static_cast<Uint32>(DescriptorType::Count) == 16, "Please update the switch below to handle the new descriptor 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
@@ -201,7 +241,6 @@ RESOURCE_STATE DescriptorTypeToResourceState(DescriptorType Type)
case DescriptorType::CombinedImageSampler: return RESOURCE_STATE_SHADER_RESOURCE;
case DescriptorType::SeparateImage: return RESOURCE_STATE_SHADER_RESOURCE;
case DescriptorType::StorageImage: return RESOURCE_STATE_UNORDERED_ACCESS;
- case DescriptorType::StorageImage_ReadOnly: return RESOURCE_STATE_SHADER_RESOURCE;
case DescriptorType::UniformTexelBuffer: return RESOURCE_STATE_SHADER_RESOURCE;
case DescriptorType::StorageTexelBuffer: return RESOURCE_STATE_UNORDERED_ACCESS;
case DescriptorType::StorageTexelBuffer_ReadOnly: return RESOURCE_STATE_SHADER_RESOURCE;
@@ -221,16 +260,14 @@ RESOURCE_STATE DescriptorTypeToResourceState(DescriptorType Type)
}
-#define LOG_PRS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of a pipeline resource signature '", (Desc.Name ? Desc.Name : ""), "' is invalid: ", ##__VA_ARGS__)
+#define LOG_PRS_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of a pipeline resource signature '", m_Desc.Name, "' is invalid: ", ##__VA_ARGS__)
PipelineResourceSignatureVkImpl::PipelineResourceSignatureVkImpl(IReferenceCounters* pRefCounters,
RenderDeviceVkImpl* pDevice,
const PipelineResourceSignatureDesc& Desc,
bool bIsDeviceInternal) :
TPipelineResourceSignatureBase{pRefCounters, pDevice, Desc, bIsDeviceInternal},
- m_SRBMemAllocator{GetRawAllocator()},
- m_DynamicBufferCount{0},
- m_NumShaders{0}
+ m_SRBMemAllocator{GetRawAllocator()}
{
try
{
@@ -242,14 +279,22 @@ PipelineResourceSignatureVkImpl::PipelineResourceSignatureVkImpl(IReferenceCount
ReserveSpaceForDescription(MemPool, Desc);
- Int8 StaticVarStageCount = 0;
- Uint32 StaticVarCount = 0;
- Uint8 DSMapping[2] = {};
- ReserveSpaceForStaticVarsMgrs(Desc, MemPool, StaticVarStageCount, StaticVarCount, DSMapping);
+ Int8 StaticVarStageCount = 0;
+ Uint32 StaticVarCount = 0;
+ Uint8 DSMapping[MAX_DESCR_SET_PER_SIGNATURE] = {};
+ CacheOffsetsType CacheSizes = {};
+ BindingCountType BindingCount = {};
+ ReserveSpaceForStaticVarsMgrs(Desc, StaticVarStageCount, StaticVarCount, CacheSizes, BindingCount, DSMapping);
+
+ if (StaticVarStageCount > 0)
+ {
+ MemPool.AddSpace<ShaderResourceCacheVk>(1);
+ MemPool.AddSpace<ShaderVariableManagerVk>(StaticVarStageCount);
+ }
MemPool.Reserve();
- m_pResourceAttribs = MemPool.ConstructArray<ResourceAttribs>(std::max(1u, m_Desc.NumResources));
+ m_pResourceAttribs = MemPool.Allocate<ResourceAttribs>(std::max(1u, m_Desc.NumResources));
m_ImmutableSamplers = MemPool.ConstructArray<ImmutableSamplerPtrType>(m_Desc.NumImmutableSamplers);
// The memory is now owned by PipelineResourceSignatureVkImpl and will be freed by Destruct().
@@ -261,11 +306,16 @@ PipelineResourceSignatureVkImpl::PipelineResourceSignatureVkImpl(IReferenceCount
if (StaticVarStageCount > 0)
{
- m_pResourceCache = MemPool.Construct<ShaderResourceCacheVk>(ShaderResourceCacheVk::StaticShaderResources);
+ m_pResourceCache = MemPool.Construct<ShaderResourceCacheVk>(CacheContentType::Signature);
m_StaticVarsMgrs = MemPool.Allocate<ShaderVariableManagerVk>(StaticVarStageCount);
m_pResourceCache->InitializeSets(GetRawAllocator(), 1, &StaticVarCount);
+ }
+ CreateLayout(CacheSizes, BindingCount, DSMapping);
+
+ if (StaticVarStageCount > 0)
+ {
const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC};
for (Uint32 i = 0; i < m_StaticVarIndex.size(); ++i)
@@ -281,7 +331,7 @@ PipelineResourceSignatureVkImpl::PipelineResourceSignatureVkImpl(IReferenceCount
}
}
- CreateLayout(StaticVarCount, DSMapping);
+ m_Hash = CalculateHash();
}
catch (...)
{
@@ -291,20 +341,22 @@ PipelineResourceSignatureVkImpl::PipelineResourceSignatureVkImpl(IReferenceCount
}
void PipelineResourceSignatureVkImpl::ReserveSpaceForStaticVarsMgrs(const PipelineResourceSignatureDesc& Desc,
- FixedLinearAllocator& MemPool,
Int8& StaticVarStageCount,
Uint32& StaticVarCount,
- Uint8 DSMapping[2])
+ CacheOffsetsType& CacheSizes,
+ BindingCountType& BindingCount,
+ Uint8 DSMapping[MAX_DESCR_SET_PER_SIGNATURE])
{
// get active shader stages
SHADER_TYPE Stages = SHADER_TYPE_UNKNOWN;
SHADER_TYPE StaticResStages = SHADER_TYPE_UNKNOWN;
- bool VarExist[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES] = {};
-
for (Uint32 i = 0; i < Desc.NumResources; ++i)
{
- const auto& Res = Desc.Resources[i];
+ const auto& Res = Desc.Resources[i];
+ const Uint32 SetIdx = (Res.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? 1 : 0);
+ const Uint32 COIdx = ResourceToCacheOffsetIndex(Res);
+
Stages |= Res.ShaderStages;
if (Res.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
@@ -313,25 +365,20 @@ void PipelineResourceSignatureVkImpl::ReserveSpaceForStaticVarsMgrs(const Pipeli
StaticVarCount += Res.ArraySize;
}
- VarExist[Res.VarType] = true;
+ ++BindingCount[COIdx];
+ CacheSizes[COIdx] += Res.ArraySize;
}
// initialize descriptor set mapping table
{
- Uint8 Idx = 0;
- if (VarExist[SHADER_RESOURCE_VARIABLE_TYPE_STATIC] || VarExist[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE])
- DSMapping[0] = Idx++;
- else
- DSMapping[0] = 0xFF;
-
- if (VarExist[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC])
- DSMapping[1] = Idx;
- else
- DSMapping[1] = 0xFF;
+ Uint8 Idx = 0;
+ DSMapping[0] = (BindingCount[0] + BindingCount[1] + BindingCount[2] ? Idx++ : 0xFF);
+ DSMapping[1] = (BindingCount[3] + BindingCount[4] + BindingCount[5] ? Idx++ : 0xFF);
+ VERIFY_EXPR(Idx <= MAX_DESCR_SET_PER_SIGNATURE);
}
m_ShaderStages = Stages;
- m_NumShaders = PlatformMisc::CountOneBits(static_cast<Uint32>(Stages));
+ m_NumShaders = static_cast<Uint8>(PlatformMisc::CountOneBits(static_cast<Uint32>(Stages)));
if (Stages == SHADER_TYPE_COMPUTE)
{
@@ -362,39 +409,54 @@ void PipelineResourceSignatureVkImpl::ReserveSpaceForStaticVarsMgrs(const Pipeli
const auto ShaderTypeInd = GetShaderTypePipelineIndex(StageBit, m_PipelineType);
m_StaticVarIndex[ShaderTypeInd] = StaticVarStageCount;
}
-
- if (StaticVarStageCount > 0)
- {
- MemPool.AddSpace<ShaderResourceCacheVk>(1);
- MemPool.AddSpace<ShaderVariableManagerVk>(StaticVarStageCount);
- }
}
#undef LOG_PRS_ERROR_AND_THROW
-void PipelineResourceSignatureVkImpl::CreateLayout(Uint32 StaticVarCount, const Uint8 DSMapping[2])
+void PipelineResourceSignatureVkImpl::CreateLayout(const CacheOffsetsType& CacheSizes,
+ const BindingCountType& BindingCount,
+ const Uint8 DSMapping[MAX_DESCR_SET_PER_SIGNATURE])
{
- std::vector<VkDescriptorSetLayoutBinding> LayoutBindings[2];
+ std::vector<VkDescriptorSetLayoutBinding> LayoutBindings[MAX_DESCR_SET_PER_SIGNATURE];
DynamicLinearAllocator TempAllocator{GetRawAllocator()};
- Uint32 CacheOffsets[Uint32{SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES}] = {0, StaticVarCount, 0};
+ // clang-format off
+ CacheOffsetsType CacheOffsets = {0, CacheSizes[0], CacheSizes[0] + CacheSizes[1], // static/mutable set
+ 0, CacheSizes[3], CacheSizes[3] + CacheSizes[4]}; // dynamic set
+ BindingCountType BindingIndices = {0, BindingCount[0], BindingCount[0] + BindingCount[1], // static/mutable set
+ 0, BindingCount[3], BindingCount[3] + BindingCount[4]}; // dynamic set
+ Uint32 StaticCacheOffset = 0;
+ // clang-format on
for (Uint32 i = 0; i < m_Desc.NumResources; ++i)
{
const auto& Res = m_Desc.Resources[i];
+ const auto DescrType = GetDescriptorType(Res);
auto& Attribs = m_pResourceAttribs[i];
- auto& CacheOffset = CacheOffsets[Uint32{Res.VarType}];
const Uint32 SetIdx = (Res.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC ? 1 : 0);
+ const Uint32 COIdx = ResourceToCacheOffsetIndex(Res);
+ auto& CacheOffset = CacheOffsets[COIdx];
// If all resources are dynamic then signature contains only one descriptor set layout with index 0,
// so remap SetIdx to actual descriptor set index.
- VERIFY_EXPR(DSMapping[SetIdx] <= 1);
+ VERIFY_EXPR(DSMapping[SetIdx] < MAX_DESCR_SET_PER_SIGNATURE);
- Attribs.DescrSet = DSMapping[SetIdx];
- Attribs.BindingIndex = static_cast<Uint16>(LayoutBindings[SetIdx].size());
- Attribs.CacheOffset = CacheOffset;
- Attribs.Type = GetDescriptorType(Res);
+ Attribs.CacheOffsets[static_cast<Uint32>(CacheContentType::Signature)] = ~0u;
+ Attribs.CacheOffsets[static_cast<Uint32>(CacheContentType::SRB)] = CacheOffset;
+
+ Attribs.DescrType = static_cast<Uint32>(DescrType);
+ Attribs.DescrSet = DSMapping[SetIdx];
+ Attribs.BindingIndex = BindingIndices[COIdx];
+ Attribs.SamplerInd = InvalidSamplerInd;
+ Attribs.ImtblSamplerAssigned = false;
+
+ // verify that data is not missed during bit packing
+ VERIFY_EXPR(Attribs.CacheOffsets[static_cast<Uint32>(CacheContentType::SRB)] == CacheOffset);
+ VERIFY_EXPR(Attribs.DescrType == static_cast<Uint32>(DescrType));
+ VERIFY_EXPR(Attribs.DescrSet == DSMapping[SetIdx]);
+ VERIFY_EXPR(Attribs.BindingIndex == BindingIndices[COIdx]);
CacheOffset += Res.ArraySize;
+ ++BindingIndices[COIdx];
LayoutBindings[SetIdx].emplace_back();
auto& LayoutBinding = LayoutBindings[SetIdx].back();
@@ -403,18 +465,18 @@ void PipelineResourceSignatureVkImpl::CreateLayout(Uint32 StaticVarCount, const
LayoutBinding.descriptorCount = Res.ArraySize;
LayoutBinding.stageFlags = ShaderTypesToVkShaderStageFlags(Res.ShaderStages);
LayoutBinding.pImmutableSamplers = nullptr;
- LayoutBinding.descriptorType = GetVkDescriptorType(Attribs.Type);
+ LayoutBinding.descriptorType = GetVkDescriptorType(Attribs.Type());
- if (Attribs.Type == DescriptorType::SeparateImage)
+ if (Attribs.Type() == DescriptorType::SeparateImage)
{
Attribs.SamplerInd = FindAssignedSampler(Res);
}
- if (Attribs.Type == DescriptorType::CombinedImageSampler ||
- Attribs.Type == DescriptorType::Sampler)
+ if (Attribs.Type() == DescriptorType::CombinedImageSampler ||
+ Attribs.Type() == DescriptorType::Sampler)
{
// Only search for the immutable sampler for combined image samplers and separate samplers
- Int32 SrcImmutableSamplerInd = FindImmutableSampler(Res, Attribs.Type, m_Desc, GetCombinedSamplerSuffix());
+ Int32 SrcImmutableSamplerInd = FindImmutableSampler(Res, Attribs.Type(), m_Desc, GetCombinedSamplerSuffix());
if (SrcImmutableSamplerInd >= 0)
{
auto& ImmutableSampler = m_ImmutableSamplers[SrcImmutableSamplerInd];
@@ -422,27 +484,37 @@ void PipelineResourceSignatureVkImpl::CreateLayout(Uint32 StaticVarCount, const
if (!ImmutableSampler)
GetDevice()->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler);
- const VkSampler VkImmutableSampler = ImmutableSampler.RawPtr<SamplerVkImpl>()->GetVkSampler();
- VkSampler* SamplerArray = TempAllocator.Allocate<VkSampler>(Res.ArraySize);
- for (Uint32 a = 0; a < Res.ArraySize; ++a)
- SamplerArray[a] = VkImmutableSampler;
-
- LayoutBinding.pImmutableSamplers = SamplerArray;
- Attribs.ImmutableSamplerAssigned = true;
+ LayoutBinding.pImmutableSamplers = TempAllocator.ConstructArray<VkSampler>(Res.ArraySize, ImmutableSampler.RawPtr<SamplerVkImpl>()->GetVkSampler());
+ Attribs.ImtblSamplerAssigned = true;
}
}
- if (Attribs.Type == DescriptorType::UniformBufferDynamic ||
- Attribs.Type == DescriptorType::StorageBufferDynamic ||
- Attribs.Type == DescriptorType::StorageBufferDynamic_ReadOnly)
+ if (Res.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
{
- m_DynamicBufferCount += Res.ArraySize;
+ Attribs.CacheOffsets[static_cast<Uint32>(CacheContentType::Signature)] = StaticCacheOffset;
+ m_pResourceCache->InitializeResources(Attribs.DescrSet, StaticCacheOffset, Res.ArraySize, Attribs.Type());
+ StaticCacheOffset += Res.ArraySize;
}
-
- if (Res.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
- m_pResourceCache->InitializeResources(Attribs.DescrSet, Attribs.CacheOffset, Res.ArraySize, Attribs.Type);
}
- VERIFY_EXPR(CacheOffsets[0] == StaticVarCount);
+
+ m_DynamicUniformBufferCount = static_cast<Uint16>(CacheSizes[0] + CacheSizes[3]);
+ m_DynamicStorageBufferCount = static_cast<Uint16>(CacheSizes[1] + CacheSizes[4]);
+
+ VERIFY_EXPR(m_pResourceCache == nullptr || m_pResourceCache->GetDescriptorSet(0).GetSize() == StaticCacheOffset);
+ VERIFY_EXPR(m_DynamicUniformBufferCount == CacheSizes[0] + CacheSizes[3]);
+ VERIFY_EXPR(m_DynamicStorageBufferCount == CacheSizes[1] + CacheSizes[4]);
+ VERIFY_EXPR(CacheOffsets[0] == CacheSizes[0]);
+ VERIFY_EXPR(CacheOffsets[1] == CacheSizes[0] + CacheSizes[1]);
+ VERIFY_EXPR(CacheOffsets[2] == CacheSizes[0] + CacheSizes[1] + CacheSizes[2]);
+ VERIFY_EXPR(CacheOffsets[3] == CacheSizes[3]);
+ VERIFY_EXPR(CacheOffsets[4] == CacheSizes[3] + CacheSizes[4]);
+ VERIFY_EXPR(CacheOffsets[5] == CacheSizes[3] + CacheSizes[4] + CacheSizes[5]);
+ VERIFY_EXPR(BindingIndices[0] == BindingCount[0]);
+ VERIFY_EXPR(BindingIndices[1] == BindingCount[0] + BindingCount[1]);
+ VERIFY_EXPR(BindingIndices[2] == BindingCount[0] + BindingCount[1] + BindingCount[2]);
+ VERIFY_EXPR(BindingIndices[3] == BindingCount[3]);
+ VERIFY_EXPR(BindingIndices[4] == BindingCount[3] + BindingCount[4]);
+ VERIFY_EXPR(BindingIndices[5] == BindingCount[3] + BindingCount[4] + BindingCount[5]);
if (m_Desc.SRBAllocationGranularity > 1)
{
@@ -455,8 +527,9 @@ void PipelineResourceSignatureVkImpl::CreateLayout(Uint32 StaticVarCount, const
ShaderVariableDataSizes[s] = ShaderVariableManagerVk::GetRequiredMemorySize(*this, AllowedVarTypes, _countof(AllowedVarTypes), GetShaderStageType(s), UnusedNumVars);
}
- Uint32 DescriptorSetSizes[2] = {CacheOffsets[SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE], CacheOffsets[SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC]};
+ Uint32 DescriptorSetSizes[2] = {CacheSizes[0] + CacheSizes[1] + CacheSizes[2], CacheSizes[3] + CacheSizes[4] + CacheSizes[5]};
const Uint32 NumSets = !!DescriptorSetSizes[0] + !!DescriptorSetSizes[1];
+ static_assert(_countof(DescriptorSetSizes) == MAX_DESCR_SET_PER_SIGNATURE, "MAX_DESCR_SET_PER_SIGNATURE was changed, update code above");
if (DescriptorSetSizes[0] == 0)
DescriptorSetSizes[0] = DescriptorSetSizes[1];
@@ -491,12 +564,14 @@ Uint32 PipelineResourceSignatureVkImpl::FindAssignedSampler(const PipelineResour
Uint32 SamplerInd = InvalidSamplerInd;
if (IsUsingCombinedSamplers())
{
- for (Uint32 i = 0; i < m_Desc.NumResources; ++i)
+ const auto IdxRange = GetResourceIndexRange(SepImg.VarType);
+
+ for (Uint32 i = IdxRange.first; i < IdxRange.second; ++i)
{
const auto& Res = m_Desc.Resources[i];
+ VERIFY_EXPR(SepImg.VarType == Res.VarType);
if (Res.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER &&
- SepImg.VarType == Res.VarType &&
(SepImg.ShaderStages & Res.ShaderStages) &&
StreqSuff(Res.Name, SepImg.Name, GetCombinedSamplerSuffix()))
{
@@ -509,6 +584,26 @@ Uint32 PipelineResourceSignatureVkImpl::FindAssignedSampler(const PipelineResour
return SamplerInd;
}
+size_t PipelineResourceSignatureVkImpl::CalculateHash() const
+{
+ size_t Hash = ComputeHash(m_Desc.NumResources, m_Desc.NumImmutableSamplers, m_Desc.BindingIndex);
+
+ for (Uint32 i = 0; i < m_Desc.NumResources; ++i)
+ {
+ const auto& Res = m_Desc.Resources[i];
+ const auto& Attr = m_pResourceAttribs[i];
+
+ HashCombine(Hash, Res.ArraySize, Res.ShaderStages, Res.VarType, Attr.Type(), Attr.BindingIndex, Attr.DescrSet, Attr.IsImmutableSamplerAssigned());
+ }
+
+ for (Uint32 i = 0; i < m_Desc.NumImmutableSamplers; ++i)
+ {
+ HashCombine(Hash, m_Desc.ImmutableSamplers[i].ShaderStages, m_Desc.ImmutableSamplers[i].Desc);
+ }
+
+ return Hash;
+}
+
PipelineResourceSignatureVkImpl::~PipelineResourceSignatureVkImpl()
{
Destruct();
@@ -582,17 +677,9 @@ bool PipelineResourceSignatureVkImpl::IsCompatibleWith(const PipelineResourceSig
for (Uint32 r = 0; r < LCount; ++r)
{
- const auto& LAttr = GetAttribs(r);
- const auto& RAttr = Other.GetAttribs(r);
-
- if (LAttr.Type != RAttr.Type ||
- LAttr.DescrSet != RAttr.DescrSet ||
- LAttr.BindingIndex != RAttr.BindingIndex ||
- LAttr.CacheOffset != RAttr.CacheOffset ||
- LAttr.ImmutableSamplerAssigned != RAttr.ImmutableSamplerAssigned)
- {
+ if (!(GetAttribs(r) == Other.GetAttribs(r)) ||
+ !(GetResource(r) == Other.GetResource(r)))
return false;
- }
}
const Uint32 LSampCount = GetDesc().NumImmutableSamplers;
@@ -678,8 +765,9 @@ void PipelineResourceSignatureVkImpl::InitResourceCache(ShaderResourceCacheVk& R
IMemoryAllocator& CacheMemAllocator,
const char* DbgPipelineName) const
{
- std::array<Uint32, 2> VarCount = {};
- Uint32 NumSets = static_cast<Uint32>(VarCount.size());
+ std::array<Uint32, MAX_DESCR_SET_PER_SIGNATURE> VarCount = {};
+
+ Uint32 NumSets = static_cast<Uint32>(VarCount.size());
for (Uint32 r = 0; r < m_Desc.NumResources; ++r)
{
@@ -732,12 +820,13 @@ Uint32 PipelineResourceSignatureVkImpl::GetNumDescriptorSets() const
void PipelineResourceSignatureVkImpl::InitializeResourceMemoryInCache(ShaderResourceCacheVk& ResourceCache) const
{
- auto TotalResources = GetTotalResourceCount();
+ const auto TotalResources = GetTotalResourceCount();
+ const auto CacheType = ResourceCache.GetContentType();
for (Uint32 r = 0; r < TotalResources; ++r)
{
const auto& Res = GetResource(r);
const auto& Attr = GetAttribs(r);
- ResourceCache.InitializeResources(Attr.DescrSet, Attr.CacheOffset, Res.ArraySize, Attr.Type);
+ ResourceCache.InitializeResources(Attr.DescrSet, Attr.CacheOffset(CacheType), Res.ArraySize, Attr.Type());
}
}
@@ -751,32 +840,33 @@ void PipelineResourceSignatureVkImpl::InitializeStaticSRBResources(ShaderResourc
const auto& SrcResourceCache = *m_pResourceCache;
const auto& SrcDescrSet = SrcResourceCache.GetDescriptorSet(GetStaticDescrSetIndex());
auto& DstDescrSet = DstResourceCache.GetDescriptorSet(GetStaticDescrSetIndex());
+ const auto ResIdxRange = GetResourceIndexRange(SHADER_RESOURCE_VARIABLE_TYPE_STATIC);
+ const auto SrcCacheType = SrcResourceCache.GetContentType();
+ const auto DstCacheType = DstResourceCache.GetContentType();
- // AZ TODO: optimize
- for (Uint32 r = 0; r < GetTotalResourceCount(); ++r)
+ for (Uint32 r = ResIdxRange.first; r < ResIdxRange.second; ++r)
{
const auto& Res = GetResource(r);
const auto& Attr = GetAttribs(r);
+ VERIFY_EXPR(Res.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC);
- if (Res.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER && Attr.ImmutableSamplerAssigned)
+ if (Res.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER && Attr.IsImmutableSamplerAssigned())
continue; // Skip immutable separate samplers
- if (Res.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
+ for (Uint32 ArrInd = 0; ArrInd < Res.ArraySize; ++ArrInd)
{
- for (Uint32 ArrInd = 0; ArrInd < Res.ArraySize; ++ArrInd)
+ auto SrcCacheOffset = Attr.CacheOffset(SrcCacheType) + ArrInd;
+ const auto& SrcCachedRes = SrcDescrSet.GetResource(SrcCacheOffset);
+ IDeviceObject* pObject = SrcCachedRes.pObject.RawPtr<IDeviceObject>();
+ if (!pObject)
+ LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", GetPrintName(Res, ArrInd), "' in pipeline resource signature '", m_Desc.Name, "'.");
+
+ auto DstCacheOffset = Attr.CacheOffset(DstCacheType) + ArrInd;
+ IDeviceObject* pCachedResource = DstDescrSet.GetResource(DstCacheOffset).pObject;
+ if (pCachedResource != pObject)
{
- auto CacheOffset = Attr.CacheOffset + ArrInd;
- const auto& SrcCachedRes = SrcDescrSet.GetResource(CacheOffset);
- IDeviceObject* pObject = SrcCachedRes.pObject.RawPtr<IDeviceObject>();
- if (!pObject)
- LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", GetPrintName(Res, ArrInd), "' in pipeline resource signature '", m_Desc.Name, "'.");
-
- IDeviceObject* pCachedResource = DstDescrSet.GetResource(CacheOffset).pObject;
- if (pCachedResource != pObject)
- {
- VERIFY(pCachedResource == nullptr, "Static resource has already been initialized, and the resource to be assigned from the shader does not match previously assigned resource");
- BindResource(pObject, ArrInd, r, DstResourceCache);
- }
+ VERIFY(pCachedResource == nullptr, "Static resource has already been initialized, and the resource to be assigned from the shader does not match previously assigned resource");
+ BindResource(pObject, ArrInd, r, DstResourceCache);
}
}
}
@@ -801,6 +891,7 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc
{
VERIFY(HasDynamicDescrSet(), "This shader resource layout does not contain dynamic resources");
VERIFY_EXPR(vkDynamicDescriptorSet != VK_NULL_HANDLE);
+ VERIFY_EXPR(ResourceCache.GetContentType() == CacheContentType::SRB);
#ifdef DILIGENT_DEBUG
static constexpr size_t ImgUpdateBatchSize = 4;
@@ -831,19 +922,18 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc
const auto& SetResources = ResourceCache.GetDescriptorSet(GetDynamicDescrSetIndex());
const auto& LogicalDevice = GetDevice()->GetLogicalDevice();
+ const auto ResIdxRange = GetResourceIndexRange(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC);
+ const auto CacheType = CacheContentType::SRB;
- // AZ TODO: optimize
- for (Uint32 ResNum = 0, ArrElem = 0, Count = GetTotalResourceCount(); ResNum < Count;)
+ for (Uint32 ResNum = ResIdxRange.first, ArrElem = 0; ResNum < ResIdxRange.second;)
{
- const auto& Res = GetResource(ResNum);
- const auto& Attr = GetAttribs(ResNum);
+ const auto& Res = GetResource(ResNum);
+ const auto& Attr = GetAttribs(ResNum);
+ const auto CacheOffset = Attr.CacheOffset(CacheType);
- if (Res.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
- {
- VERIFY_EXPR(ArrElem == 0);
- ++ResNum;
- continue;
- }
+ // AZ TODO: put ArraySize to attributes to make it more cache friendly
+
+ VERIFY_EXPR(Res.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC);
WriteDescrSetIt->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
WriteDescrSetIt->pNext = nullptr;
@@ -854,18 +944,18 @@ 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(Attr.Type);
+ WriteDescrSetIt->descriptorType = GetVkDescriptorType(Attr.Type());
// For every resource type, try to batch as many descriptor updates as we can
- static_assert(static_cast<Uint32>(DescriptorType::Count) == 16, "Please update the switch below to handle the new descriptor type");
- switch (Attr.Type)
+ static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
+ switch (Attr.Type())
{
case DescriptorType::UniformBuffer:
case DescriptorType::UniformBufferDynamic:
WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt);
while (ArrElem < Res.ArraySize && DescrBuffIt != DescrBuffInfoArr.end())
{
- const auto& CachedRes = SetResources.GetResource(Attr.CacheOffset + ArrElem);
+ const auto& CachedRes = SetResources.GetResource(CacheOffset + ArrElem);
*DescrBuffIt = CachedRes.GetUniformBufferDescriptorWriteInfo();
++DescrBuffIt;
++ArrElem;
@@ -879,7 +969,7 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc
WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt);
while (ArrElem < Res.ArraySize && DescrBuffIt != DescrBuffInfoArr.end())
{
- const auto& CachedRes = SetResources.GetResource(Attr.CacheOffset + ArrElem);
+ const auto& CachedRes = SetResources.GetResource(CacheOffset + ArrElem);
*DescrBuffIt = CachedRes.GetStorageBufferDescriptorWriteInfo();
++DescrBuffIt;
++ArrElem;
@@ -892,7 +982,7 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc
WriteDescrSetIt->pTexelBufferView = &(*BuffViewIt);
while (ArrElem < Res.ArraySize && BuffViewIt != DescrBuffViewArr.end())
{
- const auto& CachedRes = SetResources.GetResource(Attr.CacheOffset + ArrElem);
+ const auto& CachedRes = SetResources.GetResource(CacheOffset + ArrElem);
*BuffViewIt = CachedRes.GetBufferViewWriteInfo();
++BuffViewIt;
++ArrElem;
@@ -902,13 +992,12 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc
case DescriptorType::CombinedImageSampler:
case DescriptorType::SeparateImage:
case DescriptorType::StorageImage:
- case DescriptorType::StorageImage_ReadOnly:
case DescriptorType::InputAttachment:
WriteDescrSetIt->pImageInfo = &(*DescrImgIt);
while (ArrElem < Res.ArraySize && DescrImgIt != DescrImgInfoArr.end())
{
- const auto& CachedRes = SetResources.GetResource(Attr.CacheOffset + ArrElem);
- *DescrImgIt = CachedRes.GetImageDescriptorWriteInfo(Attr.ImmutableSamplerAssigned);
+ const auto& CachedRes = SetResources.GetResource(CacheOffset + ArrElem);
+ *DescrImgIt = CachedRes.GetImageDescriptorWriteInfo(Attr.IsImmutableSamplerAssigned());
++DescrImgIt;
++ArrElem;
}
@@ -917,12 +1006,12 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc
case DescriptorType::Sampler:
// 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)
- if (!Attr.ImmutableSamplerAssigned)
+ if (!Attr.IsImmutableSamplerAssigned())
{
WriteDescrSetIt->pImageInfo = &(*DescrImgIt);
while (ArrElem < Res.ArraySize && DescrImgIt != DescrImgInfoArr.end())
{
- const auto& CachedRes = SetResources.GetResource(Attr.CacheOffset + ArrElem);
+ const auto& CachedRes = SetResources.GetResource(CacheOffset + ArrElem);
*DescrImgIt = CachedRes.GetSamplerDescriptorWriteInfo();
++DescrImgIt;
++ArrElem;
@@ -939,7 +1028,7 @@ void PipelineResourceSignatureVkImpl::CommitDynamicResources(const ShaderResourc
WriteDescrSetIt->pNext = &(*AccelStructIt);
while (ArrElem < Res.ArraySize && AccelStructIt != DescrAccelStructArr.end())
{
- const auto& CachedRes = SetResources.GetResource(Attr.CacheOffset + ArrElem);
+ const auto& CachedRes = SetResources.GetResource(CacheOffset + ArrElem);
*AccelStructIt = CachedRes.GetAccelerationStructureWriteInfo();
++AccelStructIt;
++ArrElem;
@@ -1003,7 +1092,6 @@ namespace
{
struct BindResourceHelper
{
- // AZ TODO: cache DstRes.Type and ResDesc.VarType for better performace ???
ShaderResourceCacheVk::Resource& DstRes;
const PipelineResourceDesc& ResDesc;
const PipelineResourceSignatureVkImpl::ResourceAttribs& Attribs;
@@ -1042,7 +1130,7 @@ private:
bool UpdateCachedResource(RefCntAutoPtr<ObjectType>&& pObject,
TPreUpdateObject PreUpdateObject) const;
- bool IsImmutableSamplerAssigned() const { return Attribs.ImmutableSamplerAssigned; }
+ bool IsImmutableSamplerAssigned() const { return Attribs.IsImmutableSamplerAssigned(); }
// Updates resource descriptor in the descriptor set
inline void UpdateDescriptorHandle(const VkDescriptorImageInfo* pImageInfo,
@@ -1054,7 +1142,7 @@ private:
void BindResourceHelper::BindResource(IDeviceObject* pObj) const
{
#ifdef DILIGENT_DEBUG
- if (ResourceCache.DbgGetContentType() == ShaderResourceCacheVk::DbgCacheContentType::SRBResources)
+ if (ResourceCache.GetContentType() == PipelineResourceSignatureVkImpl::CacheContentType::SRB)
{
if (ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC || ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE)
{
@@ -1062,7 +1150,7 @@ void BindResourceHelper::BindResource(IDeviceObject* pObj) const
// Dynamic variables do not have vulkan descriptor set only until they are assigned one the first time
}
}
- else if (ResourceCache.DbgGetContentType() == ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources)
+ else if (ResourceCache.GetContentType() == PipelineResourceSignatureVkImpl::CacheContentType::Signature)
{
VERIFY(vkDescrSet == VK_NULL_HANDLE, "Static shader resource cache should not have vulkan descriptor set allocation");
}
@@ -1074,7 +1162,7 @@ void BindResourceHelper::BindResource(IDeviceObject* pObj) const
if (pObj)
{
- static_assert(static_cast<Uint32>(DescriptorType::Count) == 16, "Please update the switch below to handle the new descriptor type");
+ static_assert(static_cast<Uint32>(DescriptorType::Count) == 15, "Please update the switch below to handle the new descriptor type");
switch (DstRes.Type)
{
case DescriptorType::UniformBuffer:
@@ -1096,7 +1184,6 @@ void BindResourceHelper::BindResource(IDeviceObject* pObj) const
break;
case DescriptorType::StorageImage:
- case DescriptorType::StorageImage_ReadOnly:
case DescriptorType::SeparateImage:
case DescriptorType::CombinedImageSampler:
CacheImage(pObj);
@@ -1341,8 +1428,7 @@ void BindResourceHelper::CacheTexelBuffer(IDeviceObject* pBufferView,
void BindResourceHelper::CacheImage(IDeviceObject* pTexView) const
{
// clang-format off
- VERIFY(DstRes.Type == DescriptorType::StorageImage ||
- DstRes.Type == DescriptorType::StorageImage_ReadOnly ||
+ VERIFY(DstRes.Type == DescriptorType::StorageImage ||
DstRes.Type == DescriptorType::SeparateImage ||
DstRes.Type == DescriptorType::CombinedImageSampler,
"Storage image, separate image or sampled image resource is expected");
@@ -1388,7 +1474,7 @@ void BindResourceHelper::CacheImage(IDeviceObject* pTexView) const
auto& SamplerAttribs = Signature.GetAttribs(Attribs.SamplerInd);
VERIFY_EXPR(SamplerResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER);
- if (!SamplerAttribs.ImmutableSamplerAssigned)
+ if (!SamplerAttribs.IsImmutableSamplerAssigned())
{
auto* pSampler = pTexViewVk->GetSampler();
if (pSampler != nullptr)
@@ -1401,9 +1487,10 @@ void BindResourceHelper::CacheImage(IDeviceObject* pTexView) const
"' must be one or the same as the array size (", ResDesc.ArraySize,
") of separate image variable '", ResDesc.Name, "' it is assigned to");
+ const auto CacheType = ResourceCache.GetContentType();
auto& DstDescrSet = ResourceCache.GetDescriptorSet(SamplerAttribs.DescrSet);
const auto SamplerArrInd = SamplerResDesc.ArraySize == 1 ? 0 : ArrayIndex;
- auto& SampleDstRes = DstDescrSet.GetResource(SamplerAttribs.CacheOffset + SamplerArrInd);
+ auto& SampleDstRes = DstDescrSet.GetResource(SamplerAttribs.CacheOffset(CacheType) + SamplerArrInd);
BindResourceHelper SeparateSampler{
SampleDstRes,
@@ -1544,13 +1631,14 @@ void PipelineResourceSignatureVkImpl::BindResource(IDeviceObject* pObj,
Uint32 ResIndex,
ShaderResourceCacheVk& ResourceCache) const
{
- auto& ResDesc = GetResource(ResIndex);
- auto& Attribs = GetAttribs(ResIndex);
- auto& DstDescrSet = ResourceCache.GetDescriptorSet(Attribs.DescrSet);
- auto& DstRes = DstDescrSet.GetResource(Attribs.CacheOffset + ArrayIndex);
+ auto& ResDesc = GetResource(ResIndex);
+ auto& Attribs = GetAttribs(ResIndex);
+ const auto CacheType = ResourceCache.GetContentType();
+ auto& DstDescrSet = ResourceCache.GetDescriptorSet(Attribs.DescrSet);
+ auto& DstRes = DstDescrSet.GetResource(Attribs.CacheOffset(CacheType) + ArrayIndex);
VERIFY_EXPR(ArrayIndex < ResDesc.ArraySize);
- VERIFY(DstRes.Type == Attribs.Type, "Inconsistent types");
+ VERIFY(DstRes.Type == Attribs.Type(), "Inconsistent types");
BindResourceHelper Helper{
DstRes,
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index b92c94f4..4ee76d8c 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -775,7 +775,7 @@ void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& Crea
if (pCombinedSamplerSuffix != nullptr)
{
if (strcmp(pCombinedSamplerSuffix, ShaderResources.GetCombinedSamplerSuffix()) != 0)
- LOG_ERROR_AND_THROW("AZ TODO");
+ LOG_ERROR_AND_THROW("CombinedSamplerSuffix is not compatible between shaders");
}
else
{
@@ -811,18 +811,19 @@ void PipelineStateVkImpl::InitPipelineLayout(const PipelineStateCreateInfo& Crea
if (Resources.size())
{
PipelineResourceSignatureDesc ResSignDesc;
- ResSignDesc.Resources = Resources.data();
- ResSignDesc.NumResources = static_cast<Uint32>(Resources.size());
- ResSignDesc.ImmutableSamplers = LayoutDesc.ImmutableSamplers;
- ResSignDesc.NumImmutableSamplers = LayoutDesc.NumImmutableSamplers;
- ResSignDesc.BindingIndex = 0;
- ResSignDesc.SRBAllocationGranularity = CreateInfo.PSODesc.SRBAllocationGranularity;
- ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix;
+ ResSignDesc.Resources = Resources.data();
+ ResSignDesc.NumResources = static_cast<Uint32>(Resources.size());
+ ResSignDesc.ImmutableSamplers = LayoutDesc.ImmutableSamplers;
+ ResSignDesc.NumImmutableSamplers = LayoutDesc.NumImmutableSamplers;
+ ResSignDesc.BindingIndex = 0;
+ ResSignDesc.SRBAllocationGranularity = CreateInfo.PSODesc.SRBAllocationGranularity;
+ ResSignDesc.UseCombinedTextureSamplers = pCombinedSamplerSuffix != nullptr;
+ ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix;
GetDevice()->CreatePipelineResourceSignature(ResSignDesc, &TempSignature, true);
if (TempSignature == nullptr)
- LOG_ERROR_AND_THROW("AZ TODO");
+ LOG_ERROR_AND_THROW("Failed to create resource signature for pipeline state");
Signatures[0] = TempSignature;
SignatureCount = 1;
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
index a4932563..7e05e8bc 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
@@ -45,7 +45,7 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters*
pPRS,
IsPSOInternal
},
- m_ShaderResourceCache{ShaderResourceCacheVk::DbgCacheContentType::SRBResources}
+ m_ShaderResourceCache{ShaderResourceCacheVk::CacheContentType::SRB}
// clang-format on
{
try
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
index 28adf43a..2e538b2c 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
@@ -255,7 +255,6 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
case DescriptorType::CombinedImageSampler:
case DescriptorType::SeparateImage:
case DescriptorType::StorageImage:
- case DescriptorType::StorageImage_ReadOnly:
{
auto* pTextureViewVk = Res.pObject.RawPtr<TextureViewVkImpl>();
auto* pTextureVk = pTextureViewVk != nullptr ? ValidatedCast<TextureVkImpl>(pTextureViewVk->GetTexture()) : nullptr;
@@ -446,7 +445,6 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetImageDescriptorWriteIn
{
// clang-format off
VERIFY(Type == DescriptorType::StorageImage ||
- Type == DescriptorType::StorageImage_ReadOnly ||
Type == DescriptorType::SeparateImage ||
Type == DescriptorType::CombinedImageSampler,
"Storage image, separate image or sampled image resource is expected");
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
index 4eaf49bd..c700fb97 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
@@ -44,24 +44,29 @@ size_t ShaderVariableManagerVk::GetRequiredMemorySize(const PipelineResourceSign
const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
const bool UsingSeparateSamplers = Layout.IsUsingSeparateSamplers();
- for (Uint32 r = 0, Count = Layout.GetTotalResourceCount(); r < Count; ++r)
+ for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
{
- const auto& Res = Layout.GetResource(r);
- const auto& Attr = Layout.GetAttribs(r);
-
- if (!IsAllowedType(Res.VarType, AllowedTypeBits))
- continue;
+ if (IsAllowedType(VarType, AllowedTypeBits))
+ {
+ const auto ResIdxRange = Layout.GetResourceIndexRange(VarType);
+ for (Uint32 r = ResIdxRange.first; r < ResIdxRange.second; ++r)
+ {
+ const auto& Res = Layout.GetResource(r);
+ const auto& Attr = Layout.GetAttribs(r);
+ VERIFY_EXPR(Res.VarType == VarType);
- if (!(Res.ShaderStages & ShaderStages))
- continue;
+ if (!(Res.ShaderStages & ShaderStages))
+ continue;
- // When using HLSL-style combined image samplers, we need to skip separate samplers.
- // Also always skip immutable separate samplers.
- if (Res.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER &&
- (!UsingSeparateSamplers || Attr.ImmutableSamplerAssigned))
- continue;
+ // When using HLSL-style combined image samplers, we need to skip separate samplers.
+ // Also always skip immutable separate samplers.
+ if (Res.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER &&
+ (!UsingSeparateSamplers || Attr.IsImmutableSamplerAssigned()))
+ continue;
- ++NumVariables;
+ ++NumVariables;
+ }
+ }
}
return NumVariables * sizeof(ShaderVariableVkImpl);
@@ -93,24 +98,29 @@ void ShaderVariableManagerVk::Initialize(const PipelineResourceSignatureVkImpl&
Uint32 VarInd = 0;
const bool UsingSeparateSamplers = SrcLayout.IsUsingSeparateSamplers();
- for (Uint32 r = 0, Count = SrcLayout.GetTotalResourceCount(); r < Count; ++r)
+ for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
{
- const auto& Res = SrcLayout.GetResource(r);
- const auto& Attr = SrcLayout.GetAttribs(r);
-
- if (!IsAllowedType(Res.VarType, AllowedTypeBits))
- continue;
+ if (IsAllowedType(VarType, AllowedTypeBits))
+ {
+ const auto ResIdxRange = SrcLayout.GetResourceIndexRange(VarType);
+ for (Uint32 r = ResIdxRange.first; r < ResIdxRange.second; ++r)
+ {
+ const auto& Res = SrcLayout.GetResource(r);
+ const auto& Attr = SrcLayout.GetAttribs(r);
+ VERIFY_EXPR(Res.VarType == VarType);
- if (!(Res.ShaderStages & ShaderType))
- continue;
+ if (!(Res.ShaderStages & ShaderType))
+ continue;
- // Skip separate samplers when using combined HLSL-style image samplers. Also always skip immutable separate samplers.
- if (Res.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER &&
- (!UsingSeparateSamplers || Attr.ImmutableSamplerAssigned))
- continue;
+ // Skip separate samplers when using combined HLSL-style image samplers. Also always skip immutable separate samplers.
+ if (Res.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER &&
+ (!UsingSeparateSamplers || Attr.IsImmutableSamplerAssigned()))
+ continue;
- ::new (m_pVariables + VarInd) ShaderVariableVkImpl(*this, r);
- ++VarInd;
+ ::new (m_pVariables + VarInd) ShaderVariableVkImpl(*this, r);
+ ++VarInd;
+ }
+ }
}
VERIFY_EXPR(VarInd == m_NumVariables);
@@ -201,7 +211,7 @@ void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping,
const auto& Attr = Var.GetAttribs();
// There should be no immutable separate samplers
- VERIFY(Attr.Type != DescriptorType::Sampler || !Attr.ImmutableSamplerAssigned,
+ VERIFY(Attr.Type() != DescriptorType::Sampler || !Attr.IsImmutableSamplerAssigned(),
"There must be no shader resource variables for immutable separate samplers");
if ((Flags & (1u << Res.VarType)) == 0)
@@ -251,10 +261,10 @@ void ShaderVariableVkImpl::SetArray(IDeviceObject* const* ppObjects,
bool ShaderVariableVkImpl::IsBound(Uint32 ArrayIndex) const
{
- auto& ResourceCache = m_ParentManager.m_ResourceCache;
- const auto& ResDesc = GetDesc();
- const auto& Attribs = GetAttribs();
- Uint32 CacheOffset = Attribs.CacheOffset;
+ auto& ResourceCache = m_ParentManager.m_ResourceCache;
+ const auto& ResDesc = GetDesc();
+ const auto& Attribs = GetAttribs();
+ const Uint32 CacheOffset = Attribs.CacheOffset(ResourceCache.GetContentType());
VERIFY_EXPR(ArrayIndex < ResDesc.ArraySize);