summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-10-25 12:53:05 +0000
committerazhirnov <zh1dron@gmail.com>2020-10-25 13:08:57 +0000
commit7f26e40e0898391a32e6a05d91ef1a217d885668 (patch)
tree3236316d1a752e5dbbfae863f8180ff994b31d70 /Graphics/GraphicsEngineVulkan
parentMerge branch 'master' into ray_tracing (diff)
downloadDiligentCore-7f26e40e0898391a32e6a05d91ef1a217d885668.tar.gz
DiligentCore-7f26e40e0898391a32e6a05d91ef1a217d885668.zip
PSO refactoring for ray tracing
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp6
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp3
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp3
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp13
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp162
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp4
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp8
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp12
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.hpp5
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp10
-rw-r--r--Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp129
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp38
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp499
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp53
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp48
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp758
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp14
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp8
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp21
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp41
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp14
23 files changed, 1269 insertions, 584 deletions
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp
index 73fced1f..8a0fab15 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineLayout.hpp
@@ -48,7 +48,7 @@ class ShaderResourceCacheVk;
class PipelineLayout
{
public:
- static VkDescriptorType GetVkDescriptorType(const SPIRVShaderResourceAttribs& Res);
+ static VkDescriptorType GetVkDescriptorType(SPIRVShaderResourceAttribs::ResourceType Type);
PipelineLayout();
void Release(RenderDeviceVkImpl* pDeviceVkImpl, Uint64 CommandQueueMask);
@@ -69,8 +69,7 @@ public:
SHADER_TYPE ShaderType,
Uint32& DescriptorSet,
Uint32& Binding,
- Uint32& OffsetInCache,
- std::vector<uint32_t>& SPIRV);
+ Uint32& OffsetInCache);
Uint32 GetTotalDescriptors(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
{
@@ -137,7 +136,6 @@ public:
// set by the same Vulkan command. If there are no dynamic descriptors, this
// function also binds descriptor sets rightaway.
void PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
- bool IsCompute,
const ShaderResourceCacheVk& ResourceCache,
DescriptorSetBindInfo& BindInfo,
VkDescriptorSet VkDynamicDescrSet) const;
diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
index d4f2fc36..a02c8d74 100644
--- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp
@@ -59,6 +59,7 @@ public:
PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const GraphicsPipelineStateCreateInfo& CreateInfo);
PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const ComputePipelineStateCreateInfo& CreateInfo);
+ PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const RayTracingPipelineStateCreateInfo& CreateInfo);
~PipelineStateVkImpl();
virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final;
@@ -168,7 +169,7 @@ private:
// Resource layout index in m_ShaderResourceLayouts array for every shader stage,
// indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex)
- std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1};
+ std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1};
bool m_HasStaticResources = false;
bool m_HasNonStaticResources = false;
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
index d85e9ff3..9ceed3e4 100644
--- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
@@ -78,6 +78,9 @@ public:
/// Implementation of IRenderDevice::CreateComputePipelineState() in Vulkan backend.
virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final;
+ /// Implementation of IRenderDevice::CreateRayTracingPipelineState() in Vulkan backend.
+ virtual void DILIGENT_CALL_TYPE CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final;
+
/// Implementation of IRenderDevice::CreateBuffer() in Vulkan backend.
virtual void DILIGENT_CALL_TYPE CreateBuffer(const BufferDesc& BuffDesc,
const BufferData* pBuffData,
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
index 00f2c33a..68401f52 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
@@ -83,7 +83,7 @@ private:
// Resource layout index in m_ShaderResourceCache array for every shader stage,
// indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex)
- std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1};
+ std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1};
bool m_bStaticResourcesInitialized = false;
Uint8 m_NumShaders = 0;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
index 7d77ff48..0bcf79a0 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
@@ -112,12 +112,13 @@ public:
/*1-7*/ // Unused
/* 8 */ RefCntAutoPtr<IDeviceObject> pObject;
- VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo () const;
- VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo () const;
- VkDescriptorImageInfo GetImageDescriptorWriteInfo (bool IsImmutableSampler)const;
- VkBufferView GetBufferViewWriteInfo () const;
- VkDescriptorImageInfo GetSamplerDescriptorWriteInfo() const;
- VkDescriptorImageInfo GetInputAttachmentDescriptorWriteInfo() const;
+ VkDescriptorBufferInfo GetUniformBufferDescriptorWriteInfo () const;
+ VkDescriptorBufferInfo GetStorageBufferDescriptorWriteInfo () const;
+ VkDescriptorImageInfo GetImageDescriptorWriteInfo (bool IsImmutableSampler) const;
+ VkBufferView GetBufferViewWriteInfo () const;
+ VkDescriptorImageInfo GetSamplerDescriptorWriteInfo() const;
+ VkDescriptorImageInfo GetInputAttachmentDescriptorWriteInfo() const;
+ VkWriteDescriptorSetAccelerationStructureKHR GetAccelerationStructureWriteInfo() const;
// clang-format on
};
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
index 9452a390..e5cddb0c 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
@@ -113,18 +113,21 @@ namespace Diligent
class ShaderVkImpl;
/// Diligent::ShaderResourceLayoutVk class
-// sizeof(ShaderResourceLayoutVk)==56 (MS compiler, x64)
+// sizeof(ShaderResourceLayoutVk)==72 (MS compiler, x64)
class ShaderResourceLayoutVk
{
public:
struct ShaderStageInfo
{
- ShaderStageInfo(SHADER_TYPE _Type,
- const ShaderVkImpl* _pShader);
+ ShaderStageInfo() {}
+ ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader);
- const SHADER_TYPE Type;
- const ShaderVkImpl* const pShader;
- std::vector<uint32_t> SPIRV;
+ void Append(const ShaderVkImpl* pShader);
+ size_t Count() const;
+
+ SHADER_TYPE Type = SHADER_TYPE_UNKNOWN;
+ std::vector<const ShaderVkImpl*> Shaders;
+ std::vector<std::vector<uint32_t>> SPIRVs;
};
using TShaderStages = std::vector<ShaderStageInfo>;
@@ -144,10 +147,10 @@ public:
// This method is called by PipelineStateVkImpl class instance to initialize static
// shader resource layout and the cache
- void InitializeStaticResourceLayout(const ShaderVkImpl* pShader,
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- ShaderResourceCacheVk& StaticResourceCache);
+ void InitializeStaticResourceLayout(const std::vector<const ShaderVkImpl*>& Shaders,
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ ShaderResourceCacheVk& StaticResourceCache);
// This method is called by PipelineStateVkImpl class instance to initialize resource
// layouts for all shader stages in the pipeline.
@@ -160,7 +163,7 @@ public:
bool VerifyVariables,
bool VerifyImmutableSamplers);
- // sizeof(VkResource) == 24 (x64)
+ // sizeof(VkResource) == 32 (x64)
struct VkResource
{
// clang-format off
@@ -178,40 +181,56 @@ public:
static constexpr const Uint32 InvalidSamplerInd = (1 << SamplerIndBits)-1;
+ using ResourceType = SPIRVShaderResourceAttribs::ResourceType;
+
/* 0 */ const Uint16 Binding;
-/* 2 */ const Uint16 DescriptorSet;
+/* 2 */ const Uint16 ArraySize;
/* 4.0 */ const Uint32 CacheOffset : CacheOffsetBits; // Offset from the beginning of the cached descriptor set
/* 6.5 */ const Uint32 SamplerInd : SamplerIndBits; // When using combined texture samplers, index of the separate sampler
// assigned to separate image
/* 7.5 */ const Uint32 VariableType : VariableTypeBits;
/* 7.7 */ const Uint32 ImmutableSamplerAssigned : ImmutableSamplerFlagBits;
+/* 8 */ const Uint8 DescriptorSet;
+
+/* 9 */ const ResourceType Type;
+/* 10.0*/ const Uint8 ResourceDim : 7;
+/* 10.7*/ const Uint8 IsMS : 1;
+/* 16 */ const char* const Name;
+/* 24 */ const ShaderResourceLayoutVk& ParentResLayout;
+ // clang-format on
-/* 8 */ const SPIRVShaderResourceAttribs& SpirvAttribs;
-/* 16 */ const ShaderResourceLayoutVk& ParentResLayout;
-
- VkResource(const ShaderResourceLayoutVk& _ParentLayout,
- const SPIRVShaderResourceAttribs& _SpirvAttribs,
- SHADER_RESOURCE_VARIABLE_TYPE _VariableType,
- uint32_t _Binding,
- uint32_t _DescriptorSet,
- Uint32 _CacheOffset,
- Uint32 _SamplerInd,
- bool _ImmutableSamplerAssigned = false)noexcept :
+ VkResource(const ShaderResourceLayoutVk& _ParentLayout,
+ const char* _Name,
+ Uint16 _ArraySize,
+ ResourceType _Type,
+ Uint8 _ResourceDim,
+ Uint8 _IsMS,
+ SHADER_RESOURCE_VARIABLE_TYPE _VariableType,
+ uint32_t _Binding,
+ uint32_t _DescriptorSet,
+ Uint32 _CacheOffset,
+ Uint32 _SamplerInd,
+ bool _ImmutableSamplerAssigned = false) noexcept :
+ // clang-format off
Binding {static_cast<decltype(Binding)>(_Binding) },
DescriptorSet {static_cast<decltype(DescriptorSet)>(_DescriptorSet)},
CacheOffset {_CacheOffset },
SamplerInd {_SamplerInd },
VariableType {_VariableType },
ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U},
- SpirvAttribs {_SpirvAttribs },
+ Name {_Name },
+ ArraySize {_ArraySize },
+ Type {_Type },
+ ResourceDim {_ResourceDim },
+ IsMS {_IsMS },
ParentResLayout {_ParentLayout }
+ // clang-format on
{
- VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits) );
- VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits) );
- VERIFY(_Binding <= std::numeric_limits<decltype(Binding)>::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits<decltype(Binding)>::max() );
+ VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits));
+ VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits));
+ VERIFY(_Binding <= std::numeric_limits<decltype(Binding)>::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits<decltype(Binding)>::max());
VERIFY(_DescriptorSet <= std::numeric_limits<decltype(DescriptorSet)>::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits<decltype(DescriptorSet)>::max());
}
- // clang-format on
// Checks if a resource is bound in ResourceCache at the given ArrayIndex
bool IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const;
@@ -220,17 +239,18 @@ public:
void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache) const;
// Updates resource descriptor in the descriptor set
- inline void UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
- uint32_t ArrayElement,
- const VkDescriptorImageInfo* pImageInfo,
- const VkDescriptorBufferInfo* pBufferInfo,
- const VkBufferView* pTexelBufferView) const;
+ inline void UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
+ uint32_t ArrayElement,
+ const VkDescriptorImageInfo* pImageInfo,
+ const VkDescriptorBufferInfo* pBufferInfo,
+ const VkBufferView* pTexelBufferView,
+ const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo = nullptr) const;
bool IsImmutableSamplerAssigned() const
{
VERIFY(ImmutableSamplerAssigned == 0 ||
- SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
- SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler,
+ Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
+ Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler,
"Immutable sampler can only be assigned to a sampled image or separate sampler");
return ImmutableSamplerAssigned != 0;
}
@@ -240,6 +260,31 @@ public:
return static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VariableType);
}
+ String GetPrintName(Uint32 ArrayInd) const
+ {
+ VERIFY_EXPR(ArrayInd < ArraySize);
+ if (ArraySize > 1)
+ {
+ std::stringstream ss;
+ ss << Name << '[' << ArrayInd << ']';
+ return ss.str();
+ }
+ else
+ return Name;
+ }
+
+ ShaderResourceDesc GetResourceDesc() const;
+
+ RESOURCE_DIMENSION GetResourceDimension() const
+ {
+ return static_cast<RESOURCE_DIMENSION>(ResourceDim);
+ }
+
+ bool IsMultisample() const
+ {
+ return IsMS != 0;
+ }
+
private:
void CacheUniformBuffer(IDeviceObject* pBuffer,
ShaderResourceCacheVk::Resource& DstRes,
@@ -276,6 +321,11 @@ public:
VkDescriptorSet vkDescrSet,
Uint32 ArrayInd) const;
+ void CacheAccelerationStructure(IDeviceObject* pTLAS,
+ ShaderResourceCacheVk::Resource& DstRes,
+ VkDescriptorSet vkDescrSet,
+ Uint32 ArrayInd) const;
+
template <typename ObjectType, typename TPreUpdateObject>
bool UpdateCachedResource(ShaderResourceCacheVk::Resource& DstRes,
RefCntAutoPtr<ObjectType>&& pObject,
@@ -310,15 +360,10 @@ public:
const Char* GetShaderName() const
{
- return m_pResources->GetShaderName();
+ return ""; // AZ TODO
}
- SHADER_TYPE GetShaderType() const
- {
- return m_pResources->GetShaderType();
- }
-
- const SPIRVShaderResources& GetResources() const { return *m_pResources; }
+ SHADER_TYPE GetShaderType() const { return m_ShaderType; }
const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const
{
@@ -327,7 +372,7 @@ public:
return Resources[GetResourceOffset(VarType, r)];
}
- bool IsUsingSeparateSamplers() const { return !m_pResources->IsUsingCombinedSamplers(); }
+ bool IsUsingSeparateSamplers() const { return m_IsUsingSeparateSamplers; }
private:
Uint32 GetResourceOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const
@@ -358,12 +403,14 @@ private:
return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES];
}
- void AllocateMemory(const ShaderVkImpl* pShader,
- IMemoryAllocator& Allocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- bool AllocateImmutableSamplers);
+ using ResourceNameToIndex_t = std::unordered_map<HashMapStringKey, Uint32, HashMapStringKey::Hasher>;
+ void AllocateMemory(const std::vector<const ShaderVkImpl*>& Shaders,
+ IMemoryAllocator& Allocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ ResourceNameToIndex_t& UniqueNames,
+ bool AllocateImmutableSamplers);
using ImmutableSamplerPtrType = RefCntAutoPtr<ISampler>;
ImmutableSamplerPtrType& GetImmutableSampler(Uint32 n) noexcept
@@ -374,16 +421,17 @@ private:
}
// clang-format off
-/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice;
-/* 8 */ std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer;
+/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice;
+/* 8 */ std::unique_ptr<void, STDDeleterRawMem<void> > m_ResourceBuffer; // AZ TODO: use linear allocator
+/*24 */ StringPool m_StringPool;
+
+/*48 */ std::array<Uint16, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES+1> m_NumResources = {};
- // We must use shared_ptr to reference ShaderResources instance, because
- // there may be multiple objects referencing the same set of resources
-/*24 */ std::shared_ptr<const SPIRVShaderResources> m_pResources;
+/*56 */ Uint32 m_NumImmutableSamplers = 0;
+/*60 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN;
+/*64 */ bool m_IsUsingSeparateSamplers = false;
-/*40 */ std::array<Uint16, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES+1> m_NumResources = {};
-/*48 */ Uint32 m_NumImmutableSamplers = 0;
-/*56*/ // End of class
+/*72 */ // End of class
// clang-format on
};
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp
index 27689c1e..6c88bf56 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp
@@ -183,14 +183,14 @@ public:
Uint32 FirstElement,
Uint32 NumElements) override final
{
- VerifyAndCorrectSetArrayArguments(m_Resource.SpirvAttribs.Name, m_Resource.SpirvAttribs.ArraySize, FirstElement, NumElements);
+ VerifyAndCorrectSetArrayArguments(m_Resource.Name, m_Resource.ArraySize, FirstElement, NumElements);
for (Uint32 Elem = 0; Elem < NumElements; ++Elem)
m_Resource.BindResource(ppObjects[Elem], FirstElement + Elem, m_ParentManager.m_ResourceCache);
}
virtual void DILIGENT_CALL_TYPE GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final
{
- ResourceDesc = m_Resource.SpirvAttribs.GetResourceDesc();
+ ResourceDesc = m_Resource.GetResourceDesc();
}
virtual Uint32 DILIGENT_CALL_TYPE GetIndex() const override final
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp
index f5b921a6..c28be56c 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.hpp
@@ -44,7 +44,8 @@ public:
VulkanInstance& operator = ( VulkanInstance&&) = delete;
// clang-format on
- static std::shared_ptr<VulkanInstance> Create(bool EnableValidation,
+ static std::shared_ptr<VulkanInstance> Create(uint32_t ApiVersion,
+ bool EnableValidation,
uint32_t GlobalExtensionCount,
const char* const* ppGlobalExtensionNames,
VkAllocationCallbacks* pVkAllocator);
@@ -69,10 +70,12 @@ public:
VkAllocationCallbacks* GetVkAllocator()const{return m_pVkAllocator;}
VkInstance GetVkInstance() const{return m_VkInstance; }
+ uint32_t GetVkVersion() const{return m_VkVersion; }
// clang-format on
private:
- VulkanInstance(bool EnableValidation,
+ VulkanInstance(uint32_t ApiVersion,
+ bool EnableValidation,
uint32_t GlobalExtensionCount,
const char* const* ppGlobalExtensionNames,
VkAllocationCallbacks* pVkAllocator);
@@ -80,6 +83,7 @@ private:
bool m_DebugUtilsEnabled = false;
VkAllocationCallbacks* const m_pVkAllocator;
VkInstance m_VkInstance = VK_NULL_HANDLE;
+ uint32_t m_VkVersion = VK_API_VERSION_1_0;
std::vector<VkLayerProperties> m_Layers;
std::vector<VkExtensionProperties> m_Extensions;
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
index a8366551..5e60a343 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanLogicalDevice.hpp
@@ -88,8 +88,11 @@ using AccelStructWrapper = DEFINE_VULKAN_OBJECT_WRAPPER(AccelerationStru
class VulkanLogicalDevice : public std::enable_shared_from_this<VulkanLogicalDevice>
{
public:
+ using ExtensionFeatures = VulkanPhysicalDevice::ExtensionFeatures;
+
static std::shared_ptr<VulkanLogicalDevice> Create(const VulkanPhysicalDevice& PhysicalDevice,
const VkDeviceCreateInfo& DeviceCI,
+ const ExtensionFeatures& EnabledExtFeatures,
const VkAllocationCallbacks* vkAllocator);
// clang-format off
@@ -131,8 +134,9 @@ public:
RenderPassWrapper CreateRenderPass (const VkRenderPassCreateInfo& RenderPassCI,const char* DebugName = "") const;
DeviceMemoryWrapper AllocateDeviceMemory(const VkMemoryAllocateInfo & AllocInfo, const char* DebugName = "") const;
- PipelineWrapper CreateComputePipeline (const VkComputePipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const;
- PipelineWrapper CreateGraphicsPipeline(const VkGraphicsPipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const;
+ PipelineWrapper CreateComputePipeline (const VkComputePipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const;
+ PipelineWrapper CreateGraphicsPipeline (const VkGraphicsPipelineCreateInfo& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const;
+ PipelineWrapper CreateRayTracingPipeline(const VkRayTracingPipelineCreateInfoKHR& PipelineCI, VkPipelineCache cache, const char* DebugName = "") const;
ShaderModuleWrapper CreateShaderModule (const VkShaderModuleCreateInfo& ShaderModuleCI, const char* DebugName = "") const;
PipelineLayoutWrapper CreatePipelineLayout (const VkPipelineLayoutCreateInfo& LayoutCI, const char* DebugName = "") const;
@@ -216,12 +220,15 @@ public:
}
VkPipelineStageFlags GetEnabledGraphicsShaderStages() const { return m_EnabledGraphicsShaderStages; }
+ VkResult GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const;
const VkPhysicalDeviceFeatures& GetEnabledFeatures() const { return m_EnabledFeatures; }
+ const ExtensionFeatures& GetEnabledExtFeatures() const { return m_EnabledExtFeatures; }
private:
VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice,
const VkDeviceCreateInfo& DeviceCI,
+ const ExtensionFeatures& EnabledExtFeatures,
const VkAllocationCallbacks* vkAllocator);
template <typename VkObjectType,
@@ -237,6 +244,7 @@ private:
const VkAllocationCallbacks* const m_VkAllocator;
VkPipelineStageFlags m_EnabledGraphicsShaderStages = 0;
const VkPhysicalDeviceFeatures m_EnabledFeatures;
+ ExtensionFeatures m_EnabledExtFeatures = {};
};
void EnableRayTracingKHRviaNV();
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.hpp
index 7e2f8385..5e0390f5 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanObjectWrappers.hpp
@@ -87,6 +87,11 @@ public:
return m_VkObject;
}
+ const VulkanObjectType* operator&() const
+ {
+ return &m_VkObject;
+ }
+
void Release()
{
// For externally managed objects, m_pLogicalDevice is null
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
index 0adde0d6..b76648a6 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
@@ -45,6 +45,8 @@ public:
VkPhysicalDeviceShaderFloat16Int8FeaturesKHR ShaderFloat16Int8 = {};
VkPhysicalDeviceRayTracingFeaturesKHR RayTracing = {};
bool RayTracingNV = false; // indicates that KHR extension is emulated by NV extension
+ bool Spirv14 = false; // Ray tracing requires Vulkan 1.2 or SPIRV 1.4 extension
+ bool Spirv15 = false; // DXC shaders with ray tracing requires Vulkan 1.2 with SPIRV 1.5
VkPhysicalDeviceBufferDeviceAddressFeaturesKHR BufferDeviceAddress = {};
VkPhysicalDeviceDescriptorIndexingFeaturesEXT DescriptorIndexing = {};
};
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index 99050318..42f69dac 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -301,6 +301,11 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState)
m_CommandBuffer.BindComputePipeline(vkPipeline);
break;
}
+ case PIPELINE_TYPE_RAY_TRACING:
+ {
+ //m_CommandBuffer.BindRayTracingPipeline(vkPipeline);
+ break;
+ }
default:
UNEXPECTED("unknown pipeline type");
}
@@ -593,7 +598,8 @@ void DeviceContextVkImpl::DrawMesh(const DrawMeshAttribs& Attribs)
#ifdef DILIGENT_DEBUG
{
const auto& PhysicalDevice = m_pDevice->GetPhysicalDevice();
- const auto& MeshShaderFeats = PhysicalDevice.GetExtFeatures().MeshShader;
+ const auto& LogicalDevice = m_pDevice->GetLogicalDevice();
+ const auto& MeshShaderFeats = LogicalDevice.GetEnabledExtFeatures().MeshShader;
VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE);
VERIFY_EXPR(Attribs.ThreadGroupCount <= PhysicalDevice.GetExtProperties().MeshShader.maxDrawMeshTasksCount);
}
@@ -612,7 +618,7 @@ void DeviceContextVkImpl::DrawMeshIndirect(const DrawMeshIndirectAttribs& Attrib
#ifdef DILIGENT_DEBUG
{
- const auto& MeshShaderFeats = m_pDevice->GetPhysicalDevice().GetExtFeatures().MeshShader;
+ const auto& MeshShaderFeats = m_pDevice->GetLogicalDevice().GetEnabledExtFeatures().MeshShader;
VERIFY_EXPR(MeshShaderFeats.meshShader != VK_FALSE && MeshShaderFeats.taskShader != VK_FALSE);
}
#endif
diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
index d37655a5..fcb64973 100644
--- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
@@ -138,6 +138,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
try
{
auto Instance = VulkanUtilities::VulkanInstance::Create(
+ VK_API_VERSION_1_2, // AZ TODO: use 1.2 only for ray tracing, wave ops extensions
EngineCI.EnableValidation,
EngineCI.GlobalExtensionCount,
EngineCI.ppGlobalExtensionNames,
@@ -238,7 +239,11 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height
};
- const auto& DeviceExtFeatures = PhysicalDevice->GetExtFeatures();
+ const VulkanUtilities::VulkanPhysicalDevice::ExtensionFeatures& DeviceExtFeatures = PhysicalDevice->GetExtFeatures();
+ VulkanUtilities::VulkanPhysicalDevice::ExtensionFeatures EnabledExtFeats = {};
+
+ // SPIRV 1.5 is in Vulkan 1.2 core
+ EnabledExtFeats.Spirv15 = DeviceExtFeatures.Spirv15;
#define ENABLE_FEATURE(IsFeatureSupported, Feature, FeatureName) \
do \
@@ -247,33 +252,25 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
GetFeatureState(EngineCI.Features.Feature, IsFeatureSupported, FeatureName); \
} while (false)
+ ENABLE_FEATURE(DeviceExtFeatures.MeshShader.taskShader != VK_FALSE && DeviceExtFeatures.MeshShader.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are");
- auto MeshShaderFeats = DeviceExtFeatures.MeshShader;
- ENABLE_FEATURE(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are");
-
- auto ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8;
// clang-format off
- ENABLE_FEATURE(ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are");
- ENABLE_FEATURE(ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are");
+ ENABLE_FEATURE(DeviceExtFeatures.ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are");
+ ENABLE_FEATURE(DeviceExtFeatures.ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are");
// clang-format on
- auto Storage16BitFeats = DeviceExtFeatures.Storage16Bit;
// clang-format off
- ENABLE_FEATURE(Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is");
- ENABLE_FEATURE(Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is");
- ENABLE_FEATURE(Storage16BitFeats.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are");
+ ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is");
+ ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is");
+ ENABLE_FEATURE(DeviceExtFeatures.Storage16Bit.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are");
// clang-format on
- auto Storage8BitFeats = DeviceExtFeatures.Storage8Bit;
// clang-format off
- ENABLE_FEATURE(Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is");
- ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is");
+ ENABLE_FEATURE(DeviceExtFeatures.Storage8Bit.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is");
+ ENABLE_FEATURE(DeviceExtFeatures.Storage8Bit.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is");
// clang-format on
- auto RayTracingFeats = DeviceExtFeatures.RayTracing;
- auto BufferDeviceAddressFeats = DeviceExtFeatures.BufferDeviceAddress;
- auto DescriptorIndexingFeats = DeviceExtFeatures.DescriptorIndexing;
- ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is");
+ ENABLE_FEATURE((DeviceExtFeatures.RayTracing.rayTracing != VK_FALSE && DeviceExtFeatures.Spirv14) || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is");
#undef FeatureSupport
@@ -289,31 +286,33 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
// Mesh shader
if (EngineCI.Features.MeshShaders != DEVICE_FEATURE_STATE_DISABLED)
{
- VERIFY_EXPR(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE);
+ EnabledExtFeats.MeshShader = DeviceExtFeatures.MeshShader;
+ VERIFY_EXPR(EnabledExtFeats.MeshShader.taskShader != VK_FALSE && EnabledExtFeats.MeshShader.meshShader != VK_FALSE);
VERIFY(PhysicalDevice->IsExtensionSupported(VK_NV_MESH_SHADER_EXTENSION_NAME),
"VK_NV_mesh_shader extension must be supported as it has already been checked by VulkanPhysicalDevice and "
"both taskShader and meshShader features are TRUE");
DeviceExtensions.push_back(VK_NV_MESH_SHADER_EXTENSION_NAME);
- *NextExt = &MeshShaderFeats;
- NextExt = &MeshShaderFeats.pNext;
+ *NextExt = &EnabledExtFeats.MeshShader;
+ NextExt = &EnabledExtFeats.MeshShader.pNext;
}
if (EngineCI.Features.ShaderFloat16 != DEVICE_FEATURE_STATE_DISABLED ||
EngineCI.Features.ShaderInt8 != DEVICE_FEATURE_STATE_DISABLED)
{
- VERIFY_EXPR(ShaderFloat16Int8.shaderFloat16 != VK_FALSE || ShaderFloat16Int8.shaderInt8 != VK_FALSE);
+ EnabledExtFeats.ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8;
+ VERIFY_EXPR(EnabledExtFeats.ShaderFloat16Int8.shaderFloat16 != VK_FALSE || EnabledExtFeats.ShaderFloat16Int8.shaderInt8 != VK_FALSE);
VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME),
"VK_KHR_shader_float16_int8 extension must be supported as it has already been checked by VulkanPhysicalDevice "
"and at least one of shaderFloat16 or shaderInt8 features is TRUE");
DeviceExtensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
if (EngineCI.Features.ShaderFloat16 == DEVICE_FEATURE_STATE_DISABLED)
- ShaderFloat16Int8.shaderFloat16 = VK_FALSE;
+ EnabledExtFeats.ShaderFloat16Int8.shaderFloat16 = VK_FALSE;
if (EngineCI.Features.ShaderInt8 == DEVICE_FEATURE_STATE_DISABLED)
- ShaderFloat16Int8.shaderInt8 = VK_FALSE;
+ EnabledExtFeats.ShaderFloat16Int8.shaderInt8 = VK_FALSE;
- *NextExt = &ShaderFloat16Int8;
- NextExt = &ShaderFloat16Int8.pNext;
+ *NextExt = &EnabledExtFeats.ShaderFloat16Int8;
+ NextExt = &EnabledExtFeats.ShaderFloat16Int8.pNext;
}
bool StorageBufferStorageClassExtensionRequired = false;
@@ -325,9 +324,10 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
// clang-format on
{
// clang-format off
- VERIFY_EXPR(EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE);
- VERIFY_EXPR(EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE);
- VERIFY_EXPR(EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED || Storage16BitFeats.storageInputOutput16 != VK_FALSE);
+ EnabledExtFeats.Storage16Bit = DeviceExtFeatures.Storage16Bit;
+ VERIFY_EXPR(EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.storageBuffer16BitAccess != VK_FALSE);
+ VERIFY_EXPR(EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.uniformAndStorageBuffer16BitAccess != VK_FALSE);
+ VERIFY_EXPR(EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage16Bit.storageInputOutput16 != VK_FALSE);
// clang-format on
VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_16BIT_STORAGE_EXTENSION_NAME),
@@ -344,14 +344,14 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
StorageBufferStorageClassExtensionRequired = true;
if (EngineCI.Features.ResourceBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED)
- Storage16BitFeats.storageBuffer16BitAccess = VK_FALSE;
+ EnabledExtFeats.Storage16Bit.storageBuffer16BitAccess = VK_FALSE;
if (EngineCI.Features.UniformBuffer16BitAccess == DEVICE_FEATURE_STATE_DISABLED)
- Storage16BitFeats.uniformAndStorageBuffer16BitAccess = VK_FALSE;
+ EnabledExtFeats.Storage16Bit.uniformAndStorageBuffer16BitAccess = VK_FALSE;
if (EngineCI.Features.ShaderInputOutput16 == DEVICE_FEATURE_STATE_DISABLED)
- Storage16BitFeats.storageInputOutput16 = VK_FALSE;
+ EnabledExtFeats.Storage16Bit.storageInputOutput16 = VK_FALSE;
- *NextExt = &Storage16BitFeats;
- NextExt = &Storage16BitFeats.pNext;
+ *NextExt = &EnabledExtFeats.Storage16Bit;
+ NextExt = &EnabledExtFeats.Storage16Bit.pNext;
}
// clang-format off
@@ -360,8 +360,9 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
// clang-format on
{
// clang-format off
- VERIFY_EXPR(EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE);
- VERIFY_EXPR(EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE);
+ EnabledExtFeats.Storage8Bit = DeviceExtFeatures.Storage8Bit;
+ VERIFY_EXPR(EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage8Bit.storageBuffer8BitAccess != VK_FALSE);
+ VERIFY_EXPR(EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED || EnabledExtFeats.Storage8Bit.uniformAndStorageBuffer8BitAccess != VK_FALSE);
// clang-format on
VERIFY(PhysicalDevice->IsExtensionSupported(VK_KHR_8BIT_STORAGE_EXTENSION_NAME),
@@ -378,12 +379,12 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
StorageBufferStorageClassExtensionRequired = true;
if (EngineCI.Features.ResourceBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED)
- Storage8BitFeats.storageBuffer8BitAccess = VK_FALSE;
+ EnabledExtFeats.Storage8Bit.storageBuffer8BitAccess = VK_FALSE;
if (EngineCI.Features.UniformBuffer8BitAccess == DEVICE_FEATURE_STATE_DISABLED)
- Storage8BitFeats.uniformAndStorageBuffer8BitAccess = VK_FALSE;
+ EnabledExtFeats.Storage8Bit.uniformAndStorageBuffer8BitAccess = VK_FALSE;
- *NextExt = &Storage8BitFeats;
- NextExt = &Storage8BitFeats.pNext;
+ *NextExt = &EnabledExtFeats.Storage8Bit;
+ NextExt = &EnabledExtFeats.Storage8Bit.pNext;
}
if (StorageBufferStorageClassExtensionRequired)
@@ -398,29 +399,37 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
{
if (DeviceExtFeatures.RayTracingNV)
{
+ EnabledExtFeats.RayTracingNV = DeviceExtFeatures.RayTracingNV;
DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
DeviceExtensions.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME);
}
- else if (RayTracingFeats.rayTracing != VK_FALSE)
- {
- // required extensions
- DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
- DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
- DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME);
- DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME);
- DeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME);
- DeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME);
-
- *NextExt = &RayTracingFeats;
- NextExt = &RayTracingFeats.pNext;
- *NextExt = &DescriptorIndexingFeats;
- NextExt = &DescriptorIndexingFeats.pNext;
- *NextExt = &BufferDeviceAddressFeats;
- NextExt = &BufferDeviceAddressFeats.pNext;
- }
- else
+ else if (DeviceExtFeatures.RayTracing.rayTracing != VK_FALSE)
{
- UNEXPECTED("Either KHR or NV extension must be enabled");
+ DeviceExtensions.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME); // required for VK_EXT_descriptor_indexing
+ DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME); // required for VK_KHR_ray_tracing
+ DeviceExtensions.push_back(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME); // required for VK_KHR_ray_tracing
+ DeviceExtensions.push_back(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME); // required for VK_KHR_ray_tracing
+ DeviceExtensions.push_back(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME); // required for VK_KHR_ray_tracing
+ DeviceExtensions.push_back(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME); // required for VK_KHR_ray_tracing
+ DeviceExtensions.push_back(VK_KHR_RAY_TRACING_EXTENSION_NAME); // required for VK_KHR_ray_tracing
+
+ EnabledExtFeats.RayTracing = DeviceExtFeatures.RayTracing;
+ EnabledExtFeats.BufferDeviceAddress = DeviceExtFeatures.BufferDeviceAddress;
+ EnabledExtFeats.DescriptorIndexing = DeviceExtFeatures.DescriptorIndexing;
+
+ if (!DeviceExtFeatures.Spirv15)
+ {
+ DeviceExtensions.push_back(VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME); // required for VK_KHR_spirv_1_4
+ DeviceExtensions.push_back(VK_KHR_SPIRV_1_4_EXTENSION_NAME); // required for ray tracing shaders
+ EnabledExtFeats.Spirv14 = DeviceExtFeatures.Spirv14;
+ }
+
+ *NextExt = &EnabledExtFeats.RayTracing;
+ NextExt = &EnabledExtFeats.RayTracing.pNext;
+ *NextExt = &EnabledExtFeats.DescriptorIndexing;
+ NextExt = &EnabledExtFeats.DescriptorIndexing.pNext;
+ *NextExt = &EnabledExtFeats.BufferDeviceAddress;
+ NextExt = &EnabledExtFeats.BufferDeviceAddress.pNext;
}
}
@@ -436,7 +445,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
DeviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());
auto vkAllocator = Instance->GetVkAllocator();
- auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(*PhysicalDevice, DeviceCreateInfo, vkAllocator);
+ auto LogicalDevice = VulkanUtilities::VulkanLogicalDevice::Create(*PhysicalDevice, DeviceCreateInfo, EnabledExtFeats, vkAllocator);
auto& RawMemAllocator = GetRawAllocator();
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
index b221659a..d0e37670 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
@@ -45,18 +45,19 @@ class ResourceTypeToVkDescriptorType
public:
ResourceTypeToVkDescriptorType()
{
- static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please add the corresponding decriptor type");
- m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageImage] = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::SampledImage] = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::AtomicCounter] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateImage] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateSampler] = VK_DESCRIPTOR_TYPE_SAMPLER;
- m_Map[SPIRVShaderResourceAttribs::ResourceType::InputAttachment] = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please add the corresponding decriptor type");
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer] = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer] = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::StorageImage] = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::SampledImage] = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::AtomicCounter] = VK_DESCRIPTOR_TYPE_MAX_ENUM; // atomic counter doesn't exist in Vulkan
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateImage] = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::SeparateSampler] = VK_DESCRIPTOR_TYPE_SAMPLER;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::InputAttachment] = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
+ m_Map[SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure] = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
}
VkDescriptorType operator[](SPIRVShaderResourceAttribs::ResourceType ResType) const
@@ -68,10 +69,10 @@ private:
std::array<VkDescriptorType, SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes> m_Map = {};
};
-VkDescriptorType PipelineLayout::GetVkDescriptorType(const SPIRVShaderResourceAttribs& Res)
+VkDescriptorType PipelineLayout::GetVkDescriptorType(SPIRVShaderResourceAttribs::ResourceType Type)
{
static const ResourceTypeToVkDescriptorType ResTypeToVkDescrType;
- return ResTypeToVkDescrType[Res.Type];
+ return ResTypeToVkDescrType[Type];
}
PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayoutManager(IMemoryAllocator& MemAllocator) :
@@ -331,7 +332,7 @@ void PipelineLayout::DescriptorSetLayoutManager::AllocateResourceSlot(const SPIR
Binding = DescrSet.NumLayoutBindings;
VkBinding.binding = Binding;
- VkBinding.descriptorType = GetVkDescriptorType(ResAttribs);
+ VkBinding.descriptorType = GetVkDescriptorType(ResAttribs.Type);
VkBinding.descriptorCount = ResAttribs.ArraySize;
// There are no limitations on what combinations of stages can use a descriptor binding (13.2.1)
VkBinding.stageFlags = ShaderTypeToVkShaderStageFlagBit(ShaderType);
@@ -369,16 +370,13 @@ void PipelineLayout::AllocateResourceSlot(const SPIRVShaderResourceAttribs& ResA
SHADER_TYPE ShaderType,
Uint32& DescriptorSet, // Output parameter
Uint32& Binding, // Output parameter
- Uint32& OffsetInCache,
- std::vector<uint32_t>& SPIRV)
+ Uint32& OffsetInCache)
{
VERIFY((ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
ResAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) ||
vkImmutableSampler == VK_NULL_HANDLE,
"Immutable sampler should only be specified for combined image samplers or separate samplers");
m_LayoutMgr.AllocateResourceSlot(ResAttribs, VariableType, vkImmutableSampler, ShaderType, DescriptorSet, Binding, OffsetInCache);
- SPIRV[ResAttribs.BindingDecorationOffset] = Binding;
- SPIRV[ResAttribs.DescriptorSetDecorationOffset] = DescriptorSet;
}
void PipelineLayout::Finalize(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice)
@@ -435,7 +433,6 @@ void PipelineLayout::InitResourceCache(RenderDeviceVkImpl* pDeviceVkImpl,
}
void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkImpl,
- bool IsCompute,
const ShaderResourceCacheVk& ResourceCache,
DescriptorSetBindInfo& BindInfo,
VkDescriptorSet VkDynamicDescrSet) const
@@ -481,7 +478,6 @@ void PipelineLayout::PrepareDescriptorSets(DeviceContextVkImpl* pCtxVkIm
BindInfo.DynamicOffsetCount = TotalDynamicDescriptors;
if (TotalDynamicDescriptors > BindInfo.DynamicOffsets.size())
BindInfo.DynamicOffsets.resize(TotalDynamicDescriptors);
- BindInfo.BindPoint = IsCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
BindInfo.pResourceCache = &ResourceCache;
#ifdef DILIGENT_DEBUG
BindInfo.pDbgPipelineLayout = this;
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 83512870..c7b9e05f 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -44,98 +44,24 @@
namespace Diligent
{
-
-RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc(
- Uint32 NumRenderTargets,
- const TEXTURE_FORMAT RTVFormats[],
- TEXTURE_FORMAT DSVFormat,
- Uint8 SampleCount,
- std::array<RenderPassAttachmentDesc, MAX_RENDER_TARGETS + 1>& Attachments,
- std::array<AttachmentReference, MAX_RENDER_TARGETS + 1>& AttachmentReferences,
- SubpassDesc& SubpassDesc)
+namespace
{
- VERIFY_EXPR(NumRenderTargets <= MAX_RENDER_TARGETS);
-
- RenderPassDesc RPDesc;
-
- RPDesc.AttachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets;
- uint32_t AttachmentInd = 0;
- AttachmentReference* pDepthAttachmentReference = nullptr;
- if (DSVFormat != TEX_FORMAT_UNKNOWN)
- {
- auto& DepthAttachment = Attachments[AttachmentInd];
-
- DepthAttachment.Format = DSVFormat;
- DepthAttachment.SampleCount = SampleCount;
- DepthAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area
- // will be preserved. For attachments with a depth/stencil format,
- // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT.
- DepthAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render
- // area are written to memory. For attachments with a depth/stencil format,
- // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT.
- DepthAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_LOAD;
- DepthAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_STORE;
- DepthAttachment.InitialState = RESOURCE_STATE_DEPTH_WRITE;
- DepthAttachment.FinalState = RESOURCE_STATE_DEPTH_WRITE;
-
- pDepthAttachmentReference = &AttachmentReferences[AttachmentInd];
- pDepthAttachmentReference->AttachmentIndex = AttachmentInd;
- pDepthAttachmentReference->State = RESOURCE_STATE_DEPTH_WRITE;
-
- ++AttachmentInd;
- }
-
- AttachmentReference* pColorAttachmentsReference = NumRenderTargets > 0 ? &AttachmentReferences[AttachmentInd] : nullptr;
- for (Uint32 rt = 0; rt < NumRenderTargets; ++rt, ++AttachmentInd)
- {
- auto& ColorAttachment = Attachments[AttachmentInd];
-
- ColorAttachment.Format = RTVFormats[rt];
- ColorAttachment.SampleCount = SampleCount;
- ColorAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area
- // will be preserved. For attachments with a depth/stencil format,
- // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_READ_BIT.
- ColorAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render
- // area are written to memory. For attachments with a color format,
- // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT.
- ColorAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_DISCARD;
- ColorAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_DISCARD;
- ColorAttachment.InitialState = RESOURCE_STATE_RENDER_TARGET;
- ColorAttachment.FinalState = RESOURCE_STATE_RENDER_TARGET;
-
- auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd];
- ColorAttachmentRef.AttachmentIndex = AttachmentInd;
- ColorAttachmentRef.State = RESOURCE_STATE_RENDER_TARGET;
- }
-
- RPDesc.pAttachments = Attachments.data();
- RPDesc.SubpassCount = 1;
- RPDesc.pSubpasses = &SubpassDesc;
- RPDesc.DependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies.
- RPDesc.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing
- // dependencies between pairs of subpasses, or NULL if dependencyCount is zero.
-
-
- SubpassDesc.InputAttachmentCount = 0;
- SubpassDesc.pInputAttachments = nullptr;
- SubpassDesc.RenderTargetAttachmentCount = NumRenderTargets;
- SubpassDesc.pRenderTargetAttachments = pColorAttachmentsReference;
- SubpassDesc.pResolveAttachments = nullptr;
- SubpassDesc.pDepthStencilAttachment = pDepthAttachmentReference;
- SubpassDesc.PreserveAttachmentCount = 0;
- SubpassDesc.pPreserveAttachments = nullptr;
-
- return RPDesc;
-}
-
-static bool StripReflection(std::vector<uint32_t>& SPIRV)
+bool StripReflection(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, std::vector<uint32_t>& SPIRV)
{
#if DILIGENT_NO_HLSL
- return false;
+ return true;
#else
std::vector<uint32_t> StrippedSPIRV;
- spvtools::Optimizer SpirvOptimizer(SPV_ENV_VULKAN_1_0);
+ spv_target_env Target = SPV_ENV_VULKAN_1_0;
+ const auto& ExtFeats = LogicalDevice.GetEnabledExtFeatures();
+
+ if (ExtFeats.Spirv15)
+ Target = SPV_ENV_VULKAN_1_2;
+ else if (ExtFeats.Spirv14)
+ Target = SPV_ENV_VULKAN_1_1_SPIRV_1_4;
+
+ spvtools::Optimizer SpirvOptimizer(Target);
// Decorations defined in SPV_GOOGLE_hlsl_functionality1 are the only instructions
// removed by strip-reflect-info pass. SPIRV offsets become INVALID after this operation.
SpirvOptimizer.RegisterPass(spvtools::CreateStripReflectInfoPass());
@@ -149,21 +75,25 @@ static bool StripReflection(std::vector<uint32_t>& SPIRV)
#endif
}
-static void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
- ShaderResourceLayoutVk::TShaderStages& ShaderStages,
- std::vector<VulkanUtilities::ShaderModuleWrapper>& vkShaderModules,
- std::vector<VkPipelineShaderStageCreateInfo>& vkPipelineShaderStages)
+void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
+ ShaderResourceLayoutVk::TShaderStages& ShaderStages,
+ std::vector<VulkanUtilities::ShaderModuleWrapper>& ShaderModules,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages)
{
for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- auto& StageInfo = ShaderStages[s];
+ const auto& Shaders = ShaderStages[s].Shaders;
+ auto& SPIRVs = ShaderStages[s].SPIRVs;
+ const auto ShaderType = ShaderStages[s].Type;
+
+ VERIFY_EXPR(Shaders.size() == SPIRVs.size());
VkPipelineShaderStageCreateInfo StageCI = {};
StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
StageCI.pNext = nullptr;
StageCI.flags = 0; // reserved for future use
- StageCI.stage = ShaderTypeToVkShaderStageFlagBit(StageInfo.Type);
+ StageCI.stage = ShaderTypeToVkShaderStageFlagBit(ShaderType);
VkShaderModuleCreateInfo ShaderModuleCI = {};
@@ -171,33 +101,39 @@ static void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice&
ShaderModuleCI.pNext = nullptr;
ShaderModuleCI.flags = 0;
- // We have to strip reflection instructions to fix the follownig validation error:
- // SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string
- // Optimizer also performs validation and may catch problems with the byte code.
- if (!StripReflection(StageInfo.SPIRV))
- LOG_ERROR("Failed to strip reflection information from shader '", StageInfo.pShader->GetDesc().Name, "'. This may indicate a problem with the byte code.");
+ for (size_t i = 0; i < Shaders.size(); ++i)
+ {
+ auto* pShader = Shaders[i];
+ auto& SPIRV = SPIRVs[i];
+
+ // We have to strip reflection instructions to fix the follownig validation error:
+ // SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string
+ // Optimizer also performs validation and may catch problems with the byte code.
+ if (!StripReflection(LogicalDevice, SPIRV))
+ LOG_ERROR("Failed to strip reflection information from shader '", pShader->GetDesc().Name, "'. This may indicate a problem with the byte code.");
- ShaderModuleCI.codeSize = StageInfo.SPIRV.size() * sizeof(uint32_t);
- ShaderModuleCI.pCode = StageInfo.SPIRV.data();
+ ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t);
+ ShaderModuleCI.pCode = SPIRV.data();
- vkShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, StageInfo.pShader->GetDesc().Name));
+ ShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, pShader->GetDesc().Name));
- StageCI.module = vkShaderModules.back();
- StageCI.pName = StageInfo.pShader->GetEntryPoint();
- StageCI.pSpecializationInfo = nullptr;
+ StageCI.module = ShaderModules.back();
+ StageCI.pName = pShader->GetEntryPoint();
+ StageCI.pSpecializationInfo = nullptr;
- vkPipelineShaderStages.push_back(StageCI);
+ Stages.push_back(StageCI);
+ }
}
- VERIFY_EXPR(vkShaderModules.size() == vkPipelineShaderStages.size());
+ VERIFY_EXPR(ShaderModules.size() == Stages.size());
}
-static void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk,
- std::vector<VkPipelineShaderStageCreateInfo>& Stages,
- const PipelineLayout& Layout,
- const PipelineStateDesc& PSODesc,
- VulkanUtilities::PipelineWrapper& Pipeline)
+void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages,
+ const PipelineLayout& Layout,
+ const PipelineStateDesc& PSODesc,
+ VulkanUtilities::PipelineWrapper& Pipeline)
{
const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
@@ -218,13 +154,13 @@ static void CreateComputePipeline(RenderDeviceVkImpl*
}
-static void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk,
- std::vector<VkPipelineShaderStageCreateInfo>& Stages,
- const PipelineLayout& Layout,
- const PipelineStateDesc& PSODesc,
- const GraphicsPipelineDesc& GraphicsPipeline,
- VulkanUtilities::PipelineWrapper& Pipeline,
- RefCntAutoPtr<IRenderPass>& pRenderPass)
+void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages,
+ const PipelineLayout& Layout,
+ const PipelineStateDesc& PSODesc,
+ const GraphicsPipelineDesc& GraphicsPipeline,
+ VulkanUtilities::PipelineWrapper& Pipeline,
+ RefCntAutoPtr<IRenderPass>& pRenderPass)
{
const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
@@ -401,6 +337,240 @@ static void CreateGraphicsPipeline(RenderDeviceVkImpl*
Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name);
}
+
+void CreateRayTracingPipeline(RenderDeviceVkImpl* pDeviceVk,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages,
+ const std::vector<VkRayTracingShaderGroupCreateInfoKHR>& ShaderGroups,
+ const PipelineLayout& Layout,
+ const PipelineStateDesc& PSODesc,
+ const RayTracingPipelineDesc& RayTracingPipeline,
+ VulkanUtilities::PipelineWrapper& Pipeline)
+{
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+ const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
+ const auto& RTLimits = PhysicalDevice.GetExtProperties().RayTracing;
+
+ DEV_CHECK_ERR(RayTracingPipeline.MaxRecursionDepth <= RTLimits.maxRecursionDepth,
+ "RayTracingPipeline.MaxRecursionDepth must not exceed ", RTLimits.maxRecursionDepth);
+
+ VkRayTracingPipelineCreateInfoKHR PipelineCI = {};
+
+ PipelineCI.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR;
+ PipelineCI.pNext = nullptr;
+#ifdef DILIGENT_DEBUG
+ PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
+#endif
+
+ PipelineCI.stageCount = static_cast<Uint32>(Stages.size());
+ PipelineCI.pStages = Stages.data();
+ PipelineCI.layout = Layout.GetVkPipelineLayout();
+
+ PipelineCI.groupCount = static_cast<Uint32>(ShaderGroups.size());
+ PipelineCI.pGroups = ShaderGroups.data();
+ PipelineCI.maxRecursionDepth = RayTracingPipeline.MaxRecursionDepth;
+ PipelineCI.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR;
+ PipelineCI.libraries.pNext = nullptr;
+ PipelineCI.libraries.libraryCount = 0;
+ PipelineCI.libraries.pLibraries = nullptr;
+ PipelineCI.pLibraryInterface = nullptr;
+ PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
+ PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from
+
+ Pipeline = LogicalDevice.CreateRayTracingPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name);
+}
+
+
+template <typename TNameToGroupIndexMap>
+void BuildRTPipelineDescription(const RayTracingPipelineStateCreateInfo& CreateInfo,
+ TNameToGroupIndexMap& NameToGroupIndex,
+ std::vector<VkRayTracingShaderGroupCreateInfoKHR>& ShaderGroups,
+ const ShaderResourceLayoutVk::TShaderStages& ShaderStages,
+ LinearAllocator& MemPool)
+{
+#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ray tracing PSO '", CreateInfo.PSODesc.Name, "' is invalid: ", ##__VA_ARGS__)
+ ShaderGroups.reserve(CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount);
+
+ Uint32 GroupIndex = 0;
+ Uint32 ShaderIndex = 0;
+
+ std::unordered_map<const IShader*, Uint32> UniqueShaders;
+
+ const auto ShaderToIndex = [&ShaderIndex, &UniqueShaders](const IShader* pShader) -> Uint32 {
+ if (pShader != nullptr)
+ {
+ auto Result = UniqueShaders.emplace(pShader, ShaderIndex);
+ if (Result.second)
+ {
+ ++ShaderIndex;
+ }
+ return Result.first->second;
+ }
+ return VK_SHADER_UNUSED_KHR;
+ };
+
+ for (Uint32 i = 0; i < CreateInfo.GeneralShaderCount; ++i)
+ {
+ VkRayTracingShaderGroupCreateInfoKHR Group = {};
+
+ Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
+ Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR;
+ Group.generalShader = ShaderToIndex(CreateInfo.pGeneralShaders[i].pShader);
+ Group.closestHitShader = VK_SHADER_UNUSED_KHR;
+ Group.anyHitShader = VK_SHADER_UNUSED_KHR;
+ Group.intersectionShader = VK_SHADER_UNUSED_KHR;
+
+ bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pGeneralShaders[i].Name)}, GroupIndex++).second;
+ if (!IsUniqueName)
+ LOG_PSO_ERROR_AND_THROW("pGeneralShaders[", i, "].Name must be unique");
+
+ ShaderGroups.push_back(Group);
+ }
+
+ for (Uint32 i = 0; i < CreateInfo.TriangleHitShaderCount; ++i)
+ {
+ VkRayTracingShaderGroupCreateInfoKHR Group = {};
+
+ Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
+ Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR;
+ Group.generalShader = VK_SHADER_UNUSED_KHR;
+ Group.closestHitShader = ShaderToIndex(CreateInfo.pTriangleHitShaders[i].pClosestHitShader);
+ Group.anyHitShader = ShaderToIndex(CreateInfo.pTriangleHitShaders[i].pAnyHitShader);
+ Group.intersectionShader = VK_SHADER_UNUSED_KHR;
+
+ bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pTriangleHitShaders[i].Name)}, GroupIndex++).second;
+ if (!IsUniqueName)
+ LOG_PSO_ERROR_AND_THROW("pTriangleHitShaders[", i, "].Name must be unique");
+
+ ShaderGroups.push_back(Group);
+ }
+
+ for (Uint32 i = 0; i < CreateInfo.ProceduralHitShaderCount; ++i)
+ {
+ VkRayTracingShaderGroupCreateInfoKHR Group = {};
+
+ Group.sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR;
+ Group.type = VK_RAY_TRACING_SHADER_GROUP_TYPE_PROCEDURAL_HIT_GROUP_KHR;
+ Group.generalShader = VK_SHADER_UNUSED_KHR;
+ Group.intersectionShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pIntersectionShader);
+ Group.closestHitShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pClosestHitShader);
+ Group.anyHitShader = ShaderToIndex(CreateInfo.pProceduralHitShaders[i].pAnyHitShader);
+
+ bool IsUniqueName = NameToGroupIndex.emplace(HashMapStringKey{MemPool.CopyString(CreateInfo.pProceduralHitShaders[i].Name)}, GroupIndex++).second;
+ if (!IsUniqueName)
+ LOG_PSO_ERROR_AND_THROW("pProceduralHitShaders[", i, "].Name must be unique");
+
+ ShaderGroups.push_back(Group);
+ }
+
+ VERIFY_EXPR(Uint32(CreateInfo.GeneralShaderCount + CreateInfo.TriangleHitShaderCount + CreateInfo.ProceduralHitShaderCount) == GroupIndex);
+
+#ifdef DILIGENT_DEVELOPMENT
+ Uint32 ShaderIndex2 = 0;
+ for (auto& Stage : ShaderStages)
+ {
+ for (auto* pShader : Stage.Shaders)
+ {
+ auto iter = UniqueShaders.find(static_cast<const IShader*>(pShader));
+ if (iter != UniqueShaders.end())
+ VERIFY_EXPR(iter->second == ShaderIndex2);
+ else
+ UNEXPECTED("shader is not used in ray tracing shader groups");
+
+ ++ShaderIndex2;
+ }
+ }
+ VERIFY_EXPR(ShaderIndex == ShaderIndex2);
+#endif
+#undef LOG_PSO_ERROR_AND_THROW
+}
+
+} // namespace
+
+
+RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc(
+ Uint32 NumRenderTargets,
+ const TEXTURE_FORMAT RTVFormats[],
+ TEXTURE_FORMAT DSVFormat,
+ Uint8 SampleCount,
+ std::array<RenderPassAttachmentDesc, MAX_RENDER_TARGETS + 1>& Attachments,
+ std::array<AttachmentReference, MAX_RENDER_TARGETS + 1>& AttachmentReferences,
+ SubpassDesc& SubpassDesc)
+{
+ VERIFY_EXPR(NumRenderTargets <= MAX_RENDER_TARGETS);
+
+ RenderPassDesc RPDesc;
+
+ RPDesc.AttachmentCount = (DSVFormat != TEX_FORMAT_UNKNOWN ? 1 : 0) + NumRenderTargets;
+
+ uint32_t AttachmentInd = 0;
+ AttachmentReference* pDepthAttachmentReference = nullptr;
+ if (DSVFormat != TEX_FORMAT_UNKNOWN)
+ {
+ auto& DepthAttachment = Attachments[AttachmentInd];
+
+ DepthAttachment.Format = DSVFormat;
+ DepthAttachment.SampleCount = SampleCount;
+ DepthAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area
+ // will be preserved. For attachments with a depth/stencil format,
+ // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT.
+ DepthAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render
+ // area are written to memory. For attachments with a depth/stencil format,
+ // this uses the access type VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT.
+ DepthAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_LOAD;
+ DepthAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_STORE;
+ DepthAttachment.InitialState = RESOURCE_STATE_DEPTH_WRITE;
+ DepthAttachment.FinalState = RESOURCE_STATE_DEPTH_WRITE;
+
+ pDepthAttachmentReference = &AttachmentReferences[AttachmentInd];
+ pDepthAttachmentReference->AttachmentIndex = AttachmentInd;
+ pDepthAttachmentReference->State = RESOURCE_STATE_DEPTH_WRITE;
+
+ ++AttachmentInd;
+ }
+
+ AttachmentReference* pColorAttachmentsReference = NumRenderTargets > 0 ? &AttachmentReferences[AttachmentInd] : nullptr;
+ for (Uint32 rt = 0; rt < NumRenderTargets; ++rt, ++AttachmentInd)
+ {
+ auto& ColorAttachment = Attachments[AttachmentInd];
+
+ ColorAttachment.Format = RTVFormats[rt];
+ ColorAttachment.SampleCount = SampleCount;
+ ColorAttachment.LoadOp = ATTACHMENT_LOAD_OP_LOAD; // previous contents of the image within the render area
+ // will be preserved. For attachments with a depth/stencil format,
+ // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_READ_BIT.
+ ColorAttachment.StoreOp = ATTACHMENT_STORE_OP_STORE; // the contents generated during the render pass and within the render
+ // area are written to memory. For attachments with a color format,
+ // this uses the access type VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT.
+ ColorAttachment.StencilLoadOp = ATTACHMENT_LOAD_OP_DISCARD;
+ ColorAttachment.StencilStoreOp = ATTACHMENT_STORE_OP_DISCARD;
+ ColorAttachment.InitialState = RESOURCE_STATE_RENDER_TARGET;
+ ColorAttachment.FinalState = RESOURCE_STATE_RENDER_TARGET;
+
+ auto& ColorAttachmentRef = AttachmentReferences[AttachmentInd];
+ ColorAttachmentRef.AttachmentIndex = AttachmentInd;
+ ColorAttachmentRef.State = RESOURCE_STATE_RENDER_TARGET;
+ }
+
+ RPDesc.pAttachments = Attachments.data();
+ RPDesc.SubpassCount = 1;
+ RPDesc.pSubpasses = &SubpassDesc;
+ RPDesc.DependencyCount = 0; // the number of dependencies between pairs of subpasses, or zero indicating no dependencies.
+ RPDesc.pDependencies = nullptr; // an array of dependencyCount number of VkSubpassDependency structures describing
+ // dependencies between pairs of subpasses, or NULL if dependencyCount is zero.
+
+
+ SubpassDesc.InputAttachmentCount = 0;
+ SubpassDesc.pInputAttachments = nullptr;
+ SubpassDesc.RenderTargetAttachmentCount = NumRenderTargets;
+ SubpassDesc.pRenderTargetAttachments = pColorAttachmentsReference;
+ SubpassDesc.pResolveAttachments = nullptr;
+ SubpassDesc.pDepthStencilAttachment = pDepthAttachmentReference;
+ SubpassDesc.PreserveAttachmentCount = 0;
+ SubpassDesc.pPreserveAttachments = nullptr;
+
+ return RPDesc;
+}
+
void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
TShaderStages& ShaderStages)
{
@@ -416,7 +586,7 @@ void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre
m_ResourceLayoutIndex[ShaderTypeInd] = static_cast<Int8>(s);
auto& StaticResLayout = m_ShaderResourceLayouts[GetNumShaderStages() + s];
- StaticResLayout.InitializeStaticResourceLayout(StageInfo.pShader, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]);
+ StaticResLayout.InitializeStaticResourceLayout(StageInfo.Shaders, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]);
m_StaticVarsMgrs[s].Initialize(StaticResLayout, GetRawAllocator(), nullptr, 0);
}
@@ -509,6 +679,7 @@ void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType&
InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages);
}
+
PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters,
RenderDeviceVkImpl* pDeviceVk,
const GraphicsPipelineStateCreateInfo& CreateInfo) :
@@ -554,6 +725,75 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* p
}
}
+PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDeviceVk,
+ const RayTracingPipelineStateCreateInfo& CreateInfo) :
+ TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc},
+ m_SRBMemAllocator{GetRawAllocator()}
+{
+ try
+ {
+ m_ResourceLayoutIndex.fill(-1);
+
+ TShaderStages ShaderStages;
+ ExtractShaders<ShaderVkImpl>(CreateInfo, ShaderStages);
+
+ const auto ShaderGroupHandleSize = pDeviceVk->GetPhysicalDevice().GetExtProperties().RayTracing.shaderGroupHandleSize;
+ TNameToGroupIndexMap NameToGroupIndex;
+ LinearAllocator MemPool{GetRawAllocator()};
+
+ const auto NumShaderStages = GetNumShaderStages();
+ VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size());
+
+ MemPool.AddSpace<ShaderResourceCacheVk>(NumShaderStages);
+ MemPool.AddSpace<ShaderResourceLayoutVk>(NumShaderStages * 2);
+ MemPool.AddSpace<ShaderVariableManagerVk>(NumShaderStages);
+
+ ReserveSpaceForPipelineDesc(CreateInfo, ShaderGroupHandleSize, MemPool);
+
+ MemPool.Reserve();
+
+ const auto& LogicalDevice = GetDevice()->GetLogicalDevice();
+
+ m_StaticResCaches = MemPool.ConstructArray<ShaderResourceCacheVk>(NumShaderStages, ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources);
+
+ // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct().
+ auto* Ptr = MemPool.ReleaseOwnership();
+ VERIFY_EXPR(Ptr == m_StaticResCaches);
+ (void)Ptr;
+
+ m_ShaderResourceLayouts = MemPool.ConstructArray<ShaderResourceLayoutVk>(NumShaderStages * 2, LogicalDevice);
+
+ m_StaticVarsMgrs = MemPool.Allocate<ShaderVariableManagerVk>(NumShaderStages);
+ for (Uint32 s = 0; s < NumShaderStages; ++s)
+ new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]};
+
+ std::vector<VkRayTracingShaderGroupCreateInfoKHR> ShaderGroups;
+ BuildRTPipelineDescription(CreateInfo, NameToGroupIndex, ShaderGroups, ShaderStages, MemPool);
+ InitializePipelineDesc(CreateInfo, ShaderGroupHandleSize, std::move(NameToGroupIndex), MemPool);
+
+ // It is important to construct all objects before initializing them because if an exception is thrown,
+ // destructors will be called for all objects
+
+ InitResourceLayouts(CreateInfo, ShaderStages);
+
+ // Create shader modules and initialize shader stages
+ std::vector<VkPipelineShaderStageCreateInfo> vkShaderStages;
+ std::vector<VulkanUtilities::ShaderModuleWrapper> ShaderModules;
+ InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages);
+
+ CreateRayTracingPipeline(pDeviceVk, vkShaderStages, ShaderGroups, m_PipelineLayout, m_Desc, GetRayTracingPipelineDesc(), m_Pipeline);
+
+ auto err = LogicalDevice.GetRayTracingShaderGroupHandles(m_Pipeline, 0, static_cast<uint32_t>(ShaderGroups.size()), ShaderGroupHandleSize, &m_pRayTracingPipelineData->Shaders[0]);
+ VERIFY(err == VK_SUCCESS, "Failed to get shader group handles");
+ (void)err;
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
+ }
+}
PipelineStateVkImpl::~PipelineStateVkImpl()
{
@@ -562,6 +802,8 @@ PipelineStateVkImpl::~PipelineStateVkImpl()
void PipelineStateVkImpl::Destruct()
{
+ TPipelineStateBase::Destruct();
+
m_pDevice->SafeReleaseDeviceObject(std::move(m_Pipeline), m_Desc.CommandQueueMask);
m_PipelineLayout.Release(m_pDevice, m_Desc.CommandQueueMask);
@@ -617,8 +859,7 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const
return false;
auto IsSamePipelineLayout = m_PipelineLayout.IsSameAs(pPSOVk->m_PipelineLayout);
-
-#ifdef DILIGENT_DEBUG
+#if 0 //def DILIGENT_DEBUG // AZ TODO
{
bool IsCompatibleShaders = true;
if (GetNumShaderStages() != pPSOVk->GetNumShaderStages())
@@ -736,9 +977,21 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
Layout.CommitDynamicResources(ResourceCache, DynamicDescrSet);
}
}
- // Prepare descriptor sets, and also bind them if there are no dynamic descriptors
+
VERIFY_EXPR(pDescrSetBindInfo != nullptr);
- m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, m_Desc.IsComputePipeline(), ResourceCache, *pDescrSetBindInfo, DynamicDescrSet);
+ switch (m_Desc.PipelineType)
+ {
+ // clang-format off
+ case PIPELINE_TYPE_GRAPHICS:
+ case PIPELINE_TYPE_MESH: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; break;
+ case PIPELINE_TYPE_COMPUTE: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_COMPUTE; break;
+ case PIPELINE_TYPE_RAY_TRACING: pDescrSetBindInfo->BindPoint = VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR; break;
+ default: UNEXPECTED("unknown pipeline type");
+ // clang-format on
+ }
+
+ // Prepare descriptor sets, and also bind them if there are no dynamic descriptors
+ m_PipelineLayout.PrepareDescriptorSets(pCtxVkImpl, ResourceCache, *pDescrSetBindInfo, DynamicDescrSet);
// Dynamic descriptor sets are not released individually. Instead, all dynamic descriptor pools
// are released at the end of the frame by DeviceContextVkImpl::FinishFrame().
}
@@ -783,7 +1036,7 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY
if (LayoutInd < 0)
return nullptr;
- const auto& StaticVarMgr = GetStaticVarMgr(LayoutInd);
+ auto& StaticVarMgr = GetStaticVarMgr(LayoutInd);
return StaticVarMgr.GetVariable(Index);
}
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index cdcac036..3199a014 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -96,17 +96,18 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
"Main descriptor pool",
std::vector<VkDescriptorPoolSize>
{
- {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumSeparateSamplerDescriptors},
- {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumCombinedSamplerDescriptors},
- {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.MainDescriptorPoolSize.NumSampledImageDescriptors},
- {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.MainDescriptorPoolSize.NumStorageImageDescriptors},
- {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformTexelBufferDescriptors},
- {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageTexelBufferDescriptors},
- //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors},
- //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors},
- {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors},
- {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors},
- {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors},
+ {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumSeparateSamplerDescriptors},
+ {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.MainDescriptorPoolSize.NumCombinedSamplerDescriptors},
+ {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.MainDescriptorPoolSize.NumSampledImageDescriptors},
+ {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.MainDescriptorPoolSize.NumStorageImageDescriptors},
+ {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformTexelBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageTexelBufferDescriptors},
+ //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors},
+ //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors},
+ {VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, EngineCI.MainDescriptorPoolSize.NumAccelStructDescriptors}
},
EngineCI.MainDescriptorPoolSize.MaxDescriptorSets,
true
@@ -117,17 +118,18 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
"Dynamic descriptor pool",
std::vector<VkDescriptorPoolSize>
{
- {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumSeparateSamplerDescriptors},
- {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumCombinedSamplerDescriptors},
- {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumSampledImageDescriptors},
- {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumStorageImageDescriptors},
- {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformTexelBufferDescriptors},
- {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageTexelBufferDescriptors},
- //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors},
- //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors},
- {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors},
- {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors},
- {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors},
+ {VK_DESCRIPTOR_TYPE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumSeparateSamplerDescriptors},
+ {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, EngineCI.DynamicDescriptorPoolSize.NumCombinedSamplerDescriptors},
+ {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumSampledImageDescriptors},
+ {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, EngineCI.DynamicDescriptorPoolSize.NumStorageImageDescriptors},
+ {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformTexelBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageTexelBufferDescriptors},
+ //{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors},
+ //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors},
+ {VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, EngineCI.MainDescriptorPoolSize.NumAccelStructDescriptors}
},
EngineCI.DynamicDescriptorPoolSize.MaxDescriptorSets,
false // Pools can only be reset
@@ -160,6 +162,9 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
m_pDxCompiler{CreateDXCompiler(DXCompilerTarget::Vulkan, EngineCI.pDxCompilerPath)}
// clang-format on
{
+ static_assert(sizeof(VulkanDescriptorPoolSize) == sizeof(Uint32) * 11, "Please add new descriptors to m_DescriptorSetAllocator and m_DynamicDescriptorPool constructors");
+ static_assert(sizeof(DeviceObjectSizes) == sizeof(size_t) * 15, "Please add new objects to DeviceObjectSizes constructor");
+
m_DeviceCaps.DevType = RENDER_DEVICE_TYPE_VULKAN;
m_DeviceCaps.MajorVersion = 1;
m_DeviceCaps.MinorVersion = 0;
@@ -573,6 +578,10 @@ void RenderDeviceVkImpl::CreateComputePipelineState(const ComputePipelineStateCr
CreatePipelineState(PSOCreateInfo, ppPipelineState);
}
+void RenderDeviceVkImpl::CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState);
+}
void RenderDeviceVkImpl::CreateBufferFromVulkanResource(VkBuffer vkBuffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
index caf8ffd2..8a9da14e 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceCacheVk.cpp
@@ -155,7 +155,7 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
for (Uint32 res = 0; res < m_TotalResources; ++res)
{
auto& Res = pResources[res];
- static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type below");
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below");
switch (Res.Type)
{
case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
@@ -321,6 +321,36 @@ void ShaderResourceCacheVk::TransitionResources(DeviceContextVkImpl* pCtxVkImpl)
}
break;
+ case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure:
+ {
+ //auto* pTLASVk = Res.pObject.RawPtr<TopLevelASVkImpl>();
+ //if (pTLASVk != nullptr && pTLASVk->IsInKnownState())
+ //{
+ // constexpr RESOURCE_STATE RequiredState = RESOURCE_STATE_RAY_TRACING;
+ // const bool IsInRequiredState = pTLASVk->CheckState(RequiredState);
+ // if (VerifyOnly)
+ // {
+ // if (!IsInRequiredState)
+ // {
+ // LOG_ERROR_MESSAGE("State of TLAS '", pTLASVk->GetDesc().Name, "' is incorrect. Required state: ",
+ // GetResourceStateString(RequiredState), ". Actual state: ",
+ // GetResourceStateString(pTLASVk->GetState()),
+ // ". Call IDeviceContext::TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION "
+ // "when calling IDeviceContext::CommitShaderResources() or explicitly transition the TLAS state "
+ // "with IDeviceContext::TransitionResourceStates().");
+ // }
+ // }
+ // else
+ // {
+ // if (!IsInRequiredState)
+ // {
+ // pCtxVkImpl->TransitionTLASState(*pTLASVk, RESOURCE_STATE_UNKNOWN, RequiredState, true);
+ // }
+ // }
+ //}
+ }
+ break;
+
default: UNEXPECTED("Unexpected resource type");
}
}
@@ -497,4 +527,20 @@ VkDescriptorImageInfo ShaderResourceCacheVk::Resource::GetInputAttachmentDescrip
return DescrImgInfo;
}
+VkWriteDescriptorSetAccelerationStructureKHR ShaderResourceCacheVk::Resource::GetAccelerationStructureWriteInfo() const
+{
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration structure resource is expected");
+ DEV_CHECK_ERR(pObject != nullptr, "Unable to get acceleration structure write info: cached object is null");
+
+ //auto* pTLASVk = pObject.RawPtr<const TopLevelASVkImpl>();
+
+ VkWriteDescriptorSetAccelerationStructureKHR DescrAS = {};
+ //DescrAS.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR;
+ //DescrAS.pNext = nullptr;
+ //DescrAS.accelerationStructureCount = 1;
+ //DescrAS.pAccelerationStructures = pTLASVk->GetVkTLASPtr();
+
+ return DescrAS;
+}
+
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index e73ee9aa..16b6bee3 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -93,12 +93,24 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE
}
}
-ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE _Type,
- const ShaderVkImpl* _pShader) :
- Type{_Type},
- pShader{_pShader},
- SPIRV{pShader->GetSPIRV()}
+
+ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE Stage, const ShaderVkImpl* pShader) :
+ Type{Stage}
+{
+ Shaders.push_back(pShader);
+ SPIRVs.push_back(pShader->GetSPIRV());
+}
+
+void ShaderResourceLayoutVk::ShaderStageInfo::Append(const ShaderVkImpl* pShader)
{
+ Shaders.push_back(pShader);
+ SPIRVs.push_back(pShader->GetSPIRV());
+}
+
+size_t ShaderResourceLayoutVk::ShaderStageInfo::Count() const
+{
+ VERIFY_EXPR(Shaders.size() == SPIRVs.size());
+ return Shaders.size();
}
@@ -111,38 +123,53 @@ ShaderResourceLayoutVk::~ShaderResourceLayoutVk()
GetImmutableSampler(s).~ImmutableSamplerPtrType();
}
-void ShaderResourceLayoutVk::AllocateMemory(const ShaderVkImpl* pShader,
- IMemoryAllocator& Allocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- bool AllocateImmutableSamplers)
+void ShaderResourceLayoutVk::AllocateMemory(const std::vector<const ShaderVkImpl*>& Shaders,
+ IMemoryAllocator& Allocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ ResourceNameToIndex_t& UniqueNames,
+ bool AllocateImmutableSamplers)
{
VERIFY(!m_ResourceBuffer, "Memory has already been initialized");
- VERIFY_EXPR(!m_pResources);
- m_pResources = pShader->GetShaderResources();
+ VERIFY_EXPR(Shaders.size() > 0);
+ VERIFY_EXPR(m_ShaderType == SHADER_TYPE_UNKNOWN);
+
+ size_t StringPoolSize = 0;
+ m_ShaderType = Shaders[0]->GetDesc().ShaderType;
+ m_IsUsingSeparateSamplers = !Shaders[0]->GetShaderResources()->IsUsingCombinedSamplers();
+ const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
- const auto ShaderType = pShader->GetDesc().ShaderType;
- VERIFY_EXPR(m_pResources->GetShaderType() == ShaderType);
// Count the number of resources to allocate all needed memory
+ for (size_t s = 0; s < Shaders.size(); ++s)
{
- const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
- const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
- m_pResources->ProcessResources(
+ auto pResources = Shaders[s]->GetShaderResources();
+ const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix();
+ VERIFY_EXPR(pResources->GetShaderType() == m_ShaderType);
+ pResources->ProcessResources(
[&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) //
{
- auto VarType = FindShaderVariableType(ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix);
+ auto VarType = FindShaderVariableType(m_ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix);
if (IsAllowedType(VarType, AllowedTypeBits))
{
- // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app
+ bool IsUniqueName = UniqueNames.emplace(HashMapStringKey{ResAttribs.Name}, ~0u).second;
+ if (IsUniqueName)
+ {
+ StringPoolSize += strlen(ResAttribs.Name) + 1;
+
+ // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app
- VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds Uint16 maximum representable value");
- ++m_NumResources[VarType];
+ VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds Uint16 maximum representable value");
+ ++m_NumResources[VarType];
+ }
}
} //
);
+ VERIFY_EXPR(m_IsUsingSeparateSamplers == !pResources->IsUsingCombinedSamplers());
}
+ m_StringPool.Reserve(StringPoolSize, GetRawAllocator());
+
Uint32 TotalResources = 0;
for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
{
@@ -157,7 +184,7 @@ void ShaderResourceLayoutVk::AllocateMemory(const ShaderVkImpl*
for (Uint32 s = 0; s < ResourceLayoutDesc.NumImmutableSamplers; ++s)
{
const auto& ImtblSamDesc = ResourceLayoutDesc.ImmutableSamplers[s];
- if ((ImtblSamDesc.ShaderStages & ShaderType) != 0)
+ if ((ImtblSamDesc.ShaderStages & m_ShaderType) != 0)
++m_NumImmutableSamplers;
}
}
@@ -194,8 +221,8 @@ static Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout,
for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd)
{
const auto& Res = Layout.GetResource(ImgVarType, SamplerInd);
- if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
- strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0)
+ if (Res.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
+ strcmp(Res.Name, SepSampler.Name) == 0)
{
VERIFY(ImgVarType == Res.GetVariableType(),
"The type (", GetShaderVariableTypeLiteralName(ImgVarType), ") of separate image variable '", SepImg.Name,
@@ -217,62 +244,88 @@ static Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout,
}
-void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const ShaderVkImpl* pShader,
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- ShaderResourceCacheVk& StaticResourceCache)
+void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const std::vector<const ShaderVkImpl*>& Shaders,
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ ShaderResourceCacheVk& StaticResourceCache)
{
const auto AllowedVarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC;
// We do not need immutable samplers in static shader resource layout as they
// are relevant only when the main layout is initialized
- constexpr bool AllocateImmutableSamplers = false;
- AllocateMemory(pShader, LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers);
+ ResourceNameToIndex_t ResourceNameToIndex;
+ constexpr bool AllocateImmutableSamplers = false;
+ AllocateMemory(Shaders, LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, ResourceNameToIndex, AllocateImmutableSamplers);
std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES> CurrResInd = {};
- Uint32 StaticResCacheSize = 0;
+ Uint32 StaticResCacheSize = 0;
+ const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1);
- const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1);
- const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
- const auto ShaderType = pShader->GetDesc().ShaderType;
+ for (auto* pShader : Shaders)
+ {
+ auto pResources = pShader->GetShaderResources();
+ const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix();
+ pResources->ProcessResources(
+ [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) //
+ {
+ auto VarType = FindShaderVariableType(m_ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix);
+ if (!IsAllowedType(VarType, AllowedTypeBits))
+ return;
- m_pResources->ProcessResources(
- [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) //
- {
- auto VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix);
- if (!IsAllowedType(VarType, AllowedTypeBits))
- return;
+ auto ResIter = ResourceNameToIndex.find(HashMapStringKey{Attribs.Name});
+ VERIFY_EXPR(ResIter != ResourceNameToIndex.end());
- Int32 SrcImmutableSamplerInd = -1;
- if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
- Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler)
- {
- // Only search for the immutable sampler for combined image samplers and separate samplers
- SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix);
- // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app
- }
+ if (ResIter->second == ~0u)
+ {
+ Int32 SrcImmutableSamplerInd = -1;
+ if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
+ Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler)
+ {
+ // Only search for the immutable sampler for combined image samplers and separate samplers
+ SrcImmutableSamplerInd = FindImmutableSampler(m_ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix);
+ // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app
+ }
- Uint32 Binding = Attribs.Type;
- Uint32 DescriptorSet = 0;
- Uint32 CacheOffset = StaticResCacheSize;
- StaticResCacheSize += Attribs.ArraySize;
+ Uint32 Binding = Attribs.Type;
+ Uint32 DescriptorSet = 0;
+ Uint32 CacheOffset = StaticResCacheSize;
+ StaticResCacheSize += Attribs.ArraySize;
- Uint32 SamplerInd = VkResource::InvalidSamplerInd;
- if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage)
- {
- // Separate samplers are enumerated before separate images, so the sampler
- // assigned to this separate image must have already been created.
- SamplerInd = FindAssignedSampler(*this, *m_pResources, Attribs, CurrResInd[VarType], VarType);
- }
- ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0);
- } //
- );
+ Uint32 SamplerInd = VkResource::InvalidSamplerInd;
+ if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage)
+ {
+ // Separate samplers are enumerated before separate images, so the sampler
+ // assigned to this separate image must have already been created.
+ SamplerInd = FindAssignedSampler(*this, *pResources, Attribs, CurrResInd[VarType], VarType);
+ }
+
+ // add new resource
+ ResIter->second = CurrResInd[VarType];
+ ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, m_StringPool.CopyString(Attribs.Name), Attribs.ArraySize,
+ Attribs.Type, Attribs.ResourceDim, Attribs.IsMS, VarType,
+ Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0);
+ }
+ else
+ {
+ // merge with existing
+ auto& ExistingRes = GetResource(VarType, ResIter->second);
+ VERIFY_EXPR(ExistingRes.VariableType == VarType);
+ VERIFY_EXPR(ExistingRes.Type == Attribs.Type);
+ VERIFY_EXPR(ExistingRes.ResourceDim == Attribs.ResourceDim);
+ VERIFY_EXPR(ExistingRes.IsMS == Attribs.IsMS);
+ VERIFY_EXPR(ExistingRes.ArraySize == Attribs.ArraySize);
+ }
+ } //
+ );
+ }
#ifdef DILIGENT_DEBUG
for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
{
VERIFY(CurrResInd[VarType] == m_NumResources[VarType], "Not all resources have been initialized, which will cause a crash when dtor is called");
}
+
+ VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0);
#endif
StaticResourceCache.InitializeSets(GetRawAllocator(), 1, &StaticResCacheSize);
@@ -296,14 +349,15 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages&
const auto ShaderType = Stages & static_cast<SHADER_TYPE>(~(static_cast<Uint32>(Stages) - 1));
const char* ShaderName = nullptr;
- for (const auto& StageInfo : ShaderStages)
+ // AZ TODO
+ /*for (const auto& StageInfo : ShaderStages)
{
if ((Stages & StageInfo.Type) != 0)
{
ShaderName = StageInfo.pShader->GetDesc().Name;
break;
}
- }
+ }*/
if (!ShadersStr.empty())
ShadersStr.append(", ");
@@ -340,13 +394,17 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages&
bool VariableFound = false;
for (size_t s = 0; s < ShaderStages.size() && !VariableFound; ++s)
{
- const auto& Resources = *ShaderStages[s].pShader->GetShaderResources();
- if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0)
+ auto& Shaders = ShaderStages[s].Shaders;
+ for (size_t i = 0; i < Shaders.size() && !VariableFound; ++i)
{
- for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res)
+ const auto& Resources = *Shaders[i]->GetShaderResources();
+ if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0)
{
- const auto& ResAttribs = Resources.GetResource(res);
- VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0);
+ for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res)
+ {
+ const auto& ResAttribs = Resources.GetResource(res);
+ VariableFound = (strcmp(ResAttribs.Name, VarDesc.Name) == 0);
+ }
}
}
}
@@ -373,28 +431,32 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages&
bool SamplerFound = false;
for (size_t s = 0; s < ShaderStages.size() && !SamplerFound; ++s)
{
- const auto& Resources = *ShaderStages[s].pShader->GetShaderResources();
- if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0)
- continue;
-
- // Irrespective of whether HLSL-style combined image samplers are used,
- // an immutable sampler can be assigned to a GLSL sampled image (i.e. sampler2D g_tex)
- for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i)
+ auto& Shaders = ShaderStages[s].Shaders;
+ for (size_t j = 0; j < Shaders.size() && !SamplerFound; ++j)
{
- const auto& SmplImg = Resources.GetSmpldImg(i);
- SamplerFound = (strcmp(SmplImg.Name, ImtblSamDesc.SamplerOrTextureName) == 0);
- }
+ const auto& Resources = *Shaders[j]->GetShaderResources();
+ if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0)
+ continue;
- if (!SamplerFound)
- {
- // Check if an immutable sampler is assigned to a separate sampler.
- // In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler".
- // Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "".
- const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix();
- for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i)
+ // Irrespective of whether HLSL-style combined image samplers are used,
+ // a static sampler can be assigned to GLSL sampled image (i.e. sampler2D g_tex)
+ for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i)
+ {
+ const auto& SmplImg = Resources.GetSmpldImg(i);
+ SamplerFound = (strcmp(SmplImg.Name, ImtblSamDesc.SamplerOrTextureName) == 0);
+ }
+
+ if (!SamplerFound)
{
- const auto& SepSmpl = Resources.GetSepSmplr(i);
- SamplerFound = StreqSuff(SepSmpl.Name, ImtblSamDesc.SamplerOrTextureName, CombinedSamplerSuffix);
+ // Check if static sampler is assigned to a separate sampler.
+ // In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler".
+ // Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "".
+ const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix();
+ for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i)
+ {
+ const auto& SepSmpl = Resources.GetSepSmplr(i);
+ SamplerFound = StreqSuff(SepSmpl.Name, ImtblSamDesc.SamplerOrTextureName, CombinedSamplerSuffix);
+ }
}
}
}
@@ -423,15 +485,16 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende
dvpVerifyResourceLayoutDesc(ShaderStages, ResourceLayoutDesc, VerifyVariables, VerifyImmutableSamplers);
#endif
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr;
- const Uint32 NumAllowedTypes = 0;
- const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
- constexpr bool AllocateImmutableSamplers = true;
+ std::array<ResourceNameToIndex_t, MAX_SHADERS_IN_PIPELINE> ResourceNameToIndexArray;
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr;
+ const Uint32 NumAllowedTypes = 0;
+ const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+ constexpr bool AllocateImmutableSamplers = true;
for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- Layouts[s].AllocateMemory(ShaderStages[s].pShader, LayoutDataAllocator, ResourceLayoutDesc,
- AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers);
+ Layouts[s].AllocateMemory(ShaderStages[s].Shaders, LayoutDataAllocator, ResourceLayoutDesc,
+ AllowedVarTypes, NumAllowedTypes, ResourceNameToIndexArray[s], AllocateImmutableSamplers);
}
//VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE);
@@ -444,74 +507,107 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende
auto AddResource = [&](Uint32 ShaderInd,
ShaderResourceLayoutVk& ResLayout,
const SPIRVShaderResources& Resources,
- const SPIRVShaderResourceAttribs& Attribs) //
+ const SPIRVShaderResourceAttribs& Attribs,
+ ResourceNameToIndex_t& ResourceNameToIndex,
+ std::vector<uint32_t>& SPIRV) //
{
const auto ShaderType = Resources.GetShaderType();
const SHADER_RESOURCE_VARIABLE_TYPE VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, Resources.GetCombinedSamplerSuffix());
if (!IsAllowedType(VarType, AllowedTypeBits))
return;
- Uint32 Binding = 0;
- Uint32 DescriptorSet = 0;
- Uint32 CacheOffset = 0;
- Uint32 SamplerInd = VkResource::InvalidSamplerInd;
+ auto ResIter = ResourceNameToIndex.find(HashMapStringKey{Attribs.Name});
+ VERIFY_EXPR(ResIter != ResourceNameToIndex.end());
- if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage)
+ if (ResIter->second == ~0u)
{
- // Separate samplers are enumerated before separate images, so the sampler
- // assigned to this separate image must have already been created.
- SamplerInd = FindAssignedSampler(ResLayout, Resources, Attribs, CurrResInd[ShaderInd][VarType], VarType);
- }
+ // add new resource
+ Uint32 Binding = 0;
+ Uint32 DescriptorSet = 0;
+ Uint32 CacheOffset = 0;
+ Uint32 SamplerInd = VkResource::InvalidSamplerInd;
- VkSampler vkImmutableSampler = VK_NULL_HANDLE;
- if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
- Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler)
- {
- // Only search for the immutable sampler for combined image samplers and separate samplers
- Int32 SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, Resources.GetCombinedSamplerSuffix());
- if (SrcImmutableSamplerInd >= 0)
+ if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage)
{
- auto& ImmutableSampler = ResLayout.GetImmutableSampler(CurrImmutableSamplerInd[ShaderInd]++);
- VERIFY(!ImmutableSampler, "Immutable sampler has already been initialized!");
- const auto& ImmutableSamplerDesc = ResourceLayoutDesc.ImmutableSamplers[SrcImmutableSamplerInd].Desc;
- pRenderDevice->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler);
- vkImmutableSampler = ImmutableSampler.RawPtr<SamplerVkImpl>()->GetVkSampler();
+ // Separate samplers are enumerated before separate images, so the sampler
+ // assigned to this separate image must have already been created.
+ SamplerInd = FindAssignedSampler(ResLayout, Resources, Attribs, CurrResInd[ShaderInd][VarType], VarType);
}
- }
- auto& ShaderSPIRV = ShaderStages[ShaderInd].SPIRV;
- PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset, ShaderSPIRV);
- VERIFY(DescriptorSet <= std::numeric_limits<decltype(VkResource::DescriptorSet)>::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value");
- VERIFY(Binding <= std::numeric_limits<decltype(VkResource::Binding)>::max(), "Binding (", Binding, ") excceeds maximum representable value");
+ VkSampler vkImmutableSampler = VK_NULL_HANDLE;
+ if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage ||
+ Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler)
+ {
+ // Only search for the immutable sampler for combined image samplers and separate samplers
+ Int32 SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, Resources.GetCombinedSamplerSuffix());
+ if (SrcImmutableSamplerInd >= 0)
+ {
+ auto& ImmutableSampler = ResLayout.GetImmutableSampler(CurrImmutableSamplerInd[ShaderInd]++);
+ VERIFY(!ImmutableSampler, "Immutable sampler has already been initialized!");
+ const auto& ImmutableSamplerDesc = ResourceLayoutDesc.ImmutableSamplers[SrcImmutableSamplerInd].Desc;
+ pRenderDevice->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler);
+ vkImmutableSampler = ImmutableSampler.RawPtr<SamplerVkImpl>()->GetVkSampler();
+ }
+ }
+
+ PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset);
+ VERIFY(DescriptorSet <= std::numeric_limits<decltype(VkResource::DescriptorSet)>::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value");
+ VERIFY(Binding <= std::numeric_limits<decltype(VkResource::Binding)>::max(), "Binding (", Binding, ") excceeds maximum representable value");
+
+ SPIRV[Attribs.BindingDecorationOffset] = Binding;
+ SPIRV[Attribs.DescriptorSetDecorationOffset] = DescriptorSet;
#ifdef DILIGENT_DEBUG
- // Verify that bindings and cache offsets monotonically increase in every descriptor set
- auto Binding_OffsetIt = dbgBindings_CacheOffsets.find(DescriptorSet);
- if (Binding_OffsetIt != dbgBindings_CacheOffsets.end())
- {
- VERIFY(Binding > Binding_OffsetIt->second.first, "Binding for descriptor set ", DescriptorSet, " is not strictly monotonic");
- VERIFY(CacheOffset > Binding_OffsetIt->second.second, "Cache offset for descriptor set ", DescriptorSet, " is not strictly monotonic");
- }
- dbgBindings_CacheOffsets[DescriptorSet] = std::make_pair(Binding, CacheOffset);
+ // Verify that bindings and cache offsets monotonically increase in every descriptor set
+ auto Binding_OffsetIt = dbgBindings_CacheOffsets.find(DescriptorSet);
+ if (Binding_OffsetIt != dbgBindings_CacheOffsets.end())
+ {
+ VERIFY(Binding > Binding_OffsetIt->second.first, "Binding for descriptor set ", DescriptorSet, " is not strictly monotonic");
+ VERIFY(CacheOffset > Binding_OffsetIt->second.second, "Cache offset for descriptor set ", DescriptorSet, " is not strictly monotonic");
+ }
+ dbgBindings_CacheOffsets[DescriptorSet] = std::make_pair(Binding, CacheOffset);
#endif
- auto& ResInd = CurrResInd[ShaderInd][VarType];
- ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource(ResLayout, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, vkImmutableSampler != VK_NULL_HANDLE ? 1 : 0);
+ auto& ResInd = CurrResInd[ShaderInd][VarType];
+ ResIter->second = ResInd;
+ ::new (&ResLayout.GetResource(VarType, ResInd++)) VkResource(ResLayout, ResLayout.m_StringPool.CopyString(Attribs.Name), Attribs.ArraySize,
+ Attribs.Type, Attribs.ResourceDim, Attribs.IsMS, VarType,
+ Binding, DescriptorSet, CacheOffset, SamplerInd, vkImmutableSampler != VK_NULL_HANDLE ? 1 : 0);
+ }
+ else
+ {
+ // merge with existing
+ auto& ExistingRes = ResLayout.GetResource(VarType, ResIter->second);
+
+ VERIFY_EXPR(ExistingRes.VariableType == VarType);
+ VERIFY_EXPR(ExistingRes.Type == Attribs.Type);
+ VERIFY_EXPR(ExistingRes.ResourceDim == Attribs.ResourceDim);
+ VERIFY_EXPR(ExistingRes.IsMS == Attribs.IsMS);
+ VERIFY_EXPR(ExistingRes.ArraySize == Attribs.ArraySize);
+
+ SPIRV[Attribs.BindingDecorationOffset] = ExistingRes.Binding;
+ SPIRV[Attribs.DescriptorSetDecorationOffset] = ExistingRes.DescriptorSet;
+ }
};
// First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set
for (size_t s = 0; s < ShaderStages.size(); ++s)
{
+ auto& Shaders = ShaderStages[s].Shaders;
auto& Layout = Layouts[s];
- auto* pShaderVk = ShaderStages[s].pShader;
- auto& Resources = *pShaderVk->GetShaderResources();
- for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n)
+ auto& NameToIdx = ResourceNameToIndexArray[s];
+ for (size_t i = 0; i < Shaders.size(); ++i)
{
- const auto& UB = Resources.GetUB(n);
- auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc);
- if (IsAllowedType(VarType, AllowedTypeBits))
+ auto& SPIRV = ShaderStages[s].SPIRVs[i];
+ auto& Resources = *Shaders[i]->GetShaderResources();
+ for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n)
{
- AddResource(static_cast<Uint32>(s), Layout, Resources, UB);
+ const auto& UB = Resources.GetUB(n);
+ auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc);
+ if (IsAllowedType(VarType, AllowedTypeBits))
+ {
+ AddResource(static_cast<Uint32>(s), Layout, Resources, UB, NameToIdx, SPIRV);
+ }
}
}
}
@@ -519,15 +615,21 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende
// Second, process all storage buffers
for (size_t s = 0; s < ShaderStages.size(); ++s)
{
+ auto& Shaders = ShaderStages[s].Shaders;
auto& Layout = Layouts[s];
- auto& Resources = *ShaderStages[s].pShader->GetShaderResources();
- for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n)
+ auto& NameToIdx = ResourceNameToIndexArray[s];
+ for (size_t i = 0; i < Shaders.size(); ++i)
{
- const auto& SB = Resources.GetSB(n);
- auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc);
- if (IsAllowedType(VarType, AllowedTypeBits))
+ auto& Resources = *Shaders[i]->GetShaderResources();
+ auto& SPIRV = ShaderStages[s].SPIRVs[i];
+ for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n)
{
- AddResource(static_cast<Uint32>(s), Layout, Resources, SB);
+ const auto& SB = Resources.GetSB(n);
+ auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc);
+ if (IsAllowedType(VarType, AllowedTypeBits))
+ {
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SB, NameToIdx, SPIRV);
+ }
}
}
}
@@ -536,51 +638,62 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende
for (size_t s = 0; s < ShaderStages.size(); ++s)
{
auto& Layout = Layouts[s];
- auto& Resources = *ShaderStages[s].pShader->GetShaderResources();
- // clang-format off
- Resources.ProcessResources(
- [&](const SPIRVShaderResourceAttribs& UB, Uint32)
- {
- VERIFY_EXPR(UB.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer);
- // Skip
- },
- [&](const SPIRVShaderResourceAttribs& SB, Uint32)
- {
- VERIFY_EXPR(SB.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer || SB.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer);
- // Skip
- },
- [&](const SPIRVShaderResourceAttribs& Img, Uint32)
- {
- VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer);
- AddResource(static_cast<Uint32>(s), Layout, Resources, Img);
- },
- [&](const SPIRVShaderResourceAttribs& SmplImg, Uint32)
- {
- VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer);
- AddResource(static_cast<Uint32>(s), Layout, Resources, SmplImg);
- },
- [&](const SPIRVShaderResourceAttribs& AC, Uint32)
- {
- VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter);
- AddResource(static_cast<Uint32>(s), Layout, Resources, AC);
- },
- [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32)
- {
- VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler);
- AddResource(static_cast<Uint32>(s), Layout, Resources, SepSmpl);
- },
- [&](const SPIRVShaderResourceAttribs& SepImg, Uint32)
- {
- VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer);
- AddResource(static_cast<Uint32>(s), Layout, Resources, SepImg);
- },
- [&](const SPIRVShaderResourceAttribs& InputAtt, Uint32)
- {
- VERIFY_EXPR(InputAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment);
- AddResource(static_cast<Uint32>(s), Layout, Resources, InputAtt);
- }
- );
- // clang-format on
+ auto& Shaders = ShaderStages[s].Shaders;
+ auto& NameToIdx = ResourceNameToIndexArray[s];
+ for (size_t i = 0; i < Shaders.size(); ++i)
+ {
+ auto& Resources = *Shaders[i]->GetShaderResources();
+ auto& SPIRV = ShaderStages[s].SPIRVs[i];
+ // clang-format off
+ Resources.ProcessResources(
+ [&](const SPIRVShaderResourceAttribs& UB, Uint32)
+ {
+ VERIFY_EXPR(UB.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer);
+ // Skip
+ },
+ [&](const SPIRVShaderResourceAttribs& SB, Uint32)
+ {
+ VERIFY_EXPR(SB.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer || SB.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer);
+ // Skip
+ },
+ [&](const SPIRVShaderResourceAttribs& Img, Uint32)
+ {
+ VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, Img, NameToIdx, SPIRV);
+ },
+ [&](const SPIRVShaderResourceAttribs& SmplImg, Uint32)
+ {
+ VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SmplImg, NameToIdx, SPIRV);
+ },
+ [&](const SPIRVShaderResourceAttribs& AC, Uint32)
+ {
+ VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, AC, NameToIdx, SPIRV);
+ },
+ [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32)
+ {
+ VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SepSmpl, NameToIdx, SPIRV);
+ },
+ [&](const SPIRVShaderResourceAttribs& SepImg, Uint32)
+ {
+ VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SepImg, NameToIdx, SPIRV);
+ },
+ [&](const SPIRVShaderResourceAttribs& InputAtt, Uint32)
+ {
+ VERIFY_EXPR(InputAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, InputAtt, NameToIdx, SPIRV);
+ },
+ [&](const SPIRVShaderResourceAttribs& AccelStruct, Uint32)
+ {
+ VERIFY_EXPR(AccelStruct.Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, AccelStruct, NameToIdx, SPIRV);
+ }
+ );
+ // clang-format on
+ }
}
#ifdef DILIGENT_DEBUG
@@ -593,28 +706,32 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende
}
// Some immutable samplers may never be initialized if they are not present in shaders
VERIFY_EXPR(CurrImmutableSamplerInd[s] <= Layout.m_NumImmutableSamplers);
+
+ VERIFY_EXPR(Layout.m_StringPool.GetRemainingSize() == 0);
}
#endif
}
-void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
- uint32_t ArrayElement,
- const VkDescriptorImageInfo* pImageInfo,
- const VkDescriptorBufferInfo* pBufferInfo,
- const VkBufferView* pTexelBufferView) const
+
+void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
+ uint32_t ArrayElement,
+ const VkDescriptorImageInfo* pImageInfo,
+ const VkDescriptorBufferInfo* pBufferInfo,
+ const VkBufferView* pTexelBufferView,
+ const VkWriteDescriptorSetAccelerationStructureKHR* pAccelStructInfo) const
{
VERIFY_EXPR(vkDescrSet != VK_NULL_HANDLE);
VkWriteDescriptorSet WriteDescrSet;
WriteDescrSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- WriteDescrSet.pNext = nullptr;
+ WriteDescrSet.pNext = pAccelStructInfo;
WriteDescrSet.dstSet = vkDescrSet;
WriteDescrSet.dstBinding = Binding;
WriteDescrSet.dstArrayElement = ArrayElement;
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 = PipelineLayout::GetVkDescriptorType(SpirvAttribs);
+ WriteDescrSet.descriptorType = PipelineLayout::GetVkDescriptorType(Type);
WriteDescrSet.pImageInfo = pImageInfo;
WriteDescrSet.pBufferInfo = pBufferInfo;
WriteDescrSet.pTexelBufferView = pTexelBufferView;
@@ -654,10 +771,10 @@ void ShaderResourceLayoutVk::VkResource::CacheUniformBuffer(IDeviceObject*
Uint32 ArrayInd,
Uint16& DynamicBuffersCounter) const
{
- VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, "Uniform buffer resource is expected");
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::UniformBuffer, "Uniform buffer resource is expected");
RefCntAutoPtr<BufferVkImpl> pBufferVk{pBuffer, IID_BufferVk};
#ifdef DILIGENT_DEVELOPMENT
- VerifyConstantBufferBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
+ VerifyConstantBufferBinding(*this, GetVariableType(), ArrayInd, pBuffer, pBufferVk.RawPtr(), DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
#endif
auto UpdateDynamicBuffersCounter = [&DynamicBuffersCounter](const BufferVkImpl* pOldBuffer, const BufferVkImpl* pNewBuffer) {
@@ -691,8 +808,8 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject*
Uint16& DynamicBuffersCounter) const
{
// clang-format off
- VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ||
- SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer,
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ||
+ Type == SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer,
"Storage buffer resource is expected");
// clang-format on
@@ -700,8 +817,8 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject*
#ifdef DILIGENT_DEVELOPMENT
{
// HLSL buffer SRVs are mapped to storge buffers in GLSL
- auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? BUFFER_VIEW_SHADER_RESOURCE : BUFFER_VIEW_UNORDERED_ACCESS;
- VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
+ auto RequiredViewType = Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? BUFFER_VIEW_SHADER_RESOURCE : BUFFER_VIEW_UNORDERED_ACCESS;
+ VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
if (pBufferViewVk != nullptr)
{
const auto& ViewDesc = pBufferViewVk->GetDesc();
@@ -709,7 +826,7 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject*
if (BuffDesc.Mode != BUFFER_MODE_STRUCTURED && BuffDesc.Mode != BUFFER_MODE_RAW)
{
LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
- SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected.");
+ Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected.");
}
}
}
@@ -747,8 +864,8 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
Uint16& DynamicBuffersCounter) const
{
// clang-format off
- VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer ||
- SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer,
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer ||
+ Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer,
"Uniform or storage buffer resource is expected");
// clang-format on
@@ -756,8 +873,8 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
#ifdef DILIGENT_DEVELOPMENT
{
// HLSL buffer SRVs are mapped to storge buffers in GLSL
- auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer ? BUFFER_VIEW_UNORDERED_ACCESS : BUFFER_VIEW_SHADER_RESOURCE;
- VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
+ auto RequiredViewType = Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer ? BUFFER_VIEW_UNORDERED_ACCESS : BUFFER_VIEW_SHADER_RESOURCE;
+ VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
if (pBufferViewVk != nullptr)
{
const auto& ViewDesc = pBufferViewVk->GetDesc();
@@ -765,7 +882,7 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
if (!((BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED) || BuffDesc.Mode == BUFFER_MODE_RAW))
{
LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
- SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': formatted buffer view is expected.");
+ Name, "' in shader '", ParentResLayout.GetShaderName(), "': formatted buffer view is expected.");
}
}
}
@@ -805,9 +922,9 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
TCacheSampler CacheSampler) const
{
// clang-format off
- VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ||
- SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage ||
- SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage,
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ||
+ Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage ||
+ Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage,
"Storage image, separate image or sampled image resource is expected");
// clang-format on
@@ -815,8 +932,8 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
#ifdef DILIGENT_DEVELOPMENT
{
// HLSL buffer SRVs are mapped to storge buffers in GLSL
- auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ? TEXTURE_VIEW_UNORDERED_ACCESS : TEXTURE_VIEW_SHADER_RESOURCE;
- VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
+ auto RequiredViewType = Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage ? TEXTURE_VIEW_UNORDERED_ACCESS : TEXTURE_VIEW_SHADER_RESOURCE;
+ VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
}
#endif
if (UpdateCachedResource(DstRes, std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*) {}))
@@ -824,11 +941,11 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
// We can do RawPtr here safely since UpdateCachedResource() returned true
auto* pTexViewVk = DstRes.pObject.RawPtr<TextureViewVkImpl>();
#ifdef DILIGENT_DEVELOPMENT
- if (SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !IsImmutableSamplerAssigned())
+ if (Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage && !IsImmutableSamplerAssigned())
{
if (pTexViewVk->GetSampler() == nullptr)
{
- LOG_ERROR_MESSAGE("Error binding texture view '", pTexViewVk->GetDesc().Name, "' to variable '", SpirvAttribs.GetPrintName(ArrayInd),
+ LOG_ERROR_MESSAGE("Error binding texture view '", pTexViewVk->GetDesc().Name, "' to variable '", GetPrintName(ArrayInd),
"' in shader '", ParentResLayout.GetShaderName(), "'. No sampler is assigned to the view");
}
}
@@ -844,11 +961,11 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
if (SamplerInd != InvalidSamplerInd)
{
- VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage,
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage,
"Only separate images can be assigned separate samplers when using HLSL-style combined samplers.");
VERIFY(!IsImmutableSamplerAssigned(), "Separate image can't be assigned an immutable sampler.");
const auto& SamplerAttribs = ParentResLayout.GetResource(GetVariableType(), SamplerInd);
- VERIFY_EXPR(SamplerAttribs.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler);
+ VERIFY_EXPR(SamplerAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler);
if (!SamplerAttribs.IsImmutableSamplerAssigned())
{
auto* pSampler = pTexViewVk->GetSampler();
@@ -858,8 +975,8 @@ void ShaderResourceLayoutVk::VkResource::CacheImage(IDeviceObject*
}
else
{
- LOG_ERROR_MESSAGE("Failed to bind sampler to sampler variable '", SamplerAttribs.SpirvAttribs.Name,
- "' assigned to separate image '", SpirvAttribs.GetPrintName(ArrayInd), "' in shader '",
+ LOG_ERROR_MESSAGE("Failed to bind sampler to sampler variable '", SamplerAttribs.Name,
+ "' assigned to separate image '", GetPrintName(ArrayInd), "' in shader '",
ParentResLayout.GetShaderName(), "': no sampler is set in texture view '", pTexViewVk->GetDesc().Name, '\'');
}
}
@@ -872,20 +989,20 @@ void ShaderResourceLayoutVk::VkResource::CacheSeparateSampler(IDeviceObject*
VkDescriptorSet vkDescrSet,
Uint32 ArrayInd) const
{
- VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected");
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler, "Separate sampler resource is expected");
VERIFY(!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 '", SpirvAttribs.GetPrintName(ArrayInd),
+ LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '", GetPrintName(ArrayInd),
"' in shader '", ParentResLayout.GetShaderName(), "'. Unexpected object type: sampler is expected");
}
if (GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr && DstRes.pObject != pSamplerVk)
{
auto VarTypeStr = GetShaderVariableTypeLiteralName(GetVariableType());
- LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", SpirvAttribs.GetPrintName(ArrayInd),
+ LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", GetPrintName(ArrayInd),
"' in shader '", ParentResLayout.GetShaderName(),
"'. 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.");
@@ -908,10 +1025,10 @@ void ShaderResourceLayoutVk::VkResource::CacheInputAttachment(IDeviceObject*
VkDescriptorSet vkDescrSet,
Uint32 ArrayInd) const
{
- VERIFY(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment, "Input attachment resource is expected");
+ VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment, "Input attachment resource is expected");
RefCntAutoPtr<TextureViewVkImpl> pTexViewVk0{pTexView, IID_TextureViewVk};
#ifdef DILIGENT_DEVELOPMENT
- VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
+ VerifyResourceViewBinding(*this, GetVariableType(), ArrayInd, pTexView, pTexViewVk0.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
#endif
if (UpdateCachedResource(DstRes, std::move(pTexViewVk0), [](const TextureViewVkImpl*, const TextureViewVkImpl*) {}))
{
@@ -926,9 +1043,32 @@ void ShaderResourceLayoutVk::VkResource::CacheInputAttachment(IDeviceObject*
}
}
+void ShaderResourceLayoutVk::VkResource::CacheAccelerationStructure(IDeviceObject* pTLAS,
+ ShaderResourceCacheVk::Resource& DstRes,
+ VkDescriptorSet vkDescrSet,
+ Uint32 ArrayInd) const
+{
+ // VERIFY(Type == SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure, "Acceleration Structure resource is expected");
+ // RefCntAutoPtr<TopLevelASVkImpl> pTLASVk{pTLAS, IID_TopLevelASVk};
+ //#ifdef DILIGENT_DEVELOPMENT
+ // // AZ TODO
+ //#endif
+ // if (UpdateCachedResource(DstRes, 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 (vkDescrSet != VK_NULL_HANDLE && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
+ // {
+ // VkWriteDescriptorSetAccelerationStructureKHR DescrASInfo = DstRes.GetAccelerationStructureWriteInfo();
+ // UpdateDescriptorHandle(vkDescrSet, ArrayInd, nullptr, nullptr, nullptr, &DescrASInfo);
+ // }
+ // //
+ // }
+}
+
void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint32 ArrayIndex, ShaderResourceCacheVk& ResourceCache) const
{
- VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize);
+ VERIFY_EXPR(ArrayIndex < ArraySize);
auto& DstDescrSet = ResourceCache.GetDescriptorSet(DescriptorSet);
auto vkDescrSet = DstDescrSet.GetVkDescriptorSet();
@@ -951,12 +1091,12 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
}
#endif
auto& DstRes = DstDescrSet.GetResource(CacheOffset + ArrayIndex);
- VERIFY(DstRes.Type == SpirvAttribs.Type, "Inconsistent types");
+ VERIFY(DstRes.Type == Type, "Inconsistent types");
if (pObj)
{
- static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 11, "Please handle the new resource type below");
- switch (SpirvAttribs.Type)
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below");
+ switch (Type)
{
case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
CacheUniformBuffer(pObj, DstRes, vkDescrSet, ArrayIndex, ResourceCache.GetDynamicBuffersCounter());
@@ -977,15 +1117,15 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
case SPIRVShaderResourceAttribs::ResourceType::SampledImage:
CacheImage(pObj, DstRes, vkDescrSet, ArrayIndex,
[&](const VkResource& SeparateSampler, ISampler* pSampler) {
- VERIFY(!SeparateSampler.IsImmutableSamplerAssigned(), "Separate sampler '", SeparateSampler.SpirvAttribs.Name, "' is assigned an immutable sampler");
- VERIFY_EXPR(SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage);
- DEV_CHECK_ERR(SeparateSampler.SpirvAttribs.ArraySize == 1 || SeparateSampler.SpirvAttribs.ArraySize == SpirvAttribs.ArraySize,
- "Array size (", SeparateSampler.SpirvAttribs.ArraySize,
+ VERIFY(!SeparateSampler.IsImmutableSamplerAssigned(), "Separate sampler '", SeparateSampler.Name, "' is assigned an immutable sampler");
+ VERIFY_EXPR(Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage);
+ DEV_CHECK_ERR(SeparateSampler.ArraySize == 1 || SeparateSampler.ArraySize == ArraySize,
+ "Array size (", SeparateSampler.ArraySize,
") of separate sampler variable '",
- SeparateSampler.SpirvAttribs.Name,
- "' must be one or the same as the array size (", SpirvAttribs.ArraySize,
- ") of separate image variable '", SpirvAttribs.Name, "' it is assigned to");
- Uint32 SamplerArrInd = SeparateSampler.SpirvAttribs.ArraySize == 1 ? 0 : ArrayIndex;
+ SeparateSampler.Name,
+ "' must be one or the same as the array size (", ArraySize,
+ ") of separate image variable '", Name, "' it is assigned to");
+ Uint32 SamplerArrInd = SeparateSampler.ArraySize == 1 ? 0 : ArrayIndex;
SeparateSampler.BindResource(pSampler, SamplerArrInd, ResourceCache);
});
break;
@@ -999,7 +1139,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
{
// 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)
- LOG_ERROR_MESSAGE("Attempting to assign a sampler to an immutable sampler '", SpirvAttribs.Name, '\'');
+ LOG_ERROR_MESSAGE("Attempting to assign a sampler to an immutable sampler '", Name, '\'');
}
break;
@@ -1007,14 +1147,18 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
CacheInputAttachment(pObj, DstRes, vkDescrSet, ArrayIndex);
break;
- default: UNEXPECTED("Unknown resource type ", static_cast<Int32>(SpirvAttribs.Type));
+ case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure:
+ CacheAccelerationStructure(pObj, DstRes, vkDescrSet, ArrayIndex);
+ break;
+
+ default: UNEXPECTED("Unknown resource type ", static_cast<Int32>(Type));
}
}
else
{
if (DstRes.pObject && GetVariableType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
{
- LOG_ERROR_MESSAGE("Shader variable '", SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(),
+ LOG_ERROR_MESSAGE("Shader variable '", Name, "' in shader '", ParentResLayout.GetShaderName(),
"' 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.");
}
@@ -1025,7 +1169,7 @@ void ShaderResourceLayoutVk::VkResource::BindResource(IDeviceObject* pObj, Uint3
bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const
{
- VERIFY_EXPR(ArrayIndex < SpirvAttribs.ArraySize);
+ VERIFY_EXPR(ArrayIndex < ArraySize);
if (DescriptorSet < ResourceCache.GetNumDescriptorSets())
{
@@ -1040,6 +1184,72 @@ bool ShaderResourceLayoutVk::VkResource::IsBound(Uint32 ArrayIndex, const Shader
return false;
}
+ShaderResourceDesc ShaderResourceLayoutVk::VkResource::GetResourceDesc() const
+{
+ ShaderResourceDesc ResourceDesc;
+ ResourceDesc.Name = Name;
+ ResourceDesc.ArraySize = ArraySize;
+
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below");
+ switch (Type)
+ {
+ case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_CONSTANT_BUFFER;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer:
+ // Read-only storage buffers map to buffer SRV
+ // https://github.com/KhronosGroup/SPIRV-Cross/wiki/Reflection-API-user-guide#read-write-vs-read-only-resources-for-hlsl
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_SRV;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::StorageImage:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_UAV;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::SampledImage:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_SRV;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::AtomicCounter:
+ LOG_WARNING_MESSAGE("There is no appropriate shader resource type for atomic counter resource '", Name, "'");
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_BUFFER_UAV;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::SeparateImage:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_TEXTURE_SRV;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::SeparateSampler:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_SAMPLER;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::InputAttachment:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT;
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure:
+ ResourceDesc.Type = SHADER_RESOURCE_TYPE_ACCEL_STRUCT;
+ break;
+
+ default:
+ UNEXPECTED("Unknown SPIRV resource type");
+ }
+ return ResourceDesc;
+}
+
void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayoutVk& SrcLayout,
const ShaderResourceCacheVk& SrcResourceCache,
@@ -1055,21 +1265,21 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou
// Get resource attributes
const auto& DstRes = GetResource(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, r);
const auto& SrcRes = SrcLayout.GetResource(SHADER_RESOURCE_VARIABLE_TYPE_STATIC, r);
- VERIFY(SrcRes.Binding == SrcRes.SpirvAttribs.Type, "Unexpected binding");
- VERIFY(SrcRes.SpirvAttribs.ArraySize == DstRes.SpirvAttribs.ArraySize, "Inconsistent array size");
+ VERIFY(SrcRes.Binding == SrcRes.Type, "Unexpected binding");
+ VERIFY(SrcRes.ArraySize == DstRes.ArraySize, "Inconsistent array size");
- if (DstRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
+ if (DstRes.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
DstRes.IsImmutableSamplerAssigned())
continue; // Skip immutable samplers
- for (Uint32 ArrInd = 0; ArrInd < DstRes.SpirvAttribs.ArraySize; ++ArrInd)
+ for (Uint32 ArrInd = 0; ArrInd < DstRes.ArraySize; ++ArrInd)
{
auto SrcOffset = SrcRes.CacheOffset + ArrInd;
const auto& SrcCachedSet = SrcResourceCache.GetDescriptorSet(SrcRes.DescriptorSet);
const auto& SrcCachedRes = SrcCachedSet.GetResource(SrcOffset);
IDeviceObject* pObject = SrcCachedRes.pObject.RawPtr<IDeviceObject>();
if (!pObject)
- LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", SrcRes.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'.");
+ LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", SrcRes.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'.");
auto DstOffset = DstRes.CacheOffset + ArrInd;
IDeviceObject* pCachedResource = DstResourceCache.GetDescriptorSet(DstRes.DescriptorSet).GetResource(DstOffset).pObject;
@@ -1093,15 +1303,15 @@ bool ShaderResourceLayoutVk::dvpVerifyBindings(const ShaderResourceCacheVk& Reso
{
const auto& Res = GetResource(VarType, r);
VERIFY(Res.GetVariableType() == VarType, "Unexpected variable type");
- for (Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd)
+ for (Uint32 ArrInd = 0; ArrInd < Res.ArraySize; ++ArrInd)
{
const auto& CachedDescrSet = ResourceCache.GetDescriptorSet(Res.DescriptorSet);
const auto& CachedRes = CachedDescrSet.GetResource(Res.CacheOffset + ArrInd);
- VERIFY(CachedRes.Type == Res.SpirvAttribs.Type, "Inconsistent types");
+ VERIFY(CachedRes.Type == Res.Type, "Inconsistent types");
if (CachedRes.pObject == nullptr &&
- !(Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.IsImmutableSamplerAssigned()))
+ !(Res.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && Res.IsImmutableSamplerAssigned()))
{
- LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.GetVariableType()), " variable '", Res.SpirvAttribs.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'");
+ LOG_ERROR_MESSAGE("No resource is bound to ", GetShaderVariableTypeLiteralName(Res.GetVariableType()), " variable '", Res.GetPrintName(ArrInd), "' in shader '", GetShaderName(), "'");
BindingsOK = false;
}
# ifdef DILIGENT_DEBUG
@@ -1136,7 +1346,7 @@ void ShaderResourceLayoutVk::InitializeResourceMemoryInCache(ShaderResourceCache
for (Uint32 r = 0; r < TotalResources; ++r)
{
const auto& Res = GetResource(r);
- ResourceCache.InitializeResources(Res.DescriptorSet, Res.CacheOffset, Res.SpirvAttribs.ArraySize, Res.SpirvAttribs.Type);
+ ResourceCache.InitializeResources(Res.DescriptorSet, Res.CacheOffset, Res.ArraySize, Res.Type);
}
}
@@ -1151,24 +1361,28 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
static constexpr size_t ImgUpdateBatchSize = 4;
static constexpr size_t BuffUpdateBatchSize = 2;
static constexpr size_t TexelBuffUpdateBatchSize = 2;
+ static constexpr size_t AccelStructBatchSize = 2;
static constexpr size_t WriteDescriptorSetBatchSize = 2;
#else
static constexpr size_t ImgUpdateBatchSize = 128;
static constexpr size_t BuffUpdateBatchSize = 64;
static constexpr size_t TexelBuffUpdateBatchSize = 32;
+ static constexpr size_t AccelStructBatchSize = 32;
static constexpr size_t WriteDescriptorSetBatchSize = 32;
#endif
// Do not zero-initiaize arrays!
- std::array<VkDescriptorImageInfo, ImgUpdateBatchSize> DescrImgInfoArr;
- std::array<VkDescriptorBufferInfo, BuffUpdateBatchSize> DescrBuffInfoArr;
- std::array<VkBufferView, TexelBuffUpdateBatchSize> DescrBuffViewArr;
- std::array<VkWriteDescriptorSet, WriteDescriptorSetBatchSize> WriteDescrSetArr;
+ std::array<VkDescriptorImageInfo, ImgUpdateBatchSize> DescrImgInfoArr;
+ std::array<VkDescriptorBufferInfo, BuffUpdateBatchSize> DescrBuffInfoArr;
+ std::array<VkBufferView, TexelBuffUpdateBatchSize> DescrBuffViewArr;
+ std::array<VkWriteDescriptorSetAccelerationStructureKHR, AccelStructBatchSize> DescrAccelStructArr;
+ std::array<VkWriteDescriptorSet, WriteDescriptorSetBatchSize> WriteDescrSetArr;
Uint32 ResNum = 0, ArrElem = 0;
auto DescrImgIt = DescrImgInfoArr.begin();
auto DescrBuffIt = DescrBuffInfoArr.begin();
auto BuffViewIt = DescrBuffViewArr.begin();
+ auto AccelStructIt = DescrAccelStructArr.begin();
auto WriteDescrSetIt = WriteDescrSetArr.begin();
#ifdef DILIGENT_DEBUG
@@ -1195,14 +1409,15 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
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 = PipelineLayout::GetVkDescriptorType(Res.SpirvAttribs);
+ WriteDescrSetIt->descriptorType = PipelineLayout::GetVkDescriptorType(Res.Type);
// For every resource type, try to batch as many descriptor updates as we can
- switch (Res.SpirvAttribs.Type)
+ static_assert(SPIRVShaderResourceAttribs::ResourceType::NumResourceTypes == 12, "Please handle the new resource type below");
+ switch (Res.Type)
{
case SPIRVShaderResourceAttribs::ResourceType::UniformBuffer:
WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt);
- while (ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end())
+ while (ArrElem < Res.ArraySize && DescrBuffIt != DescrBuffInfoArr.end())
{
const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
*DescrBuffIt = CachedRes.GetUniformBufferDescriptorWriteInfo();
@@ -1214,7 +1429,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
case SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer:
case SPIRVShaderResourceAttribs::ResourceType::RWStorageBuffer:
WriteDescrSetIt->pBufferInfo = &(*DescrBuffIt);
- while (ArrElem < Res.SpirvAttribs.ArraySize && DescrBuffIt != DescrBuffInfoArr.end())
+ while (ArrElem < Res.ArraySize && DescrBuffIt != DescrBuffInfoArr.end())
{
const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
*DescrBuffIt = CachedRes.GetStorageBufferDescriptorWriteInfo();
@@ -1226,7 +1441,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
case SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer:
case SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer:
WriteDescrSetIt->pTexelBufferView = &(*BuffViewIt);
- while (ArrElem < Res.SpirvAttribs.ArraySize && BuffViewIt != DescrBuffViewArr.end())
+ while (ArrElem < Res.ArraySize && BuffViewIt != DescrBuffViewArr.end())
{
const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
*BuffViewIt = CachedRes.GetBufferViewWriteInfo();
@@ -1239,7 +1454,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
case SPIRVShaderResourceAttribs::ResourceType::StorageImage:
case SPIRVShaderResourceAttribs::ResourceType::SampledImage:
WriteDescrSetIt->pImageInfo = &(*DescrImgIt);
- while (ArrElem < Res.SpirvAttribs.ArraySize && DescrImgIt != DescrImgInfoArr.end())
+ while (ArrElem < Res.ArraySize && DescrImgIt != DescrImgInfoArr.end())
{
const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
*DescrImgIt = CachedRes.GetImageDescriptorWriteInfo(Res.IsImmutableSamplerAssigned());
@@ -1259,7 +1474,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
if (!Res.IsImmutableSamplerAssigned())
{
WriteDescrSetIt->pImageInfo = &(*DescrImgIt);
- while (ArrElem < Res.SpirvAttribs.ArraySize && DescrImgIt != DescrImgInfoArr.end())
+ while (ArrElem < Res.ArraySize && DescrImgIt != DescrImgInfoArr.end())
{
const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
*DescrImgIt = CachedRes.GetSamplerDescriptorWriteInfo();
@@ -1269,8 +1484,19 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
}
else
{
- ArrElem = Res.SpirvAttribs.ArraySize;
- WriteDescrSetIt->dstArrayElement = Res.SpirvAttribs.ArraySize;
+ ArrElem = Res.ArraySize;
+ WriteDescrSetIt->dstArrayElement = Res.ArraySize;
+ }
+ break;
+
+ case SPIRVShaderResourceAttribs::ResourceType::AccelerationStructure:
+ WriteDescrSetIt->pNext = &(*AccelStructIt);
+ while (ArrElem < Res.ArraySize && AccelStructIt != DescrAccelStructArr.end())
+ {
+ const auto& CachedRes = SetResources.GetResource(Res.CacheOffset + ArrElem);
+ *AccelStructIt = CachedRes.GetAccelerationStructureWriteInfo();
+ ++AccelStructIt;
+ ++ArrElem;
}
break;
@@ -1279,7 +1505,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
}
WriteDescrSetIt->descriptorCount = ArrElem - WriteDescrSetIt->dstArrayElement;
- if (ArrElem == Res.SpirvAttribs.ArraySize)
+ if (ArrElem == Res.ArraySize)
{
ArrElem = 0;
++ResNum;
@@ -1294,6 +1520,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
DescrImgIt == DescrImgInfoArr.end() ||
DescrBuffIt == DescrBuffInfoArr.end() ||
BuffViewIt == DescrBuffViewArr.end() ||
+ AccelStructIt == DescrAccelStructArr.end() ||
WriteDescrSetIt == WriteDescrSetArr.end())
{
auto DescrWriteCount = static_cast<Uint32>(std::distance(WriteDescrSetArr.begin(), WriteDescrSetIt));
@@ -1303,6 +1530,7 @@ void ShaderResourceLayoutVk::CommitDynamicResources(const ShaderResourceCacheVk&
DescrImgIt = DescrImgInfoArr.begin();
DescrBuffIt = DescrBuffInfoArr.begin();
BuffViewIt = DescrBuffViewArr.begin();
+ AccelStructIt = DescrAccelStructArr.begin();
WriteDescrSetIt = WriteDescrSetArr.begin();
}
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
index 7e06bd69..062a5725 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
@@ -52,7 +52,7 @@ size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayout
// When using HLSL-style combined image samplers, we need to skip separate samplers.
// Also always skip immutable separate samplers.
- if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
+ if (SrcRes.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
(!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned()))
continue;
@@ -96,7 +96,7 @@ void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& Sr
{
const auto& SrcRes = SrcLayout.GetResource(VarType, r);
// Skip separate samplers when using combined HLSL-style image samplers. Also always skip immutable separate samplers.
- if (SrcRes.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
+ if (SrcRes.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
(!UsingSeparateSamplers || SrcRes.IsImmutableSamplerAssigned()))
continue;
@@ -132,7 +132,7 @@ ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) con
{
auto& Var = m_pVariables[v];
const auto& Res = Var.m_Resource;
- if (strcmp(Res.SpirvAttribs.Name, Name) == 0)
+ if (strcmp(Res.Name, Name) == 0)
{
pVar = &Var;
break;
@@ -190,18 +190,18 @@ void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping,
const auto& Res = Var.m_Resource;
// There should be no immutable separate samplers
- VERIFY(Res.SpirvAttribs.Type != SPIRVShaderResourceAttribs::ResourceType::SeparateSampler || !Res.IsImmutableSamplerAssigned(),
+ VERIFY(Res.Type != SPIRVShaderResourceAttribs::ResourceType::SeparateSampler || !Res.IsImmutableSamplerAssigned(),
"There must be no shader resource variables for immutable separate samplers");
if ((Flags & (1 << Res.GetVariableType())) == 0)
continue;
- for (Uint32 ArrInd = 0; ArrInd < Res.SpirvAttribs.ArraySize; ++ArrInd)
+ for (Uint32 ArrInd = 0; ArrInd < Res.ArraySize; ++ArrInd)
{
if ((Flags & BIND_SHADER_RESOURCES_KEEP_EXISTING) && Res.IsBound(ArrInd, m_ResourceCache))
continue;
- const auto* VarName = Res.SpirvAttribs.Name;
+ const auto* VarName = Res.Name;
RefCntAutoPtr<IDeviceObject> pObj;
pResourceMapping->GetResource(VarName, &pObj, ArrInd);
if (pObj)
@@ -212,7 +212,7 @@ void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping,
{
if ((Flags & BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED) && !Res.IsBound(ArrInd, m_ResourceCache))
{
- LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", Res.SpirvAttribs.GetPrintName(ArrInd),
+ LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", Res.GetPrintName(ArrInd),
"': resource is not found in the resource mapping. "
"Do not use BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED flag to suppress the message if this is not an issue.");
}
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
index 65505ad3..66393e9b 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVkImpl.cpp
@@ -122,9 +122,17 @@ ShaderVkImpl::ShaderVkImpl(IReferenceCounters* pRefCounters,
SourceLength = GLSLSourceString.length();
}
+ GLSLangUtils::SpirvVersion spvVersion = GLSLangUtils::SpirvVersion::Vk100;
+ const auto& ExtFeats = GetDevice()->GetLogicalDevice().GetEnabledExtFeatures();
+ if (ExtFeats.Spirv15)
+ spvVersion = GLSLangUtils::SpirvVersion::Vk120;
+ else if (ExtFeats.Spirv14)
+ spvVersion = GLSLangUtils::SpirvVersion::Vk110_Spirv14;
+
m_SPIRV = GLSLangUtils::GLSLtoSPIRV(m_Desc.ShaderType, ShaderSource,
static_cast<int>(SourceLength), Macros,
ShaderCI.pShaderSourceStreamFactory,
+ spvVersion,
ShaderCI.ppCompilerOutput);
}
#endif
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
index a03102d0..825bf872 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
@@ -73,16 +73,18 @@ bool VulkanInstance::IsExtensionEnabled(const char* ExtensionName) const
return false;
}
-std::shared_ptr<VulkanInstance> VulkanInstance::Create(bool EnableValidation,
+std::shared_ptr<VulkanInstance> VulkanInstance::Create(uint32_t ApiVersion,
+ bool EnableValidation,
uint32_t GlobalExtensionCount,
const char* const* ppGlobalExtensionNames,
VkAllocationCallbacks* pVkAllocator)
{
- auto Instance = new VulkanInstance{EnableValidation, GlobalExtensionCount, ppGlobalExtensionNames, pVkAllocator};
+ auto Instance = new VulkanInstance{ApiVersion, EnableValidation, GlobalExtensionCount, ppGlobalExtensionNames, pVkAllocator};
return std::shared_ptr<VulkanInstance>{Instance};
}
-VulkanInstance::VulkanInstance(bool EnableValidation,
+VulkanInstance::VulkanInstance(uint32_t ApiVersion,
+ bool EnableValidation,
uint32_t GlobalExtensionCount,
const char* const* ppGlobalExtensionNames,
VkAllocationCallbacks* pVkAllocator) :
@@ -184,6 +186,16 @@ VulkanInstance::VulkanInstance(bool EnableValidation,
}
}
+#if DILIGENT_USE_VOLK
+ if (vkEnumerateInstanceVersion != nullptr && ApiVersion > VK_API_VERSION_1_0)
+ {
+ uint32_t MaxApiVersion = 0;
+ vkEnumerateInstanceVersion(&MaxApiVersion);
+ ApiVersion = std::min(ApiVersion, MaxApiVersion);
+ LOG_INFO_MESSAGE("Used Vulkan API version ", VK_VERSION_MAJOR(ApiVersion), ".", VK_VERSION_MINOR(ApiVersion));
+ }
+#endif
+
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@@ -192,7 +204,7 @@ VulkanInstance::VulkanInstance(bool EnableValidation,
appInfo.applicationVersion = 0; // Developer-supplied version number of the application
appInfo.pEngineName = "Diligent Engine";
appInfo.engineVersion = 0; // Developer-supplied version number of the engine used to create the application.
- appInfo.apiVersion = VK_API_VERSION_1_0;
+ appInfo.apiVersion = ApiVersion;
VkInstanceCreateInfo InstanceCreateInfo = {};
@@ -229,6 +241,7 @@ VulkanInstance::VulkanInstance(bool EnableValidation,
#endif
m_EnabledExtensions = std::move(GlobalExtensions);
+ m_VkVersion = ApiVersion;
// If requested, we enable the default validation layers for debugging
if (m_DebugUtilsEnabled)
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
index f9e190d8..358bdec5 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanLogicalDevice.cpp
@@ -36,9 +36,10 @@ namespace VulkanUtilities
std::shared_ptr<VulkanLogicalDevice> VulkanLogicalDevice::Create(const VulkanPhysicalDevice& PhysicalDevice,
const VkDeviceCreateInfo& DeviceCI,
+ const ExtensionFeatures& EnabledExtFeatures,
const VkAllocationCallbacks* vkAllocator)
{
- auto* LogicalDevice = new VulkanLogicalDevice{PhysicalDevice, DeviceCI, vkAllocator};
+ auto* LogicalDevice = new VulkanLogicalDevice{PhysicalDevice, DeviceCI, EnabledExtFeatures, vkAllocator};
return std::shared_ptr<VulkanLogicalDevice>{LogicalDevice};
}
@@ -49,9 +50,11 @@ VulkanLogicalDevice::~VulkanLogicalDevice()
VulkanLogicalDevice::VulkanLogicalDevice(const VulkanPhysicalDevice& PhysicalDevice,
const VkDeviceCreateInfo& DeviceCI,
+ const ExtensionFeatures& EnabledExtFeatures,
const VkAllocationCallbacks* vkAllocator) :
m_VkAllocator{vkAllocator},
- m_EnabledFeatures{*DeviceCI.pEnabledFeatures}
+ m_EnabledFeatures{*DeviceCI.pEnabledFeatures},
+ m_EnabledExtFeatures{EnabledExtFeatures}
{
auto res = vkCreateDevice(PhysicalDevice.GetVkDeviceHandle(), &DeviceCI, vkAllocator, &m_VkDevice);
CHECK_VK_ERROR_AND_THROW(res, "Failed to create logical device");
@@ -225,6 +228,29 @@ PipelineWrapper VulkanLogicalDevice::CreateGraphicsPipeline(const VkGraphicsPipe
return PipelineWrapper{GetSharedPtr(), std::move(vkPipeline)};
}
+PipelineWrapper VulkanLogicalDevice::CreateRayTracingPipeline(const VkRayTracingPipelineCreateInfoKHR& PipelineCI, VkPipelineCache cache, const char* DebugName) const
+{
+#if DILIGENT_USE_VOLK
+ VERIFY_EXPR(PipelineCI.sType == VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR);
+
+ if (DebugName == nullptr)
+ DebugName = "";
+
+ VkPipeline vkPipeline = VK_NULL_HANDLE;
+
+ auto err = vkCreateRayTracingPipelinesKHR(m_VkDevice, cache, 1, &PipelineCI, m_VkAllocator, &vkPipeline);
+ CHECK_VK_ERROR_AND_THROW(err, "Failed to create ray tracing pipeline '", DebugName, '\'');
+
+ if (*DebugName != 0)
+ SetPipelineName(m_VkDevice, vkPipeline, DebugName);
+
+ return PipelineWrapper{GetSharedPtr(), std::move(vkPipeline)};
+#else
+ UNSUPPORTED("vkCreateRayTracingPipelinesKHR is only available through Volk");
+ return PipelineWrapper{};
+#endif
+}
+
ShaderModuleWrapper VulkanLogicalDevice::CreateShaderModule(const VkShaderModuleCreateInfo& ShaderModuleCI, const char* DebugName) const
{
VERIFY_EXPR(ShaderModuleCI.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO);
@@ -455,6 +481,7 @@ VkMemoryRequirements VulkanLogicalDevice::GetImageMemoryRequirements(VkImage vkI
VkMemoryRequirements VulkanLogicalDevice::GetASMemoryRequirements(const VkAccelerationStructureMemoryRequirementsInfoKHR& Info) const
{
VkMemoryRequirements2 MemReqs = {};
+ MemReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
#if DILIGENT_USE_VOLK
vkGetAccelerationStructureMemoryRequirementsKHR(m_VkDevice, &Info, &MemReqs);
#else
@@ -571,4 +598,14 @@ VkResult VulkanLogicalDevice::ResetDescriptorPool(VkDescriptorPool vkD
return err;
}
+VkResult VulkanLogicalDevice::GetRayTracingShaderGroupHandles(VkPipeline pipeline, uint32_t firstGroup, uint32_t groupCount, size_t dataSize, void* pData) const
+{
+#if DILIGENT_USE_VOLK
+ return vkGetRayTracingShaderGroupHandlesKHR(m_VkDevice, pipeline, firstGroup, groupCount, dataSize, pData);
+#else
+ UNSUPPORTED("vkGetRayTracingShaderGroupHandlesKHR is only available through Volk");
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+#endif
+}
+
} // namespace VulkanUtilities
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
index 3e5f28d4..b66ac8af 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
@@ -166,6 +166,17 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice,
m_ExtProperties.DescriptorIndexing.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT;
}
+ // Additional extension that is required for ray tracing shader.
+ if (IsExtensionSupported(VK_KHR_SPIRV_1_4_EXTENSION_NAME))
+ m_ExtFeatures.Spirv14 = true;
+
+ // Some features requires SPIRV 1.4 or 1.5 that added to Vulkan 1.2 core.
+ if (Instance.GetVkVersion() >= VK_API_VERSION_1_2)
+ {
+ m_ExtFeatures.Spirv14 = true;
+ m_ExtFeatures.Spirv15 = true;
+ }
+
// make sure that last pNext is null
*NextFeat = nullptr;
*NextProp = nullptr;
@@ -178,7 +189,6 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice,
// Emulate KHR extension
if (m_ExtFeatures.RayTracingNV)
{
- //m_ExtFeatures.RayTracing.sType
//m_ExtFeatures.RayTracing.rayTracingPrimitiveCulling = true; // AZ TODO
m_ExtFeatures.RayTracing.rayTracing = VK_TRUE;
@@ -188,7 +198,7 @@ VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkDevice,
m_ExtProperties.RayTracing.shaderGroupBaseAlignment = RayTracingNV.shaderGroupBaseAlignment;
m_ExtProperties.RayTracing.maxGeometryCount = RayTracingNV.maxGeometryCount;
m_ExtProperties.RayTracing.maxInstanceCount = RayTracingNV.maxInstanceCount;
- m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount;
+ m_ExtProperties.RayTracing.maxPrimitiveCount = RayTracingNV.maxTriangleCount / 3;
m_ExtProperties.RayTracing.maxDescriptorSetAccelerationStructures = RayTracingNV.maxDescriptorSetAccelerationStructures;
m_ExtProperties.RayTracing.shaderGroupHandleCaptureReplaySize = 0;
}